Problem with FreeRTOS ISR Task Notification

I am using Nucleo F411RE dev borad. When I using the FreeRTOS, I found that the xTaskNotifyFromISR always stuck.

my handler function as below and I can enter it normally.

the program stop at

	xTaskNotifyFromISR(next_task_handle, 0, eNoAction, &pxHigherPriorityTaskWoken);

/* USER CODE BEGIN 4 */
 
void button_interrupt_handler(void) {
 
SEGGER_SYSVIEW_PrintfTarget("button_interrupt_handler\n");
 
	BaseType_t pxHigherPriorityTaskWoken;
 
	pxHigherPriorityTaskWoken = pdFALSE;
 
	traceISR_ENTER();
 
	SEGGER_SYSVIEW_PrintfTarget("next_task_handle %X\n",next_task_handle);
 
	SEGGER_SYSVIEW_PrintfTarget("eNoAction %X\n",eNoAction);
 
SEGGER_SYSVIEW_PrintfTarget("pxHigherPriorityTaskWoken %X\n",pxHigherPriorityTaskWoken);
 
	xTaskNotifyFromISR(next_task_handle, 0, eNoAction, &pxHigherPriorityTaskWoken);
 
	//xTaskNotify(task2_handle, 0, eNoAction);
	/* once the ISR exits, the below macro makes higher priority task which got unblocked to resume on the CPU */
 
	portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
	traceISR_EXIT();
}

I follow the trace and the finialy stop at

configASSERT( xTaskToNotify );

in the tasks.c file of FreeRTOS

The actual function as below


