Entering prvTaskExitError from prvIsQueueEmpty

Hey

I have issue where my code enter prvTaskExitError from prvIsQueueEmpty.
This happens after a while when the application has been running for about a minute.

The system stops at: configASSERT( uxCriticalNesting == ~0UL );

My system/application communicating with another system over a dual-port memory, where I am using 2 channels, which each sets an interrupts when a change in the handshake flags occurs, belonging to the given channel. So I have 2 interrupts, with each a Deffered service routine task(or DSR_task) and 2 packetHandler tasks (one for each channel).

The Interrupt write the handshake flag over to a register and clear the interrupt, and uses xSemaphoreGiveFromISR and portYIELD_FROM_ISR to indicate the one of DSR_task to read the register and trigger xSemaphoreGive if a new packet is available, on the given channel. The packetHandler task, which have been waiting, will then take the semaphore read the packet and act on it.

My DSR_task have task priority 3 and my packetHandler tasks have task priority 5.

All semaphore so far have been binary semaphores, and down below are some of the config option that I think is relevant. If you need more pls say so.

#define configMAX_PRIORITIES                    5

#define configKERNEL_INTERRUPT_PRIORITY         1
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    4
#define configTIMER_TASK_PRIORITY               2

The Hardware I am running on are a Cortex-m4f with CMSIS, and per

NVIC_SetPriorityGrouping(0);

is there something I am forgetting or the very least missing out on?

hope that you can help me.

best regard
Bjoerk

Those interrupt priorities seem totally wrong for a Cortex M4 processor.

First note that Interrupt Priorities are very different than task priorities, and configMAX_PRIORITIES deals with task priorities, and typically, the Timer Task will be one of the highest priority tasks in the system.

If you have define configMAX_PRIORITIES to be 5, then you have available priorities 0, 1, 2, 3, and 4, so you can’t set you packetHandler to have priority 5.

If you processor has 4 bits of interrupt priority, then typically your configKERNAL_INTERRUPT_PRIORITY will be set to 15 (the largest value, and thus the lowest priority), and all interrupt need to have a priority assigned >= configMAX_SYSCALL_INTERRUPT_PRIORITY.

(Read the section of the documentation about Cortex M interrupt priorities)

You also want to define configASSERT to catch these sorts of errors, I suspect the configuration errors are getting FreeRTOS into a mess.

Hey again

firstly:

If you have define configMAX_PRIORITIES to be 5, then you have available priorities 0, 1, 2, 3, and 4, so you can’t set you packetHandler to have priority 5.

My bad it was ment to say configMAX_PRIORITIES 6.

You also want to define configASSERT to catch these sorts of errors

configASSERT is defined and working. I usually get stuck in prvTaskExitError at:

configASSERT( uxCriticalNesting == ~0UL );

I have tried to change the priority as you mentioned so they now says:

#define configKERNEL_INTERRUPT_PRIORITY         15 
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    4   
#define configTIMER_TASK_PRIORITY               5
#define configMAX_CO_ROUTINE_PRIORITIES         1

And also I am setting the interrupt priority to 4, same as configMAX_SYSCALL_INTERRUPT_PRIORITY which only landed me in a Usage_Fault with INVPC sat high. And when I change it to another number say like 3 or 5, the same thing happens. The Usage_Fault comes when portYIELD_FROM_ISR is reached.

Hope that you can help me.

First question, how many interrupt priority bits does your processor have? The numbers I gave assumed 4. Double check the processor documentation and see if it matches the #define

What is the stack traceback for the configASSERT(uxCriticalNesting == ~0UL), that implies (if I understand it right) that you are leaving a critical section that wasn’t entered.

First question, how many interrupt priority bits does your processor have?

In CMSIS the following is defined:

#define __NVIC_PRIO_BITS 4

So yes you where correct in you’re assumption.

Second, stack traceback

The back trace when asking the compiler for it, is this:

#0 UsageFault_InlineHandler () at …\Targets\NXHX90-JTAG\Source\handler.c:152
#1 0x00000510 in HardFault_Handler () at …\Targets\NXHX90-JTAG\Source\handler.c:178
#2
#3 HSC2_IRQHandler () at …\Targets\NXHX90-JTAG\Source\main.c:208
#4 0x00009b74 in OS_ReleaseMutex (pvMutex=0xe72bb23) at …\Components\cifXToolkit\OSAbstraction\OS_Custom.c:328
Backtrace stopped: previous frame inner to this frame (corrupt stack?)>

