#include <Arduino_FreeRTOS.h>
#include <semphr.h>
/* Define the traceTASK_SWITCHED_IN() macro to switch ON and OFF the led on pin 13
with the task being selected to run. */ /*modified by Aradhana Dhumal*/
/* #define traceTASK_SWITCHED_IN() digitalWrite(13, (int)pxCurrentTCB->pxTaskTag); */
/* --- Konfiguration --- */
// 1 = Mutex (Nutzt Priority Inheritance -> Korrektes Verhalten)
// 0 = Semaphore (Erlaubt Priority Inversion -> Task_High wird blockiert)
#define USE_MUTEX 1
/* Pins für den Logic Analyzer */
const int PIN_LOW = 8;
const int PIN_MID = 9;
const int PIN_HIGH = 10;
SemaphoreHandle_t xResource;
// Hilfsfunktion für Busy-Waiting, um CPU-Last zu simulieren
// Wir nutzen kein vTaskDelay im "kritischen Bereich", um reale Arbeit zu simulieren
void busyWait(uint32_t ms) {
uint32_t start = millis();
while (millis() - start < ms) {
// Nichts tun, CPU aktiv halten
}
}
void taskLow(void *pv) {
vTaskSetApplicationTaskTag( NULL, ( void * )PIN_LOW);
for (;;) {
vTaskDelay(pdMS_TO_TICKS(100)); // Warten bis Zyklus-Start
if (xSemaphoreTake(xResource, portMAX_DELAY)) {
busyWait(300); // Hält die Ressource für 300ms
xSemaphoreGive(xResource);
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void taskMid(void *pv) {
vTaskSetApplicationTaskTag( NULL, ( void * )PIN_MID);
for (;;) {
vTaskDelay(pdMS_TO_TICKS(150)); // Startet kurz nach TaskLow
busyWait(400); // Blockiert die CPU für 400ms (Prio 2)
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void taskHigh(void *pv) {
vTaskSetApplicationTaskTag( NULL, ( void * )PIN_HIGH);
for (;;) {
vTaskDelay(pdMS_TO_TICKS(200)); // Startet, wenn TaskLow die Ressource hält
if (xSemaphoreTake(xResource, portMAX_DELAY)) {
busyWait(50); // Braucht die Ressource nur kurz
xSemaphoreGive(xResource);
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void setup() {
pinMode(PIN_LOW, OUTPUT);
pinMode(PIN_MID, OUTPUT);
pinMode(PIN_HIGH, OUTPUT);
#if USE_MUTEX
xResource = xSemaphoreCreateMutex();
#else
xResource = xSemaphoreCreateBinary();
xSemaphoreGive(xResource); // Semaphore muss beim Uno initial freigegeben werden
#endif
// Stack-Größen beim Uno müssen sehr klein sein (in Wörtern/Bytes je nach Port)
xTaskCreate(taskLow, "LOW", 100, NULL, 1, NULL);
xTaskCreate(taskMid, "MID", 100, NULL, 2, NULL);
xTaskCreate(taskHigh, "HIGH", 100, NULL, 3, NULL);
vTaskStartScheduler();
}
void loop() {}