xTaskNotifyWait ulBitsToClearOnEntry and ulBitsToClearOnExit example

Wasabinary
Posts: 13
Joined: Fri Apr 23, 2021 10:09 am

xTaskNotifyWait ulBitsToClearOnEntry and ulBitsToClearOnExit example

Postby Wasabinary » Fri Apr 28, 2023 9:28 am

Hi,

I have been trying to use FreeRTOS task notification on ESP32 for a few days, and I am not sure I really understand the effect of the ulBitsToClearOnEntry and ulBitsToClearOnExit parameters of the xTaskNotifyWait() function.

I am able to send notifications between 2 tasks with xTaskNotify() and xTaskNotifyWait() functions, but even when tickling with the parameters of xTaskNotifyWait(), I don't really see any difference in the behavior. Here is the base code I used:

Code: Select all


const char *TAG = "MAIN";

TaskHandle_t TaskHandler1 = NULL;
TaskHandle_t TaskHandler2 = NULL;


void myTask1(void *pvParameters)
{
	vTaskDelay(pdMS_TO_TICKS(1000)); // wait for the other task to be created
	while(1)
	{
		xTaskNotify(TaskHandler2, 1 << 0, eSetBits);
		vTaskDelay(pdMS_TO_TICKS(1000));
	}
}

void myTask2(void *pvParameters)
{
	uint32_t val = 0;
	while(1)
	{
		if(xTaskNotifyWait(0x00, 0x00, &val, 0) == pdPASS)
		{
			if(val & (1 << 0))
			{
				ESP_LOGI(TAG, "Received notification %u", val);
			}
		}
		vTaskDelay(pdMS_TO_TICKS(10));
	}
}

void app_main(void)
{
	xTaskCreate(myTask1, "Task1", 2048, NULL, 2, &TaskHandler1);
	xTaskCreate(myTask2, "Task2", 2048, NULL, 2, &TaskHandler2);
}
Does anyone can explain what to do with ulBitsToClearOnEntry and ulBitsToClearOnExit parameters better then the documention, may be with an example that shows the behavior difference ?

Thank you in advance!

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: xTaskNotifyWait ulBitsToClearOnEntry and ulBitsToClearOnExit example

Postby MicroController » Fri Apr 28, 2023 9:51 am

The "bits to clear" parameters allow you to atomically have bits in the notification value cleared.
When using e.g. bit flags in a task notification, often one task A sets a certain bit which the other task B then evaluates. However, for the mechanism to work repeatedly, the bit has to be cleared at some point by task B when the notification is received, so that task A can set the bit again when it needs to. On many platforms, setting or clearing bits in a word in RAM is not an atomic operation, requiring a read-modify-write sequence of instructions which is prone to race conditions and the "lost update problem".
To avoid that issue, you can use e.g. ulBitsToClearOnExit which makes FreeRTOS clear the bits you specify atomically (inside a critical section) together with receiving the notification so that you can be certain that no bits get accidentally cleared without being received in task B's notification value.
It may be worth noting that this mechanism is not needed if you only use a single possible notification value (e.g. always "1"). In fact, in this case you don't even need the notification value at all because the only information carried is that a notification was sent. If you have more than one possible value (e.g. "1" or "0", or any other set of bits) the provided atomicity comes in really handy.
Last edited by MicroController on Fri Apr 28, 2023 10:02 am, edited 1 time in total.

Wasabinary
Posts: 13
Joined: Fri Apr 23, 2021 10:09 am

Re: xTaskNotifyWait ulBitsToClearOnEntry and ulBitsToClearOnExit example

Postby Wasabinary » Fri Apr 28, 2023 9:55 am

Thank you for your answer,

So, what happens if I set both ulBitsToClearOnEntry and ulBitsToClearOnExit to 0? The value is not cleared at all?

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: xTaskNotifyWait ulBitsToClearOnEntry and ulBitsToClearOnExit example

Postby MicroController » Fri Apr 28, 2023 10:06 am

Correct.
If you still needed to clear the value, you'd use ulTaskNotifyValueClear(...), but that wouldn't be atomic w.r.t. the receiving of the notification which, depending on the algorithm/use case, may or may not be a problem.

Wasabinary
Posts: 13
Joined: Fri Apr 23, 2021 10:09 am

Re: xTaskNotifyWait ulBitsToClearOnEntry and ulBitsToClearOnExit example

Postby Wasabinary » Fri Apr 28, 2023 12:57 pm

