xTaskNotifyIndexed() and xTaskNotifyWaitIndexed() crashes

While trying that two tasks to write on two different receiver task indexes, my system crashes (it resets itself continuosly):

TaskR[1] ← TaskA
TaskR[2] ← TaskB

In isolation both approaches work as expected, but whenever I activate both, then the system crashes. Before moving on let me show you my code:

#include <FreeRTOS.h>
#include <task.h>

TaskHandle_t consumidor_h;

void Productor1_task( void* pvParameters )
{
   uint16_t time_to_sleep = (uint16_t) pvParameters;

   TickType_t last_wake_time = xTaskGetTickCount();

   while( 1 )
   {
      vTaskDelayUntil( &last_wake_time, pdMS_TO_TICKS( time_to_sleep ) );

      xTaskNotifyIndexed( consumidor_h, 1, (uint32_t) time_to_sleep, eSetValueWithOverwrite );
   }
}

void Productor2_task( void* pvParameters )
{
   uint16_t time_to_sleep = (uint16_t) pvParameters;

   while( 1 )
   {
      vTaskDelay( pdMS_TO_TICKS( time_to_sleep ) );

      xTaskNotifyIndexed( consumidor_h, 2, (uint32_t) time_to_sleep, eSetValueWithOverwrite );
   }
}

void Consumidor_task( void* pvParameters )
{
   pinMode( 13, OUTPUT );

   uint32_t value;

   while( 1 )
   {
#if 1
      xTaskNotifyWaitIndexed( 1, 0x00, 0x00, &value, portMAX_DELAY );

      Serial.println( value );
#endif

#if 1
      xTaskNotifyWaitIndexed( 2, 0x00, 0x00, &value, portMAX_DELAY );

      Serial.println( value );
#endif
   }
}

void setup()
{
   Serial.begin( 115200 );

   xTaskCreate( Productor1_task, "PROD1", 256, (void*) 997, tskIDLE_PRIORITY + 1, NULL );
   xTaskCreate( Productor2_task, "PROD2", 256, (void*) 1747, tskIDLE_PRIORITY + 1, NULL );

   xTaskCreate( Consumidor_task, "CONS", 256, NULL, tskIDLE_PRIORITY, &consumidor_h );

   vTaskStartScheduler();
}

void loop() 
{
}

In my FreeRTOSConfig.h file I’ve set it up:

#define configUSE_TASK_NOTIFICATIONS            1
#define configTASK_NOTIFICATION_ARRAY_ENTRIES   5

What am I missing? What am I not understanding on the xTaskNotifyIndexed() and xTaskNotifyWaitIndexed() functions?

Maybe I’m not understanding the official documentation on xTaskNotifyWaitIndexed():

Note: Each notification within the array operates independently – a task can only block on one notification within the array at a time and will not be unblocked by a notification sent to any other array index.

If this is my case, would you point me out to a scenario or example where these two functions are used for passing a single value?

Note aside, an intriguing fact is that there are no information on the Internet! Google only found 10 entries on “xTaskNotifyIndexed()” and most of them are mirror of the official documentation.

Thank you!

Are you really sure about stack size 256 ? Because you’re using a usually stack hungry printf function in this task. I guess it’s just a stack overflow causing the problem.
You really should always enable stack checking and assertions for development.

@hs2: Yes, I’m pretty sure. printf() is highly optimized in the GCC-AVR compiler. Actually, a task (out of the problem I described) using Serial.println() runs perfectly with 128 bytes. In this example I rose the stack size just to be sure. And yes, I’m very sure.

Anyway, I disabled their calls in order to follow your advice, but the problem is still there, so it’s not a printf() problem.

My next step is to use asserts sparingly, and lastly, to use my Dragon hardware debugger (I was hoping this issue was a misundertanding of my own).

Thank you!

Ok - seems that you have a very lean printf implementation.
Just to be clear I mean (also) using configASSERT() to make use of FreeRTOS internal error checking. It’s extremely helpful during development.
Good luck !

1 Like

I tried your code on a different STM32 hardware (after removing Serial and pinMode calls ) and it works as expected. So something else is wrong probably somewhere else which is causing the reset.

Thanks.

@aggarg My application would be pointless if I remove Arduino stuff because … it’s an Arduino app on top of FreeRTOS =) (You might want to take a look to my project Molcajete.)

I’ve been writing some examples using Serial, analogRead and pin functions without any conflict between Arduino and FreeRTOS. The issue here is whenever I want to use 2 notifications slots on the receiver, as the example has shown.

Using the (old) one slot approach and the function xTaskNotifyWait(), the program runs as expected. But there’s a problem when two or more slots are enabled, either in FreeRTOS or in my understanding on how this feature is used.

And there are no information other than the official documentation. I couldn’t find a single example. Even the documentation doesn’t provide an example in which two or more slots are used. Glad if you can point me out to one working example.

Thank you!

A little complex perhaps as the code is in part to test, but you will find lots of usage in this file: https://github.com/FreeRTOS/FreeRTOS/blob/master/FreeRTOS/Demo/Common/Minimal/TaskNotifyArray.c

Hi again,

Sorry for my long delay, some things showed up. I did what you’ve recommended, and the problem is still there, even within the debugger.

  1. I added the configAssert() support as you’ve mentioned in all critical points, like:

configASSERT( xTaskNotifyIndexed( consumidor_h, 2, (uint32_t) time_to_sleep, eSetValueWithOverwrite ) == pdPASS );

  1. I added the support for stacks overflows.

And I can say the program never gets into any of this cases. When I let the program to run, it does what it has been doing it all this time: it doesn’t work as expected.

Whenever I stop the debugger the program stops into the FreeRTOS code, for example:

(gdb) c
Continuando.
^C
Program received signal SIGINT, Interrupt.
0x0000085c in prvAddNewTaskToReadyList (pxNewTCB=0x802928)
    at /home/fjrg76/ard_linux_molcaj/Molcajete-0.9.3/Linux/arduino-1.8.13/libraries/FreeRTOS/src/tasks.c:1080
1080	            pxCurrentTCB = pxNewTCB;
(gdb) c
Continuando.
^C
Program received signal SIGINT, Interrupt.
0x00000858 in prvAddNewTaskToReadyList (pxNewTCB=0x802928)
    at /home/fjrg76/ard_linux_molcaj/Molcajete-0.9.3/Linux/arduino-1.8.13/libraries/FreeRTOS/src/tasks.c:1076
1076	        if( pxCurrentTCB == NULL )
(gdb) 

Although it’s a pain in the back to debug the ATMEGA328 chip, I can confirm the program runs without any stack problem nor assert issues.

The best I can do from now is not to use this FreeRTOS mechanism until I found the problem. I’ll try a chip (from LPC family) with better debugging support to traceback this issue. The test bed you’re using runs on a PC (as far as I understand), and maybe something related with microcontrollers isn’t working as it should.

Anyway, thank you all for your time and experience :grinning:

UPDATE: Both functions work as expected in the LPC1549 Cortex-M3 chip from NXP. So, there’s a problem with the ATmega323 port that I should investigate deeply.