Hi,
I was writing an example code using xTaskNotify() and xTaskNotifyWait() functions, where the TaskP is the producer and the TaskC is the consumer. I’m using this mechanism to send a single 32 bit value from one task to another. TaskC has lower priority than TaskP.
Purposely I make the TaskP to fail, so TaskC might recover after a time-over (avoiding starvation). TaskP enters into an infinite loop without doing anything useful. However, as TaskP is more important, TaskC never reaches the timed-out code. taskYIELD() doesn’t work in this scenario.
The know solution is that TaskP might rise the TaskC’s priority before it fails (or lower its own), however, the point here is that if TaskP fails then TaskC must go on (we don’t know when and how TaskP is going to fail).
Is there a better way for a lower priority task waiting for higher priority task to recover from starvation other than playing with priorities? How can we use the time-out parameter (for the xTaskNotifyWait() function) if it only will work with tasks of the same priority?
Here is my test code. Thank you!
#include <FreeRTOS.h>
#include <task.h>
TaskHandle_t consumidor_h;
// consumer handler
// producer task:
void Productor_task( void* pvParameters )
{
uint32_t cont = 1;
uint8_t cont_to_fail = 10;
TickType_t last_wake_time = xTaskGetTickCount();
while( 1 )
{
vTaskDelayUntil( &last_wake_time, pdMS_TO_TICKS( 1000 ) );
Serial.println( "P" );
xTaskNotify( consumidor_h, cont, eSetValueWithOverwrite );
++cont;
if( cont > 3 ) cont = 1;
// WE MAKE THE PRODUCER TASK TO FAIL:
if( --cont_to_fail == 0 ){
while( 1 ) taskYIELD();
}
}
}
// consumer task:
void Consumidor_task( void* pvParameters )
{
pinMode( 13, OUTPUT );
uint32_t blinks;
while( 1 )
{
if( xTaskNotifyWait( 0x00, 0x00, &blinks, pdMS_TO_TICKS( 2000 ) ) == pdPASS ){
Serial.println( blinks );
for( uint8_t i = 0; i < blinks; ++i ){
digitalWrite( 13, HIGH );
vTaskDelay( pdMS_TO_TICKS( 100 ) );
digitalWrite( 13, LOW );
vTaskDelay( pdMS_TO_TICKS( 100 ) );
}
} else{ // time-over:
// THIS CODE IS NEVER REACHED
digitalWrite( 13, HIGH );
while( 1 ){
Serial.println( "Error" );
vTaskDelay( pdMS_TO_TICKS( 1000 ) );
}
}
}
}
void setup()
{
Serial.begin( 115200 );
xTaskCreate( Productor_task, "PROD", 128, NULL, tskIDLE_PRIORITY + 1, NULL );
xTaskCreate( Consumidor_task, "CONS", 128, NULL, tskIDLE_PRIORITY, &consumidor_h );
vTaskStartScheduler();
}
void loop()
{
}