#include <Arduino.h>
//Definição dos tempos de execução em ms
#define TASK_A_EXEC_TIME 100
#define TASK_B_EXEC_TIME 200
#define TASK_C_EXEC_TIME 150
//Definição dos períodos em ms
#define TASK_A_PERIOD 500
#define TASK_B_PERIOD 1000
#define TASK_C_PERIOD 700
#define EDF_SUPERVISOR_PERIOD 50
typedef struct{
const char *name;
TaskHandle_t handle;
uint32_t period_ms; //Período da tarefa
uint32_t exec_time_ms; //Período de execução
uint32_t last_release_time; //Ultimo instante que a tarefa foi ativada
UBaseType_t current_priority; //Prioridade Atual
}EDF_TaskControlBlock;
//Vetor com as tarefas
EDF_TaskControlBlock tasks[3];
void taskFunction(void* param){
EDF_TaskControlBlock *tcb = (EDF_TaskControlBlock *) param;
while(1){
uint32_t start = millis(); //Pega o tempo de inicio da tarefa
Serial.printf("[%lu ms] Iniciando a tarefa %s (prioridade %u)\n", start, tcb->name, uxTaskPriorityGet(NULL));
vTaskDelay(pdMS_TO_TICKS(tcb->exec_time_ms));
uint32_t end = millis(); //Pega o tempo de finlização da tarefa
Serial.printf("[%lu ms] Finalizou a tarefa %s\n", end, tcb->name);
//Verifica se perdeu o deadline
uint32_t expected_finish = tcb->last_release_time + tcb->period_ms;
if (end > expected_finish){
Serial.printf(">> %s perdeu o deadline! Deadline era %lu ms \n", tcb->name, expected_finish);
}
//Atualiza o tempo da ativação
tcb->last_release_time += tcb->period_ms;
vTaskDelayUntil((TickType_t *)&tcb->last_release_time, pdMS_TO_TICKS(tcb->period_ms));
}
}
void edfSupervisorTask(void *param) {
while (1) {
uint32_t now = xTaskGetTickCount() * portTICK_PERIOD_MS;
uint32_t deadlines[3];
for (int i = 0; i < 3; i++) {
deadlines[i] = tasks[i].last_release_time + tasks[i].period_ms - now;
}
//bubble sort para ordenar a tarefa com próximo deadline
int order[3] = {0,1,2};
for (int i = 0; i<2; i++){
for(int j=i+1; j<3; j++){
if(deadlines[order[j]] < deadlines[order[i]]){
int temp = order[i];
order[i] = order[j];
order[j] = temp;
}
}
}
//Coloca prioridade em ordem decrescente de acordo com próximo deadline
for (int i = 0; i < 3; i++){
UBaseType_t priority = configMAX_PRIORITIES - 1 - i;
vTaskPrioritySet(tasks[order[i]].handle,priority);
tasks[order[i]].current_priority = priority;
}
vTaskDelay(pdMS_TO_TICKS(EDF_SUPERVISOR_PERIOD));
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(1000);
uint32_t now=millis();
//Inicia as tarefas
tasks[0] = {"tarefa A", NULL, TASK_A_PERIOD, TASK_A_EXEC_TIME, now, 1};
tasks[1] = {"tarefa B", NULL, TASK_B_PERIOD, TASK_B_EXEC_TIME, now, 1};
tasks[2] = {"tarefa C", NULL, TASK_C_PERIOD, TASK_C_EXEC_TIME, now, 1};
//Cria as tarefas com prioridade 1
xTaskCreate(taskFunction, tasks[0].name, 2048, &tasks[0], 1, &tasks[0].handle);
xTaskCreate(taskFunction, tasks[1].name, 2048, &tasks[1], 1, &tasks[1].handle);
xTaskCreate(taskFunction, tasks[2].name, 2048, &tasks[2], 1, &tasks[2].handle);
xTaskCreate(edfSupervisorTask, "EDF Supervisor", 2048, NULL, configMAX_PRIORITIES - 1, NULL);
}
void loop() {
}