ATMega32 and V4.6.1

[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!

ATMega32 and V4.6.1

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.

ATMega32 and V4.6.1

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.