inclined to suspect a bug in ESP's FreeRTOS
Unlikely.
I'll readily admit I sometimes write some very bad code, but in this case it's a port of an existing, functional codebase from an STM32 project that does not suffer the same problem. Of course, with heap corruption, seemingly unrelated code can make all the difference.
Here's an example of a notification sent to this task:
Code: Select all
xTaskNotify(task_data->tx_task, HLC_PTT_NOTIFY_BIT_CTS, eSetBits);
That is the pattern I use throughout (this is a communication protocol; I use notifications to communicate certain state information among tasks, e.g., notify the transmit task that the wire task received a Clear-To-Send signal). My calls to xTaskNotify always use the eSetBits operation, and none of them ever set bits 14 - 30. Here's the list of HLC_PTT_NOTIFY_ symbols:
Code: Select all
enum {
HLC_PTT_NOTIFY_BIT_CTS = 0x01,
HLC_PTT_NOTIFY_BIT_nCTS = 0x02,
HLC_PTT_NOTIFY_BIT_CRC_ERROR = 0x04,
HLC_PTT_NOTIFY_BIT_ACK = 0x08,
HLC_PTT_NOTIFY_BIT_CRC_READY = 0x10,
HLC_PTT_NOTIFY_BIT_SEND_CTS = 0x100,
HLC_PTT_NOTIFY_BIT_SEND_nCTS = 0x200,
HLC_PTT_NOTIFY_BIT_SEND_BAD_CRC = 0x400,
HLC_PTT_NOTIFY_BIT_SEND_ACK = 0x800,
HLC_PTT_NOTIFY_BIT_XMIT_WTG = 0x1000,
HLC_PTT_NOTIFY_BIT_SEND_RETRAN = 0x2000,
HLC_PTT_NOTIFY_BIT_SIG_SYNC = 0x80000000,
};
That's it; I haven't redacted anything from that set. I use only those symbols as arguments to xTaskNotify; there are no magic numbers or variables used.
Another puzzle piece is that sometimes the garbage value is 0xa5a5a5a5, which looks very much like some sort of canary value. But other times it's something different, so that could be a red herring.
Btw,
Code: Select all
... xTaskNotifyWait(SEND_SIGNAL_NOTIFICATION_MASK, ...)
may make you miss/lose notifications, namely all notifications generated while the task is not blocked in xTaskNotifyWait().
That's not how I interpret the
FreeRTOS docs about pending notifications (emphasis added):
Any bits set in ulBitsToClearOnEntry will be cleared in the calling RTOS task's notification value on entry to the xTaskNotifyWait() function (before the task waits for a new notification)
provided a notification is not already pending when xTaskNotifyWait() is called. For example, if ulBitsToClearOnEntry is 0x01, then bit 0 of the task's notification value will be cleared on entry to the function.Setting ulBitsToClearOnEntry to 0xffffffff (ULONG_MAX) will clear all the bits in the task's notification value, effectively clearing the value to 0.
If a notification is already pending (i.e., sent while the task was not blocked in its call to xTaskNotifyWait), ulBitsToClearOnEntry bits are
not cleared. So I am not at risk of missing notifications (unless the pending state was cleared in the interim).
In any case, my next step is to try to set a watch on that piece of memory to see when it gets written with the garbage value. Since my last post, I added code to verify that the notification value is indeed 0x00000000 right after the task starts up, so something is definitely writing the garbage to that location. Maybe there's a buffer overflow in another module I created. Once I nail down the cause, I'll update this thread with what I discovered.