FreeRTOS task notifications interfere with IDF

LSitar
Posts: 4
Joined: Wed Jul 19, 2023 10:05 am

FreeRTOS task notifications interfere with IDF

Postby LSitar » Thu Aug 10, 2023 6:49 am

Hello,
#ESP32-S3 #ESP-IDF-5.1 master #custom-board
I'm having weird behaviour of notifications to main task, i.e. the task is notified, but does not receive the notify. When the task occasionally receives the notification, its value seems to have some random/trash value. It can even cath a notification when my code didn't sent notify yet.

other_task.c

Code: Select all

	extern TaskHandle_t main_task_handle;

	void some_event(void)
	{
		//this task is started by app_main() after the main_task_handle is initialized
		//the below event is triggered from e.g. uart communication
		xTaskNotify(main_task_handle, MAIN_TASK_NOTIFY_MEASURE, eSetBits);
	}
main.c

Code: Select all

	
	TaskHandle_t main_task_handle;
	void app_main(void)
	{
		main_task_handle = xTaskGetCurrentTaskHandle();
		while (1)
		{
			//some other code e.g. reading internal ADC
			adcIntRoutine();
			
			uint32_t ulNotifyValue;
			if (pdPASS == xTaskNotifyWait(0, UINT32_MAX, &ulNotifyValue, 0))
			{
				ESP_LOGI(TAG, "%s notified: %lu", __func__, ulNotifyValue);
			}
			vTaskDelay(1);
		}
	}
Under debug I've seen that the task is notified by some IDF code, e.g. DMA callback, that explains the above behaviour.
Intruder that interferes with my notifications:

Code: Select all

Thread #1 [IDLE] 1070210576 (Name: IDLE, State: Running @CPU0) (Suspended : Signal : SIGTRAP:Trace/breakpoint trap)	
vTaskGenericNotifyGiveFromISR() at tasks.c:6 171 0x4037fc64	
prvConvDoneCallback() at adcInt.c:112 0x40377952	
s_adc_dma_intr() at adc_continuous.c:310 0x4037ac12	
adc_dma_in_suc_eof_callback() at adc_continuous.c:264 0x4037ac70	
gdma_default_rx_isr() at gdma.c:701 0x4037aba7	
_xt_medint2() at xtensa_vectors.S:1 215 0x4037720c	
xt_utils_get_core_id() at xt_utils.h:36 0x40375981	
esp_cpu_get_core_id() at esp_cpu.h:126 0x40375981	
tick_hook() at int_wdt.c:64 0x40375981	
esp_vApplicationTickHook() at freertos_hooks.c:37 0x40375fcc	
xPortSysTickHandler() at port_systick.c:179 0x403806fe	
SysTickIsrHandler() at port_systick.c:149 0x40376d14	
_xt_lowint1() at xtensa_vectors.S:1 126 0x40377170	
gpio_intr_service() at gpio.c:488 0x40377abe	
esp_vApplicationIdleHook() at freertos_hooks.c:59 0x42003829	
prvIdleTask() at tasks.c:4 249 0x4037e8b4	
vPortTaskWrapper() at port.c:162 0x4037ff98
So my question is, since I didn't found anything about this in docs.espressif:
How should I use the task notification feature to not interfer with IDF ?

Maybe the IDF uses only index 0 of notifications and users should utilize only >0 indexes?
Last edited by LSitar on Thu Aug 10, 2023 8:55 am, edited 1 time in total.

ESP_Sprite
Posts: 9730
Joined: Thu Nov 26, 2015 4:08 am

Re: FreeRTOS task notifications interfere with IDF

Postby ESP_Sprite » Thu Aug 10, 2023 7:07 am

The file that calls the task notification in your callback (adcInt.c) does not exist in my version of ESP-IDF... are you sure you're not using the same notification somewhere else in your code?

LSitar
Posts: 4
Joined: Wed Jul 19, 2023 10:05 am

Re: FreeRTOS task notifications interfere with IDF

Postby LSitar » Thu Aug 10, 2023 8:40 am

You are right... the bug is in my code :(
I'm sorry for bothering You with my lack of experience in RTOS architecture.

So it is caused by adcIntRoutine(). It sets once at first call a handle to calling task, and then uses notify to signal samples ready via callback. It occured in default task, so I suspected IDF code without investigating it further. I must re-design the ADC.

Code: Select all

static bool IRAM_ATTR prvConvDoneCallback(adc_continuous_handle_t adcHandle, const adc_continuous_evt_data_t *edata, void *user_data)
{
	BaseType_t mustYield = pdFALSE;
	//Notify that ADC continuous driver has done enough number of conversions
	vTaskNotifyGiveFromISR(adcIntConsumerTaskHandle, &mustYield);

	return (mustYield == pdTRUE);
}

static inline bool prvIsAdcDataToRead(void)
{
	return pdTRUE == ulTaskNotifyTake(pdTRUE, 0);
}

void adcIntRoutine(void)
{
	static bool bOnce = true;

	if (bOnce)
	{	//set data ready notification to current task and start ADC
		adcIntConsumerTaskHandle = xTaskGetCurrentTaskHandle();
		ESP_ERROR_CHECK(adc_continuous_start(adcIntHandle));
		bOnce = false;
	}

Who is online

Users browsing this forum: Baidu [Spider], MicroController and 134 guests