From 85531eedb912a18cb6f763a35ec84ac0eaff1ddc Mon Sep 17 00:00:00 2001 From: toddmorehouse Date: Thu, 16 May 2019 21:29:17 -0400 Subject: [PATCH] Implemented task scheduler. Did not implement priority queue. Could not test. TIVA on hand was defective. --- .cproject | 74 +++++++-------- .launches/TIVA-Task-Scheduler.launch | 15 +++ .settings/org.eclipse.core.resources.prefs | 6 -- TaskScheduler/TaskScheduler.c | 101 ++++++++++++++++++++- TaskScheduler/TaskScheduler.h | 16 +++- main.c | 11 +++ 6 files changed, 174 insertions(+), 49 deletions(-) create mode 100644 .launches/TIVA-Task-Scheduler.launch diff --git a/.cproject b/.cproject index c775d77..3531f71 100644 --- a/.cproject +++ b/.cproject @@ -13,10 +13,10 @@ - + - - diff --git a/.launches/TIVA-Task-Scheduler.launch b/.launches/TIVA-Task-Scheduler.launch new file mode 100644 index 0000000..15a0020 --- /dev/null +++ b/.launches/TIVA-Task-Scheduler.launch @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs index 84767e5..af592f4 100644 --- a/.settings/org.eclipse.core.resources.prefs +++ b/.settings/org.eclipse.core.resources.prefs @@ -1,10 +1,4 @@ eclipse.preferences.version=1 -encoding//Debug/ControlLoop/subdir_rules.mk=UTF-8 -encoding//Debug/ControlLoop/subdir_vars.mk=UTF-8 -encoding//Debug/EIB/subdir_rules.mk=UTF-8 -encoding//Debug/EIB/subdir_vars.mk=UTF-8 -encoding//Debug/MotorDriver/subdir_rules.mk=UTF-8 -encoding//Debug/MotorDriver/subdir_vars.mk=UTF-8 encoding//Debug/TaskScheduler/subdir_rules.mk=UTF-8 encoding//Debug/TaskScheduler/subdir_vars.mk=UTF-8 encoding//Debug/makefile=UTF-8 diff --git a/TaskScheduler/TaskScheduler.c b/TaskScheduler/TaskScheduler.c index 98df68e..e227925 100644 --- a/TaskScheduler/TaskScheduler.c +++ b/TaskScheduler/TaskScheduler.c @@ -1,16 +1,113 @@ +//Project includes #include "TaskScheduler.h" +//Tivaware includes +#include +#include +#include +#include + +#ifndef NULL + #define NULL 0 +#endif + static volatile TaskScheduler scheduler; -void InitializeTaskScheduler(uint32_t timerBase){ +/* + * Timer ISR for the task scheduler + * + * Updates each timer's task + * If the task is ready to be fired, then it is added to a queue and processed + * + * This timer must be given a low priority ISR because it is possible to have + * a heavy load to process + */ +void TaskSchedulerTimer_ISR(void){ + //Loop through every task + Task *pTask = scheduler.pTaskListRoot; + while(pTask){ + if(pTask->enabled){ + pTask->ticks++; + + if(pTask->ticks >= pTask->maxTicks){ + pTask->ticks = 0; + + //Add task to priority queue + //TODO: Implement priority queue + pTask->pCallback(); + } + } + else{ + //Do nothing + } + + //Move to next task + pTask = pTask->pNextTask; + } + + TimerIntClear(scheduler.timerBase, TIMER_TIMA_TIMEOUT); +} + +void InitializeTaskScheduler(uint32_t timerBase, uint16_t sysClkFreq, uint32_t timerIntBase){ + //Initialize the task scheduler + scheduler.timerBase = timerBase; + scheduler.pTaskListRoot = NULL; + + //Initialize the timer + SysCtlPeripheralEnable(timerBase); + + //Wait for the clock to stabilize + SysCtlDelay(10); + + //Configure the timer to be a periodic 100us timer + TimerConfigure(timerBase, TIMER_CFG_PERIODIC); + TimerLoadSet(timerBase, TIMER_A, sysClkFreq * TASK_SCHEDULER_TIMER_PERIOD / 1000000); + + //Configure the ISR + TimerIntRegister(timerBase, TIMER_BOTH, TaskSchedulerTimer_ISR); + IntEnable(timerIntBase); + TimerIntEnable(timerBase, TIMER_TIMA_TIMEOUT); + + //Enable the timer and interrupts + TimerEnable(timerBase, TIMER_A); + IntMasterEnable(); } void AddTask(Task *pTask){ + //Reset the task and calculate the max ticks + pTask->ticks = 0; + pTask->maxTicks = pTask->period * TASK_SCHEDULER_TICKS_IN_ONE_SECOND; + //Add the task to the list + pTask->pNextTask = scheduler.pTaskListRoot; + scheduler.pTaskListRoot = pTask; } + +//Only remove the task if you must +//It is recommended to just disable the task void RemoveTask(Task *pTask){ + Task *pTaskRoot = scheduler.pTaskListRoot; + + //Loop until we are pointing to the task before the one to be removed + //Or no task was found + bool taskFound = false; + while(pTaskRoot->pNextTask){ + if(pTaskRoot->pNextTask == pTask){ + taskFound = true; + break; + } + else{ + //Keep searching + pTaskRoot = pTaskRoot->pNextTask; + } + } + if(taskFound){ + //Remove the task from the list + pTaskRoot->pNextTask = pTask->pNextTask; + } } -void DisableTask(Task *pTask){ +void DisableTask(Task *pTask){ + pTask->enabled = false; } diff --git a/TaskScheduler/TaskScheduler.h b/TaskScheduler/TaskScheduler.h index 5544571..858ec37 100644 --- a/TaskScheduler/TaskScheduler.h +++ b/TaskScheduler/TaskScheduler.h @@ -4,14 +4,22 @@ #include #include +//For the most accurate timer, choose a frequency that is an integer +#define TASK_SCHEDULER_TIMER_PERIOD 100 //us +#define TASK_SCHEDULER_TICKS_IN_ONE_SECOND 1/TASK_SCHEDULER_TIMER_PERIOD + struct Task_tag; typedef struct Task_tag Task; struct Task_tag { - uint32_t taskTimerTicks; - float taskPeriod; + uint32_t ticks; + uint32_t maxTicks; + float period; + + uint8_t priority; + bool enabled; + void (*pCallback)(void); - bool taskEnabled; Task *pNextTask; }; @@ -20,7 +28,7 @@ typedef struct TaskScheduler_tag{ Task *pTaskListRoot; } TaskScheduler; -void InitializeTaskScheduler(uint32_t timerBase); +void InitializeTaskScheduler(uint32_t timerBase, uint16_t sysClkFreq, uint32_t timerIntBase); void AddTask(Task *pTask); void RemoveTask(Task *pTask); diff --git a/main.c b/main.c index c947ade..9b953cd 100644 --- a/main.c +++ b/main.c @@ -1,3 +1,6 @@ +//Project includes +#include "TaskScheduler/TaskScheduler.h" + //Standard includes #include #include @@ -6,6 +9,7 @@ //Tivaware includes #include "inc/hw_memmap.h" +#include "inc/hw_ints.h" #include "driverlib/gpio.h" #include "driverlib/rom.h" #include "driverlib/sysctl.h" @@ -49,6 +53,13 @@ void EnableClock(void){ */ void EnablePeripherals(void){ InitConsole(); + + InitializeTaskScheduler(TIMER0_BASE, SYS_CLK, INT_TIMER0A); + + while(1){ + UARTprintf("Hello world!"); + SysCtlDelay(SYS_CLK / 3); + } } //Initializes UART0 to be used as a console.