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 "stm32l1xx.h"
19
24void akos_port_systick_init_freq(uint32_t cpu_freq)
25{
26 volatile uint32_t ticks = cpu_freq / 1000u;
27
28 SysTick->LOAD = ticks - 1u;
29 SysTick->VAL = 0u;
30 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
31 SysTick_CTRL_TICKINT_Msk |
32 SysTick_CTRL_ENABLE_Msk;
33
34 *(volatile uint32_t *)0xE000ED20UL &= ~(0xFFUL << 24);
35 *(volatile uint32_t *)0xE000ED20UL |= ((uint32_t)1u << (8U - __NVIC_PRIO_BITS)) << 24;
36}
37
42{
43 __asm volatile(
44 " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
45 " ldr r0, [r0] \n"
46 " ldr r0, [r0] \n"
47 " msr msp, r0 \n" /* Set the msp back to the start of the stack. */
48 " cpsie i \n" /* Globally enable interrupts. */
49 " cpsie f \n"
50 " dsb \n"
51 " isb \n"
52 " svc 0 \n" /* System call to start first thread. */
53 " nop \n"
54 " .ltorg \n"
55 );
56}
57
66uint32_t *akos_port_task_stack_init(uint32_t *p_stack,
67 size_t stack_size,
68 void (*pf_task)(void *),
69 void *p_arg)
70{
71 uint32_t *p_stack_ptr;
72
73 p_stack_ptr = &p_stack[stack_size - (uint32_t)1];
74 p_stack_ptr = (uint32_t *)(((uint32_t)p_stack_ptr) & (~((uint32_t)0x007)));
75
76 *(--p_stack_ptr) = (uint32_t)0x01000000UL;
77 *(--p_stack_ptr) = ((uint32_t)pf_task) & ((uint32_t)0xfffffffeUL);
78 *(--p_stack_ptr) = (uint32_t)0x0000000EUL;
79 p_stack_ptr -= 5;
80 *p_stack_ptr = (uint32_t)p_arg;
81 p_stack_ptr -= 8;
82
83 return p_stack_ptr;
84}
85
86#ifdef __cplusplus
87extern "C"
88{
89#endif
93 void port_SVCHandler(void)
94 {
95 __asm volatile(
96 "CPSID I \n" // Prevent interruption during context switch
97 "LDR R1, =tcb_curr_ptr \n" // get pointer to TCB current
98 "LDR R1, [R1] \n" // get TCB current = pointer to StkPtr
99 "LDR R0, [R1] \n" // get StkPtr
100 "LDMIA R0!, {R4-R11} \n" //
101 "MSR PSP, R0 \n" //
102 "ORR LR, #0xD \n" // LR = 0xFFFFFFFD return to threadmode
103 "CPSIE I \n" //
104 "BX LR \n" //
105 );
106 }
107#ifdef __cplusplus
108}
109#endif
110
111#ifdef __cplusplus
112extern "C"
113{
114#endif
119 {
120 __asm volatile(
121 //"CPSID I \n" //Prevent interruption during context switch
122 "MRS R0, PSP \n" // PSP is process stack pointer
123 "CBZ R0, OS_CPU_PendSVHandler_nosave \n" // Skip register save the first time
124
125 "SUBS R0, R0, #0x20 \n" // Save remaining regs r4-11 on process stack
126 "STM R0, {R4-R11} \n" //
127
128 "LDR R1, =tcb_curr_ptr \n" // OSTCBCur->OSTCBStkPtr = SP;
129 "LDR R1, [R1]\n" //
130 "STR R0, [R1] \n" // R0 is SP of process being switched out
131
132 /* At this point, entire context of process has been saved */
133
134 "OS_CPU_PendSVHandler_nosave: \n" //
135 "LDR R0, =tcb_curr_ptr \n" // OSTCBCur = OSTCBHighRdy;
136 "LDR R1, =tcb_high_rdy_ptr \n" //
137 "LDR R2, [R1] \n" //
138 "STR R2, [R0] \n" //
139
140 "LDR R0, [R2] \n" // R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
141 "LDM R0, {R4-R11} \n" // Restore r4-11 from new process stack
142 "ADDS R0, R0, #0x20 \n" //
143 "MSR PSP, R0 \n" // Load PSP with new process SP
144 "ORR LR, LR, #0x04 \n" // Ensure exception return uses process stack
145 //"CPSIE I \n" //
146 "BX LR \n" // Exception return will restore remaining context
147 );
148 }
149#ifdef __cplusplus
150}
151#endif
152
153#ifdef __cplusplus
154extern "C"
155{
156#endif
161 {
162 port_disable_interrupts
163 /* Increment the RTOS tick. */
164 if (akos_thread_increment_tick() == OS_TRUE)
165 {
166 /* A context switch is required. Context switching is performed in
167 * the PendSV interrupt. Pend the PendSV interrupt. */
168 port_trigger_PendSV();
169 }
170 port_enable_interrupts
171 }
172
173#ifdef __cplusplus
174}
175#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