we’re running freeRTOS 8.2.0 on a NXP LPX4078 successfully since many years. Due to new similar product developments we needed to change parts of the source code.
Unfortunately now in special circumstances it seems that freeRTOS hangs and it’s not easy to go some steps back since there were a lot of changes over many months.
But actually it doesn’t stop, e.g. idle task is running but another one definitively stopped.
With a lot of debug variables I found out that after calling xQueueSend(consoleQueue, (void * ) &newMessage, portMAX_DELAY);
it doesn’t continue.
It calls xQueueGenericSend() and inside that function it doesn’t continue after portYIELD_WITHIN_API(); exactly at this position:
We set configUSE_PREEMPTION to 1 if important.
Does it mean that portYIELD_WITHIN_API()" proceeds a context switch to another task and if that one finished it comes back and continues with xQueueGenericSend?
How can I find out to which task the context switches? Where is the position it comes back?
What infos do you need to help me in this issue that xQueueGenericSend() doesn’t finish?
This code point is normally hit when the queue is full and a non-zero timeout is specified.
port. So, the queue is full, and the task must block until either the timeout expires or the queue has elements popped off, creating space.
portYIELD is a macro which forces a context switch. With preemption disabled, this is the only way to defer execution to another task. But, with preemption enabled, portYIELD is not required, and a forced context switch will run the new task for the remainder of the current tick. portYIELD_WITHIN_API is a specialization of portYIELD, although it is usually defined as an alias.
Execution of a task resumes at the instruction after portYIELD_WITHIN_API, if it is ever put on the ready list by the scheduler.
The simplest possibility is that none of the consumers of the queue call xQueueReceive from another context. These are likely blocked tasks or masked ISRs.
Another way for this behavior to occur is that xTaskResumeAll leaves the scheduler suspended while returning pdFALSE, and portYIELD switches contexts to the idle task. This is a bug almost certainly caused by changes to the kernel.
The easiest way to root cause this is to find where all tasks are stuck executing before they are blocked. If it is possible, compile the kernel and code with the POSIX port on a Linux box in order to debug the problem under gdb. Examining the call stacks and states of each of the task threads should make it easy to understand why all of them are blocked.
Otherwise, stepping through with a FreeRTOS-aware debugger on hardware would also work. I’m not familiar with what tools exist for this board.
sorry for the delayed answer and thanks a lot for your hints.
Indeed simply the queue “consoleQueue” with 20 elements was full and since timeout was specified with “portMAX_DELAY” it would wait for maybe 42 days
My colleague set a task in comment which normally processes the queue with xQueueReceive. Therefore after some calls of xQueueSend() the queue is full and it would wait until timeout at the mentioned position. Unfortunately I currently cannot ask my colleague for reasons.
When I re-activate the task with xQueueReceive(consoleQueue…) it works like it should.
Now I want to return to the proper code state before I started with a lot of auxiliary variables to examine this issue.
It’s still not a guarantee that all works like it should but it seems I’m a big step further.