At wits end - going to unhandled-IRQ handler from vTaskSwitchContext for no apparent reason

Don’t get confused by FreeRTOS task priorities and hardware interrupt priorities. These are different things.
Great that you found the issue :+1:

Well, that wasn’t it. There was a loop problem, but the hard fault continues. I managed to trace it down to a call to xQueueSendToBack

BaseType_t FPGA_Handler_task::send8Data_to_user(uint8_t *data_p, uint8_t count)
{
  BaseType_t ErrorVal = pdPASS;
  char dataString[16];
  
  //get semaphore
  ErrorVal = xSemaphoreTake(GlobalFlags.UserInterface_TxQueue_Semaphore_Handle, 100);
  if (ErrorVal == pdPASS) {
  
    for (int i = 0; i < count; i++) {
      sprintf(dataString, "%#.2x ", data_p[i]);
    
      char *cp = dataString;
      for (size_t j = 0; j < strlen(dataString); j++) { //do not include terminal NULL, do not trigger addition of CRLF and CURSOR
        ErrorVal = xQueueSendToBack(GlobalFlags.UserInterface_TxQueue_Handle, (const void *)(cp+j), pdMS_TO_TICKS(100));
        if (ErrorVal != pdPASS) {
        
          //release semaphore
          xSemaphoreGive(GlobalFlags.UserInterface_TxQueue_Semaphore_Handle);
        
          return ErrorVal;
        }
      } //end for
    } //end for
  
    char lineEnd = 0;
    ErrorVal = xQueueSendToBack(GlobalFlags.UserInterface_TxQueue_Handle, (const void *)&lineEnd, pdMS_TO_TICKS(100));  <=====
  
    //release semaphore
    xSemaphoreGive(GlobalFlags.UserInterface_TxQueue_Semaphore_Handle);
  } //end if
  
  //done
  return ErrorVal;
}

If I read the registers right, somewhere in there it’s trying to execute a non-Thumb instruction.

BTW sprintf already returns the number of chars converted. I’d use it instead of calling extra, lengthy strlen to get the same number.
Edit: I wouldn’t call strlen in a loop. Better determine the const loop limit before entering a loop even though the compiler might or might not optimize/move e.g. the strlen call out of the loop.
However, the code seems ok so far and this really strange issue still occurs … :thinking:
How is the queue created ? As a queue of N char items ? And I guess the queue is never destroyed elsewhere, right ? dataString[16] should be large enough, too.
This brings me back to a possible stack overflow… can you retry using a (much) larger stack ?

Thanks. I create the queue staticly at the start of the program

//User Interface
// outgoing - 1 character at a time
UserInterface_TxQueue_Handle = xQueueCreateStatic((UBaseType_t)USERINTERFACE_MSG_LEN,
(UBaseType_t)sizeof(uint8_t),
UserInterface_TxQueue_buffer,
&UserInterface_TxQueue_data);
if (UserInterface_TxQueue_Handle == NULL) {
Error.Info.ErrorCode = FailCodes::FC_GlobalFlags;
Error.Info.ErrorTrace = HANDLE_CREATION_ERROR;
Error.Info.ErrorData = LINE; //location
return;
}
#ifdef DEBUG
vQueueAddToRegistry(UserInterface_TxQueue_Handle, “UI_RX”);
#endif
where
QueueHandle_t UserInterface_TxQueue_Handle; ///<Outgoing to user
and
uint8_t UserInterface_TxQueue_buffer[USERINTERFACE_MSG_LEN*sizeof(uint8_t)];

Thing is, I’ve been using this for a long time. It’s the primary user interface and everything gets dumped to it. In the user-interface task there’s a loop that takes one character at a time and feeds it to the USART. Never had a problem with it.
I’ll try increasing the stack.

and
#define USERINTERFACE_MSG_LEN 64
so there’s lots of room in the queue.

I agree, the queue and the related code is most likely not the problem.

Hmm. Doubling the stack size seems to have worked! Thanks. I have the vApplicationStackOverflowHook routine in there and that wasn’t triggered. I wonder why?

we discussed this before:

Right. Oh well, live and learn. Thanks.