Hard fault exception

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 :

static void task (void *pvParameters)
{
  msg_t msg; 
  BaseType_t enu_ret; 
  while(1)
  {
      /*Check if Data Report Received*/
      enu_ret = xQueueReceive(ghdl_data_queue, &msg, 0);
      if(enu_ret == pdPASS)
      {
         printf("msg rcvd \n");
       }
    }
} 

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 :

static check_msg (void)
{
  msg_t msg; 
  BaseType_t enu_ret; 
      /*Check if Data Report Received*/
      enu_ret = xQueueReceive(ghdl_data_queue, &msg, 0);
      if(enu_ret == pdPASS)
      {
         printf("msg rcvd \n");
       }
}
static void task (void *pvParameters)
{
  while(1)
  {
     check_msg ();
  }
} 

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?

This is the message ISR :

static void  ISR (void)
{
msg_t msg; 
  BaseType_t enu_ret; 
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  read_msg (&msg);
  enu_ret = xQueueSendFromISR(ghdl_data_queue, &msg, &xHigherPriorityTaskWoken);
  if(enu_ret == pdPASS)
  {
    portYIELD_FROM_ISR (xHigherPriorityTaskWoken);
  }
}

These are the priority configurations (Cortex M7) :

#define configPRIO_BITS       		4   
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			0xf
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	        5
#define configKERNEL_INTERRUPT_PRIORIT (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
#define configMAX_API_CALL_INTERRUPT_PRIORITY         
 configMAX_SYSCALL_INTERRUPT_PRIORITY

I create the queue in system initialization as follows :

       ghdl_data_queue = xQueueCreateStatic(MAX_NUM_MSG , MSG_SIZE, (uint8_t*)gastr_msgs, &gstr_data_queue);
       configASSERT(ghdl_data_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 !

Is that your problem?

Not really !
again , here is the problem in simpler pseudo code :

void task () 
{
while(1)
{
  Some code ; 
}
}

Works perfectly !
But

void function (void)
{
Some code ; 
}
void task () 
{
while(1)
{
  function () ; 
}
}

Hardfault !

Sorry for being unclear.

xQueueSendFromISR(ghdl_data_queue, msg, &xHigherPriorityTaskWoken);

should really read

xQueueSendFromISR(ghdl_data_queue, &msg, &xHigherPriorityTaskWoken);

1 Like

I edited that already.
I was trying to simplify and I made the mistake on the way :smile:
But in the code its a pointer , so this should be ok

Did you define configASSERT and enabled stack overflow checking (for development/debugging) ?
Did you have a debugger connected ?

BTW:
Please quote code blocks using 3 tildas ‘~’ or 3 backticks ‘'’ for better readabilty.
Thanks !

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)

What is your definition of msg_t, and MSG_SIZE?

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.

1 Like

@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…

1 Like

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 ?

1 Like

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

1 Like

yep, my mistake, sorry.