#if ( configUSE_TASK_NOTIFICATIONS == 1 )
 
 
 
  BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
 
                     UBaseType_t uxIndexToNotify,
 
                     uint32_t ulValue,
 
                     eNotifyAction eAction,
 
                     uint32_t * pulPreviousNotificationValue,
 
                     BaseType_t * pxHigherPriorityTaskWoken )
 
  {
 
    TCB_t * pxTCB;
 
    uint8_t ucOriginalNotifyState;
 
    BaseType_t xReturn = pdPASS;
 
    UBaseType_t uxSavedInterruptStatus;
 
 
 
    configASSERT( xTaskToNotify );
 
    configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
 
 
 
    /* RTOS ports that support interrupt nesting have the concept of a
 
     * maximum system call (or maximum API call) interrupt priority.
 
     * Interrupts that are above the maximum system call priority are keep
 
     * permanently enabled, even when the RTOS kernel is in a critical section,
 
     * but cannot make any calls to FreeRTOS API functions. If configASSERT()
 
     * is defined in FreeRTOSConfig.h then
 
     * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
 
     * failure if a FreeRTOS API function is called from an interrupt that has
 
     * been assigned a priority above the configured maximum system call
 
     * priority. Only FreeRTOS functions that end in FromISR can be called
 
     * from interrupts that have been assigned a priority at or (logically)
 
     * below the maximum system call interrupt priority. FreeRTOS maintains a
 
     * separate interrupt safe API to ensure interrupt entry is as fast and as
 
     * simple as possible. More information (albeit Cortex-M specific) is
 
     * provided on the following link:
 
     * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
 
    portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
 
 
 
    pxTCB = xTaskToNotify;
 
 
 
    uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
 
    {
 
      if( pulPreviousNotificationValue != NULL )
 
      {
 
        *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
 
      }
 
 
 
      ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
 
      pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
 
 
 
      switch( eAction )
 
      {
 
        case eSetBits:
 
          pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
 
          break;
 
 
 
        case eIncrement:
 
          ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
 
          break;
 
omit................

That assert means that the next_task_handle is NULL. Where do you assign next_task_handle?

assigned at the led handler.

next_task_handle = task3_handle;/task2_handle;

handler as below


static void led_green_handler(void *parameters) {

	BaseType_t status;
	while (1) {
		//printf("led_green_handler\n");
		SEGGER_SYSVIEW_PrintfTarget("Toggling green LED\n");
		HAL_GPIO_TogglePin(GPIOA, GREEN_PIN_Pin);
		//HAL_Delay(1000);
		status = xTaskNotifyWait(0, 0, NULL, pdMS_TO_TICKS(1000));
		if (status == pdTRUE) {
			portENTER_CRITICAL();
			next_task_handle = task2_handle;
			//xTaskResumeAll();
			HAL_GPIO_WritePin(GPIOA, GREEN_PIN_Pin, GPIO_PIN_SET);
			SEGGER_SYSVIEW_PrintfTarget("Delete green LED task\n");
			portEXIT_CRITICAL();
			vTaskDelete(NULL);
		}
	}
}

static void led_orange_handler(void *parameters) {
	BaseType_t status;

	while (1) {
		//printf("led_orange_handler\n");
		SEGGER_SYSVIEW_PrintfTarget("Toggling orange LED\n");
		HAL_GPIO_TogglePin(GPIOA, BLUE_PIN_Pin);
		//HAL_Delay(800);
		status = xTaskNotifyWait(0, 0, NULL, pdMS_TO_TICKS(800));
		if (status == pdTRUE) {
			portENTER_CRITICAL();
			next_task_handle = task3_handle;
			HAL_GPIO_WritePin(GPIOA, BLUE_PIN_Pin, GPIO_PIN_SET);
			SEGGER_SYSVIEW_PrintfTarget("Delete orange LED task\n");
			portEXIT_CRITICAL();
			vTaskDelete(NULL);
		}
	}

}

static void led_red_handler(void *parameters) {
	BaseType_t status;

	while (1) {
		//printf("led_red_handler\n");
		SEGGER_SYSVIEW_PrintfTarget("Toggling red LED\n");
		HAL_GPIO_TogglePin(GPIOA, RED_PIN_Pin);
		//HAL_Delay(400);
		status = xTaskNotifyWait(0, 0, NULL, pdMS_TO_TICKS(400));
		if (status == pdTRUE) {
			portENTER_CRITICAL();
			next_task_handle = task1_handle;
			HAL_GPIO_WritePin(GPIOA, RED_PIN_Pin, GPIO_PIN_SET);
			SEGGER_SYSVIEW_PrintfTarget("Delete red LED task\n");
			portEXIT_CRITICAL();
			vTaskDelete(NULL);
		}
	}

}

Where are these tasks created and what are the priorities of these tasks? Can you share the complete project?

status = xTaskNotifyWait(0, 0, NULL, pdMS_TO_TICKS(1000));
		if (status == pdTRUE) {
			portENTER_CRITICAL();
			next_task_handle = task2_handle;

In the above code snippet, you are first waiting for a task notification and after you receive one, you set the next_task_handle variable. Are you initializing this variable for the first notification somewhere?

the handler seem normal after I add the

next_task_handle = task3_handle;

before the xTaskNotifyFromISR.

void button_interrupt_handler(void) {
	SEGGER_SYSVIEW_PrintfTarget("button_interrupt_handler\n");
	BaseType_t pxHigherPriorityTaskWoken;

	pxHigherPriorityTaskWoken = pdFALSE;

	traceISR_ENTER();
	next_task_handle = task3_handle;
	SEGGER_SYSVIEW_PrintfTarget("next_task_handle %X\n", next_task_handle);
	SEGGER_SYSVIEW_PrintfTarget("eNoAction %X\n", eNoAction);
	SEGGER_SYSVIEW_PrintfTarget("pxHigherPriorityTaskWoken %X\n",
			pxHigherPriorityTaskWoken);

	xTaskNotifyFromISR(next_task_handle, 0, eNoAction,
			&pxHigherPriorityTaskWoken);
	//xTaskNotify(task2_handle, 0, eNoAction);

	/* once the ISR exits, the below macro makes higher priority task which got unblocked to resume on the CPU */
	portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);

	traceISR_EXIT();
}

I cannot upload the project as attachment because I am still a new user.

the task porpority are all 2 as below.

	status = xTaskCreate(led_green_handler, "LED_green_task", 200, NULL, 2,
			&task1_handle);

	configASSERT(status == pdPASS);

	status = xTaskCreate(led_red_handler, "LED_red_task", 200, NULL, 2,
			&task2_handle);

	configASSERT(status == pdPASS);

	status = xTaskCreate(led_orange_handler, "LED_orange_task", 200, NULL, 2,
			&task3_handle);

You should now be able to attach.

test_006.zip (1.3 MB)

project file attached

