#include "FreeRTOS.h"
#include "task.h"
#include "stm32c0xx_hal.h"
#include "semphr.h"
// GPIO Pins pour les LEDs
#define LED1_PIN GPIO_PIN_5
#define LED2_PIN GPIO_PIN_6
#define LED3_PIN GPIO_PIN_7
#define LED_PORT GPIOA
typedef struct {
TaskHandle_t taskHandle;
uint32_t deadline; // Deadline de la tâche
} EDF_Task_t;
// Sémaphore binaire
SemaphoreHandle_t xSemaphore;
// Tableau de tâches EDF
EDF_Task_t edfTasks[3];
// Initialisation des GPIO
void MX_GPIO_Init(void) {
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = LED1_PIN | LED2_PIN | LED3_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
}
// Sélection de la tâche avec la deadline la plus proche
EDF_Task_t* SelectTaskWithEarliestDeadline() {
EDF_Task_t* selectedTask = &edfTasks[0];
for (int i = 1; i < 3; i++) {
if (edfTasks[i].deadline < selectedTask->deadline) {
selectedTask = &edfTasks[i];
}
}
return selectedTask;
}
// Tâches EDF
void Task1(void *pvParameters) {
for (;;) {
// Attendre la permission du scheduler
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// Prendre le sémaphore
xSemaphoreTake(xSemaphore, portMAX_DELAY);
HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET);
vTaskDelay(pdMS_TO_TICKS(200)); // Temps d'exécution de la LED1
HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET);
((EDF_Task_t*)pvParameters)->deadline += 1000; // Mise à jour de la deadline
// Libérer le sémaphore
xSemaphoreGive(xSemaphore);
vTaskDelay(pdMS_TO_TICKS(100)); // Délai avant la prochaine exécution
}
}
void Task2(void *pvParameters) {
for (;;) {
// Attendre la permission du scheduler
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// Prendre le sémaphore
xSemaphoreTake(xSemaphore, portMAX_DELAY);
HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_SET);
vTaskDelay(pdMS_TO_TICKS(300)); // Temps d'exécution de la LED2
HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_RESET);
((EDF_Task_t*)pvParameters)->deadline += 1500; // Mise à jour de la deadline
// Libérer le sémaphore
xSemaphoreGive(xSemaphore);
vTaskDelay(pdMS_TO_TICKS(100)); // Délai avant la prochaine exécution
}
}
void Task3(void *pvParameters) {
for (;;) {
// Attendre la permission du scheduler
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// Prendre le sémaphore
xSemaphoreTake(xSemaphore, portMAX_DELAY);
HAL_GPIO_WritePin(LED_PORT, LED3_PIN, GPIO_PIN_SET);
vTaskDelay(pdMS_TO_TICKS(500)); // Temps d'exécution de la LED3
HAL_GPIO_WritePin(LED_PORT, LED3_PIN, GPIO_PIN_RESET);
((EDF_Task_t*)pvParameters)->deadline += 2000; // Mise à jour de la deadline
// Libérer le sémaphore
xSemaphoreGive(xSemaphore);
vTaskDelay(pdMS_TO_TICKS(100)); // Délai avant la prochaine exécution
}
}
// Tâche du scheduler EDF
void EDF_Scheduler_Task(void *pvParameters) {
for (;;) {
// Sélectionner la tâche avec la deadline la plus proche
EDF_Task_t* nextTask = SelectTaskWithEarliestDeadline();
// Notifier la tâche sélectionnée
xTaskNotifyGive(nextTask->taskHandle);
// Attendre avant de réévaluer
vTaskDelay(pdMS_TO_TICKS(100)); // Fréquence de vérification EDF
}
}
int main(void) {
HAL_Init();
MX_GPIO_Init();
// Initialiser le tableau EDF
for (int i = 0; i < 3; i++) {
edfTasks[i].taskHandle = NULL;
edfTasks[i].deadline = (i + 1) * 1000;
}
// Créer le sémaphore
xSemaphore = xSemaphoreCreateBinary();
xSemaphoreGive(xSemaphore); // Libérer une première fois
// Créer les tâches
xTaskCreate(Task1, "Task1", 128, &edfTasks[0], 1, &edfTasks[0].taskHandle);
xTaskCreate(Task2, "Task2", 128, &edfTasks[1], 1, &edfTasks[1].taskHandle);
xTaskCreate(Task3, "Task3", 128, &edfTasks[2], 1, &edfTasks[2].taskHandle);
// Créer la tâche EDF Scheduler
xTaskCreate(EDF_Scheduler_Task, "EDF_Scheduler", 128, NULL, 2, NULL);
vTaskStartScheduler();
while (1);
}
void loop() {
// Le contrôle est pris en charge par FreeRTOS, donc le loop reste vide.
}