One task is not running or crashes after a while in PIC32MX795F512L

I have the FreeRTOS running in PIC32MX795F512L , we are using 6 tasks.

  1. CAN Communication
  2. Memory writing to save device parameters
  3. Digital Out
  4. Digital In
  5. Blinking LED
  6. Task Watchdog

After a while CAN communication task stops, I am not sure about the problem, I will appreciate very much if someone can provide some debug and troubleshoot advices.

Thanks!!

Did you define configASSERT and also enable stack overflow checking for development/debugging ?
The FreeRTOS FAQ is also very helpful.

From your description I presume the other tasks continue executing. Is that correct? If so, after checking Hartmut’s suggestion (ensuring you don’t have a stack overflow, don’t hit an assert(), etc.), please provide more information on the structure of the CAN communication task. For example, is CAN controlled by interrupts? How are those interrupts communicating with the CAN Communication task?

Thank you for your reply, I think we are not using Assert function. I am not sure about the stack size. I will try to check the stack following your recommendations.

Yes can communication is implemented with interrupts.

void __ISR(_CAN_1_VECTOR, ipl4) vCANInterruptWrapper(void); //For CAN use only ipl4!!!
//void __attribute__((vector(46), interrupt(ipl4), nomips16)) vCANInterruptWrapper(void);

void vCANInterruptHandler ( void )
{
    //interrup handler for CAN1
    if((CANGetModuleEvent(CAN1) & CAN_RX_EVENT) != 0)
    {
        if(CANGetPendingEventCode(CAN1) == CAN_CHANNEL1_EVENT)
        {
            CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE);
//            isCAN1MsgReceived = TRUE;
            portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
            xSemaphoreGiveFromISR(xBinarySemaphore,xHigherPriorityTaskWoken);
            portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
        }
    }
    INTClearFlag(INT_CAN1);
}
void CAN1RxMsgProcess(void)
{

    xSemaphoreTake( xBinarySemaphore, 0 );
    canID_master=0x02;
    //canID_master= ReadShortEEPROM(EE_CAN_ID_MASTER);

    CANRxMessageBuffer * message;

    while(1){
        CanRXProcess_timeout = 1;
        //vParTestToggleLEDA( 0 );
        if(xSemaphoreTake(xBinarySemaphore,portMAX_DELAY2))
        {
            message = (CANRxMessageBuffer *)CANGetRxMessage(CAN1,CAN_CHANNEL1);
            
            //vParTestToggleLED3( 0 );
            CANUpdateChannel(CAN1, CAN_CHANNEL1);
            CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);

            //send confirm response for set data commands
            CANMessageProcessing(canID_master, message);
        }else{
           CANResetChannel(CAN1,CAN_CHANNEL1);
        }
    }
}

extract from main()

     /* --- APPLICATION TASKS CAN BE CREATED HERE --- */
     xBinarySemaphore = xSemaphoreCreateBinary();
     xBinarySemaphoreIO = xSemaphoreCreateBinary();     // Not used
     xBinarySemaphoreADC = xSemaphoreCreateBinary();

   if( xBinarySemaphore != NULL )
    {
        xTaskCreate( CAN1RxMsgProcess,  "CANHandler", 1024, NULL, 4, &xTaskRX_CANHandler );      //id:1
        xTaskCreate( EEPROMGetValuesTask,  "EEPROMRead", 240, NULL, 5, &xTask_EEPROM );         //id:2   
        xTaskCreate( DigitalOutputsTask,  "DigitalOutputs", 240, NULL, 2, &xTaskDigOutHandler); //id:3
        xTaskCreate( DigitalInputsTask,  "DigitalInputs", 240, NULL, 2, &xTaskDigInHandler );   //id:4
        xTaskCreate( StatusValuesTask,  "StatusHandler", 240, NULL, 2, &xTaskStatValHandler );  //id:5
        xTaskCreate( WatchdogProcess,  "Watchdog", 240, NULL, 3, NULL );
        /* Start the scheduler so the created tasks start executing.  */
        vTaskStartScheduler();
    }
  while(1);

This code was developed by another programmer, I am not sure about the xSemaphore use for CAN communication, please advise. Thanks

A couple of suggestions to make the code more robust:

  1. If you want to use a semaphore, then use a counting semaphore. Currently you are using a binary semaphore. Depending on the behaviour of the hardware, and the rate at which data comes in, you may have two interrupts that occur before the task has processed the first - leaving the second unprocessed - which could (again not familiar with the exact workings of the PIC32 CAN) leave the CAN peripheral waiting for you to do something while you are blocked on the semaphore take again (for how long depends on portMAX_DELAY2).

  2. Better still, use a direct to task notification instead of a semaphore. Again, use it as a counting semaphore. Task notifications are faster that semaphores.

  3. Check for error conditions in the CAN peripheral in addition to just whether data is available - that will give you the opportunity to clear errors.

To help with debugging, when the condition arises, break on the debugger and see what the CAN task is doing. Is it in an assert()? Is it blocking on the semaphore - and if so - when it unblocks due to a timeout why is it not resetting the CAN as intended? What is the status of the CAN peripheral - are any errors set? What is the status of the CAN interrupts - are they still enabled?

Additionally you may consider obtaining the CAN frame from within the ISR and only processing the received frame from the task (rather than receiving and processing the frame in the task).

That is a good idea, I will change that and remove the semaphore and test.

Thank you.

We removed the use of semaphores in our code and pick the data in the ISR, so far our tests are providing good results.

Thank you very much for your support.