MicroController wrote:
Fri Apr 28, 2023 10:06 am
Correct.
If you still needed to clear the value, you'd use ulTaskNotifyValueClear(...), but that wouldn't be atomic w.r.t. the receiving of the notification which, depending on the algorithm/use case, may or may not be a problem.

If I understand correctly, the bits I set in the Task1 would not be cleared with both parameters = 0. If so, the following code should print the message "Received notification" 2 times:

Code: Select all

const char *TAG = "MAIN";

TaskHandle_t TaskHandler1 = NULL;
TaskHandle_t TaskHandler2 = NULL;


void myTask1(void *pvParameters)
{
	vTaskDelay(pdMS_TO_TICKS(1000)); // wait for the other task to be created
	uint32_t _ret = 0;
	while(1)
	{
		_ret = xTaskNotify(TaskHandler2, 1 << 0, eSetBits);
		ESP_LOGI(TAG, "return = %u", _ret);
		vTaskDelay(pdMS_TO_TICKS(1000));
	}
}

void myTask2(void *pvParameters)
{
	uint32_t val = 0;
	while(1)
	{
		if(xTaskNotifyWait(0x00, 0x00, &val, 0) == pdPASS)
		{
			if(val & (1 << 0))
			{
				ESP_LOGI(TAG, "Received notification %u", val);
			}
		}
		if(xTaskNotifyWait(0x00, 0x00, &val, 0) == pdPASS)
		{
			if(val & (1 << 0))
			{
				ESP_LOGI(TAG, "Received notification %u", val);
			}
		}
		vTaskDelay(pdMS_TO_TICKS(10));
	}
}
Am I right?

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: xTaskNotifyWait ulBitsToClearOnEntry and ulBitsToClearOnExit example

Postby MicroController » Fri Apr 28, 2023 2:16 pm

Not quite sure what you mean. myTask1 sends a notification with a value every second in a loop, so you'll see one "notification received" every second.
To clarify what I edited in in my first answer: The notification state is independent of a notification value. You send one notification, the receiver receives one notification. If/how you change/set the notification value doesn't matter for this; you can perfectly send a notification value of '0' for example, or 0xffffffff, or any other value, or "no" value by means of "eNoAction".
You can think of the notification state of a task as an additional, "hidden" bit flag: It can be true or false, where xTaskNotify sets it to true and xTaskNotifyWait waits for it to become true and sets it back to false. The mechanism doesn't care about the notification value you may send along with the notification. (So, in fact, you can call xTaskNotify any number of times before the receiver gets a chance to pick up the notification, and the receiver will still only see one notification.)

Wasabinary
Posts: 13
Joined: Fri Apr 23, 2021 10:09 am

Re: xTaskNotifyWait ulBitsToClearOnEntry and ulBitsToClearOnExit example

Postby Wasabinary » Fri Apr 28, 2023 3:03 pm

Alright so ulBitsToClearOnEntry and ulBitsToClearOnExit only has an effect on the notification state, but the value (in my example 1 << 0) remains unchanged.

I am not sure why we should clear wether on entry or on exit. What is the difference in my case ? (even though I only set to 1, but let's say I would send any number for the sender task)

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: xTaskNotifyWait ulBitsToClearOnEntry and ulBitsToClearOnExit example

Postby MicroController » Sat Apr 29, 2023 6:19 pm

Wasabinary wrote:
Fri Apr 28, 2023 3:03 pm
Alright so ulBitsToClearOnEntry and ulBitsToClearOnExit only has an effect on the notification state, but the value (in my example 1 << 0) remains unchanged.
No, it's the opposite :) BitsToClear affects the value, but the notification state, i.e. the information that/if a task was notified, is independent thereof.
I am not sure why we should clear wether on entry or on exit. What is the difference in my case ? (even though I only set to 1, but let's say I would send any number for the sender task)
To me, clearing on exit makes sense in most cases because you get the pre-clear value as output from xTaskNotifyWait and hence never lose any information. clearOnEntry however... not sure about the use case, and I can't seem to find any code which uses a non-0 value.

Wasabinary
Posts: 13
Joined: Fri Apr 23, 2021 10:09 am

Re: xTaskNotifyWait ulBitsToClearOnEntry and ulBitsToClearOnExit example

Postby Wasabinary » Tue May 02, 2023 6:50 am

Thank you for the explanation, I will keep it simple and clear on exit then :D

Who is online

Users browsing this forum: Bing [Bot] and 129 guests