# Idle task not yielding immediately after ISR until next tick when
 preemption enabled

**URL:** <https://forums.freertos.org/t/idle-task-not-yielding-immediately-after-isr-until-next-tick-when-preemption-enabled/7986>\
**Category:** Kernel\
**Created:** [July 28, 2019, 7:11pm UTC](https://forums.freertos.org/t/idle-task-not-yielding-immediately-after-isr-until-next-tick-when-preemption-enabled/7986 "2019-07-28T19:11:39Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 28, 2019, 7:11pm UTC](https://forums.freertos.org/t/idle-task-not-yielding-immediately-after-isr-until-next-tick-when-preemption-enabled/7986/1 "2019-07-28T19:11:39Z")

</div>

**[eve-shadow](https://sourceforge.net/u/eve-shadow/)** wrote on [Sunday, July 28, 2019](https://sourceforge.net/p/freertos/discussion/382005/thread/62805f4259/#e42b):

Hi all,  
I have run into an interesting issue that seems to be related to the  
scheduler. I’m on an STM32F4 (using CubeMX to generate HAL and FreeRTOS  
code). For the purposes of this discussion let’s say I have 1 running task  
(for gathering read data from a uart). Here is the task code:

```auto
for (;;) {
/* unmask receive data register not empty interrupt */
SET_BIT(stx->uart->Instance->CR1, USART_CR1_RXNEIE);
/* unmask receive parity error interrupt */
SET_BIT(stx->uart->Instance->CR1, USART_CR1_PEIE);

/* wait for receive data register not empty interrupt */
rstat = xSemaphoreTake(stx->rxSemaphore, portMAX_DELAY);
assert(rstat == pdPASS);

/* receive byte */
if (stx->uart->Init.Parity == UART_PARITY_NONE) {
buff = (char)(stx->uart->Instance->DR & 0x000000FF);
} else {
buff = (char)(stx->uart->Instance->DR & 0x0000007F);
}

/* place byte in read queue */
rstat = xQueueSendToBack(stx->rxFIFO, &buff, portMAX_DELAY);
assert(rstat == pdPASS);
}

```

Here is the relevant part of the receive byte ISR:

```auto
 if ( ((status_reg & USART_SR_RXNE) != RESET) && ((cr1 & USART_CR1_RXNEIE)
!= RESET) ) {
/* rx data register byte available */
/* mask receive data register not empty interrupt */
CLEAR_BIT(stx->uart->Instance->CR1, USART_CR1_RXNEIE);
/* unblock receive task */
rstat = xSemaphoreGiveFromISR(stx->rxSemaphore, NULL);
assert(rstat == pdPASS);
}

```

Here is the source of error / confusion. Using this code, sending any more  
than 1 byte in a short period of time causes a uart overrun error  
interrupt. I have traced the code and the problem appears to be that the  
idle task does not yield properly. Here is the sequence of events:

- read task is blocked on xSemaphoreTake()
- ISR is called and reaches xSemaphoreGiveFromISR()
- after this call, the read task is put in the ready state (according to  
Atollic TrueStudio FreeRTOS Task List tool, which displays all running  
tasks, state, stack size, etc.)
- the ISR exits and we return to line 3258 in tasks.c (inside the idle  
task):

```auto
(3258) if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY
] ) ) > ( UBaseType_t ) 1 )
(3259) {
(3260) taskYIELD();
(3261) }

```

- idle task now appears to loop between lines 3258 and 3235 (the if  
statement on 3258 evaluates to FALSE and does not taskYIELD() )  
`(3235) prvCheckTasksWaitingTermination();`
- the uart read task only resumes at the next TICK event

The overrun error then occurs because by the time the uart read task starts  
running, another byte has already been received in the uart. Obviously the  
desired behavior is for the idle task to immediately yield to the uart read  
tasks. Now, if I disable configUSE\_PREEMPTION, everything works and the  
idle task yields immediately (line 3243 in tasks.c). Am I misunderstanding  
what preemption is supposed to do?

Thanks,  
Jacob

---

<div class="post-metadata">

**Author:** ![richard-damon](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/richard-damon/32/38_2.png) [@richard-damon](https://forums.freertos.org/u/richard-damon)\
**Post date:** [July 28, 2019, 7:34pm UTC](https://forums.freertos.org/t/idle-task-not-yielding-immediately-after-isr-until-next-tick-when-preemption-enabled/7986/2 "2019-07-28T19:34:27Z")

</div>

**[richard\_damon](https://sourceforge.net/u/richard_damon/)** wrote on [Sunday, July 28, 2019](https://sourceforge.net/p/freertos/discussion/382005/thread/62805f4259/#4833):

Your ISR is ignoring the Higher Priority Task was woken signal (and in fact passing NULL pointers there, so you are not invoking premption. Fix that and you will fix your problem.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 28, 2019, 7:39pm UTC](https://forums.freertos.org/t/idle-task-not-yielding-immediately-after-isr-until-next-tick-when-preemption-enabled/7986/3 "2019-07-28T19:39:29Z")

</div>

**[eve-shadow](https://sourceforge.net/u/eve-shadow/)** wrote on [Sunday, July 28, 2019](https://sourceforge.net/p/freertos/discussion/382005/thread/62805f4259/#2865):

Ah. Failure to read documentation :). Appreciate it, thanks!

Jacob
