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  SCB->ICSR |= 1 << 28; //pendSV interrupt trigger
34 }
35 
36 void* RtosPortable::stackInit(void* stack, size_t stackSize, void(*run)(void*), void *parameter) {
37  uint32_t* ptr = (uint32_t*) stack;
38  size_t stackSizeWords = stackSize >> 2;
39 
40  for (size_t i = 0; i < stackSizeWords; i++) {
41  ptr[i] = STACK_FILL_VALUE;
42  }
43 
44  ptr = &(((uint32_t*) stack)[stackSizeWords - 1]);
45 
46  *--ptr = 0x01000000; // PSR
47  *--ptr = (uint32_t) run; // PC (R15)
48  *--ptr = (uint32_t) 0; // LR (R14)
49  *--ptr = 0x12121212; // R12
50  *--ptr = 0x03030303; // R3
51  *--ptr = 0x02020202; // R2
52  *--ptr = 0x01010101; // R1
53  *--ptr = (uint32_t) parameter; // R0
54  *--ptr = 0xFFFFFFFD; // EXC_RETURN
55  *--ptr = 0x11111111; // R11
56  *--ptr = 0x10101010; // R10
57  *--ptr = 0x09090909; // R9
58  *--ptr = 0x08080808; // R8
59  *--ptr = 0x07070707; // R7
60  *--ptr = 0x06060606; // R6
61  *--ptr = 0x05050505; // R5
62  *--ptr = 0x04040404; // R4
63 
64  return ptr;
65 }
66 
67 bool RtosPortable::isStackOverflow(void* stack, size_t stackSize) {
68  return (((uint32_t*) stack)[0] != STACK_FILL_VALUE);
69 }
70 
71 size_t RtosPortable::getFreeStackSize(void* stack, size_t stackSize) {
72  uint32_t* p = (uint32_t*) stack;
73  size_t size = 0;
74  for (; size < stackSize; size += 4) {
75  if (*p++ != STACK_FILL_VALUE) {
76  break;
77  }
78  }
79  return size;
80 }
81 
82 uint32_t RtosPortable::getCyclesCounter() {
83  uint32_t cycles = SysTick->LOAD - SysTick->VAL;
84  uint32_t ticks = Rtos::sTick;
85  if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) { //Systick overflow?
86  ticks++;
87  cycles = SysTick->LOAD - SysTick->VAL;
88  }
89  return ((ticks * (RTOS_CFG_CPU_FREQUENCY / RTOS_CFG_TICK_FREQUENCY)) + cycles);
90 }
91 
92 void RtosPortable::enterCriticalSection() {
93  __asm volatile
94  (
95  " mov r0, #0x80 \n"
96  " msr basepri, r0 \n"
97  :::"r0"
98  );
99 }
100 
101 void RtosPortable::exitCriticalSection() {
102  __asm volatile
103  (
104  " mov r0, #0 \n"
105  " msr basepri, r0 \n"
106  :::"r0"
107  );
108 }
109 
110 void RtosPortable::disableAllInt() {
111  __asm volatile
112  (
113  " mov r0, #1 \n "
114  " msr primask, r0 \n "
115  :::"r0"
116  );
117 }
118 
119 void RtosPortable::enableAllInt() {
120  __asm volatile
121  (
122  " mov r0, #0 \n "
123  " msr primask, r0 \n "
124  :::"r0"
125  );
126 }
127 
128 __attribute__((naked)) void RtosInterrupt::IRQ_SVCall(void) {
129  __asm volatile (
130  " mov r0, %[currentTask] \n"
131  " ldmia r0!, {r4-r11} \n"
132  " ldmia r0!, {lr} \n"
133  " msr psp, r0 \n"
134  " mov r0, #0 \n"
135  " msr basepri, r0 \n"
136  " bx lr \n"
137  ::[currentTask]"r"(Rtos::sCurrentTask->mCurrentStackPointer):);
138 }
139 
140 __attribute__((naked)) void RtosInterrupt::IRQ_SysTick(void) {
141  __asm volatile (
142  " mrs r0, psp \n"
143  " stmdb r0!, {lr} \n"
144  " stmdb r0!, {r4-r11} \n"
145  " push {r0} \n"
146  " bl _ZN4Rtos6onTickEv \n"
147 #if RTOS_CFG_TRACE_BUFFER_SIZE
148  " movw r0, #0xe010 \n" //Reset COUNTFLAG bit
149  " movt r0, #0xe000 \n"
150  " ldr r0,[r0] \n"
151 #endif
152  " pop {r0} \n"
153  " bl _ZN4Rtos8scheduleEPv \n"
154  " ldmia r0!, {r4-r11} \n"
155  " ldmia r0!, {lr} \n"
156  " msr psp, r0 \n"
157  " mov r0, #0 \n"
158  " msr basepri, r0 \n"
159  " bx lr \n"
160  );
161 }
162 
163 __attribute__((naked)) void RtosInterrupt::IRQ_PendSV(void) {
164  __asm volatile (
165  " mrs r0, psp \n"
166  " stmdb r0!, {lr} \n"
167  " stmdb r0!, {r4-r11} \n"
168  " bl _ZN4Rtos8scheduleEPv \n"
169  " ldmia r0!, {r4-r11} \n"
170  " ldmia r0!, {lr} \n"
171  " msr psp, r0 \n"
172  " mov r0, #0 \n"
173  " msr basepri, r0 \n"
174  " bx lr \n"
175  );
176 }
177