-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
239 lines (195 loc) · 5.55 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/**
******************************************************************************
* @file : main.c
* @author : Auto-generated by STM32CubeIDE
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#if !defined(__SOFT_FP__) && defined(__ARM_FP)
#warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
#endif
// we will schedule 4 tasks by our scheduler in round robin fashion. In our application, tasks will keep executing infinitely
#include<stdio.h>
#include "main.h"
void enable_processor_faults(void);
void task1_handler(void);
void task2_handler(void);
void task3_handler(void);
void task4_handler(void);
void init_systick_timer(uint32_t tick_hz);
__attribute__((naked)) void init_schedular_stack(uint32_t sched_top_of_stack);
void init_tasks_stack(void);
void enable_processor_faults(void);
void switch_sp_to_psp();
uint32_t get_psp_value(void);
uint32_t psp_of_tasks[MAX_TASKS] = {T1_STACK_START, T2_STACK_START, T3_STACK_START, T4_STACK_START};
uint32_t task_handlers[MAX_TASKS];
uint8_t current_task = 0;// task 1 is running
int main(void)
{
enable_processor_faults();
init_schedular_stack(SCHED_STACK_START);
task_handlers[0] = (uint32_t)task1_handler;
task_handlers[1] = (uint32_t)task2_handler;
task_handlers[2] = (uint32_t)task3_handler;
task_handlers[3] = (uint32_t)task4_handler;
init_tasks_stack();
init_systick_timer(TICK_HZ);
switch_sp_to_psp();
task1_handler();
for(;;);
}
void task1_handler(void)
{
while(1)
{
printf("task1\n");
}
}
void task2_handler(void)
{
while(1)
{
printf("task2\n");
}
}
void task3_handler(void)
{
while(1){
printf("task3\n");
}
}
void task4_handler(void)
{
while(1)
{
printf("task4\n");
}
}
void init_systick_timer(uint32_t tick_hz)
{
uint32_t *pSRVR = (uint32_t*)0xE000E014;
uint32_t *pSCSR = (uint32_t*)0xE000E010;
uint32_t count_value = (SYSTICK_TIM_CLK/tick_hz)-1;
//clear the value of SVR
*pSRVR &= ~(0x00ffffffff);
//load the value into SVR
*pSRVR |= count_value;
// do some settings
*pSCSR |= (1<<1); //Enables Systick exception request;
*pSCSR |= (1<<2); // Indicates the clock source as processor clock source
//enable the systick
*pSCSR |= (1<<0);
}
void enable_processor_faults(void)
{
uint32_t *pSHCSR = (uint32_t*)0xE000ED24;
*pSHCSR |= ( 1 << 16); //mem manage
*pSHCSR |= ( 1 << 17); //bus fault
*pSHCSR |= ( 1 << 18); //usage fault
}
__attribute__((naked)) void init_schedular_stack(uint32_t sched_top_of_stack)
{
__asm volatile("MSR MSP, R0");
__asm volatile("BX LR"); // BX copies the value of LR into PC : BX : branch indirect
}
void init_tasks_stack(void)
{
uint32_t *pPSP;
for(int i = 0; i <MAX_TASKS ; i++)
{
pPSP = (uint32_t *)psp_of_tasks[i];
pPSP-- ;
*pPSP = DUMMY_XPSR;// 0x01000000
pPSP--;
*pPSP = task_handlers[i];
pPSP--;
*pPSP = 0xFFFFFFFD;
for(int j = 0; j < 13; j++)
{
pPSP-- ;
*pPSP = 0;
}
psp_of_tasks[i]= (uint32_t)pPSP;
}
}
uint32_t get_psp_value(void)
{
return psp_of_tasks[current_task];
}
void save_psp_value(uint32_t current_psp_value)
{
psp_of_tasks[current_task] = current_psp_value;
}
void update_next_task(void)
{
current_task++;
current_task %= MAX_TASKS;
}
__attribute__((naked)) void switch_sp_to_psp()
{
//1. initialize the psp with task1 stack start address
//get the value of psp of current stack
__asm volatile("PUSH {LR}");
__asm volatile("BL get_psp_value");
// here the value of LR is corrupted, here LR holds some value as this function is called from main.
//Using PUSH we preserve LR which connects back to main
__asm volatile("MSR PSP, R0");// initialize psp
__asm volatile("POP {LR}"); // pops back LR value
//2. switch from SP to PSP using control register
__asm volatile("MOV R0, #0X02");
__asm volatile("MSR CONTROL, R0");
__asm volatile("BX LR");
}
__attribute__((naked))void SysTick_Handler(void)
{
/*save the context of current task */
//1. Get current running task's PSP value
__asm volatile("MRS R0, PSP");
//2. Using that PSP value store SF2( R4 to R11 )--
/*It's like a Push operation, but we cannot use push
instruction because MSP will be effected.In the handler mode processor uses MSP
Here we have to store multiple registers into task's private stack which
is referenced by R0. For this we use STMDB instruction*/
__asm volatile("STMDB R0!, {R4-R11}");
__asm volatile("PUSH {LR}");
//3. Save the current value of PSP
__asm volatile("BL save_psp_value");
/* Retrieve the context of next task */
//1. Decide next task to run
__asm volatile("BL update_next_task");
//2. Get its past PSP value
__asm volatile("BL get_psp_value");
//3. Using that PSP value retrieve SF2( R4 to R11 )
__asm volatile("LDMIA R0!, {R4- R11}");
//4. Update PSP and exit
__asm volatile("MSR PSP, R0");
__asm volatile("POP {LR}");
__asm volatile("BX LR");
}
void HardFault_Handler(void)
{
printf("Exception : Hardfault\n");
while(1);
}
void MemManage_Handler(void)
{
printf("Exception : MemManage\n");
while(1);
}
void BusFault_Handler(void)
{
printf("Exception : BusFault\n");
while(1);
}