The status is always 0. I am not sure why…

		status = xTaskNotifyWait(0, 0, NULL, pdMS_TO_TICKS(1000));

		if (status == pdTRUE) {
			portENTER_CRITICAL();
			next_task_handle = task1_handle;
			//xTaskResumeAll();
			HAL_GPIO_WritePin(GPIOA, GREEN_PIN_Pin, GPIO_PIN_SET);
			SEGGER_SYSVIEW_PrintfTarget("Delete green LED task\n");
			portEXIT_CRITICAL();
			vTaskDelete(NULL);
		}

test_006_updated.zip (1.3 MB)

Look at the changes I made. Basically you need to make sure that you update next_task_handle correctly so that the notification is delivered to the correct task.

seem work after I place the ext_task_handle outside the if statement. I am still finding why the xTaskNotifyWait always return 0.

			next_task_handle = task1_handle;
		if (status == pdTRUE) {
			SEGGER_SYSVIEW_PrintfTarget("the status is 1 pdTRUE\n");
			portENTER_CRITICAL();

			//xTaskResumeAll();
			HAL_GPIO_WritePin(GPIOA, GREEN_PIN_Pin, GPIO_PIN_SET);

			portEXIT_CRITICAL();
			vTaskDelete(NULL);
		}

Even after changing timeout to portMAX_DELAY?

After I clean the project and rebuild it. The xTaskNotifyWait seem normal again. Thank @aggarg for helping me check the code. :smiling_face_with_tear:


/* task 1. */
static void led_green_handler(void *parameters) {

	BaseType_t status;
	while (1) {
		//printf("led_green_handler\n");
		SEGGER_SYSVIEW_PrintfTarget("Toggling green LED\n");
		HAL_GPIO_TogglePin(GPIOA, GREEN_PIN_Pin);
		//HAL_Delay(1000);
		status = xTaskNotifyWait(0, 0, NULL, pdMS_TO_TICKS(1000));

		if (status == pdTRUE) {
			portENTER_CRITICAL();
			/* The next notification should be delivered to task 2 (i.e. led_red_handler). */
			next_task_handle = task2_handle;
			//xTaskResumeAll();
			HAL_GPIO_WritePin(GPIOA, GREEN_PIN_Pin, GPIO_PIN_SET);
			SEGGER_SYSVIEW_PrintfTarget("Delete green LED task\n");
			portEXIT_CRITICAL();
			vTaskDelete(NULL);
		}
	}
}

/* task 3. */
static void led_orange_handler(void *parameters) {
	BaseType_t status;

	while (1) {
		//printf("led_orange_handler\n");
		SEGGER_SYSVIEW_PrintfTarget("Toggling orange LED\n");
		HAL_GPIO_TogglePin(GPIOA, BLUE_PIN_Pin);
		//HAL_Delay(800);
		status = xTaskNotifyWait(0, 0, NULL, pdMS_TO_TICKS(800));

		if (status == pdTRUE) {
			portENTER_CRITICAL();
			/* The next notification will not be delivered to any task as all the tasks are deleted now. */
			next_task_handle = NULL;
			HAL_GPIO_WritePin(GPIOA, BLUE_PIN_Pin, GPIO_PIN_SET);
			SEGGER_SYSVIEW_PrintfTarget("Delete orange LED task\n");
			portEXIT_CRITICAL();
			vTaskDelete(NULL);
		}
	}

}

/* task 2. */
static void led_red_handler(void *parameters) {
	BaseType_t status;

	while (1) {
		//printf("led_red_handler\n");
		SEGGER_SYSVIEW_PrintfTarget("Toggling red LED\n");
		HAL_GPIO_TogglePin(GPIOA, RED_PIN_Pin);
		//HAL_Delay(400);
		status = xTaskNotifyWait(0, 0, NULL, pdMS_TO_TICKS(100));

		if (status == pdTRUE) {
			portENTER_CRITICAL();
			/* The next notification should be delivered to task 3 (i.e. led_orange_handler). */
			next_task_handle = task3_handle;
			HAL_GPIO_WritePin(GPIOA, RED_PIN_Pin, GPIO_PIN_SET);
			SEGGER_SYSVIEW_PrintfTarget("Delete red LED task\n");
			portEXIT_CRITICAL();
			vTaskDelete(NULL);
		}
	}

}