Hello all,
I have a simple scenario of using queues in which ISR of serial port queues messages and the one and only task keeps checking to dequeue the message.
The App is just this single task
The problem is that if I check for the data in queue inside the task loop directly as follows :
Things work as expected , and I get the messages when they r sent.
But if I put the checking section inside a function and call this function as follows :
Hardfault exception occurs inside xQueueReceive !
The problem may seem to be stack limitation , but I have increased the stack size significantly and I still get the same exception !!!
Any Ideas ?
Thank u
What is your ISR code to send the messages? What priority does the isr run on, and what is your configured max syscall priority? How and where do you create the queue?
I use static configuration and I provide all the related memories as global variables.
The fact that it runs of if I just check for messages directly inside the while loop and fails if I call a simple function that does the checking seems a bit of Black Magic , unless I miss something !
Thanks @hs2 .
I do not think its a stack issue , I increased stack size from 2k to 10k (real usage is less than 1K)
Yes I have the config assert enabled and here is the printing of the debug info :
[Hard fault handler]
R0 = 6020180
R1 = 0
R2 = 0
R3 = 0
R12 = 1
LR = 8006035
PC = 200113a4
PSR = 0
the LR address comes from inside a uart function (simply because of the log printing) but if I comment the statement printf(âmsg rcvd \nâ);
the LR is stuck inside xQueueReceive .
So Iâm sure its not about the uart or xQueueReceive, but it has sth to do with the stack !
but which stack and how ?
I also increased the main stack (the one used by ISR through the linker script to 4 k)
But the issue is still there !
Problem is that this use case is very simple (I disabled two other tasks for the sake of narrowing down the root cause , and still no luck)
Note that your ISR keeps its message on its stack, so you better make sure that no references into that stack are attempted to be looked at by the application, meaning you need a full copy in the message buffer.
In your setup, your ISR always executes in the stack of your task (or the idle task, depending on the waiting behavior of the task), so if the task ever attempts to look at local ISR data that was vaild as the ISR executed but isnât necessarily valid anymore when the ISR has terminated, you get undefined behavior.
The Problem you outline very strongly hints at something along those lines.
@RAc
I believe u r right , but nothing accessed while local to the ISR.
In the ISR I just push the message inside the queue.
All other variables (Queue handle , queue stack and queue instance) are all static global variables.
Iâm not even using any heap.
I beleive the ISR uses the main stack thats defined in the linker script
I still suspect that the size of msg_t is NOT MSG_SIZE (if MSG_SIZE is larger than the size of msg_t, then copying the message will overtrample your stack), but since you donât disclose these, itâs up to everybodyâs guessâŚ
Youâre right, Cortex-M ports (re-)use main stack (MSP) for ISRs and process stack (PSP) for tasks.
Also right, 4k main and 10k resp. > 2k task stack should be far more than enough.
Why not just using sizeof( msg_t ) when creating the queue ?
@RAc@hs2
You both were right !
The size of the message was set to a different structure that had similar name to the real structure but way larger size !!!
Thank you very much guys for pointing out at it.
Thatâs now solved !