[moved from private email]
I’m using the FreeRTOS kernelin one of my applications for ATmega32,
and I just ran into the following problems:
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?
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)
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.
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!