Task notification timeout problem

Hi
I have a really strange behaviour using the task notifications. I’m using the FreeRTOS LTS version 2020.12.03 on a STM32 Cortex M4 processor.
How my program structure looks like:

Master
Not part of the system, sends a CAN message with the COMMAND_NUMBER

Slave Command Task
Receives the command and then puts a peripheral access request to a queue

switch(COMMAND_NUMBER){
case: COMMAND1:
sendPeripheralRequest(COMMAND1);
break;

case: COMMAND2:
sendPeripheralRequest(COMMAND2);
break;

default:
//do something
}

Then the peripheral request function:

ErrorCodeCAN sendPeripheralRequest(PeripheralAccessRequest* peripheral_access_req,
                                   uint32_t* return_value) {

  //Clear all existing notifications for this task (NULL takes the current task)
  xTaskNotifyStateClear(NULL);
  ulTaskNotifyValueClear(NULL, 0xFFFFFFFF);

//Put a request on a queue
  if (addPeripheralAccessWithAnswer(peripheral_access_req,
                                    &peripheral_access_answer,
                                    &req_id) != pdTRUE) {
    //Request was not placed, don't wait for an answer
    return ERR_QueueFull;
  }

  //Wait for the notification
  //If no notification arrives
  if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(MAX_ACC_WAIT_TIME_MS)) == 0) {
    return ERR_ReqTimeout;
  }
  //Check if sent and received id matches
  //If not wait until the correct arrives or there is no notification anymore
  while (req_id != peripheral_access_answer.requestId) {
    //Wait for the next notification
    if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(MAX_ACC_WAIT_TIME_MS)) == 0) {
      return ERR_ReqMismatch;
    }
  }

Peripheral Access Task
Reads from the queue, performs the access and sends back an notification when done.

void peripheralAccessTask(void* argument) {
  UNUSED(argument);

  ErrorCodeCAN status = ERR_NoError;

  PeripheralAccess peripheralAccess = { 0 };

  while (1) {

    if (xQueueReceive(peripheralAccessQueue, &peripheralAccess, portMAX_DELAY) == pdPASS) {

    //Do something
    //Notify the calling task
    //Always returning pdPASS
    xTaskNotifyGive(peripheralAccess.callingTask);
    }
  }
}

This works perfectly fine as long as the peripheral access task is faster and sends the notification when the slave command task is still waiting. But if it takes to long to answer, the slave command task stops waiting and runs into a timeout (what is what it should do). This means that the task receives the notfication from the peripheral access task when it is not waiting anymore. And there the strange behavior starts.

The next time I send absolutly the same command via CAN, it jumps to the default case in the switch statement. I can put a breakpoint there, the debugger says that the COMMAND_NUMBER is COMMAND1, then make the next step and it jumps to the default case. So it seems that the code execution or the memory has a problem.

The third identical CAN message (triggering a timeout) works again, the forth not and so on. Does anybody has an idea what the problem could be?

Thanks.

Do you need these lines? Won’t the loop matching the IDs take care?

It might just be the debugger behaving incorrectly. Can you also put a breakpoint in sendPeripheralRequest? Or you can try stepping through the assembly.

Hi
Thanks for the answer and sorry for the delay.

It’s not a debugger problem. In the default case statement, there is a warning log. That’s how I discovered that something is going wrong.

But I found the problem, was not FreeRTOS related. Was a memory corruption, a variable that was not available anymore when a timeout occurs. Bad programming :sweat_smile: