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#include "thread.h"
15#include "core.h"
16#include "config.h"
17
18#include "core_cm0.h"
19#include "core_cmFunc.h"
20
25void akos_port_systick_init_freq(uint32_t cpu_freq)
26{
27 volatile uint32_t ticks = cpu_freq / 1000u;
28
29 SysTick->LOAD = ticks - 1u;
30 SysTick->VAL = 0u;
31 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
32 SysTick_CTRL_TICKINT_Msk |
33 SysTick_CTRL_ENABLE_Msk;
34
35 *(volatile uint32_t *)0xE000ED20UL &= ~(0xFFUL << 24);
36 *(volatile uint32_t *)0xE000ED20UL |= ((uint32_t)1u << (8U - __NVIC_PRIO_BITS)) << 24;
37}
38
43{
44 __asm volatile(
45 " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
46 " ldr r0, [r0] \n"
47 " ldr r0, [r0] \n"
48 " msr msp, r0 \n" /* Set the msp back to the start of the stack. */
49 " cpsie i \n" /* Globally enable interrupts. */
50 " cpsie f \n"
51 " dsb \n"
52 " isb \n"
53 " svc 0 \n" /* System call to start first thread. */
54 " nop \n"
55 " .ltorg \n"
56 );
57}
58
67uint32_t *akos_port_task_stack_init(uint32_t *p_stack,
68 size_t stack_size,
69 void (*pf_task)(void *),
70 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{
90#endif
94 void port_SVCHandler(void)
95 {
96 __asm volatile(
97 "cpsid i \n" // Prevent interrupt during context switch
98 "ldr r1, =tcb_curr_ptr \n" // get pointer to TCB current
99 "ldr r1, [r1] \n" // get TCB current = pointer to StkPtr
100 "ldr r0, [r1] \n" // get StkPtr
101
102 "adds r0, #16 \n"
103 "ldmia r0!, {r4-r7} \n" //
104 "msr psp, r0 \n" //
105
106 // Double-hop context restore
107 "mov r8, r4 \n"
108 "mov r9, r5 \n"
109 "mov r10, r6 \n"
110 "mov r11, r7 \n"
111 "subs r0, #32 \n"
112 "ldmia r0!, {r4-r7} \n"
113
114 "mov r2, #0xD \n"
115 "orrs lr, r2 \n" // LR = 0xFFFFFFFD return to threadmode
116 "cpsie i \n" //
117 "bx lr \n" //
118
119 ".ltorg \n"
120 );
121 }
122#ifdef __cplusplus
123}
124#endif
125
126#ifdef __cplusplus
127extern "C"
128{
129#endif
134 {
135 __asm volatile(
136 "mrs r0, psp \n" // PSP is process stack pointer
137 "cbz r0, OS_CPU_PendSVHandler_nosave \n" // Skip register save the first time
138
139 "subs r0, #32 \n" // Save remaining regs r4-11 on process stack
140 "stmia r0!, {r4-r7} \n" //
141 "mov r8, r4 \n"
142 "mov r9, r5 \n"
143 "mov r10, r6 \n"
144 "mov r11, r7 \n"
145 "stmia r0!, {r4-r7} \n"
146 "subs r0, #32 \n"
147
148 "ldr r1, =tcb_curr_ptr \n" // OSTCBCur->OSTCBStkPtr = SP;
149 "ldr r1, [r1] \n" //
150 "str r0, [r1] \n" // R0 is SP of process being switched out
151
152 /* At this point, entire context of process has been saved */
153
154 "OS_CPU_PendSVHandler_nosave: \n" //
155 "ldr r0, =tcb_curr_ptr \n" // OSTCBCur = OSTCBHighRdy;
156 "ldr r1, =tcb_high_rdy_ptr \n" //
157 "ldr r2, [r1] \n" //
158 "str r2, [r0] \n" //
159
160 "ldr r0, [r2] \n" // R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
161 "adds r0, #16 \n"
162 "ldmia r0!, {r4-r7} \n" // Restore r4-11 from new process stack
163
164 "msr psp, r0 \n" // Load PSP with new process SP
165
166 "mov r8, r4 \n"
167 "mov r9, r5 \n"
168 "mov r10, r6 \n"
169 "mov r11, r7 \n"
170 "subs r0, #32 \n" //
171 "ldmia r0!, {r4-r7} \n"
172
173 "mov r3, #0xD \n"
174 "orrs lr, r3 \n" // Ensure exception return uses process stack
175 "bx lr \n" // Exception return will restore remaining context
176
177 ".ltorg \n"
178 );
179 }
180#ifdef __cplusplus
181}
182#endif
183
184#ifdef __cplusplus
185extern "C"
186{
187#endif
192 {
193 port_disable_interrupts
194 /* Increment the RTOS tick. */
195 if (akos_thread_increment_tick() == OS_TRUE)
196 {
197 /* A context switch is required. Context switching is performed in
198 * the PendSV interrupt. Pend the PendSV interrupt. */
199 port_trigger_PendSV();
200 }
201 port_enable_interrupts
202 }
203
204#ifdef __cplusplus
205}
206#endif
Build-time configuration macros for AK-mOS.
Kernel control and critical-section API.
CMSIS Cortex-M Core Function Access Header File.
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:67
void port_PendSVHandler(void)
PendSV handler used for context switching between threads.
Definition port.c:133
void port_SVCHandler(void)
SVC handler used to restore the first thread context.
Definition port.c:94
void port_SysTickHandler()
SysTick ISR hook for scheduler tick updates.
Definition port.c:191
void akos_port_start_first_task(void)
Start the first thread by restoring the initial exception context.
Definition port.c:42
void akos_port_systick_init_freq(uint32_t cpu_freq)
Initialize SysTick to generate 1ms OS ticks.
Definition port.c:25
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:471