Vehicle Control Unit 0.01
This is the c library for controlling the car.
Loading...
Searching...
No Matches
Scheduler.c
Go to the documentation of this file.
1#include "FreeRTOS.h"
2#include "task.h"
3#include "timers.h"
4#include "queue.h"
5#include "../../Inc/Scheduler/Scheduler.h"
6
7typedef struct {
9 TimerHandle_t timer;
11
12// Work item for the worker task
13typedef struct {
15 TickType_t timestamp;
16} WorkItem;
17
19static int taskCount = 0;
20
21// Worker task handles
22static TaskHandle_t workerTaskHandle = NULL;
23static QueueHandle_t workQueue = NULL;
24
25#define WORK_QUEUE_SIZE 32
26#define WORKER_STACK_SIZE 1024
27#define WORKER_PRIORITY (tskIDLE_PRIORITY + 2)
28
29// Worker task that processes updateables
30static void workerTask(void* pvParameters) {
31 WorkItem workItem;
32
33 while (1) {
34 // Wait for work items from timer callbacks
35 if (xQueueReceive(workQueue, &workItem, portMAX_DELAY) == pdTRUE) {
36 if (workItem.updateable != NULL) {
37 // Record start time for performance monitoring
38 TickType_t startTime = xTaskGetTickCount();
39
40 // Execute the updateable
41 Task task;
42 TaskInit(&task, workItem.updateable, workItem.updateable->hz);
43 TaskExecute(&task);
44
45 // Check execution time
46 TickType_t executionTime = xTaskGetTickCount() - startTime;
47 TickType_t maxTime = pdMS_TO_TICKS(1000 / workItem.updateable->hz) / 2; // 50% of period
48
49 if (executionTime > maxTime) {
50 printf("WARNING: %s took %lu ticks (max recommended: %lu)\n",
51 workItem.updateable->name, executionTime, maxTime);
52 }
53 }
54 }
55 }
56}
57
58// Fast timer callback - just queues work item
59static void updateableTimerCallback(TimerHandle_t xTimer) {
60 Updateable* updateable = (Updateable*)pvTimerGetTimerID(xTimer);
61
62 if (updateable != NULL && workQueue != NULL) {
63 WorkItem workItem = {
64 .updateable = updateable,
65 .timestamp = xTaskGetTickCount()
66 };
67
68 // Send to worker task (non-blocking from timer context)
69 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
70 if (xQueueSendFromISR(workQueue, &workItem, &xHigherPriorityTaskWoken) != pdTRUE) {
71 // Queue full - this indicates the worker task is overloaded
72 printf("ERROR: Work queue full for %s - dropping task\n", updateable->name);
73 }
74
75 // Yield if higher priority task was woken
76 portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
77 }
78}
79
80void SchedulerInit(Scheduler* scheduler, Updateable* updatableArray[]) {
81 scheduler->running = 0;
82 taskCount = 0;
83
84 // Create work queue for communicating between timer callbacks and worker task
85 workQueue = xQueueCreate(WORK_QUEUE_SIZE, sizeof(WorkItem));
86 if (workQueue == NULL) {
87 printf("ERROR: Failed to create work queue\n");
88 return;
89 }
90
91 // Create worker task to handle updateables
92 if (xTaskCreate(workerTask, "SchedulerWorker", WORKER_STACK_SIZE, NULL,
93 WORKER_PRIORITY, &workerTaskHandle) != pdPASS) {
94 printf("ERROR: Failed to create worker task\n");
95 return;
96 }
97
98 printf("Created scheduler worker task\n");
99
100 // Create timers for each updateable
101 for (int i = 0; updatableArray[i] != NULL && i < MAX_SENSORS; i++) {
102 Updateable* updateable = updatableArray[i];
103
104 if (updateable->hz <= 0 || updateable->hz > MAX_HZ) {
105 printf("Warning: Skipping %s - invalid frequency %d Hz\n",
106 updateable->name, updateable->hz);
107 continue;
108 }
109
110 // Calculate period in FreeRTOS ticks
111 TickType_t period = pdMS_TO_TICKS(1000 / updateable->hz);
112 if (period == 0) period = 1; // Minimum 1 tick for 1kHz tasks
113
114 // Create timer name
115 char timerName[32];
116 snprintf(timerName, sizeof(timerName), "T_%s", updateable->name);
117
118 // Create FreeRTOS software timer
119 TimerHandle_t timer = xTimerCreate(
120 timerName, // Timer name
121 period, // Period in ticks
122 pdTRUE, // Auto-reload (periodic)
123 updateable, // Timer ID
124 updateableTimerCallback // Callback function
125 );
126
127 if (timer != NULL) {
128 scheduledTasks[taskCount].updateable = updateable;
130 taskCount++;
131
132 printf("Created timer: %s at %dHz (period: %lu ticks)\n",
133 updateable->name, updateable->hz, period);
134 } else {
135 printf("ERROR: Failed to create timer for %s\n", updateable->name);
136 }
137 }
138
139 printf("Scheduler initialized with %d timers and worker task\n", taskCount);
140}
141
142void SchedulerRun(Scheduler* scheduler) {
143 scheduler->running = 1;
144
145 // Start all timers
146 int started = 0;
147 for (int i = 0; i < taskCount; i++) {
148 if (xTimerStart(scheduledTasks[i].timer, 0) == pdPASS) {
149 started++;
150 } else {
151 printf("ERROR: Failed to start timer for %s\n",
152 scheduledTasks[i].updateable->name);
153 }
154 }
155
156 printf("Started %d/%d timers\n", started, taskCount);
157
158 // Start FreeRTOS scheduler
159 vTaskStartScheduler();
160}
161
162void SchedulerStop(Scheduler* scheduler) {
163 scheduler->running = 0;
164
165 // Stop all timers
166 for (int i = 0; i < taskCount; i++) {
167 if (scheduledTasks[i].timer != NULL) {
168 xTimerStop(scheduledTasks[i].timer, portMAX_DELAY);
169 }
170 }
171
172 printf("All timers stopped\n");
173}
174
175// Utility functions
176void SchedulerSuspendUpdateable(const char* name) {
177 for (int i = 0; i < taskCount; i++) {
178 if (scheduledTasks[i].updateable &&
179 strcmp(scheduledTasks[i].updateable->name, name) == 0) {
180 if (xTimerStop(scheduledTasks[i].timer, 0) == pdPASS) {
181 printf("Suspended timer for %s\n", name);
182 return;
183 }
184 }
185 }
186 printf("Warning: Could not find or suspend timer for %s\n", name);
187}
188
189void SchedulerResumeUpdateable(const char* name) {
190 for (int i = 0; i < taskCount; i++) {
191 if (scheduledTasks[i].updateable &&
192 strcmp(scheduledTasks[i].updateable->name, name) == 0) {
193 if (xTimerStart(scheduledTasks[i].timer, 0) == pdPASS) {
194 printf("Resumed timer for %s\n", name);
195 return;
196 }
197 }
198 }
199 printf("Warning: Could not find or resume timer for %s\n", name);
200}
201
203 UBaseType_t queueLength = uxQueueMessagesWaiting(workQueue);
204 UBaseType_t queueSpaces = uxQueueSpacesAvailable(workQueue);
205
206 printf("Scheduler Statistics:\n");
207 printf("- Active timers: %d\n", taskCount);
208 printf("- Work queue: %lu items pending, %lu spaces available\n",
209 queueLength, queueSpaces);
210
211 if (workerTaskHandle != NULL) {
212 TaskStatus_t taskStatus;
213 vTaskGetInfo(workerTaskHandle, &taskStatus, pdTRUE, eInvalid);
214 printf("- Worker task stack high water mark: %u words\n",
215 taskStatus.usStackHighWaterMark);
216 }
217
218 if (queueLength > (WORK_QUEUE_SIZE * 3 / 4)) {
219 printf("WARNING: Work queue is %lu%% full - worker may be overloaded\n",
220 (queueLength * 100) / WORK_QUEUE_SIZE);
221 }
222}
223
224// Cleanup function for proper shutdown
226 // Delete worker task
227 if (workerTaskHandle != NULL) {
228 vTaskDelete(workerTaskHandle);
229 workerTaskHandle = NULL;
230 }
231
232 // Delete work queue
233 if (workQueue != NULL) {
234 vQueueDelete(workQueue);
235 workQueue = NULL;
236 }
237
238 // Delete all timers
239 for (int i = 0; i < taskCount; i++) {
240 if (scheduledTasks[i].timer != NULL) {
241 xTimerDelete(scheduledTasks[i].timer, portMAX_DELAY);
242 scheduledTasks[i].timer = NULL;
243 }
244 }
245
246 taskCount = 0;
247 printf("Scheduler cleaned up\n");
248}
#define MAX_SENSORS
Definition: PriorityQueue.h:8
void SchedulerResumeUpdateable(const char *name)
Definition: Scheduler.c:189
static ScheduledUpdateable scheduledTasks[MAX_SENSORS]
Definition: Scheduler.c:18
static QueueHandle_t workQueue
Definition: Scheduler.c:23
void SchedulerCleanup(void)
Definition: Scheduler.c:225
#define WORKER_STACK_SIZE
Definition: Scheduler.c:26
void SchedulerInit(Scheduler *scheduler, Updateable *updatableArray[])
Definition: Scheduler.c:80
static TaskHandle_t workerTaskHandle
Definition: Scheduler.c:22
static void workerTask(void *pvParameters)
Definition: Scheduler.c:30
#define WORKER_PRIORITY
Definition: Scheduler.c:27
void SchedulerStop(Scheduler *scheduler)
Definition: Scheduler.c:162
#define WORK_QUEUE_SIZE
Definition: Scheduler.c:25
void SchedulerRun(Scheduler *scheduler)
Definition: Scheduler.c:142
static int taskCount
Definition: Scheduler.c:19
void SchedulerGetStats(void)
Definition: Scheduler.c:202
static void updateableTimerCallback(TimerHandle_t xTimer)
Definition: Scheduler.c:59
void SchedulerSuspendUpdateable(const char *name)
Definition: Scheduler.c:176
#define MAX_HZ
Definition: Scheduler.h:8
void TaskInit(Task *task, Updateable *updateable, int hz)
Initializes a task with the given sensor and update frequency.
Definition: Task.c:3
void TaskExecute(Task *task)
Executes the task by calling the sensor's update function.
Definition: Task.c:9
Updateable * updateable
Definition: Scheduler.c:8
TimerHandle_t timer
Definition: Scheduler.c:9
int running
Definition: Scheduler.h:11
Definition: Task.h:8
char name[MAX_NAME_LENGTH]
Definition: Updateable.h:24
Updateable * updateable
Definition: Scheduler.c:14
TickType_t timestamp
Definition: Scheduler.c:15