configASSERT(uxCriticalNesting == ~0UL) disappeared after I sat the interrupt priorities manually to 4. via:

NVIC_SetPriority(IRQ_34, 4);

I would expect this assert to be hit if you return from the function that implements a task. Is that what you are doing? If you want to exit a task you have to call vTaskDelete( NULL ); uxCriticalNesting is used to force and “assert always” - that is - it asserts every time you attempt to return from a function - uxCriticalNesting is just used for convenience as the variable exists, if volatile, and should never equal ~0.

These values should be shifted into the most significant bits. See https://www.freertos.org/RTOS-Cortex-M3-M4.html

hey again

So I have change the following as you ask:,

configKERNEL_INTERRUPT_PRIORITY                (15U << (8U - __NVIC_BITS))
configMAX_SYSCALL_INTERRUPT_PRIORITY           (4U  << (8U - __NVIC_BITS))

Sorry for being slow-witted on that one…
But I still get caught in prvTaskExitError assert:

configASSERT( uxCriticalNesting == ~0UL );

My back trace can be seen here:

#0  prvTaskExitError () at ..\..\Components\FreeRTOS\Sources\port.c:229
#1  0x00010762 in prvIsQueueEmpty (pxQueue=0x0 <__Vectors>) at ..\..\Components\FreeRTOS\Sources\queue.c:2306
#2  0x00000000 in ?? ()

I don’t have a function that implements a task, all functions are being called by my task’s, and all except 1 task run in a while loop. This one initialize some stuff that need RTOS resource, like wait/sleep function and semaphores. It uses xTaskDelete(NULL) when it is done.

Is it possible that the uxCriticalNesting gets corrupted at some point?

A couple of comments to get information that might help us,
You are clearly not using the ‘official’ FreeRTOS release, as there isn’t a file called Sources\Port.c, since in the Official release Port.c would be in a directory like Source/portable/compiler/processor/

There are also mentions of CMSIS classes in your report, which aren’t part of FreeRTOS.

FreeRTOS should only get to prvTaskExitError is some task returns from its task function, you say that can’t happen but that is what the evidence is saying is happening. You might check what the current task pointer (pxCurrentTCB) is pointing to, as that should be the task that is exiting. It may have a forever loop, but it might have a return statement inside it.

You are clearly not using the ‘official’ FreeRTOS release
kinda true, I have copy pasted from the ‘official’ release and only took what I needed, for the project. Like the port.c and portcmacro.h from GCC/ARM_CM4F and heap_3.c from MemMange. The rest have stayed the same.

CMSIS is mentioned and only used to get access to function used to enable and configure interrupts and finding the #define __NVIC_PRIO_BITS.
I am well aware that it is not a part of FreeRTOS, but CMSIS keeps appears in some of you material as something to be aware of so I thought it was important.

pxCurrentTCB, that narrowed it down, and I found the error. I found that this function was the problem, or rather the way I was using it was wrong.

xSemaphoreTake(BinarySemaphore, ticks);

Every time the time had run out, and the semaphore still was not available, it created the aforementioned error. I change ticks to portMAX_DELAY, after I defined the INCLUDE_vTaskSuspend and sat it to 1 in FreeRTOSConfig.h and that solved the problem.

I find it easier to just use a common repository for FreeRTOS in all my projects and either delete the pieces I will never use, or exclude them from the build system.

As it xSemaphoreTake(), you need to check the return value of all these sorts of functions, and only do what you would do when they succeed if they actually did succeed. One danger of just counting on portMAX_DELAY is that there are ways to end that timeout early, so you still want to check the error return, and with infinite delays, if something goes wrong it is harder to figure out what happened, while with reasonable timeout, you can get a report from the error path that something is wrong, and possibly attempt a recovery.

I think that is a distraction - although the assert is checking uxCriticalNesting it is only doing it to force the assert to be hit by checking it against a value it knows it won’t have. The error occurs BEFORE the assert as evidenced by the the task exit error function being called. Are you 100% sure you are not exiting the function that implements the task?

@rtel. As I have been speaking with @richard-damon about, it was not one of my function that created the error, but my misuse(or misunderstanding) of the freeRTOS function xSemaphoreTake. The problem have been solved. @richard-damon was kind enough to give some advice on how to debug and cleared some of my misunderstandings.