AKOS  v1.0.0
Documentation
Loading...
Searching...
No Matches
port.c
Go to the documentation of this file.
1/****************************************************************************/
12
13#include "port.h"
14
15#include "config.h"
16#include "core.h"
17#include "core_cm0.h"
18#include "core_cmFunc.h"
19#include "stm32f030x6.h"
20#include "thread.h"
21
26void akos_port_systick_init_freq(uint32_t cpu_freq)
27{
28 volatile uint32_t ticks = cpu_freq / 1000u;
29
30 SysTick->LOAD = ticks - 1u;
31 SysTick->VAL = 0u;
32 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk |
33 SysTick_CTRL_ENABLE_Msk;
34
35 *(volatile uint32_t*)0xE000ED20UL &= ~(0xFFUL << 24);
36 *(volatile uint32_t*)0xE000ED20UL |= ((1 << __NVIC_PRIO_BITS) - 2)
37 << (32 - __NVIC_PRIO_BITS);
38}
39
44{
45 __asm volatile(
46 " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to
47 locate the stack. */
48 " ldr r0, [r0] \n"
49 " ldr r0, [r0] \n"
50 " msr msp, r0 \n" /* Set the msp back to the start of the
51 stack. */
52 " cpsie i \n" /* Globally enable interrupts. */
53 " cpsie f \n"
54 " dsb \n"
55 " isb \n"
56 " svc 0 \n" /* System call to start first thread. */
57 " nop \n"
58 " .ltorg \n");
59}
60
69uint32_t* akos_port_task_stack_init(uint32_t* p_stack, size_t stack_size,
70 void (*pf_task)(void*), void* p_arg)
71{
72 uint32_t* p_stack_ptr;
73
74 p_stack_ptr = &p_stack[stack_size - (uint32_t)1];
75 p_stack_ptr = (uint32_t*)(((uint32_t)p_stack_ptr) & (~((uint32_t)0x007)));
76
77 *(--p_stack_ptr) = (uint32_t)0x01000000UL;
78 *(--p_stack_ptr) = ((uint32_t)pf_task) & ((uint32_t)0xfffffffeUL);
79 *(--p_stack_ptr) = (uint32_t)0x0000000EUL;
80 p_stack_ptr -= 5;
81 *p_stack_ptr = (uint32_t)p_arg;
82 p_stack_ptr -= 8;
83
84 return p_stack_ptr;
85}
86
87#ifdef __cplusplus
88extern "C" {
89#endif
94{
95 __asm volatile(
96 ".syntax unified \n"
97 "cpsid i \n" // Prevent interrupt during
98 // context switch
99 "ldr r1, =tcb_curr_ptr \n" // get pointer to TCB current
100 "ldr r1, [r1] \n" // get TCB current = pointer to
101 // StkPtr
102 "ldr r0, [r1] \n" // get StkPtr
103
104 "adds r0, #16 \n"
105 "ldmia r0!, {r4-r7} \n" //
106 "msr psp, r0 \n" //
107
108 // Double-hop context restore
109 "mov r8, r4 \n"
110 "mov r9, r5 \n"
111 "mov r10, r6 \n"
112 "mov r11, r7 \n"
113 "subs r0, #32 \n"
114 "ldmia r0!, {r4-r7} \n"
115
116 "mov r0, lr \n"
117 "movs r1, #0xD \n"
118 "orrs r0, r1 \n" // LR = 0xFFFFFFFD return to
119 // threadmode
120 "mov lr, r0 \n"
121 "cpsie i \n" //
122 "bx lr \n" //
123
124 ".ltorg \n");
125}
126#ifdef __cplusplus
127}
128#endif
129
130#ifdef __cplusplus
131extern "C" {
132#endif
137{
138 __asm volatile(
139 ".syntax unified \n"
140 "mrs r0, psp \n" // PSP is process
141 // stack pointer
142 "cmp r0, #0 \n"
143 "beq OS_CPU_PendSVHandler_nosave \n"
144
145 "subs r0, #32 \n" // Save remaining regs
146 // r4-11 on process
147 // stack
148 "stmia r0!, {r4-r7} \n" //
149 "mov r8, r4 \n"
150 "mov r9, r5 \n"
151 "mov r10, r6 \n"
152 "mov r11, r7 \n"
153 "stmia r0!, {r4-r7} \n"
154 "subs r0, #32 \n"
155
156 "ldr r1, =tcb_curr_ptr \n" // OSTCBCur->OSTCBStkPtr
157 // = SP;
158 "ldr r1, [r1] \n" //
159 "str r0, [r1] \n" // R0 is SP of process
160 // being switched out
161
162 /* At this point, entire context of process has been saved */
163
164 "OS_CPU_PendSVHandler_nosave: \n" //
165 "ldr r0, =tcb_curr_ptr \n" // OSTCBCur =
166 // OSTCBHighRdy;
167 "ldr r1, =tcb_high_rdy_ptr \n" //
168 "ldr r2, [r1] \n" //
169 "str r2, [r0] \n" //
170
171 "ldr r0, [r2] \n" // R0 is new process
172 // SP; SP =
173 // OSTCBHighRdy->OSTCBStkPtr;
174 "adds r0, #16 \n"
175 "ldmia r0!, {r4-r7} \n" // Restore r4-11 from
176 // new process stack
177
178 "msr psp, r0 \n" // Load PSP with new
179 // process SP
180
181 "mov r8, r4 \n"
182 "mov r9, r5 \n"
183 "mov r10, r6 \n"
184 "mov r11, r7 \n"
185 "subs r0, #32 \n" //
186 "ldmia r0!, {r4-r7} \n"
187
188 "mov r0, lr \n"
189 "movs r1, #0xD \n"
190 "orrs r0, r1 \n" // Ensure exception
191 // return uses process
192 // stack
193 "mov lr, r0 \n"
194 "bx lr \n" // Exception return
195 // will restore
196 // remaining context
197
198 ".ltorg \n");
199}
200#ifdef __cplusplus
201}
202#endif
203
204#ifdef __cplusplus
205extern "C" {
206#endif
211{
212 port_disable_interrupts
213 /* Increment the RTOS tick. */
214 if (akos_thread_increment_tick() == OS_TRUE)
215 {
216 /* A context switch is required. Context switching is performed in
217 * the PendSV interrupt. Pend the PendSV interrupt. */
218 port_trigger_PendSV();
219 }
220 port_enable_interrupts
221}
222
223#ifdef __cplusplus
224}
225#endif
Build-time configuration macros for AK-mOS.
Kernel control and critical-section API.
uint32_t * akos_port_task_stack_init(uint32_t *p_stack, size_t stack_size, void(*pf_task)(void *), void *p_arg)
Build the initial Cortex-M thread stack frame.
Definition port.c:69
void port_PendSVHandler(void)
PendSV handler used for context switching between threads.
Definition port.c:136
void port_SVCHandler(void)
SVC handler used to restore the first thread context.
Definition port.c:93
void port_SysTickHandler()
SysTick ISR hook for scheduler tick updates.
Definition port.c:210
void akos_port_start_first_task(void)
Start the first thread by restoring the initial exception context.
Definition port.c:43
void akos_port_systick_init_freq(uint32_t cpu_freq)
Initialize SysTick to generate 1ms OS ticks.
Definition port.c:26
Cortex-M3 port API for AKOS.
Thread scheduling and thread messaging APIs.
uint8_t akos_thread_increment_tick(void)
Tick handler routine called from SysTick.
Definition thread.c:560