14static uint32_t prvCurTaskIDNum = 0;
16static TaskNode *prvBlockedTasks = NULL;
18static TCB idleTaskTCB;
19static TCB *idleTaskTCBptr = &idleTaskTCB;
22static TaskNode *idleTaskNodePtr = &idleTaskNode;
25static TaskNode *prvGetHighestTaskReadyToExecute ();
26static void prvAddTaskToBlockedList (
TaskNode *task);
27static void prvUnblockDelayedTasksReadyToUnblock ();
29static void idleTask ();
30static void prvCheckCurTaskForStackOverflow ();
57 taskStack[
STACK_SIZE - 2] = ((uint32_t)taskFunc) | 0x1;
77createTask (uint32_t taskStack[],
void (*taskFunc) (
void),
78 unsigned int priority,
TCB *userAllocatedTCB,
81 if (!taskFunc || !userAllocatedTCB || !userAllocatedTaskNode)
89 userAllocatedTCB->
priority = priority;
90 userAllocatedTCB->
id = prvCurTaskIDNum;
95 userAllocatedTaskNode->
taskTCB = userAllocatedTCB;
96 userAllocatedTaskNode->
next = NULL;
101 resStatus = prvAddTaskNodeToReadyList (userAllocatedTaskNode);
119 prvUnblockDelayedTasksReadyToUnblock ();
126 uint32_t curExecutingPriority =
curTask->taskTCB->priority;
128 TaskNode *highestPriorityPossibleExecute
129 = prvGetHighestTaskReadyToExecute ();
132 if (curExecutingPriority < highestPriorityPossibleExecute->taskTCB->priority)
134 prvNextTask = highestPriorityPossibleExecute;
144 prvNextTask = highestPriorityPossibleExecute;
168 prvCheckCurTaskForStackOverflow ();
171 __asm
volatile (
"mrs r0, PSP\n"
172 "stmdb r0!, {r4-r11}\n"
173 "mov %[spToSave], r0\n"
174 : [spToSave]
"=r"(spToSave));
176 curTask->taskTCB->sp = (uint32_t *)spToSave;
181 nextSP = (uint32_t)prvNextTask->taskTCB->sp;
186 __asm
volatile (
"mov r2, %[nextSP]\n"
187 "ldmia r2!, {r4-r11}\n"
190 : [nextSP]
"r"(nextSP));
192 __asm
volatile (
"ldr lr, =0xFFFFFFFD\n"
206 uint32_t spToStart = (uint32_t)tcbToStart->
sp;
208 __asm
volatile (
"ldr r0, %[sp]\n"
209 "ldmia r0!, {r4-r11}\n"
211 "ldr lr, =0xFFFFFFFD\n"
214 : [sp]
"m"(spToStart));
220 prvIdleTask = createIdleTask ();
221 curTask = prvGetHighestTaskReadyToExecute ();
222 __asm
volatile (
"svc #0");
241 uint32_t curTaskID =
curTask->taskTCB->id;
242 uint32_t curTaskPriority =
curTask->taskTCB->priority;
250 if (cur->
next == NULL)
254 prvNextTask = prvGetHighestTaskReadyToExecute ();
255 prvAddTaskToBlockedList (
curTask);
266 prvNextTask = prvGetHighestTaskReadyToExecute ();
267 prvAddTaskToBlockedList (
curTask);
281 prev->
next = afterCur;
283 prvNextTask = prvGetHighestTaskReadyToExecute ();
284 prvAddTaskToBlockedList (
curTask);
300prvAddTaskNodeToReadyList (
TaskNode *task)
322 while (curHead->
next != NULL)
324 curHead = curHead->
next;
327 curHead->
next = task;
339prvGetHighestTaskReadyToExecute ()
363prvAddTaskToBlockedList (
TaskNode *task)
367 if (prvBlockedTasks == NULL)
369 prvBlockedTasks = task;
375 while (cur->
next != NULL)
391prvUnblockDelayedTasksReadyToUnblock ()
401 if (cur->
next == NULL)
405 prvBlockedTasks = NULL;
406 prvAddTaskNodeToReadyList (cur);
418 prvBlockedTasks = cur->
next;
419 prvAddTaskNodeToReadyList (cur);
424 prvAddTaskNodeToReadyList (cur);
446 idleTaskTCBptr->priority = 0;
447 idleTaskTCBptr->id = prvCurTaskIDNum;
448 idleTaskTCBptr->stackFrameLowerBoundAddr = &idleTaskStack[0];
449 idleTaskNodePtr->taskTCB = idleTaskTCBptr;
450 idleTaskNodePtr->next = NULL;
453 return idleTaskNodePtr;
466 __asm
volatile (
"wfi");
478prvCheckCurTaskForStackOverflow ()
480 uint32_t *curTaskStackFrameLowerBound;
483 curTaskStackFrameLowerBound =
curTask->taskTCB->stackFrameLowerBoundAddr;
505 uint32_t *curTaskStackFrameLowerBound;
508 curTaskStackFrameLowerBound =
curTask->taskTCB->stackFrameLowerBoundAddr;
512 curTaskStackFrameLowerBound
515 uint32_t amtWordsAvailable = 0;
519 curTaskStackFrameLowerBound++;
523 return amtWordsAvailable;
#define STACK_SIZE
Default stack size for each task, in 32-bit words.
#define MAX_PRIORITIES
Number of unique task priority levels supported by the scheduler.
#define STACK_OVERFLOW_CANARY_VALUE
#define STACK_USAGE_WATERMARK
This struct is the Task Control Block (TCB), which is what stores a task's properties.
uint32_t * stackFrameLowerBoundAddr
void systemEXIT_CRITICAL()
Exit a critical section by enabling all interrupts.
void systemENTER_CRITICAL()
Enter a critical section by disabling all interrupts.
volatile uint32_t msTicks
msTicks contains the amount of ticks that have occured since the scheduler started.
void taskDelay(uint32_t ticksToDelay)
This function will delay a task's execution for ticksToDelay ms.
uint32_t * initTaskStackFrame(uint32_t taskStack[], void(*taskFunc)(void))
Initializes a task's stack frame.
void __attribute__((weak))
void startScheduler()
Start the scheduler.
void PendSV_Handler()
This interrupt will be pended when a context switch is needed.
void SVC_Handler()
This interrupt will be executed when the scheduler is started.
void SysTick_Handler()
This interrupt handler will be called every 1 ms, checking if any tasks need to be unblocked or block...
uint32_t getCurTaskWordsAvailable()
This function will return the minimum number of words left on the stack.
TaskNode * readyTasksList[MAX_PRIORITIES]
This is a list of linked lists that contain the ready tasks.
void setPendSVPending()
This function will be called when a context-switch is needed.
STATUS createTask(uint32_t taskStack[], void(*taskFunc)(void), unsigned int priority, TCB *userAllocatedTCB, TaskNode *userAllocatedTaskNode)
Add a task to the scheduler's ready list.
Task management and scheduler API for SRTOS.
STATUS
This enum is used to indicate whether an operation was sucessful or not.
void handleStackOverflow()
This function will be called when a stack overflow is detected. This function will only be called if ...