Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

Best practice to avoid ISR race conditions

Posted by Engin AYDOGAN on September 3, 2008
Hello,

I have an ISR to handle UART input. It pushes the data it receives into a buffer. On the other hand, I have t o parse that buffer and extract each meaningfull message (each message is wrapped with a \r\n in this case).

I'm planning to parse the buffer and extract messages in a task but I need to make sure that during that parsing the buffer shouldn't be modified.

What would be the safest solution ?

From the docs it looks like I cannot LOCK a mutex in ISR but only release it. On the other hand, using ENTER_CRITICAL might be a simple solution but I don't think it is intended for this purpose.

I'd love to hear best practices about the subject in the FreeRTOS world.

Kind regards

RE: Best practice to avoid ISR race conditions

Posted by Engin AYDOGAN on September 3, 2008
Maybe this might be a possible solution ?

void ISR(void)
{
xQueueSendFromISR(...); /* Append a "lock" */
...
xQueueReceiveFromISR(...); /* Remove the "lock" */
}

void task(void)
{
if( xQueuePeek(...) ) return; /* Check if there's any lock */
...
}

RE: Best practice to avoid ISR race conditions

Posted by Engin AYDOGAN on September 3, 2008
I've also seen Richard Barry doing this;

----- taken from emac.c -----
void FOO_ISR(void)
{
xSemaphoreGiveFromISR();
DISABLE_FOO_INTERRUPTS();
portEND_SWITCHING_ISR;
}

void task(void)
{
xSemaphoreTake();
// do stuff
ENABLE_FOO_INTERRUPT();
}
-----------

First of all, task never gives the semaphore back. Second, isn't disabling an interrupt can cause data loss on the peripheral if the hardware buffer is full ?

Now that I've looked into FreeRTOS source I've noticed that queue thread-safety is done by vPortEnterCritical. I thought it would be with an atomic assembly instruction.

If Queue infrastructure uses vPortEnterCritical to ensure thread-safety I think I can safely use that as my lock without ever using Queues, since Queues looks like just a fancy way of vPortEnterCritical.

What am I missing ?

Kind regards

RE: Best practice to avoid ISR race condition

Posted by Çağlar Akyüz on September 3, 2008
Merhaba :)

When you have long chunks of data, like in ethernet, in order to get rid of extra copy
you may use semaphore especially if dma is involved. On the other hand, if you have
relatively small data source queues will provide better programming practice.

In my uart interrupt, I send data to a queue and then process queue in a task. If you use
portENTERCRITICAL you will lose data if you can not process character in a timely manner.
But with the queues, you can wait as long as you want provided that your queue size is adequate
for your data rate.

Caglar

RE: Best practice to avoid ISR race conditions

Posted by Richard on September 3, 2008
Just as a summary of posts in this thread -

Note that between a task and an interrupt the mutual exclusion is normally in one direction only. An interrupt can interrupt a task, but a task cannot interrupt an interrupt. Therefore it is very rare to need to take a semaphore in an ISR.

If you place received data in a circular buffer then the ISR can access the write pointer, and the task the read pointer, with little potential for a conflict. You are only writing to the pointers from one place - the write pointer from the ISR and the read pointer from the task.

Another method is to use an array of buffers. The ISR can use one buffer, when it has filled it or a complete message has arrived, it then moves onto the next buffer leaving the task to process the first buffer without fear of a conflict. The ISR and task are always working on different buffers. This is how many DMA systems work, especially on Ethernet controllers.

Regards.

RE: Best practice to avoid ISR race conditions

Posted by Engin AYDOGAN on September 3, 2008
Thank you very much for your prompt responses, but answer to my questions are still not clear to me.

Cağlar:

Queues also uses vPortEnterCritical to lock the queue, i.e. each time you append a char to the queue it will enter and exit critical region. This is not true if you use FromISR relatives though, they don't disable interrupts since it is apparently assumed that they won't be preempted which I don't know if it is true.

I've though of vPortEnterCritical to only lock and release a mutex (in traditional sense), so it would a little time and I'd just use that ensure the atomicity of the mutex operation.

Richard Barry:

My platform is cortex-m3. Can't interrupts in this MCU be preempted by other interrupts ? Say if SYSTICK interrupt has occured, won't it interrupt a perihperal interrupt and do a FreeRTOS stuff such as context switching.

If we can assume that the UART ISR won't be interrupt by anything else my problem is easy to fix. As you suggested I'd just use double buffering, and we are good to go. Is that the case ?

Kind regards

RE: Best practice to avoid ISR race conditions

Posted by Richard on September 3, 2008
> My platform is cortex-m3. Can't interrupts in this MCU be
> preempted by other interrupts ?

Yes - full interrupt nesting is supported, however....

> Say if SYSTICK interrupt has
> occured, won't it interrupt a perihperal interrupt and do a
> FreeRTOS stuff such as context switching.

.... SYSTICK operates at the lowest priority so will never interrupt a peripheral ISR (assuming you have not changed the value of configKERNEL_INTERRUPT_PRIORITY from 255). SYSTICK can itself be interrupted by a peripheral ISR but this is ok, the design will allow this safely.

You can use queues from interrupts provided the interrupt priority is equal to or below portMAX_SYSCALL_INTERRUPT_PRIORITY - note that on Cortex M3 the lowest priority is the highest numeric value, so 255 has lower priority than 254. Again this is safe as the kernel is designed to allow this.

See http://www.freertos.org/a00110.html#kernel_priority.

> If we can assume that the UART ISR won't be interrupt by
> anything else my problem is easy to fix. As you suggested I'd
> just use double buffering, and we are good to go. Is that the case ?

Hopefully I have answered that. They wont get interrupted by the kernel but I cannot say whether any other interrupts using the same buffers will interrupt your UART interrupt because this depends how you have designed your system and set your interrupt priorities.

Regards.

RE: Best practice to avoid ISR race conditions

Posted by Engin AYDOGAN on September 9, 2008
Hello Richard,

Thank you very much for taking time to explain these. I really appreciate it.

I have a question about your ethernet driver implementation in Luminary example. In the ethernet interrupt routine (vEMAC_ISR) you just give a semaphore and in the vMACHandleTask takes that semaphore and process the incoming data. During this processing you disable interrupts to ethernet port. Now, I know that this code works fine because I'm using it for a few months now but I wonder how come it never happens to cause hardware buffer overruns. i.e. what if the processing took long during that time interrupts are disabled. Wouldn't that cause a buffer overrun and loss of data permenantly ?

You rely on TCP to recover that ?

Kind regards,

Engin


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists