This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS570LS3137: CAN ISR issue

Part Number: TMS570LS3137


Hello,

I have troubles trying to make work the CAN interruption implementng freeRTOS. It only triggers the ISR only once and it never is executed again.

I connected CAN2 and CAN3 between them to check the communication.
I attach the complete code below:

/** @file sys_main.c 
*   @brief Application main file
*   @date 07-July-2017
*   @version 04.07.00
*
*   This file contains an empty main function,
*   which can be used for the application.
*/

/* 
* Copyright (C) 2009-2016 Texas Instruments Incorporated - www.ti.com 
* 
* 
*  Redistribution and use in source and binary forms, with or without 
*  modification, are permitted provided that the following conditions 
*  are met:
*
*    Redistributions of source code must retain the above copyright 
*    notice, this list of conditions and the following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the 
*    documentation and/or other materials provided with the   
*    distribution.
*
*    Neither the name of Texas Instruments Incorporated nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/


/* USER CODE BEGIN (0) */

#define EXTWD_PRIORITY          ( tskIDLE_PRIORITY + 3)
#define SCI_PRIORITY            ( tskIDLE_PRIORITY + 2)
#define MAIN_PRIORITY           ( tskIDLE_PRIORITY + 2)
#define CAN_PRIORITY            ( tskIDLE_PRIORITY + 2)

/* USER CODE END */

/* Include Files */

#include "sys_common.h"

/* USER CODE BEGIN (1) */
#include "system.h"
#include "het.h"
#include "gio.h"
#include "reg_pcr.h"
#include "sys_pcr.h"
#include "sys_pmm.h"
#include "reg_vim.h"
#include "sci.h"
#include "string.h"
#include "reg_can.h"
#include "bl_can.h"
#include "can.h"
#include "sys_common.h"
#include "sys_core.h"

/* Include FreeRTOS scheduler files */
#include "FreeRTOS.h"
#include "os_task.h"
#include "os_queue.h"

//Command List:
#include "interfacesCommandDef.h"
/* USER CODE END */

/** @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.
*/

/* USER CODE BEGIN (2) */
//Settings:
//Globals:

//Task Handlers:
xTaskHandle xTask1Handle1;          //vExtWD task handle
xTaskHandle xTask2Handle1;          //vUART task handle
xTaskHandle xTask3Handle1;          //vMain task handle
xTaskHandle xTask4Handle1;          //vCAN task handle

//Queue handlers:
QueueHandle_t xQueue1;              //Queue1 is used to send data from vUART to vMain task.
QueueHandle_t xQueue2;              //Queue2 is used to send data from sciNotification to vUART task.
QueueHandle_t xQueue3;              //Queue3 is used to send data from canMessageNotification to vCAN task.

//Set of structures to be sent through queues:
struct qMessage
{
    uint8_t     len, sciRxMessage, rxData;
    uint8_t     buffer[128];
}xMessage;

struct qMessage2
{
    uint8_t     len, sciRxMessage, rxData;
    uint8_t     buffer[128];
}xMessage2;

struct qMessage3
{
    uint8_t     len, sciRxMessage, rxData;
    uint8_t     buffer[128];
}xMessage3;

//Functions:
void sysInit(void);
void osInit(void);
void sciDisplayData(sciBASE_t *, uint8 *,uint32);
bool cDecoder(struct qMessage *);
uint8_t delayms(uint16);

//Tasks:
void vExtWD(void *pvParameters);        //External watchdog pulse generation
void vCAN(void *pvParameters);          //CAN communication task
void vUART(void *pvParameters);         //Debug UART communication task
void vMain(void *pvParameters);         //Main task
/* USER CODE END */

int main(void)
{
/* USER CODE BEGIN (3) */
    sysInit();  //System initialization.
    osInit();   //Operative System initialization.

    /* Run forever */
    while(1);

/* USER CODE END */

    return 0;
}


/* USER CODE BEGIN (4) */

/*************************************
 * Functions, Tasks and ISR routines *
 *************************************/

/*********************************
 * CAN interrupt service routine *
 *********************************/
void canMessageNotification(canBASE_t *node, uint32 messageBox)
{
    //uint8_t rxKey;
    uint8_t *Buffer;
    uint16_t teleBuffer[8];
    Buffer = ((uint8_t *)teleBuffer);
    uint32_t ulBytes;
    sciSend(scilinREG, 18, "CAN ISR entered.\r\n");
    //struct qMessage3 *rxCanMessage;
    //rxCanMessage = &xMessage3;

    //We have not woken a task at the start of the ISR.
    //BaseType_t canHigherPriorityTaskWoken = pdFALSE;

    if(node == canREG2)
    {
        PacketRead(canREG2, Buffer, &ulBytes);
        delayms(100);
        PacketRead(canREG2, Buffer, &ulBytes);
    }
    else if(node == canREG3)
    {
        PacketRead(canREG3, Buffer, &ulBytes);
        delayms(100);
        PacketRead(canREG3, Buffer, &ulBytes);
    }

    //if(xQueueIsQueueEmptyFromISR(xQueue3) == pdTRUE)
    //{
        //sciDisplayData(scilinREG, (uint8 *) fillQ, 1);                          //Only for printing on the terminal.
    //    if(xQueueSendToBackFromISR(xQueue3, &rxCanMessage, &canHigherPriorityTaskWoken) == errQUEUE_FULL)
    //    {
            //xQueueReset(xQueue2);
    //        sciSend(scilinREG, 68, "\r\nError: Data did not send from CAN interrupt service routine [TBD].");
    //    }
    //}
}


/*********************************
 * SCI interrupt service routine *
 *********************************/
void sciNotification(sciBASE_t *sci, unsigned flags)
{
    uint8_t rxKey;
    struct qMessage2 *rxUartMessage;
    rxUartMessage = &xMessage2;
    BaseType_t sciYieldRequired;

    //We have not woken a task at the start of the ISR.
    BaseType_t sciHigherPriorityTaskWoken = pdFALSE;//, fillQ;

    sciYieldRequired = xTaskResumeFromISR(xTask2Handle1);          //This ISR wakes up the vUART task each time a character is received.

    sciReceive(scilinREG, 1, (unsigned char *)&rxKey);
    rxUartMessage->rxData = rxKey;

    //fillQ = uxQueueSpacesAvailable(xQueue2);    //xQueueIsQueueFullFromISR

    if(xQueueIsQueueEmptyFromISR(xQueue2) == pdTRUE)
    {
        //sciDisplayData(scilinREG, (uint8 *) fillQ, 1);                          //Only for printing on the terminal.
        if(xQueueSendToBackFromISR(xQueue2, &rxUartMessage, &sciHigherPriorityTaskWoken) == errQUEUE_FULL)
        {
            //xQueueReset(xQueue2);
            sciSend(scilinREG, 73, "\r\nError: Data did not send from UART SCI interrupt service routine [TBD].");
        }
    }

    portYIELD_FROM_ISR(sciYieldRequired);
}

/********************************
 * Delay in ms.                 *
 * t: time in ms to be delayed. *
 * ******************************/
uint8_t delayms(uint16 t)
{
    uint16 h, i, j;
    for(h = 0; h < t; h++){                 //ts = 1000 to set 1 second.
        for(i = 0; i<1350; i++)             //Time between samples 1 ms.
            for(j = 0; j< 8; j++);}
    return 1;
}

/********************
 * sysInit function *
 ********************/
void sysInit()
{
    uint8_t generic;
    sciInit();                                      //SCI initialization.
    canInit();                                      //CAN initialization.

    //Enable interrupts:
    _enable_interrupt_();                           //General interrupt flag.
    //Enable SCI interrupt:
    sciEnableNotification(scilinREG,SCI_RX_INT);    //Enable SCI interrupt by Rx.
    //Enable CAN interrupt:
    canEnableErrorNotification(canREG2);            //Enable canREG2 interrupt.
    canEnableErrorNotification(canREG3);            //Enable canREG3 interrupt.

    sciReceive(scilinREG,1, (unsigned char *)&generic);

    sciSend(scilinREG, 37, (unsigned char *)"Initializing system. Please wait...\r\n");
    gioInit();                                      //GIO module initialization.
    gioSetDirection(hetPORT1, 1 << 15);             //Enable N2HET1[15] as output. This is the output signal to the external watch-dog.

    sciSend(scilinREG, 27, (unsigned char *)"\t************************\r\n");
    sciSend(scilinREG, 27, (unsigned char *)"\tLabOSat-02 [OBC] OS V1.0\r\n");
    sciSend(scilinREG, 27, (unsigned char *)"\t************************\r\n");
    sciSend(scilinREG, 1, (unsigned char *)"\n");
    sciSend(scilinREG, 14, (unsigned char *)"Developers: \r\n");
    sciSend(scilinREG, 30, (unsigned char *)"\t Gagliardi Leandro Luciano \r\n");
    sciSend(scilinREG, 22, (unsigned char *)"\t Di Nardo Federico \r\n");
    sciSend(scilinREG, 1, (unsigned char *)"\n");
}

/********************
 * osInit function  *
 ********************/
void osInit()
{
    //Queues Creation:
    xQueue1 = xQueueCreate(20, sizeof(struct xMessage *));                   //Queue used between vUART task and vMain task.
    xQueue2 = xQueueCreate(200, sizeof(struct xMessage *));                  //Queue used between sciNotification ISR and vUART task.
    xQueue3 = xQueueCreate(200, sizeof(struct xMessage3 *));                 //Queue used between canMessageNotification ISR and vCAN task.

    //if( xQueue1 == NULL || xQueue2 == NULL || xQueue3 == NULL){sciSend(scilinREG, 58, (unsigned char *)"\r\nError: Queue was not created and must not be used [TBD].");}

    if(xQueue1 == NULL){sciSend(scilinREG, 59, (unsigned char *)"\r\nError: Queue1 was not created and must not be used [TBD].");}
    if(xQueue2 == NULL){sciSend(scilinREG, 59, (unsigned char *)"\r\nError: Queue2 was not created and must not be used [TBD].");}
    if(xQueue3 == NULL){sciSend(scilinREG, 59, (unsigned char *)"\r\nError: Queue3 was not created and must not be used [TBD].");}

    //Tasks Creation:
    if (xTaskCreate(vExtWD,"vExtWD", configMINIMAL_STACK_SIZE, NULL, EXTWD_PRIORITY, &xTask1Handle1) != pdTRUE){while(1);}  //Task could not be created
    if (xTaskCreate(vUART,"vUART", configMINIMAL_STACK_SIZE, NULL, SCI_PRIORITY, &xTask2Handle1) != pdTRUE){while(1);}      //Task could not be created
    if (xTaskCreate(vMain,"vMain", configMINIMAL_STACK_SIZE, NULL, MAIN_PRIORITY, &xTask3Handle1) != pdTRUE){while(1);}     //Task could not be created
    if (xTaskCreate(vCAN,"vCAN", configMINIMAL_STACK_SIZE, NULL, CAN_PRIORITY, &xTask4Handle1) != pdTRUE){while(1);}     //Task could not be created
    //Start Scheduler:
    vTaskStartScheduler();
}


/***************************
 * sciDisplayData function *
 ***************************/
void sciDisplayData(sciBASE_t *sci, uint8 *text,uint32 length)
{
    uint8 txt = 0;
    uint8 txt1 = 0;

#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
text = text + (length -1);
#endif

    while(length--)
    {
#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
        txt = *text--;
#else
        txt = *text++;
#endif

        txt1 = txt;

        txt  &= ~(0xF0);
        txt1 &= ~(0x0F);
        txt1  =txt1>>4;

        if(txt<=0x9)
        {
            txt +=0x30;
        }
        else if(txt > 0x9 && txt <= 0xF)
        {
            txt +=0x37;
        }
        else
        {
            txt = 0x30;
        }

        if(txt1 <= 0x9)
        {
            txt1 +=0x30;
        }
        else if((txt1 > 0x9) && (txt1 <= 0xF))
        {
            txt1 +=0x37;
        }
        else
        {
            txt1 = 0x30;
        }

        while ((scilinREG->FLR & 0x4) == 4); /* wait until busy */
        sciSendByte(scilinREG,txt1);      /* send out text   */
        while ((scilinREG->FLR & 0x4) == 4); /* wait until busy */
        sciSendByte(scilinREG,txt);      /* send out text   */
    };
}

/********************************************************
 * This task avoids external watch-dog reset            *
 * It considers the following watch-dog configuration:  *
 * SET0 = 0;                                            *
 * SET1 = 0;                                            *
 * twdu(min) = 77.455 s * 0.905 = 70.09 s               *
 * twdu(typ) = 77.4 * Ccwd + 0.055 = 77.455 s           *
 * twdu(max) = 1.095 * 77.455 s = 85 s                  *
 * twdl(min) = 70096 s * 0.125 = 8.762 s                *
 * twdl(typ) = 77455 s * 0.125 = 9.682 s                *
 * twdl(max) = 70096 s * 0.125 = 10.602 s               *
 *             10.602 s < tpulse < 70.09 s              *
 ********************************************************/
void vExtWD(void *pvParameters)     //Watchdog send a pulse each 77 seconds.
{
    uint8_t i, j;
    TickType_t xLastWakeTime;
    const TickType_t xTimeIncrement = 30000; //Each 30 seconds the MCU generates a pulse that avoids the system reset.
    //Initialise the xLastWakeTime variable with the current time.
    xLastWakeTime = xTaskGetTickCount();

    //Meter un sciSend para ver si esta tarea se está ejecutando.

    for(;;)
    {
        sciSend(scilinREG, 11, (unsigned char *)" vExtWD\r\n> ");       //A signal to know if the task is executed.
        vTaskDelayUntil( &xLastWakeTime, xTimeIncrement);
        //vTaskDelay(xTimeIncrement);
        gioSetBit(hetPORT1, 15, 1);  //0x00100000
        for(i = 0; i<10; i++){for(j = 0; j<100; j++){}} // It defines the pulse width (100us approximately)
        gioSetBit(hetPORT1, 15, 0);  //0x00000000
    }
}


/********************************************************
 * CAN Communication interface task                     *
 * Through this interface the user can send commands    *
 * and execute experiments on the payloads.             *
 ********************************************************/
void vCAN(void *pvParameters)
{
    sciSend(scilinREG, 23, (unsigned char *)"CAN message received.\r\n");
    vTaskSuspend(NULL);                                             //The task is suspended up to the CAN interrupt wakes it up.
}


/********************************************************
 * Debug UART Communication interface task              *
 * Through this interface the user can send commands    *
 * and execute experiments on the payloads.             *
 ********************************************************/
void vUART(void *pvParameters)     //Debug UART communication task
{
    //Basic variables:
    uint8_t com_char = 0, i = 0, message[8] = {0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E};
    uint8_t *uBuffer;
    uint8_t UART_Buffer[128];
    uBuffer = ((uint8_t *)UART_Buffer);
    uint32_t msgId = (0 << 30 | 1 << 29 | 0x06);            //CAN test ID

    //qMessage Structure creation to send data through a queue
    struct qMessage *uartMessage;
    uartMessage = &xMessage;

    //UART_Buffer initialization:
    for(i = 0; i < 128; i++)
        UART_Buffer[i] = 0;

    //Delay of 50 ms:
    const TickType_t xUART_delay = 50;
    vTaskDelay(xUART_delay);

    sciSend(scilinREG, 34, (unsigned char *)"Debug UART communication started\r\n");        //A signal to know if the task is executed.
    sciSend(scilinREG, 17, (unsigned char *)"< Press any key >");                           //Press any key to start.

    for(;;)
    {
        //UART com
        if(xQueue2 != NULL)
        {
            if(xQueueReceive(xQueue2, &uartMessage, (TickType_t) 10) == pdPASS)
            {
                //CAN Test frame
                PacketWrite(canREG2, CAN_ALIVE, message, 8, 2);                    //Test frame sent through messageBox1. CAN_ALIVE has an ID of 0x06 and null payload.

                *uBuffer = uartMessage->rxData;
                sciSend(scilinREG, 1, uBuffer);                                      //Print a keyboard symbol

                if(*uBuffer == 0x0D && com_char < 128)                                                                //If we press enter...
                {
                    sciSend(scilinREG, 4, (unsigned char *)"\r\n> ");               //New command line
                    uBuffer++;
                    com_char++;
                    uBuffer = uBuffer - com_char;                                                   //Return to the first buffer position

                    uartMessage->len = com_char;                                                    //Number of characters
                    for(i = 0; i < com_char; i++)                                                   //Data stored in the structure
                        uartMessage->buffer[i] = UART_Buffer[i];

                    if(5 < uxQueueSpacesAvailable(xQueue1))
                    {
                        if(xQueueSendToBack(xQueue1, (void *) &uartMessage, (TickType_t) 10) == errQUEUE_FULL)
                        {
                            sciSend(scilinREG, 49, "\r\nError: Data did not send from vUART task [TBD].");
                        }
                    }
                    else
                    {
                        xQueueReset(xQueue1);
                        //sciSend(scilinREG, 30, "\r\nError: Queue1 is full [TBD].");
                    }
                    com_char = 0;                                                           //Number of characters variable reseted
                }
                else
                {
                    uBuffer++;
                    com_char++;
                    if(127 < com_char)
                    {
                        uBuffer = uBuffer - com_char;
                        com_char = 0;

                        for(i = 0; i < uartMessage->len; i++)
                            uartMessage->buffer[i] = 0;
                        uartMessage->len = 1;

                        sciSend(scilinREG, 31, (unsigned char *)"\r\n> Error: uBuffer Filled [TBD]");                     //uBuffer filled
                    }
                }

                if(uxQueueSpacesAvailable(xQueue2) < 10)
                {
                    xQueueReset(xQueue2);
                    sciSend(scilinREG, 37, "\r\nError: Queue2 is almost full [TBD].");
                }
            }
            else{}  //sciSend(scilinREG, 33, "\r\nError: Data not received [TBD].");

            vTaskResume(xTask3Handle1);                                     //This task wakes up vMain task each time an enter key is pressed.
            vTaskSuspend(NULL);                                             //The task is suspended up to the sci interrupt wakes up it.
        }
        else{sciSend(scilinREG, 27, "\r\nError: Null Queue2 [TBD].");}      //sciSend(scilinREG, 27, "\r\nError: Null Queue2 [TBD].");
    }
}

/********************************************************
 * Main Application task                                *
 * Through this task all commands received from the     *
 * communication interfaces are decoded and an action   *
 * is executed.                                         *
 ********************************************************/
void vMain(void *pvParameters)
{
    //Basic variables:
    uint8_t i=0;
    bool isValid = false;
    //qMessage Structure creation to receive data through a queue
    struct qMessage *dMessage;

    //Delay of 100 ms
    //const TickType_t xDeco_delay = 100;

    for(;;)
    {
        if(xQueue1 != NULL)
        {
            //sciSend(scilinREG, 6, "\r\nChau");
            if(5 < uxQueueSpacesAvailable(xQueue1) && xQueueReceive(xQueue1, &dMessage, (TickType_t) 10) == pdPASS)
            {
              sciSend(scilinREG, dMessage->len, dMessage->buffer);          //Print the command received
              isValid = cDecoder(dMessage);

              if(dMessage->buffer[0] == 0x0D){sciSend(scilinREG, 4, (unsigned char *)"\r\n> ");}    //New command line
              else
              {
                  if(isValid == false){sciSend(scilinREG, 32, (unsigned char *)"\r\n. Error: Unknown Command [TBD]");}//Error Message.
                  else{sciSend(scilinREG, 22, (unsigned char *)"\r\n. Execute an action.");}
                  sciSend(scilinREG, 4, (unsigned char *)"\r\n> ");             //New command line
              }

              for(i = 0; i < dMessage->len; i++)
                  dMessage->buffer[i] = 0;
              dMessage->len = 1;
            }
            else{}    //sciSend(scilinREG, 33, "\r\nError: Data not received [TBD].");
            vTaskSuspend(NULL);     //The task is suspended up to the vUART task wakes it up.
        }
        else{sciSend(scilinREG, 27, "\r\nError: Null Queue1 [TBD].");}       //sciSend(scilinREG, 27, "\r\nError: Null Queue1 [TBD].");
    }
}

//Include 'interfacesCommandDef.h' before use this function in your project.

bool cDecoder(struct qMessage * command)
{
    bool            isValid = false;
    uint8_t         i = 0, j = 0;
    command->len = command->len - 1;                    //Enter (0x0D) is ignored.

    for(i = 0; i < COMMAND_LIST_LEN; i++)
    {
        if(commandLength[i] == command->len)            //It compares the command length received with the command in the list.
        {
            for(j = 0; j < command->len; j++)
            {
                if(command->buffer[j] == *(commandList[i] + j))     //It comapres character by character the command received and the command in list.
                    isValid = true;
                else
                {
                    isValid = false;
                    j = command->len;
                }
            }
            if(isValid == true)
                return isValid;
        }
    }

    return isValid;
}

/* USER CODE END */

The code has four tasks at now.

vCAN has to be waked up if a CAN ISR is triggered.

vUART works as vCAN but it works fine. Inside this task, a CAN frame is sent from CAN2 to CAN3 each time an enter key is pressed. I have done it as a simple test.

I attach below a picture of the serial Terminal that shows a basic user interface:

Initializing system. Please wait...
************************
LabOSat-02 [OBC] OS V1.0
************************

Developers:
Gagliardi Leandro Luciano
Di Nardo Federico

vExtWD
> CAN message received.
Debug UART communication started
< Press any key >CAN ISR entered.

>
. Error: Unknown Command [TBD]
>
>

CAN ISR started is a notification after the first enter key pressed. Then, after various enter key, never is triggered again.

Somebody has an idea about this strange behaviour?

Thanks a lot and regards,

Leandro

  • Hi Leandro,

    I don't understand why you are calling "PacketRead" function two times in handler?

    I am trying to trigger issue at my end so i used your code but i am getting error for below .h files not found

    #include "bl_can.h"

    #include "interfacesCommandDef.h"

    So, can you please provide above .h files to trigger issue at my end?

    --
    Thanks & Regards,
    Jagadish.

  • Hello Jagadish,

    Thank you for your reply. I attach the .h and .c files.

    I think that the issue could be in the PacketRead function because of I used "canGetData(canREG2, canMESSAGE_BOX2, Buffer);" function and it worked. I attach the modified code below:

    /** @file sys_main.c 
    *   @brief Application main file
    *   @date 07-July-2017
    *   @version 04.07.00
    *
    *   This file contains an empty main function,
    *   which can be used for the application.
    */
    
    /* 
    * Copyright (C) 2009-2016 Texas Instruments Incorporated - www.ti.com 
    * 
    * 
    *  Redistribution and use in source and binary forms, with or without 
    *  modification, are permitted provided that the following conditions 
    *  are met:
    *
    *    Redistributions of source code must retain the above copyright 
    *    notice, this list of conditions and the following disclaimer.
    *
    *    Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the 
    *    documentation and/or other materials provided with the   
    *    distribution.
    *
    *    Neither the name of Texas Instruments Incorporated nor the names of
    *    its contributors may be used to endorse or promote products derived
    *    from this software without specific prior written permission.
    *
    *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    */
    
    
    /* USER CODE BEGIN (0) */
    
    #define EXTWD_PRIORITY          ( tskIDLE_PRIORITY + 3)
    #define SCI_PRIORITY            ( tskIDLE_PRIORITY + 2)
    #define MAIN_PRIORITY           ( tskIDLE_PRIORITY + 2)
    #define CAN_PRIORITY            ( tskIDLE_PRIORITY + 2)
    
    /* USER CODE END */
    
    /* Include Files */
    
    #include "sys_common.h"
    
    /* USER CODE BEGIN (1) */
    #include "system.h"
    #include "het.h"
    #include "gio.h"
    #include "reg_pcr.h"
    #include "sys_pcr.h"
    #include "sys_pmm.h"
    #include "reg_vim.h"
    #include "sci.h"
    #include "string.h"
    #include "reg_can.h"
    #include "bl_can.h"
    #include "can.h"
    #include "sys_common.h"
    #include "sys_core.h"
    #include "sys_vim.h"
    
    /* Include FreeRTOS scheduler files */
    #include "FreeRTOS.h"
    #include "os_task.h"
    #include "os_queue.h"
    
    //Command List:
    #include "interfacesCommandDef.h"
    /* USER CODE END */
    
    /** @fn void main(void)
    *   @brief Application main function
    *   @note This function is empty by default.
    *
    *   This function is called after startup.
    *   The user can use this function to implement the application.
    */
    
    /* USER CODE BEGIN (2) */
    //Settings:
    //Globals:
    
    //Task Handlers:
    xTaskHandle xTask1Handle1;          //vExtWD task handle
    xTaskHandle xTask2Handle1;          //vUART task handle
    xTaskHandle xTask3Handle1;          //vMain task handle
    xTaskHandle xTask4Handle1;          //vCAN task handle
    
    //Queue handlers:
    QueueHandle_t xQueue1;              //Queue1 is used to send data from vUART to vMain task.
    QueueHandle_t xQueue2;              //Queue2 is used to send data from sciNotification to vUART task.
    QueueHandle_t xQueue3;              //Queue3 is used to send data from canMessageNotification to vCAN task.
    
    //Set of structures to be sent through queues:
    struct qMessage
    {
        uint8_t     len, sciRxMessage, rxData;
        uint8_t     buffer[128];
    }xMessage;
    
    struct qMessage2
    {
        uint8_t     len, sciRxMessage, rxData;
        uint8_t     buffer[128];
    }xMessage2;
    
    struct qMessage3
    {
        uint8_t     len, sciRxMessage, rxData;
        uint8_t     buffer[128];
    }xMessage3;
    
    //Functions:
    void sysInit(void);
    void osInit(void);
    void sciDisplayData(sciBASE_t *, uint8 *,uint32);
    bool cDecoder(struct qMessage *);
    uint8_t delayms(uint16);
    
    //Tasks:
    void vExtWD(void *pvParameters);        //External watchdog pulse generation
    void vCAN(void *pvParameters);          //CAN communication task
    void vUART(void *pvParameters);         //Debug UART communication task
    void vMain(void *pvParameters);         //Main task
    /* USER CODE END */
    
    int main(void)
    {
    /* USER CODE BEGIN (3) */
        sysInit();  //System initialization.
        osInit();   //Operative System initialization.
    
        /* Run forever */
        while(1);
    
    /* USER CODE END */
    
        return 0;
    }
    
    
    /* USER CODE BEGIN (4) */
    
    /*************************************
     * Functions, Tasks and ISR routines *
     *************************************/
    
    /*********************************
     * CAN interrupt service routine *
     *********************************/
    void canMessageNotification(canBASE_t *node, uint32 messageBox)
    {
        //uint8_t rxKey;
        uint8_t *Buffer;
        uint16_t teleBuffer[8];
        Buffer = ((uint8_t *)teleBuffer);
        uint32_t ulBytes;
        sciSend(scilinREG, 18, "CAN ISR entered.\r\n");
        //struct qMessage3 *rxCanMessage;
        //rxCanMessage = &xMessage3;
    
        //We have not woken a task at the start of the ISR.
        //BaseType_t canHigherPriorityTaskWoken = pdFALSE;
    
        if(node == canREG2)
        {
            while(!canIsRxMessageArrived(canREG2, canMESSAGE_BOX2));
            //PacketRead(canREG2, Buffer, &ulBytes, 2);
            canGetData(canREG2, canMESSAGE_BOX2, Buffer); /* copy to RAM */
        }
        else if(node == canREG3)
        {
            while(!canIsRxMessageArrived(canREG3, canMESSAGE_BOX2));
            //PacketRead(canREG3, Buffer, &ulBytes, 2);
            canGetData(canREG3, canMESSAGE_BOX2, Buffer); /* copy to RAM */
        }
    
        //if(xQueueIsQueueEmptyFromISR(xQueue3) == pdTRUE)
        //{
            //sciDisplayData(scilinREG, (uint8 *) fillQ, 1);                          //Only for printing on the terminal.
        //    if(xQueueSendToBackFromISR(xQueue3, &rxCanMessage, &canHigherPriorityTaskWoken) == errQUEUE_FULL)
        //    {
                //xQueueReset(xQueue2);
        //        sciSend(scilinREG, 68, "\r\nError: Data did not send from CAN interrupt service routine [TBD].");
        //    }
        //}
    }
    
    
    /*********************************
     * SCI interrupt service routine *
     *********************************/
    void sciNotification(sciBASE_t *sci, unsigned flags)
    {
        uint8_t rxKey;
        struct qMessage2 *rxUartMessage;
        rxUartMessage = &xMessage2;
        BaseType_t sciYieldRequired;
    
        //We have not woken a task at the start of the ISR.
        BaseType_t sciHigherPriorityTaskWoken = pdFALSE;//, fillQ;
    
        sciYieldRequired = xTaskResumeFromISR(xTask2Handle1);          //This ISR wakes up the vUART task each time a character is received.
    
        sciReceive(scilinREG, 1, (unsigned char *)&rxKey);
        rxUartMessage->rxData = rxKey;
    
        //fillQ = uxQueueSpacesAvailable(xQueue2);    //xQueueIsQueueFullFromISR
    
        if(xQueueIsQueueEmptyFromISR(xQueue2) == pdTRUE)
        {
            //sciDisplayData(scilinREG, (uint8 *) fillQ, 1);                          //Only for printing on the terminal.
            if(xQueueSendToBackFromISR(xQueue2, &rxUartMessage, &sciHigherPriorityTaskWoken) == errQUEUE_FULL)
            {
                //xQueueReset(xQueue2);
                sciSend(scilinREG, 73, "\r\nError: Data did not send from UART SCI interrupt service routine [TBD].");
            }
        }
    
        portYIELD_FROM_ISR(sciYieldRequired);
    }
    
    /********************************
     * Delay in ms.                 *
     * t: time in ms to be delayed. *
     * ******************************/
    uint8_t delayms(uint16 t)
    {
        uint16 h, i, j;
        for(h = 0; h < t; h++){                 //ts = 1000 to set 1 second.
            for(i = 0; i<1350; i++)             //Time between samples 1 ms.
                for(j = 0; j< 8; j++);}
        return 1;
    }
    
    /********************
     * sysInit function *
     ********************/
    void sysInit()
    {
        uint8_t generic;
        sciInit();                                      //SCI initialization.
        canInit();                                      //CAN initialization.
    
        //Enable interrupts:
        vimInit();
        _enable_interrupt_();                           //General interrupt flag.
        //Enable SCI interrupt:
        sciEnableNotification(scilinREG,SCI_RX_INT);    //Enable SCI interrupt by Rx.
        //Enable CAN interrupt:
        canEnableErrorNotification(canREG2);            //Enable canREG2 interrupt.
        canEnableErrorNotification(canREG3);            //Enable canREG3 interrupt.
    
        sciReceive(scilinREG,1, (unsigned char *)&generic);
    
        sciSend(scilinREG, 37, (unsigned char *)"Initializing system. Please wait...\r\n");
        gioInit();                                      //GIO module initialization.
        gioSetDirection(hetPORT1, 1 << 15);             //Enable N2HET1[15] as output. This is the output signal to the external watch-dog.
    
        sciSend(scilinREG, 27, (unsigned char *)"\t************************\r\n");
        sciSend(scilinREG, 27, (unsigned char *)"\tLabOSat-02 [OBC] OS V1.0\r\n");
        sciSend(scilinREG, 27, (unsigned char *)"\t************************\r\n");
        sciSend(scilinREG, 1, (unsigned char *)"\n");
        sciSend(scilinREG, 14, (unsigned char *)"Developers: \r\n");
        sciSend(scilinREG, 30, (unsigned char *)"\t Gagliardi Leandro Luciano \r\n");
        sciSend(scilinREG, 22, (unsigned char *)"\t Di Nardo Federico \r\n");
        sciSend(scilinREG, 1, (unsigned char *)"\n");
    }
    
    /********************
     * osInit function  *
     ********************/
    void osInit()
    {
        //Queues Creation:
        xQueue1 = xQueueCreate(20, sizeof(struct xMessage *));                   //Queue used between vUART task and vMain task.
        xQueue2 = xQueueCreate(200, sizeof(struct xMessage *));                  //Queue used between sciNotification ISR and vUART task.
        xQueue3 = xQueueCreate(200, sizeof(struct xMessage3 *));                 //Queue used between canMessageNotification ISR and vCAN task.
    
        //if( xQueue1 == NULL || xQueue2 == NULL || xQueue3 == NULL){sciSend(scilinREG, 58, (unsigned char *)"\r\nError: Queue was not created and must not be used [TBD].");}
    
        if(xQueue1 == NULL){sciSend(scilinREG, 59, (unsigned char *)"\r\nError: Queue1 was not created and must not be used [TBD].");}
        if(xQueue2 == NULL){sciSend(scilinREG, 59, (unsigned char *)"\r\nError: Queue2 was not created and must not be used [TBD].");}
        if(xQueue3 == NULL){sciSend(scilinREG, 59, (unsigned char *)"\r\nError: Queue3 was not created and must not be used [TBD].");}
    
        //Tasks Creation:
        if (xTaskCreate(vExtWD,"vExtWD", configMINIMAL_STACK_SIZE, NULL, EXTWD_PRIORITY, &xTask1Handle1) != pdTRUE){while(1);}  //Task could not be created
        if (xTaskCreate(vUART,"vUART", configMINIMAL_STACK_SIZE, NULL, SCI_PRIORITY, &xTask2Handle1) != pdTRUE){while(1);}      //Task could not be created
        if (xTaskCreate(vMain,"vMain", configMINIMAL_STACK_SIZE, NULL, MAIN_PRIORITY, &xTask3Handle1) != pdTRUE){while(1);}     //Task could not be created
        if (xTaskCreate(vCAN,"vCAN", configMINIMAL_STACK_SIZE, NULL, CAN_PRIORITY, &xTask4Handle1) != pdTRUE){while(1);}     //Task could not be created
        //Start Scheduler:
        vTaskStartScheduler();
    }
    
    
    /***************************
     * sciDisplayData function *
     ***************************/
    void sciDisplayData(sciBASE_t *sci, uint8 *text,uint32 length)
    {
        uint8 txt = 0;
        uint8 txt1 = 0;
    
    #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
    text = text + (length -1);
    #endif
    
        while(length--)
        {
    #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
            txt = *text--;
    #else
            txt = *text++;
    #endif
    
            txt1 = txt;
    
            txt  &= ~(0xF0);
            txt1 &= ~(0x0F);
            txt1  =txt1>>4;
    
            if(txt<=0x9)
            {
                txt +=0x30;
            }
            else if(txt > 0x9 && txt <= 0xF)
            {
                txt +=0x37;
            }
            else
            {
                txt = 0x30;
            }
    
            if(txt1 <= 0x9)
            {
                txt1 +=0x30;
            }
            else if((txt1 > 0x9) && (txt1 <= 0xF))
            {
                txt1 +=0x37;
            }
            else
            {
                txt1 = 0x30;
            }
    
            while ((scilinREG->FLR & 0x4) == 4); /* wait until busy */
            sciSendByte(scilinREG,txt1);      /* send out text   */
            while ((scilinREG->FLR & 0x4) == 4); /* wait until busy */
            sciSendByte(scilinREG,txt);      /* send out text   */
        };
    }
    
    /********************************************************
     * This task avoids external watch-dog reset            *
     * It considers the following watch-dog configuration:  *
     * SET0 = 0;                                            *
     * SET1 = 0;                                            *
     * twdu(min) = 77.455 s * 0.905 = 70.09 s               *
     * twdu(typ) = 77.4 * Ccwd + 0.055 = 77.455 s           *
     * twdu(max) = 1.095 * 77.455 s = 85 s                  *
     * twdl(min) = 70096 s * 0.125 = 8.762 s                *
     * twdl(typ) = 77455 s * 0.125 = 9.682 s                *
     * twdl(max) = 70096 s * 0.125 = 10.602 s               *
     *             10.602 s < tpulse < 70.09 s              *
     ********************************************************/
    void vExtWD(void *pvParameters)     //Watchdog send a pulse each 77 seconds.
    {
        uint8_t i, j;
        TickType_t xLastWakeTime;
        const TickType_t xTimeIncrement = 30000; //Each 30 seconds the MCU generates a pulse that avoids the system reset.
        //Initialise the xLastWakeTime variable with the current time.
        xLastWakeTime = xTaskGetTickCount();
    
        //Meter un sciSend para ver si esta tarea se está ejecutando.
    
        for(;;)
        {
            sciSend(scilinREG, 11, (unsigned char *)" vExtWD\r\n> ");       //A signal to know if the task is executed.
            vTaskDelayUntil( &xLastWakeTime, xTimeIncrement);
            //vTaskDelay(xTimeIncrement);
            gioSetBit(hetPORT1, 15, 1);  //0x00100000
            for(i = 0; i<10; i++){for(j = 0; j<100; j++){}} // It defines the pulse width (100us approximately)
            gioSetBit(hetPORT1, 15, 0);  //0x00000000
        }
    }
    
    
    /********************************************************
     * CAN Communication interface task                     *
     * Through this interface the user can send commands    *
     * and execute experiments on the payloads.             *
     ********************************************************/
    void vCAN(void *pvParameters)
    {
        sciSend(scilinREG, 23, (unsigned char *)"CAN message received.\r\n");
        vTaskSuspend(NULL);                                             //The task is suspended up to the CAN interrupt wakes it up.
    }
    
    
    /********************************************************
     * Debug UART Communication interface task              *
     * Through this interface the user can send commands    *
     * and execute experiments on the payloads.             *
     ********************************************************/
    void vUART(void *pvParameters)     //Debug UART communication task
    {
        //Basic variables:
        uint8_t com_char = 0, i = 0, message[8] = {0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E};
        uint8_t *uBuffer;
        uint8_t UART_Buffer[128];
        uBuffer = ((uint8_t *)UART_Buffer);
    
        //qMessage Structure creation to send data through a queue
        struct qMessage *uartMessage;
        uartMessage = &xMessage;
    
        //UART_Buffer initialization:
        for(i = 0; i < 128; i++)
            UART_Buffer[i] = 0;
    
        //Delay of 50 ms:
        const TickType_t xUART_delay = 50;
        vTaskDelay(xUART_delay);
    
        sciSend(scilinREG, 34, (unsigned char *)"Debug UART communication started\r\n");        //A signal to know if the task is executed.
        sciSend(scilinREG, 17, (unsigned char *)"< Press any key >");                           //Press any key to start.
    
        for(;;)
        {
            //UART com
            if(xQueue2 != NULL)
            {
                if(xQueueReceive(xQueue2, &uartMessage, (TickType_t) 10) == pdPASS)
                {
                    //CAN Test frame
                    PacketWrite(canREG2, CAN_ALIVE, message, 8, 2);                    //Test frame sent through messageBox1. CAN_ALIVE has an ID of 0x06 and null payload.
    
                    *uBuffer = uartMessage->rxData;
                    sciSend(scilinREG, 1, uBuffer);                                      //Print a keyboard symbol
    
                    if(*uBuffer == 0x0D && com_char < 128)                                                                //If we press enter...
                    {
                        sciSend(scilinREG, 4, (unsigned char *)"\r\n> ");               //New command line
                        uBuffer++;
                        com_char++;
                        uBuffer = uBuffer - com_char;                                                   //Return to the first buffer position
    
                        uartMessage->len = com_char;                                                    //Number of characters
                        for(i = 0; i < com_char; i++)                                                   //Data stored in the structure
                            uartMessage->buffer[i] = UART_Buffer[i];
    
                        if(5 < uxQueueSpacesAvailable(xQueue1))
                        {
                            if(xQueueSendToBack(xQueue1, (void *) &uartMessage, (TickType_t) 10) == errQUEUE_FULL)
                            {
                                sciSend(scilinREG, 49, "\r\nError: Data did not send from vUART task [TBD].");
                            }
                        }
                        else
                        {
                            xQueueReset(xQueue1);
                            //sciSend(scilinREG, 30, "\r\nError: Queue1 is full [TBD].");
                        }
                        com_char = 0;                                                           //Number of characters variable reseted
                    }
                    else
                    {
                        uBuffer++;
                        com_char++;
                        if(127 < com_char)
                        {
                            uBuffer = uBuffer - com_char;
                            com_char = 0;
    
                            for(i = 0; i < uartMessage->len; i++)
                                uartMessage->buffer[i] = 0;
                            uartMessage->len = 1;
    
                            sciSend(scilinREG, 31, (unsigned char *)"\r\n> Error: uBuffer Filled [TBD]");                     //uBuffer filled
                        }
                    }
    
                    if(uxQueueSpacesAvailable(xQueue2) < 10)
                    {
                        xQueueReset(xQueue2);
                        sciSend(scilinREG, 37, "\r\nError: Queue2 is almost full [TBD].");
                    }
                }
                else{}  //sciSend(scilinREG, 33, "\r\nError: Data not received [TBD].");
    
                vTaskResume(xTask3Handle1);                                     //This task wakes up vMain task each time an enter key is pressed.
                vTaskSuspend(NULL);                                             //The task is suspended up to the sci interrupt wakes up it.
            }
            else{sciSend(scilinREG, 27, "\r\nError: Null Queue2 [TBD].");}      //sciSend(scilinREG, 27, "\r\nError: Null Queue2 [TBD].");
        }
    }
    
    /********************************************************
     * Main Application task                                *
     * Through this task all commands received from the     *
     * communication interfaces are decoded and an action   *
     * is executed.                                         *
     ********************************************************/
    void vMain(void *pvParameters)
    {
        //Basic variables:
        uint8_t i=0;
        bool isValid = false;
        //qMessage Structure creation to receive data through a queue
        struct qMessage *dMessage;
    
        //Delay of 100 ms
        //const TickType_t xDeco_delay = 100;
    
        for(;;)
        {
            if(xQueue1 != NULL)
            {
                //sciSend(scilinREG, 6, "\r\nChau");
                if(5 < uxQueueSpacesAvailable(xQueue1) && xQueueReceive(xQueue1, &dMessage, (TickType_t) 10) == pdPASS)
                {
                  sciSend(scilinREG, dMessage->len, dMessage->buffer);          //Print the command received
                  isValid = cDecoder(dMessage);
    
                  if(dMessage->buffer[0] == 0x0D){sciSend(scilinREG, 4, (unsigned char *)"\r\n> ");}    //New command line
                  else
                  {
                      if(isValid == false){sciSend(scilinREG, 32, (unsigned char *)"\r\n. Error: Unknown Command [TBD]");}//Error Message.
                      else{sciSend(scilinREG, 22, (unsigned char *)"\r\n. Execute an action.");}
                      sciSend(scilinREG, 4, (unsigned char *)"\r\n> ");             //New command line
                  }
    
                  for(i = 0; i < dMessage->len; i++)
                      dMessage->buffer[i] = 0;
                  dMessage->len = 1;
                }
                else{}    //sciSend(scilinREG, 33, "\r\nError: Data not received [TBD].");
                vTaskSuspend(NULL);     //The task is suspended up to the vUART task wakes it up.
            }
            else{sciSend(scilinREG, 27, "\r\nError: Null Queue1 [TBD].");}       //sciSend(scilinREG, 27, "\r\nError: Null Queue1 [TBD].");
        }
    }
    
    //Include 'interfacesCommandDef.h' before use this function in your project.
    
    bool cDecoder(struct qMessage * command)
    {
        bool            isValid = false;
        uint8_t         i = 0, j = 0;
        command->len = command->len - 1;                    //Enter (0x0D) is ignored.
    
        for(i = 0; i < COMMAND_LIST_LEN; i++)
        {
            if(commandLength[i] == command->len)            //It compares the command length received with the command in the list.
            {
                for(j = 0; j < command->len; j++)
                {
                    if(command->buffer[j] == *(commandList[i] + j))     //It comapres character by character the command received and the command in list.
                        isValid = true;
                    else
                    {
                        isValid = false;
                        j = command->len;
                    }
                }
                if(isValid == true)
                    return isValid;
            }
        }
    
        return isValid;
    }
    
    /* USER CODE END */
    

    Regards,

    Leandro

    interfacesCommandDef.hbl_can.h

    /** @file adc.c
    *   @brief ADC Driver Source File
    *   @date 11-Dec-2018
    *   @version 04.07.01
    *
    *   This file contains:
    *   - API Functions
    *   - Interrupt Handlers
    *   .
    *   which are relevant for the ADC driver.
    */
    
    /* 
    * Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com  
    * 
    * 
    *  Redistribution and use in source and binary forms, with or without 
    *  modification, are permitted provided that the following conditions 
    *  are met:
    *
    *    Redistributions of source code must retain the above copyright 
    *    notice, this list of conditions and the following disclaimer.
    *
    *    Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the 
    *    documentation and/or other materials provided with the   
    *    distribution.
    *
    *    Neither the name of Texas Instruments Incorporated nor the names of
    *    its contributors may be used to endorse or promote products derived
    *    from this software without specific prior written permission.
    *
    *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    */
    
    
    /* USER CODE BEGIN (0) */
    /* USER CODE END */
    
    /* Include Files */
    
    #include "bl_can.h"
    #include "can.h"
    #include "sci.h"
    #include "system.h"
    
    #define BUFFER_SIZE             64       /*words in the data buffer used for receiving packets*/
    
    #define CAN_PORT                 canREG1
    
    
    //*****************************************************************************
    //
    // The message object number and index to the local message object memory to
    // use when accessing the messages.
    //
    //*****************************************************************************
    #define MSG_OBJ_BCAST_RX_ID     1
    #define MSG_OBJ_BCAST_TX_ID     2
    
    
    
    
    
    /* Global and Static Variables */
    #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
     //   static const uint32_t g_ulCanByteOrder[] = {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U};
    #else
        static const uint32_t g_ulCanByteOrder[] = {3U, 2U, 1U, 0U, 7U, 6U, 5U, 4U};
    #endif
    
    
    
    /*****************************************************************************
    *
    * This is the data buffer used during transfers to the boot loader.
    *
    ******************************************************************************/
    uint32_t g_pulDataBuffer[BUFFER_SIZE];
    
    //*****************************************************************************
    //
    // The buffer used to receive data from the update.
    //
    //*****************************************************************************
    uint8_t *CommandBuffer;
    
    
    /*****************************************************************************
    *
    * This is the data buffer used for update status.
    *
    * g_pulUpdateSuccess[] are used to store application update status and application
    * image's version etc
    ******************************************************************************/
    
    
    
    #define E_PASS          0
    #define E_FAIL          0x1U
    #define E_TIMEOUT       0x2U
    
    
    
    //*****************************************************************************
    //
    //! This function sends data using the transmit message object.
    //!
    //! \param ulId is the ID to use with this message.
    //! \param pucData is a pointer to the buffer with the data to be sent.
    //! \param ulSize is the number of bytes to send and should not be more than
    //! 8 bytes.
    //!
    //! This function will reads and acknowledges the data read from the message
    //! object used to receive all CAN firmware update messages.  It will also
    //! return the message identifier as this holds the API number that was
    //! attached to the data.  This message identifier should be one of the
    //! CAN_COMMAND_* definitions.
    //!
    //! \return None.
    //
    //*****************************************************************************
    //static void
    void CANMessageSetTx(canBASE_t *node, uint32_t ulId, const uint8_t *pucData, uint32_t ulSize)
    {
        uint8_t usCmdReg;
        uint32_t usArbReg, i;
        uint32_t usMsgCtrl;
    
        //
        // Wait for busy bit to clear
        //
        while(node->IF1STAT & CAN_IFCMD_BUSY)
        {
        }
    
        //
        // This is always a write to the Message object as this call is setting a
        // message object.  This call will also always set all size bits so it sets
        // both data bits.  The call will use the CONTROL register to set control
        // bits so this bit needs to be set as well.
        //
        usCmdReg = (CAN_IFCMD_WRNRD | CAN_IFCMD_DATAA | CAN_IFCMD_DATAB |
                        CAN_IFCMD_CONTROL | CAN_IFCMD_ARB);
    
        //
        // Mark the message as valid and set the extended ID bit.
        //
        usArbReg = (((ulId << 18) & CAN_IFARB_11ID_M) | (CAN_IFARB_DIR | CAN_IFARB_MSGVAL));
    
        //
        // Set the TXRQST bit and the reset the rest of the register.
        // Set the data length since this is set for all transfers.  This is also a
        // single transfer and not a FIFO transfer so set EOB bit.
        //
        //
        usMsgCtrl = (CAN_IFMCTL_TXRQST | CAN_IFMCTL_EOB | (ulSize & CAN_IFMCTL_DLC_M));
    
        //
        // Write the data out to the CAN Data registers if needed.
        //
        for (i = 0U; i < 8U; i++)
        {
    #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
            node->IF1DATx[i] = *pucData++;
    #else
            node->IF1DATx[g_ulCanByteOrder[i]] = *pucData++;
    #endif
         }
    
        //
        // Write out the registers to program the message object.
        //
        node->IF1CMD = usCmdReg;
        node->IF1ARB = usArbReg;
        node->IF1MCTL = usMsgCtrl;
    
        //
        // Transfer the message object to the message object specifiec by
        // MSG_OBJ_BCAST_RX_ID.
        //
        node->IF1NO = (MSG_OBJ_BCAST_TX_ID) & (CAN_IFCMD_MNUM_M);  //msg box 2
    }
    
    
    
    
    
    
    //*****************************************************************************
    //
    //! This function reads data from the receive message object.
    //!
    //! \param pucData is a pointer to the buffer to store the data read from the
    //! CAN controller.
    //! \param pulMsgID is a pointer to the ID that was received with the data.
    //!
    //! This function will reads and acknowledges the data read from the message
    //! object used to receive all CAN firmware update messages.  It will also
    //! return the message identifier as this holds the API number that was
    //! attached to the data.  This message identifier should be one of the
    //! CAN_COMMAND_* definitions.
    //!
    //! \return The number of valid bytes returned in the \e pucData buffer or
    //! 0xffffffff if data was overwritten in the buffer.
    //
    //*****************************************************************************
    uint32_t
    CANMessageGetRx(canBASE_t *node, uint8_t *pucData, uint32_t *pulMsgID)
    {
        uint8_t usCmdReg;
        uint32_t usArbReg;
        uint32_t usMsgCtrl;
        uint32_t ulBytes;
        uint8_t *pusData;
        uint32_t i;
    
        //
        // This is always a read to the Message object as this call is setting a
        // message object.
        // Clear a pending interrupt and new data in a message object.
        //
        usCmdReg = (CAN_IFCMD_DATAA | CAN_IFCMD_DATAB |
                        CAN_IFCMD_CONTROL | CAN_IFCMD_CLRINTPND |
                        CAN_IFCMD_ARB);
    
        //
        // Set up the request for data from the message object.
        //
        node->IF1CMD  = usCmdReg;
    
        //
        // Transfer the message object to the message object specific by
        // MSG_OBJ_BCAST_RX_ID.
        //
        node->IF1NO = (MSG_OBJ_BCAST_RX_ID & CAN_IFCMD_MNUM_M);  //msg box 1
    
    
        //
        // Wait for busy bit to clear
        //
        while(node->IF1STAT & CAN_IFCMD_BUSY)
        {
        }
    
        //
        // Read out the IF Registers.
        //
        usArbReg = node->IF1ARB;
        usMsgCtrl = node->IF1MCTL;
    
        //
        // Set the 29 bit version of the Identifier for this message object.
        //
        *pulMsgID = (usArbReg & CAN_IFARB_11ID_M) >> 18;
    
        //
        // See if there is new data available.
        //
        if((usMsgCtrl & (CAN_IFMCTL_NEWDAT | CAN_IFMCTL_MSGLST)) == CAN_IFMCTL_NEWDAT)
        {
            //
            // Get the amount of data needed to be read.
            //
            ulBytes = (usMsgCtrl & CAN_IFMCTL_DLC_M) ;
    
            //
            // Read out the data from the CAN registers 16 bits at a time.
            //
            pusData = (uint8_t*)pucData;
    
            /** - Copy RX data into destination buffer */
            for (i = 0U; i < ulBytes; i++)
            {
    #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
                *pusData++ = node->IF1DATx[i];
    #else
                *pusData++ = node->IF1DATx[g_ulCanByteOrder[i]];
    #endif
            }
    
            //
            // Now clear out the new data flag.
            //
            node->IF1CMD =  CAN_IFCMD_NEWDAT;
    
            //
            // Transfer the message object to the message object specific by
            // MSG_OBJ_BCAST_RX_ID.
            //
            node->IF1NO = MSG_OBJ_BCAST_RX_ID;
    
            //
            // Wait for busy bit to clear
            //
            while(node->IF1STAT & CAN_IFCMD_BUSY)
            {
            }
        }
        else
        {
            //
            // Data was lost so inform the caller.
            //
            ulBytes = 0xffffffff;
        }
        return(ulBytes);
    }
    
    
    //*****************************************************************************
    //
    // Reads the next packet that is sent to the boot loader.
    //
    //*****************************************************************************
    uint32_t
    PacketRead(canBASE_t *node, uint8_t *pucData, uint32_t *pulSize, uint32_t messageBox)
    {
        int count = 0;
        uint32_t ErrorTime;
    
        uint32_t ulMsgID;
    
        //uint32_t messageBox = 1;
    
        uint32_t regIndex = (messageBox - 1U) >> 5U;
        uint32_t bitIndex = 1U << ((messageBox - 1U) & 0x1FU);
    
        uint32 ID;
        //
        // Wait until a packet has been received.
        //
    
        while((node->NWDATx[regIndex] & bitIndex) == 0)
        {
            count++;
            if (count > 1000000)
            {
                ErrorTime = 0;
                return ErrorTime;
            }
        }
    
    
        /*Read the packet*/
        *pulSize = CANMessageGetRx(node, pucData, &ulMsgID);
    
        /* Return the message ID of the packet that was received. */
        return(ulMsgID);
    }
    
    
    //*****************************************************************************
    //
    // Sends a packet to the controller that is communicating with the boot loader.
    //
    //*****************************************************************************
    //static void
    void PacketWrite(canBASE_t *node, uint32_t ulId, const uint8_t *pucData, uint32_t ulSize, uint32_t messageBox)
    {
        uint32_t ulIdx;
    
        //uint32_t messageBox = 2;
    
        uint32_t regIndex = (messageBox - 1U) >> 5U;
        uint32_t bitIndex = 1U << ((messageBox - 1U) & 0x1FU);
    
        //
        // Wait until the previous packet has been sent, providing a time out so
        // that the boot loader does not hang here.
        //
        for(ulIdx = 1000; (ulIdx != 0) && ((node->TXRQx[regIndex] & bitIndex) != 0); ulIdx--)
        {
        }
    
        //
        // If the previous packet was sent, then send this packet.
        //
        if(ulIdx != 0)
        {
            CANMessageSetTx(node, ulId, pucData, ulSize);
        }
    }
    
    
    
    
    
    
    
    

  • Hi Leandro,

    I think that the issue could be in the PacketRead function because of I used "canGetData(canREG2, canMESSAGE_BOX2, Buffer);" function and it worked.

    So, is that means handler is calling more than once right if we used "canGetData" right?

    Issue is not occurring right?

    --

    Thanks & Regards,
    Jagadish.

  • Hello Jagadish,

    Indeed, If I implement "canGetData" I have no problems in de ISR handle.

    I will use this function. Thanks a lot.

    Regards,

    Leandro