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.

CCS/TMS570LS1227: Dynamic management of CAN message box

Part Number: TMS570LS1227


Tool/software: Code Composer Studio

Dear team,

CANID and CAN message content are misaligned When dynamically managing the CAN message box.

Are there routines or source codes for CAN dynamic management?

The sending method I have used is:

void CANSimpleSend(canBASE_t *const canreg, uint32_t msgbox, uint32_t ID, uint8_t *const data) {
    static uint32_t ret = 0U;
    uint8_t trytimes = 3U;

    canUpdateID(canreg, msgbox, 1U << 30U | 1U << 29U | (ID & 0x1FFFFFFFU));
    do {
        ret = canTransmit(canreg, msgbox, data);
        if (ret == 0U) {
            int16_t i = 1000U;
            while (i > 0) i--;
        }
        trytimes--;
    } while ((ret == 0U) && (trytimes > 0U));
}
uint16 CANSend(uint8 Dest, CAN_MSG_TYPE type, uint8 *const data)
{
    uint32 canid = 0U;
    canid |= (type & 0xFFU);
    canid |= Dest << 8U;
    canid |= GetBoardID() << 16U;
    /* CANID 30bit: ext_ID 29bit: Dir Transmit */
    static uint32_t msgbox = canMESSAGE_BOX1;
    data[0U] = canindex++;                          /* data[0] is frame index */
    /* CAN1 */
    CANSimpleSend(canREG1,msgbox,canid,data);
    /* CAN2 */
    CANSimpleSend(canREG2,msgbox,canid,data);
    msgbox++;
    if (msgbox == canMESSAGE_BOX9) msgbox = canMESSAGE_BOX1;
    return 0;
}

Send dynamically through messagebox1-8, in this case, the error rate is very high when sending at high speed.

The modified sending method combines the changed ID and the changed data

uint8_t canSimpleTransmit(canBASE_t *const canreg, uint32_t msgbox, uint32_t ID, uint8_t * data)
{
    uint32 i;
    uint32 success  = 0U;
    uint32 regIndex = (msgbox - 1U) >> 5U;
    uint32 bitIndex = 1U << ((msgbox - 1U) & 0x1FU);

    /** - Check for pending message:
    *     - pending message, return 0
    *     - no pending message, start new transmission
    */
    if ((canreg->TXRQx[regIndex] & bitIndex) != 0U)
    {
        success = 0U;
    }
    else
    {
        /** - Wait until IF1 and IF2 is ready for use */
        while(
                ((canreg->IF1STAT & 0x80U) ==0x80U) ||
                ((canreg->IF2STAT & 0x80U) ==0x80U)
                )
        {
        } /* Wait */

        /** - Configure IF2 for
        *     - Message direction - Read
        *     - Data Read
        *     - Clears NewDat bit in the message object.
        */
        canreg->IF2CMD = 0xA0U;
        /* Copy passed value into the arbitration register. */
        canreg->IF2ARB &= 0x80000000U;
        canreg->IF2ARB |= (ID & 0x7FFFFFFFU);

        /** - Configure IF1 for
        *     - Message direction - Write
        *     - Data Update
        *     - Start Transmission
        */
        canreg->IF1CMD = 0x87U;

        /** - Copy TX data into IF1 */
        for (i = 0U; i < 8U; i++)
        {
#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
            /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
            node->IF1DATx[i] = *data;
            /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
            /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
            data++;
#else
            /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
            canreg->IF1DATx[s_canByteOrder[i]] = *data;
            /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
            /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
            data++;
#endif
        }

        /** - Update message box number. */
        /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */
        canreg->IF2NO = (uint8) msgbox;

        /** - Wait until data are copied into IF2 */
        while ((canreg->IF2STAT & 0x80U) ==0x80U)
        {
        } /* Wait */

        /** - Copy TX data into message box */
        /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */
        canreg->IF1NO = (uint8) msgbox;

        /** - Wait until data are copied into IF1 */
        while ((canreg->IF1STAT & 0x80U) ==0x80U)
        {
        } /* Wait */

        success = 1U;
    }
    return success;
}

After the modification, the error rate is greatly reduced, but there are still occasional errors.

Now the application is built on the basis of high security requirements. This requirement is relatively strict, and I hope to get a stable management plan.

When multiple message boxes are sent, how to determine that the sending is complete?

After enabling the tx interrupt, can it be judged through the INTPNDx register? (This messagebox is only for sending)

BR,

