The vTaskGenericNotifyGiveFromISR function need call prvResetNextTaskUnblockTime()

I’m having an issue with the CPU did not sleep in time.

I have a task that calls ulTaskGenericNotifyTake function to delay for 5 milliseconds. At this time, the TCB is added to pxDelayedTaskList. After 2 milliseconds, an interrupt is received to call vTaskGenericNotifyGiveFromISR function to wake up the task. Then, the task is added to xSuspendedTaskList through ulTaskGenericNotifyTake function. At this time, the program is expected to enter sleep in prvIdleTask, but because xNextTaskUnblockTime is not reset, the program does not enter sleep immediately, but after 3ms.

Can I call prvResetNextTaskUnblockTime in vTaskGenericNotifyGiveFromISR function to solve this problem?

Thank you!

Hi @zhiqiang6
Can you share the code snippets for the task and the ISR code?

I am not sure I understand this, why do you think the task is going to the suspended list?

Hi, karahulx

The actual code is more complicated, the following code gives a simple example:

TaskHandle_t taskHandle = NULL;
uint8_t recv_uart = 0;

void uart_isr(void)
{
    recv_uart = 1;
    BaseType_t xHighPriorityTaskWoken = pdFALSE;
    vTaskNotifyGiveFromISR(taskHandle, &(xHighPriorityTaskWoken));
    portYIELD_FROM_ISR(xHighPriorityTaskWoken);
}

void taskFunction(void *param) {
    for(;;) {
        if (recv_uart) {
			ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
		} else {
			ulTaskNotifyTake(pdTRUE, 5);
		}
    }
}
 
int main() {
    xTaskCreate(taskFunction, "TaskName", 256, NULL, 1, &taskHandle);
    vTaskStartScheduler();
    return 0;
}

After receiving the UART interrupt, it is expected that the task execution can be suspended as soon as possible, and then the CPU can enter sleep. When I tested the power consumption, I found that the CPU could not enter sleep in time because the xNextTaskUnblockTime value was not reset after the task was woken up in vTaskNotifyGiveFromISR.

Please try the following code -

TaskHandle_t taskHandle = NULL;

void uart_isr(void)
{
    BaseType_t xHighPriorityTaskWoken = pdFALSE;
    vTaskNotifyGiveFromISR(taskHandle, &(xHighPriorityTaskWoken));
    portYIELD_FROM_ISR(xHighPriorityTaskWoken);
}

void taskFunction(void *param)
{
    for(;;)
    {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
    }
}

int main()
{
    xTaskCreate(taskFunction, "TaskName", 256, NULL, 1, &taskHandle);
    vTaskStartScheduler();
    return 0;
}

Hi, aggarg
Thank you for your method!
What I provided is just a simple example. I know your code can solve the problem, but my question is whether it is necessary to call prvResetNextTaskUnblockTime in the vTaskGenericNotifyGiveFromISR function.

Thank you

Apologies - I misunderstood it as your code. I understand your issue now and you are right. This PR addresses the issue - Reset xNextTaskUnblockTime in task notify FromISR APIs by aggarg · Pull Request #1111 · FreeRTOS/FreeRTOS-Kernel · GitHub. Please let us know if this solves your problem.

1 Like

Thank you, it solved my problem.