I have a number of projects that I’ve done with FreeRTOS over the past couple of years. I just about every project, there is some task that needs to send a notification to itself. It’s typically a task that parses data from the outside world (usually a UART) and then the task sends a notification to itself to perform some action based on the parsing of the data.
So the task is an infinite loop calling
xTaskNotifyWait(0x0, 0xFFFFFFFF, ¬ifications, portMAX_DELAY);
at the beginning of the loop. After this call, all the notifications received are processed. In my current project, the processing of certain notification cause another notification to be sent to the task (from the same task).
This has worked fine for all my projects until my last one as the task stops at xTaskNotifyWait() and doesn’t return - as if the notification was never received.
I know the notification gets set because I can step through the source code of xTaskGenericNotify() and see
pxTCB->ulNotifiedValue[ uxIndexToNotify ]
gets set along with
/* Mark this task as waiting for a notification. */
pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
xTaskNotify is called with the eSetBits option. There are no ISRs involved in either of the notifications here.
Aftert setting the notification, I keep stepping through the code to the call to xTaskNotifyWait at the top of the loop (which calls xTaskGenericNotifyWait() in tasks.c):
BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait,
uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t * pulNotificationValue,
TickType_t xTicksToWait )
{
BaseType_t xReturn;
configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
taskENTER_CRITICAL();
{
/* Only block if a notification is not already pending. */
if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
{
/* Clear bits in the task's notification value as bits may get
What I see is that pxCurrentTCB->ucNotifyState[uxIndexToWait] is no longer set to taskNOTIFICATION_RECEIVED. It is set to taskWAITING_NOTIFICATION so the notification doesn’t get processed. It’s not clear to me why this gets changed.
I can work around it with what I consider a hack of adding a do-while loop after xTaskNotifyWait() like this:
do
{
/* Process all notifications here */
}
while ((notifications = ulTaskNotifyTake(true, 0)) != 0);
This way, any notifications that are sent during processing of notifications are immediately read and continue to be processed. This tells me that the notification was definately sent and is waiting, I just don’t think/hope this should be required.
The FreeRTOS version that works is “V10.4.3 LTS Patch 2” as defined in tasks.h. It’s running on an NXP LPC54102. The directory from FreeRTOS is “amazon-freertos”.
The one that doesn’t work is running on an NXP K22FN512VMP12. The FreeRTOS directory is “freertos” and the version is “V10.2.0”.
I have done diffs of the FreeRTOS code, specifically tasks.c and tasks.h and didn’t see anything obvious. The version, 10.2.0, doesn’t have an array of notification values. The 10.4.3, does.
Both of these are provided by NXP and are integrated with their SDK.
I have functions for malloc failed hook and the stack overflow. I have upped the stack size to see if it was a stack problem. Same issue.
Any ideas?