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_cm3.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 interruption 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 "LDMIA R0!, {R4-R11} \n" //
102 "MSR PSP, R0 \n" //
103 "ORR LR, #0xD \n" // LR = 0xFFFFFFFD return to threadmode
104 "CPSIE I \n" //
105 "BX LR \n" //
106 );
107 }
108#ifdef __cplusplus
109}
110#endif
111
112#ifdef __cplusplus
113extern "C"
114{
115#endif
120 {
121 __asm volatile(
122 //"CPSID I \n" //Prevent interruption during context switch
123 "MRS R0, PSP \n" // PSP is process stack pointer
124 "CBZ R0, OS_CPU_PendSVHandler_nosave \n" // Skip register save the first time
125
126 "SUBS R0, R0, #0x20 \n" // Save remaining regs r4-11 on process stack
127 "STM R0, {R4-R11} \n" //
128
129 "LDR R1, =tcb_curr_ptr \n" // OSTCBCur->OSTCBStkPtr = SP;
130 "LDR R1, [R1]\n" //
131 "STR R0, [R1] \n" // R0 is SP of process being switched out
132
133 /* At this point, entire context of process has been saved */
134
135 "OS_CPU_PendSVHandler_nosave: \n" //
136 "LDR R0, =tcb_curr_ptr \n" // OSTCBCur = OSTCBHighRdy;
137 "LDR R1, =tcb_high_rdy_ptr \n" //
138 "LDR R2, [R1] \n" //
139 "STR R2, [R0] \n" //
140
141 "LDR R0, [R2] \n" // R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
142 "LDM R0, {R4-R11} \n" // Restore r4-11 from new process stack
143 "ADDS R0, R0, #0x20 \n" //
144 "MSR PSP, R0 \n" // Load PSP with new process SP
145 "ORR LR, LR, #0x04 \n" // Ensure exception return uses process stack
146 //"CPSIE I \n" //
147 "BX LR \n" // Exception return will restore remaining context
148 );
149 }
150#ifdef __cplusplus
151}
152#endif
153
154#ifdef __cplusplus
155extern "C"
156{
157#endif
162 {
163 port_disable_interrupts
164 /* Increment the RTOS tick. */
165 if (akos_thread_increment_tick() == OS_TRUE)
166 {
167 /* A context switch is required. Context switching is performed in
168 * the PendSV interrupt. Pend the PendSV interrupt. */
169 port_trigger_PendSV();
170 }
171 port_enable_interrupts
172 }
173
174#ifdef __cplusplus
175}
176#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: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