embkernel
 All Classes Functions Variables Typedefs Groups Pages
RtosPortable.cpp
1 //------------------------------------------------------------------------------
2 //This file is part of embKernel.
3 //See license.txt for the full license governing this code.
4 //------------------------------------------------------------------------------
5 
6 #include "RtosPortable.hpp"
7 #include "RtosInterrupt.hpp"
8 #include "RtosCfg.hpp"
9 #include "Rtos.hpp"
10 #include "RtosTask.hpp"
11 #include "RtosMacros.hpp"
12 #include <stdint.h>
13 
14 void RtosPortable::start() {
15  SCB ->SHP[7] = RTOS_INT_PRI; //SVCall interrupt priority
16  SCB ->SHP[10] = RTOS_INT_PRI; //SysTick interrupt priority
17  SCB ->SHP[11] = RTOS_INT_PRI; //PendSV interrupt priority
18 
19  SysTick ->LOAD = (RTOS_CFG_CPU_FREQUENCY / RTOS_CFG_TICK_FREQUENCY) - 1; //set frequency
20  SysTick ->CTRL = 0x00000007; //uC clock, interrupt enabled, counter enabled
21 
22  //Start the first task
23  __asm volatile(
24  " ldr r0, =0xE000ED08 \n"
25  " ldr r0, [r0] \n"
26  " ldr r0, [r0] \n"
27  " msr msp, r0 \n"
28  " svc 0 \n"
29  );
30 }
31 
32 void RtosPortable::yield() {
33  RTOS_ASSERT((uint32_t) Rtos::sCurrentTask->mIterableCore.mTaskOwner && (uint32_t) Rtos::sCurrentTask->mIterableCore.mTaskOwner < 0x2000A000); //
34  SCB ->ICSR |= 1 << 28; //pendSV interrupt trigger
35 }
36 
37 void* RtosPortable::stackInit(void* stack, size_t stackSize, void (*run)(void*), void *parameter) {
38  uint32_t* ptr = (uint32_t*) stack;
39  size_t stackSizeWords = stackSize >> 2;
40 
41  for (size_t i = 0; i < stackSizeWords; i++) {
42  ptr[i] = STACK_FILL_VALUE;
43  }
44 
45  ptr = &(((uint32_t*) stack)[stackSizeWords - 1]);
46 
47  *--ptr = 0x01000000; // PSR
48  *--ptr = (uint32_t) run; // PC (R15)
49  *--ptr = (uint32_t) 0; // LR (R14)
50  *--ptr = 0x12121212; // R12
51  *--ptr = 0x03030303; // R3
52  *--ptr = 0x02020202; // R2
53  *--ptr = 0x01010101; // R1
54  *--ptr = (uint32_t) parameter; // R0
55  *--ptr = 0xFFFFFFFD; // EXC_RETURN
56  *--ptr = 0x11111111; // R11
57  *--ptr = 0x10101010; // R10
58  *--ptr = 0x09090909; // R9
59  *--ptr = 0x08080808; // R8
60  *--ptr = 0x07070707; // R7
61  *--ptr = 0x06060606; // R6
62  *--ptr = 0x05050505; // R5
63  *--ptr = 0x04040404; // R4
64 
65  return ptr;
66 }
67 
68 bool RtosPortable::isStackOverflow(void* stack, size_t stackSize) {
69  return (((uint32_t*) stack)[0] != STACK_FILL_VALUE);
70 }
71 
72 size_t RtosPortable::getFreeStackSize(void* stack, size_t stackSize) {
73  uint32_t* p = (uint32_t*) stack;
74  size_t size = 0;
75  for (; size < stackSize; size += 4) {
76  if (*p++ != STACK_FILL_VALUE) {
77  break;
78  }
79  }
80  return size;
81 }
82 
83 uint32_t RtosPortable::getCyclesCounter() {
84  uint32_t cycles = SysTick ->LOAD - SysTick ->VAL;
85  uint32_t ticks = Rtos::sTick;
86  if (SysTick ->CTRL & SysTick_CTRL_COUNTFLAG_Msk) { //Systick overflow?
87  ticks++;
88  cycles = SysTick ->LOAD - SysTick ->VAL;
89  }
90  return ((ticks * (RTOS_CFG_CPU_FREQUENCY / RTOS_CFG_TICK_FREQUENCY)) + cycles);
91 }
92 
93 void RtosPortable::enterCriticalSection() {
94  __asm volatile
95  (
96  " mov r0, #0x80 \n"
97  " msr basepri, r0 \n"
98  :::"r0"
99  );
100 }
101 
102 void RtosPortable::exitCriticalSection() {
103  __asm volatile
104  (
105  " mov r0, #0 \n"
106  " msr basepri, r0 \n"
107  :::"r0"
108  );
109 }
110 
111 void RtosPortable::disableAllInt() {
112  __asm volatile
113  (
114  " mov r0, #1 \n "
115  " msr primask, r0 \n "
116  :::"r0"
117  );
118 }
119 
120 void RtosPortable::enableAllInt() {
121  __asm volatile
122  (
123  " mov r0, #0 \n "
124  " msr primask, r0 \n "
125  :::"r0"
126  );
127 }
128 
129 __attribute__((naked)) void RtosInterrupt::IRQ_SVCall(void) {
130  __asm volatile (
131  " mov r0, %[currentTask] \n"
132  " ldmia r0!, {r4-r11} \n"
133  " ldmia r0!, {lr} \n"
134  " msr psp, r0 \n"
135  " mov r0, #0 \n"
136  " msr basepri, r0 \n"
137  " bx lr \n"
138  ::[currentTask]"r"(Rtos::sCurrentTask->mCurrentStackPointer):);
139 }
140 
141 __attribute__((naked)) void RtosInterrupt::IRQ_SysTick(void) {
142  __asm volatile (
143  " mrs r0, psp \n"
144  " tst r14, #0x10 \n" // Is the task is using the FPU context save hi vfp registers
145  " it eq \n"
146  " vstmdbeq r0!, {s16-s31} \n"
147  " stmdb r0!, {lr} \n"
148  " stmdb r0!, {r4-r11} \n"
149  " push {r0} \n"
150  " bl _ZN4Rtos6onTickEv \n"
151 #if RTOS_CFG_TRACE_BUFFER_SIZE
152  " movw r0, #0xe010 \n" //Reset COUNTFLAG bit
153  " movt r0, #0xe000 \n"
154  " ldr r0,[r0] \n"
155 #endif
156  " pop {r0} \n"
157  " bl _ZN4Rtos8scheduleEPv \n"
158  " ldmia r0!, {r4-r11} \n"
159  " ldmia r0!, {lr} \n"
160  " tst r14, #0x10 \n" // If the task is using the FPU context restore hi vfp registers
161  " it eq \n"
162  " vldmiaeq r0!, {s16-s31} \n"
163  " msr psp, r0 \n"
164  " mov r0, #0 \n"
165  " msr basepri, r0 \n"
166  " bx lr \n"
167  );
168 }
169 
170 __attribute__((naked)) void RtosInterrupt::IRQ_PendSV(void) {
171  __asm volatile (
172  " mrs r0, psp \n"
173  " tst r14, #0x10 \n" // If the task is using the FPU context save hi vfp registers
174  " it eq \n"
175  " vstmdbeq r0!, {s16-s31} \n"
176  " stmdb r0!, {lr} \n"
177  " stmdb r0!, {r4-r11} \n"
178  " bl _ZN4Rtos8scheduleEPv \n"
179  " ldmia r0!, {r4-r11} \n"
180  " ldmia r0!, {lr} \n"
181  " tst r14, #0x10 \n"// If the task is using the FPU context restore hi vfp registers
182  " it eq \n"
183  " vldmiaeq r0!, {s16-s31} \n"
184  " msr psp, r0 \n"
185  " mov r0, #0 \n"
186  " msr basepri, r0 \n"
187  " bx lr \n"
188  );
189 }
190