Quality RTOS & Embedded Software

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




Loading

ATMega32 and V4.6.1

Posted by Richard on November 18, 2007
[moved from private email]

I'm using the FreeRTOS kernelin one of my applications for ATmega32,
and I just ran into the following problems:

(1)
I have an UART Tx ISR which gets its input from a queue. The
transmission is interrupt based, therefore the Tx ISR has to be able
to disable itself when the Tx queue is over. To accomplish this task,
it needs to track the status of the queue so that it's aware of the
elements present in the queue. The xQueueReceiveFromISR () and
uxQueueMessagesWaiting() functions are used in the ISR, and the latter
seems to enable the interrupts by invoking the portEXIT_CRITICAL()
function. Is this a correct and permissible behavior in an ISR? Or
should there be a uxQueueMessagesWaitingFromISR() function to handle
the situation correctly?

(2)
This one is more severe than the first one. The tick ISR (the main
timing ISR of the scheduler based on Timer1 of the ATmega) seems to -
perhaps unwantedly - enable the interrupts by using the
portEXIT_CRITICAL() function somewhere in the core of the kernel. On
very rare occasions my Tx ISR is invoked during the execution of the
vTaskSwitchContext() function in the tick ISR. My Tx ISR has the
following code fragment:
...
xQueueReceiveFromISR(UART_TxQueue, (const void *)&tmp1, (signed portBASE_TYPE *)&tmp2);
...
if (pdFALSE != tmp2)
{
taskYIELD();
}
...
In most cases the tmp2 does not equal pdFALSE, since taking en element
out of the queue almost always makes my transmitting task ready.
Therefore the taskYIELD() function is called at the end of the Tx ISR,
even if the Tx ISR was invoked during a tick ISR in its task switching
phase. It leads to _weird_ failures (e.g. jumping to nowhere in the
flash, etc.). I figured a - maybe just quick'n'dirty - workaround for
that problem. I modified the portmacro.s90 file the following way:
...
lds r0, uxCriticalNesting
st -y, r0 ; Store the critical nesting counter.
inc r0
sts uxCriticalNesting, r0
...
This way the vTaskSwitchContext() and other functions don't get to
enable the interrupts while in the tick ISR and the Tx ISR function
cannot execute until the tick ISR has finished. The task switch is
done correctly when not in the middle of another task switch.

Are there actually other workarounds for the previously described
problems? This critical section nesting is a bit weird when called
from interrupts and other situations where interrupt are disabled...

Thanks for your answer in advance!

RE: ATMega32 and V4.6.1

Posted by Richard on November 18, 2007
Hi,

Thank you for your feedback. I have some comments below:

> (1)
> I have an UART Tx ISR which gets its input from a queue. The
> transmission is interrupt based, therefore the Tx ISR has to be able
> to disable itself when the Tx queue is over. To accomplish this task,
> it needs to track the status of the queue so that it's aware of the
> elements present in the queue. The xQueueReceiveFromISR () and
> uxQueueMessagesWaiting() functions are used in the ISR, and the latter
> seems to enable the interrupts by invoking the portEXIT_CRITICAL()
> function. Is this a correct and permissible behavior in an ISR? Or
> should there be a uxQueueMessagesWaitingFromISR() function to handle
> the situation correctly?

Only functions that end in "FromISR" can be used within an ISR. You could add a function uxQueueMessagesWaitingFromISR() with the following:

unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
{
return pxQueue->uxMessagesWaiting;
}

See http://www.freertos.org/api.html

> (2)
> This one is more severe than the first one. The tick ISR (the main
> timing ISR of the scheduler based on Timer1 of the ATmega) seems to -
> perhaps unwantedly - enable the interrupts by using the
> portEXIT_CRITICAL() function somewhere in the core of the kernel.


portEXIT_CRITICAL() should not called from within the tick code. The only functions that are called from the preemptive tick are vTaskIncrementTick() and vTaskSwitchContext(). If portEXIT_CRITICAL() is being called then something must have gone wrong prior to the tick.


>On
> very rare occasions my Tx ISR is invoked during the execution of the
> vTaskSwitchContext() function in the tick ISR.


It should not be possible for interrupts to nest in this way. Interrupts are disabled upon entry to the ISR, or within the portSAVE_CONTEXT() macro should a yield have been performed.

Are there any other interrupts running?
Does your code explicitly allow interrupt nesting?
Have you checked that you are not getting a stack overflow?

Regards.

RE: ATMega32 and V4.6.1

Posted by Geza on November 18, 2007
Thanks for the rapid answer, both the problems rooted on the uxQueueMessagesWaiting() function. I added the uxQueueMessagesWaitingFromISR() function to the queue.c and queue.h files, now it works correctly. Maybe it would be useful to contain the function in future releases of FreeRTOS, too.

The problem was that I had a tick hook function which also used the uxQueueMessagesWaiting() to check whether to re-enable the Tx ISR or not (the Tx ISR is capable of disabling itself based on flow control signals, I'm using the tick hook to check the condition for re-enabling). This function enabled the interrupts, so the Tx ISR was able to execute during the tick ISR.


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




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

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

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

OpenRTOS and SafeRTOS