susan

  • Hi Susan,

    What error do you get?

    The transmit priority for the message objects is attached to the message number. Smaller message number has higher priority. If more than one transmission request (Transmission Request X Registers) is pending, the message with the highest priority will be serviced. The message with lower priority might not be transmitted forever. 

    You can check all the pending TX request flags before you transmit new data. For example:

    if ((canreg->TXRQX != 0U)   {
            success = 0U;
    }

  • void user_main(void)
    {
      SystemInit();
      while (1)
      {
         uint8_t temp[8] = {0};
         memset(temp, 0x00, 8);
         CANSimpleSend(canREG3, temp, 0x00);
         memset(temp, 0xff, 8);
         CANSimpleSend(canREG3, temp, 0xff);
      }
    }

    In theory, there will be: ID is 0xff, data : 8 frames of 0xff 

                                 AND   ID is 0x00, data: 8 frames of 0x00

    The current situation is that there will be a crossover:

                                           ID is 0x00,data: 8 frames of 0xff,

                                  AND ID is 0xff , data:8 frames of 0x00

  • Hi Susan,

    Did you see any compiler errors on the calls "CANSimpleSend(canREG3, temp, 0xff)" in your main loop. It does not match the routine declared with 4 arguments "void CANSimpleSend(canBASE_t *const canreg, uint32_t msgbox, uint32_t ID, uint8_t *const data);"

  • I'm sorry for this mistake.

    I first asked this question and Susan help me to move here.

    I just put some pseudocode up there. there is no compiler errors.

    My code is 

    void user_main(void)
    {
      SystemInit();
      while (1)
      {
         uint8_t temp[8] = {0};
         memset(temp, 0x00, 8);
         CANSendToStatus(canREG3, temp, 0x00);
         memset(temp, 0xff, 8);
         CANSendToStatus(canREG3, temp, 0xff);
      }
    }
    
    int CAN3DropMsgCount = 0;
    int CANSendToStatusRunning = 0;
    void CANSendToStatus(uint8_t source, CAN_MSG_TYPE type, uint8_t *const data) {
        uint32_t CANID = 0U;
        static uint32_t msgbox = canMESSAGE_BOX1;
        uint8 SwitchCount = 0;
        if(CANSendToStatusRunning)
        {
            CAN3DropMsgCount++;
            return;
        }
        CANSendToStatusRunning = 1;
        while(candata[2].isSending[msgbox])
        {
            msgbox++;
            if (msgbox == canMESSAGE_BOX9) msgbox = canMESSAGE_BOX1;
            SwitchCount++;
            if(SwitchCount > 8)                                             //No msg box available
            {
                CAN3DropMsgCount++;
                CANSendToStatusRunning = 0;
                return ;
            }
        }
        candata[2].isSending[msgbox] = 1;
        CANID |= type;
        CANID |= source << 8U;
        if (cancommhelper.GetBoardID != NULL_PTR) CANID |= cancommhelper.GetBoardID() << 16U;
        CANID |= 0x03U << 24U;
        CANID |= 0x01U << 26U;
        CANID |= 1U << 28U;
    
        CANSimpleSend(candata[2].canreg, msgbox, CANID, data);
        msgbox++;
        if (msgbox == canMESSAGE_BOX9) msgbox = canMESSAGE_BOX1;
        CANSendToStatusRunning = 0;
    }
    
    void CANSimpleSend(canBASE_t *const canreg, uint32_t msgbox, uint32_t ID, uint8_t *const data) {
        static uint32_t ret = 0U;
        uint8_t trytimes = 200U;
    
        do {
            ret = canSimpleTransmit(canreg, msgbox, 1U << 30U | 1U << 29U | (ID & 0x1FFFFFFFU), data);
            if (ret == 0U) {
                int16_t i = 1000U;
                while (i > 0) i--;
            }
            trytimes--;
        } while ((ret == 0U) && (trytimes > 0U));
    }
    #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
    #else
        static const uint32 s_canByteOrder[8U] = {3U, 2U, 1U, 0U, 7U, 6U, 5U, 4U};
    #endif
    
    uint8_t canSimpleTransmit(canBASE_t *const canreg, uint32_t msgbox, uint32_t ID, uint8_t * data)
    {
        uint32 i;
        uint32 success  = 0U;
        uint32 regIndex = (msgbox - 1U) >> 5U;
        uint32 bitIndex = 1U << ((msgbox - 1U) & 0x1FU);
    
        /** - Check for pending message:
        *     - pending message, return 0
        *     - no pending message, start new transmission
        */
        if ((canreg->TXRQx[regIndex] & bitIndex) != 0U)
        {
            success = 0U;
        }
        else
        {
            /** - Wait until IF1 and IF2 is ready for use */
            while(
                    ((canreg->IF1STAT & 0x80U) ==0x80U) ||
                    ((canreg->IF2STAT & 0x80U) ==0x80U)
                    )
            {
            } /* Wait */
    
            /** - Configure IF2 for
            *     - Message direction - Read
            *     - Data Read
            *     - Clears NewDat bit in the message object.
            */
            canreg->IF2CMD = 0xA0U;
            /* Copy passed value into the arbitration register. */
            canreg->IF2ARB &= 0x80000000U;
            canreg->IF2ARB |= (ID & 0x7FFFFFFFU);
    
            /** - Configure IF1 for
            *     - Message direction - Write
            *     - Data Update
            *     - Start Transmission
            */
            canreg->IF1CMD = 0x83U;
    
            /** - Copy TX data into IF1 */
            for (i = 0U; i < 8U; i++)
            {
    #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
                /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
                node->IF1DATx[i] = *data;
                /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
                /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
                data++;
    #else
                /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
                canreg->IF1DATx[s_canByteOrder[i]] = *data;
                /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
                /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
                data++;
    #endif
            }
    
            /** - Update message box number. */
            /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */
            canreg->IF2NO = (uint8) msgbox;
    
            /** - Wait until data are copied into IF2 */
            while ((canreg->IF2STAT & 0x80U) ==0x80U)
            {
            } /* Wait */
    
            /** - Copy TX data into message box */
            /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */
            canreg->IF1NO = (uint8) msgbox;
    
            /** - Wait until data are copied into IF1 */
            while ((canreg->IF1STAT & 0x80U) ==0x80U)
            {
            } /* Wait */
    
            canreg->IF1CMD = 0x84U;
    
            /** - Copy TX data into message box */
            /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */
            canreg->IF1NO = (uint8) msgbox;
    
            /** - Wait until data are copied into IF1 */
            while ((canreg->IF1STAT & 0x80U) ==0x80U)
            {
            } /* Wait */
    
            success = 1U;
        }
        return success;
    }
    void canStatusChangeNotification(canBASE_t *node, uint32 notification)
    {
        int i = 0;
        if((node == canREG3)&&(notification & canLEVEL_TxOK))
        {
            for(i=0;i<8;i++)
            {
                if((candata[2].canreg->MSGVALx[0] & (1<<i)) != 0)
                    candata[2].isSending[i+1] = 0;
            }
        }
    }

    I'v protect

    the interrupt of sending process(by CANSendToStatusRunning )

    the misuse of unfinish sending messagebox (by candata[2].isSending)

    I‘v also tried to fix the send function again, make it :

    1、update ID(IF1)

    2、update Data (IF2)

    3、Start tx (IF2)

    It still happen. Is there any way to protect the message?

  • Hello RuiZhi,

    Quick question:

    You use IF1 to update ID and IF2 to update data in the function canSimpleTransmit(). Does this function work? 

  • yes,this function works , I triggered the IF1\IF2 by reg NO at the end of the function canSimpleTransmitz()

  • Hi Ruizhi,

    The calls on line 8&10 are still wrong, "CANSendToStatus(canREG3, temp, 0x00);" it should be "CANSendToStatus(canREG3, 0, temp);"

    You don't need to use IF1 and IF2, you could load IF1 with ID and DATA and transfer it to the MBOX in one shot.

    Like QJ mentioned before, lower mailboxes have higher priority and higher mailboxes will never get transmitted!

     

  • I'v tried use IF1 only. It doesn't work.

    Maybe I have something wrong, I'll try this way again.

  • Both work. You can use either IF1 or IF2, or both.

    This is my test case:

    I use IF1 for transferring data to message objects, and use IF2 to update message ID. 

    55611.sys_main.c

  • Thanks for your help.

    There are some differences between yours and mine.

    I send CAN Msg continuously in the forever loop and you only send CAN Msg once in one messagebox.

    I use outside CAN receiver to check the message on CAN H/L, you use the CAN module inside the TMS570 to check the message.

    I think , this may cause the different in final result.

  • #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
    #else
        static const uint32 s_canByteOrder[8U] = {3U, 2U, 1U, 0U, 7U, 6U, 5U, 4U};
    #endif
    
    uint8_t canSimpleTransmit1(canBASE_t *const canreg, uint32_t msgbox, uint32_t ID, uint8_t * data)
    {
        uint32 i;
        uint32 success  = 0U;
        uint32 regIndex = (msgbox - 1U) >> 5U;
        uint32 bitIndex = 1U << ((msgbox - 1U) & 0x1FU);
    
        /** - Check for pending message:
        *     - pending message, return 0
        *     - no pending message, start new transmission
        */
        if ((canreg->TXRQx[regIndex] & bitIndex) != 0U)
        {
            success = 0U;
        }
        else
        {
            /** - Wait until IF1 is ready for use */
            while(
                    ((canreg->IF1STAT & 0x80U) ==0x80U)
                    )
            {
            } /* Wait */
    
            /** - Configure IF1 for
            *     - Message direction - Read
            *     - Data Read
            *     - Clears NewDat bit in the message object.
            */
            canreg->IF1CMD = 0xA0U;
            /* Copy passed value into the arbitration register. */
            canreg->IF1ARB &= 0x80000000U;
            canreg->IF1ARB |= (ID & 0x7FFFFFFFU);
    
            /** - Update message box number. */
            /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */
            canreg->IF1NO = (uint8) msgbox;
    
            /** - Wait until data are copied into IF1 */
            while ((canreg->IF1STAT & 0x80U) ==0x80U)
            {
            } /* Wait */
    
            /** - Configure IF1 for
            *     - Message direction - Write
            *     - Data Update
            *     - Start Transmission
            */
            canreg->IF1CMD = 0x83U;
    
            /** - Copy TX data into IF1 */
            for (i = 0U; i < 8U; i++)
            {
    #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
                /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
                node->IF1DATx[i] = *data;
                /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
                /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
                data++;
    #else
                /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
                canreg->IF1DATx[s_canByteOrder[i]] = *data;
                /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
                /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
                data++;
    #endif
            }
    
            /** - Copy TX data into message box */
            /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */
            canreg->IF1NO = (uint8) msgbox;
    
            /** - Wait until data are copied into IF1 */
            while ((canreg->IF1STAT & 0x80U) ==0x80U)
            {
            } /* Wait */
    
            canreg->IF1CMD = 0x84U;
    
            /** - Copy TX data into message box */
            /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */
            canreg->IF1NO = (uint8) msgbox;
    
            /** - Wait until data are copied into IF1 */
            while ((canreg->IF1STAT & 0x80U) ==0x80U)
            {
            } /* Wait */
    
            success = 1U;
        }
        return success;
    }

    My Tx Code is now IF1 only. 

    In my usage, I receive Can Msg from Can1&Can2, Send this Msg to CAN3

    I save the messages which indicate the error of my equp.

    CAN1&2 Data

    2020-10-14 17:24:30:1532051   : 614152 6D,11,11,11,32,21,00,00    **
    2020-10-14 17:24:30:1532056   : 614153 6E,11,11,11,32,22,00,00    **

    CAN3 Data

    2020-10-14 17:22:52:1719344   : 17413260 85,00,00,FF,FF,00,00,00
    2020-10-14 17:22:52:1719350   : 17413260 00,FF,FF,00,00,00,00,00
    2020-10-14 17:23:32:2117092   : 17413160 BB,00,00,FF,FF,00,00,00
    2020-10-14 17:24:30:2700886   : 17416152 6D,11,11,11,32,21,00,00    **
    2020-10-14 17:24:30:2700892   : 17416152 6D,11,11,11,32,21,00,00    **
    2020-10-14 17:24:30:2700897   : 17416153 6E,11,11,11,32,22,00,00    **
    2020-10-14 17:24:30:2700902   : 17416153 6E,11,11,11,32,22,00,00    **
    2020-10-14 17:30:17:6164970   : 17415820 90,00,00,00,00,00,00,00
    2020-10-14 17:32:16:7350478   : 17415820 F3,00,00,00,00,00,00,00
    2020-10-14 17:38:22:11010371  : 17415120 C9,00,00,00,00,00,00,00
    2020-10-14 17:38:59:11376901  : 17415120 49,00,00,00,00,00,00,00
    2020-10-14 17:39:13:11513721  : 17415120 59,00,00,00,00,00,00,00
    2020-10-14 17:39:41:11791378  : 17415120 91,00,00,00,00,00,00,00
    2020-10-14 17:39:47:11854306  : 17415120 E3,00,00,00,00,00,00,00
    2020-10-14 17:40:07:12059059  : 17415120 72,00,00,00,00,00,00,00
    2020-10-14 17:40:08:12064048  : 17415120 A2,00,00,00,00,00,00,00
    2020-10-14 17:40:56:12541463  : 17415120 3C,00,00,00,00,00,00,00
    2020-10-14 17:40:58:12567425  : 17415120 32,00,00,00,00,00,00,00
    2020-10-14 17:41:05:12630342  : 17415120 81,00,00,00,00,00,00,00
    2020-10-14 17:44:26:14649467  : 17415220 F7,00,00,00,00,00,00,00
    2020-10-14 17:44:48:14859196  : 17415220 B6,00,00,00,00,00,00,00
    2020-10-14 17:44:53:14911149  : 17415220 9C,00,00,00,00,00,00,00
    2020-10-14 17:45:22:15204792  : 17415220 6E,00,00,00,00,00,00,00
    2020-10-14 17:45:30:15283684  : 17415220 AE,00,00,00,00,00,00,00
    2020-10-14 17:45:47:15456470  : 17415220 B6,00,00,00,00,00,00,00
    2020-10-14 17:46:47:16054720  : 17415220 C7,00,00,00,00,00,00,00
    2020-10-14 17:48:02:16798801  : 17415220 36,00,00,00,00,00,00,00
    2020-10-14 17:48:53:17313172  : 17415220 2F,00,00,00,00,00,00,00
    2020-10-14 17:49:02:17402068  : 17415220 77,00,00,00,00,00,00,00
    2020-10-14 17:49:07:17448999  : 17415220 85,00,00,00,00,00,00,00
    2020-10-14 17:49:07:17449620  : 17413160 15,11,11,11,32,21,00,00
    2020-10-14 17:50:10:18073239  : 17415220 37,00,00,00,00,00,00,00
    2020-10-14 17:53:05:19829670  : 17413160 64,11,11,11,32,21,00,00
    

    Only lines mark with star is match, which means that the msg is from CAN1&2 to CAN3.

  • Hello,

    My code keeps sending CAN message for messagebox1 and messagebox2 for 64 times. Before transferring the next message, the code checks the TX Complete flag first. 

  • Thanks for your help.

    If I may ask you for a dynamic message box sample in about 8 msgboxes in both ID and data.

    In your code ,the ID in msgbox get no changes in different sending.

    It's like, different ID, different Data and msgboxes use in a circle~

    Thanks and Regards,

    Ruizhi Lee

  • Hello Ruizhi,

    I call the function to update the message ID, but the function uses the same message ID. After you change the message ID, you have to change the filer setting in receive side, otherwise the message may be ignored or over-write another mail box.

    I can do a test using 8 mailboxes. 

  • I used to use a CAN debugger outside to receive the can msg.

    I think in your test program

    you may use a message box filter in 0xFFFFFFFF which means receive all messages.

    judge the can message by ID-Data such as:

    ID 0x00 Data 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

    ID 0xff Data 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

    make it send in a infinite loop.

    Thank you very much, you and TI have a great support for us users.

  • Thanks. We are working this issue offline.

  • I'm looking forward to hearing from you~

    Have you reproduced the malfunction?

    Thanks and Regards,

    RZ Lee

  • Hi RZ,

    I did similar test: keeping transmitting data, and update the ID every time. I didn't see the error. The next transfer doesn't start until the previous packet is transmitted successfully:

    while(1){
    /** - starting transmission */
    tx_ptr = &tx_data[0][0];
    j++;

    for(cnt=1; cnt<17; cnt++)
    {
    msgBox = cnt%17;
    boxID = 0x5A0000 | (j<<8) + msgBox;
    canUpdateID(canREG1, msgBox, 3U << 30U | 1U << 29U | (boxID & 0x1FFFFFFFU));
    canUpdateID(canREG2, msgBox, 3U << 30U | 0U << 29U | (boxID & 0x1FFFFFFFU));

    do{
    loopcnt++;
    send_ret = canTransmit(canREG1, msgBox, tx_ptr);
    if (send_ret != 1) {
    delayus(10);
    }
    }while((send_ret == 0) && (loopcnt < PF_CAN_SEND_RETRY));

    u8_lastErr = canGetLastError(canREG1);
    u8_levelErr = canGetErrorLevel(canREG1);

    if (loopcnt >= PF_CAN_SEND_RETRY || u8_levelErr != 0 || (u8_lastErr != 0 && u8_lastErr != 7))
    {
    txerror++;
    }

    while(tx_done == 0){};
    tx_done=0;
    tx_ptr +=8; /* next chunk ...*/
    }
    }