I have some rookie questions on how to port an existing application on ESP32 to freeRTOS. I have a first setup running but am hitting some roadblocks.
We have built a test device that exercises a unit under test by stepping through several steps. The proof-of-concept is running freeRTOS on an ESP32 with an LCD display, user buttons, and all the needed I/O circuits. In general, the procedure for each measurement step is:
We have 12 different steps as outlined above plus some extra ones to select the test protocol and configure the WiFi interface. We reasoned (wrongly?) that we want to create individual tasks on the fly when needed and not create them at the start and kept in suspended mode. This is as safety measure since we want to avoid that (inadvertently) two different tasks would be running simultaneously when they shouldn't: that might create the danger of messing up the relays that control AC power.
So, we want to create two tasks for each test step:
The problem I have is that the for(;;) that is in the function that creates Task1 never ends, so we can´t fire off TaskCheck1.
The abbreviated code is below:
/************************************************************************
*
* MAIN LOOP
*
************************************************************************/
void loop()
{
// We keep the main loop always running and firing off the different tasks.
if (some_condition_to_create_task_1){
startTask1(); // Creates a task that shows an analog reading on the display
startCheckTask1(); // Creates a task that waits x secs, then deletes Task1 and deletes itself
// --> PROBLEM: startCheckTask1() is never executed, the for(;;) in startTask1() never exits
}
// Similar code to above for additional tasks to create when their turn comes
}
/************************************************************************
*
* TASKS
*
************************************************************************/
void Task1(void *pvParameters) // Reads analog value and shows on display
{
(void) pvParameters;
for(;;){
readAnalogValue();
showOnDisplay();
vTaskDelay(500); // Update reading every 0,5 sec to avoid flicker
}
}
void startCheckTask1(void *pvParameters) // Waits for 5 seconds, then deletes Task1, interprets results and shows
// passed/failed on screen
{
(void) pvParameters;
unsigned long oldTicks, NewTicks;
vTaskDelay(5000); // Allow 5 secs for readings to stabilize
showResultOnDisplay(); // Show passed/failed on the display
// Now delete both tasks
vTaskDelete(hTask1);
vTaskDelete(hCheckTask1);
}
/************************************************************************
*
* FUNCTIONS
*
************************************************************************/
void startTask1(){
xTaskCreatePinnedToCore(Task1,"Task 1", 1024, NULL, 1, &hTask1, 1);
for(;;){ // PROBLEM: This is the loop that prevents creating CheckTask1
}
}
void startCheckTask1(){
xTaskCreatePinnedToCore(CheckTask1,"Check Task 1", 1024, NULL, 1, &hCheckTask1, 1);
for(;;){
}
}
Any ideas how to solve this? Thx!
I would put some vTaskDelay(1000) inside each for() loop both into startTask1() and into startCheckTask1().
I assume loop() is called by app_main() which is a priority 1 task itself. If you don't put something that blocks the fors(), same priority tasks that you created never get CPU.
Hope this helps.
Have a nice day
PS. Take into account that vTaskDelay() is not measured in msecs, but in RTOS ticks. You must use pdMS_TO_TICKS(x) macro instead, as in: vTaskDelay( pdMS_TO_TICKS(1000) ) // This blocks until passed 1sec