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.

TMS570 CAN RX problem

Other Parts Discussed in Thread: HALCOGEN

Hello all,

I have problems receiving can messages. I'm working with a LAUNCHXL2-TMS57012 and I configured CAN2 for sending messages via Messagebox 1 and receiving messages via Messagebox 2 using HalCoGen like shown below.

I also enabled the VIM Channel 35 CAN2 High Interrupt.

I'm able now to receive messages and send messages. But after I send the first message I don't receive any messages any more. I dont even get an RX Interrupt. On a CAN-BUS monitor the messages looks fine.

Here's my  code for sending  messages:

bool Can_Send(CanHandlePtr_t _p_Handle, uint32_t _u32_ID, CanMsgIdType_t _e_MsgIdType, CanFrameType_t _e_FrameType, uint8_t _u8_DataLen, uint8_t* _p_u8_Data) {

    uint32_t regIndex = (DCAN_TX_MESSAGE_BOX - 1U) >> 5U;
    uint32_t bitIndex = 1U << ((DCAN_TX_MESSAGE_BOX - 1U) & 0x1FU);

    if ( NULL == _p_Handle ) {

        return(false);
    }


    /*  - Check for pending message:
     *  - pending message, return 0
     *  - no pending message, start new transmission
     */
    if ((_p_Handle->p_CAN->TXRQx[regIndex] & bitIndex) != 0U) {

        return(false);
    }


    /* - Wait until IF1 is ready for use
     */
    while ((_p_Handle->p_CAN->IF1STAT & (1U<<7)) == (1U<<7));


    _p_Handle->p_CAN->IF1MSK =  0           // Msk = Don't care
                              | (0U<<29)    // Rsvd
                              | (0U<<30)    // MDir
                              | (0U<<31);   // MXtd

    _p_Handle->p_CAN->IF1CMD =  (1U<<7)     // WR
                              | (1U<<6)     // Write Mask Bits
                              | (1U<<5)     // Write Arbitration Bits
                              | (1U<<4)     // Write Control Bits
                              | (0U<<3)     // CtrlIntPnd
                              | (1U<<2)     // TxReqst
                              | (1U<<1)     // DATA A
                              | (1U<<0);    // DATA B

    _p_Handle->p_CAN->IF1ARB =  _u32_ID                                          // Message ID
                              | ((E_CAN_DATA_FRAME == _e_FrameType ? 1U : 0U) << 29)  // Data or Remote Frame
                              | (1U<<30)                                         // Extended Frame
                              | (1U<<31);                                        // Message Valid

    /* Set Data Bytes */
    for (int i = 0U; i < _u8_DataLen; i++) {

        _p_Handle->p_CAN->IF1DATx[s_canByteOrder[i]] = _p_u8_Data[i];
    }


    /* Copy TX data into message box */
    _p_Handle->p_CAN->IF1NO = (uint8)DCAN_TX_MESSAGE_BOX;

    return(true);
}

And the Interrupt Handler for receiving messages:

void canMessageNotification(canBASE_t *node, uint32 messageBox) {

    uint32_t u32_MsgID              = 0;
    uint32_t u8_DLC                 = 0;
    uint8_t  au8_Data[8]            = {0};
    CanMsgIdType_t e_MsgIdType      = E_CAN_EXT_MSG;
    CanFrameType_t e_MsgFrameType   = E_CAN_DATA_FRAME;

    CanHandle_t* p_Handle = NULL;


    if( !canIsRxMessageArrived(node, DCAN_RX_MESSAGE_BOX) ) {

        return;
    }


    if( node == canREG1 ) {

        p_Handle = GetInstance(E_CAN_NO_0);

    } else if ( node == canREG2 ) {

        p_Handle = GetInstance(E_CAN_NO_1);

    } else if ( node == canREG3 ) {

        p_Handle = GetInstance(E_CAN_NO_2);
    }


    if( NULL == p_Handle ) {

        return;
    }

    /* Wait until IF2 is ready for use */
    while ((p_Handle->p_CAN->IF2STAT & 0x80U) == 0x80U);


    p_Handle->p_CAN->IF2CMD =   (0U<<7)     // RD
                              | (1U<<6)     // Read Mask Bits
                              | (1U<<5)     // Read Arbitration Bits
                              | (1U<<4)     // Read Control Bits
                              | (0U<<3)     // CtrlIntPnd
                              | (1U<<2)     // TxReqst
                              | (1U<<1)     // DATA A
                              | (1U<<0);    // DATA B

    /* Copy data into IF2 */
    p_Handle->p_CAN->IF2NO = (uint8)DCAN_RX_MESSAGE_BOX;

    /* Wait until data are copied into IF2 */
    while ((p_Handle->p_CAN->IF2STAT & 0x80U) ==0x80U);

    /** - Get number of received bytes
    *   - Value from 0x8 to 0xF equals length 8.
    */
    u8_DLC = (uint8_t)p_Handle->p_CAN->IF2MCTL & 0xFU;

    if(u8_DLC > 8) {

        u8_DLC = 8;
    }

    /* Copy RX data into destination buffer */
    for (int i = 0; i < u8_DLC; i++) {

        au8_Data[i] = p_Handle->p_CAN->IF2DATx[s_canByteOrder[i]];
    }


    /* Read Message ID from Arbitration register. */
    u32_MsgID = (p_Handle->p_CAN->IF2ARB & 0x1FFFFFFFU);

    /* Read Message ID Type from Arbitration register. */
    e_MsgIdType = (p_Handle->p_CAN->IF2ARB & (1<<30)) == (1<<30) ? E_CAN_EXT_MSG : E_CAN_STD_MSG;

    /* Read Message Frame Type from Mask register. */
    e_MsgFrameType = (p_Handle->p_CAN->IF2MSK & (1<<8)) == (1<<8) ? E_CAN_REMOTE_FRAME : E_CAN_DATA_FRAME;


    if( NULL != p_Handle->Callback )  {

        (p_Handle->Callback)(p_Handle->p_ClientData, u32_MsgID, e_MsgIdType, e_MsgFrameType, u8_DLC, &(au8_Data[0]));
    }

}

 

Any help is appreciated!
Best Regards
Jens

  • I would suggest you to take a look at the CAN communication module of the TMS570 bootloader in the following link.

    processors.wiki.ti.com/.../TMS570_Hercules_MCU_Bootloader

    Thanks and regards,

    Zhaohong
  • Hello Zhaohong,

    thank you very much for your reply. I just looked at the example code of the bootloader but I can't find a out what I'm doing wrong. In principle I'm doing it the same way. I tried to break down the the problem and I figured out that I don't receive any messages any more after I write the the message number of the transmit messagebox (1U) to the IF1NO register. I don't get any receive interrupts any more but I still get transmit complete interrupts after each message sent.

    Best Regards
    Jens
  • Jens, You need to clear the interrupt pending flag in canMessageNotification() by setting BIT_3 of IF2->CMD Register. -Joe
  • Hello Joe,

    thank you for your hint. I checked that but the interrupt pending flag is alredy cleared by the code generated by HalcoGen (see below):

    void can2HighLevelInterrupt(void)
    {
        uint32 value = canREG2->INT;
        uint32 ES_value;
        
    /* USER CODE BEGIN (47) */
    /* USER CODE END */

        if (value == 0x8000U)
        {
            /* Read Error and Status Register*/
            ES_value = canREG2->ES;
            
            /* Check for Error (PES, Boff, EWarn & EPass) captured */
            if((ES_value & 0x1E0U) != 0U)
            {
                canErrorNotification(canREG2, ES_value & 0x1E0U);
            }
            else
            {   
                /* Call General Can notification incase of RxOK, TxOK, PDA, WakeupPnd Interrupt */
                canStatusChangeNotification(canREG2, ES_value & 0x618U);
            }
        }
        else
        {
            /** - Setup IF1 for clear pending interrupt flag */
            /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */
            while ((canREG2->IF1STAT & 0x80U) ==0x80U)
            {
            } /* Wait */

            canREG2->IF1CMD = 0x08U;
            /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */
            canREG2->IF1NO  = (uint8) value;
            
            /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */
            while ((canREG2->IF1STAT & 0x80U) ==0x80U)
            {
            } /* Wait */
            canREG2->IF1CMD = 0x87U;

            canMessageNotification(canREG2, value);
        }
    /* USER CODE BEGIN (48) */
    /* USER CODE END */
        
    }

    Furthermore the code works fine as long I only receive can messages. After the first transmit I don't recieve any messges any more until I reset the controller.

    All the examples I found either use no interrupts or send messages from one CAN Interface to another CAN Interface.

    Any other Ideas?

    Kind Regards

    Jens

  • Jens, You may run into a race condition by using IF2 in your RX() interrupt and IF2 in your TX() routine. Change your Notification() routine to use IF1 as used by the ISR() and use IF2 just only in TX(). -Joe
  • Hello Joe,

    I finanly solved the problem. While debugging I observed the CAN Message RAM. After the first transmission and after the next message I want to receive I found the missing message in MessageBox 1 instead of MessageBox2. The reason is this part of my transmit function:

    ...

    _p_Handle->p_CAN->IF1CMD =  (1U<<7)     // WR
                               | (1U<<6)     // Write Mask Bits
                               | (1U<<5)     // Write Arbitration Bits
                               | (1U<<4)     // Write Control Bits
                               | (0U<<3)     // CtrlIntPnd
                               | (1U<<2)     // TxReqst
                               | (1U<<1)     // DATA A
                               | (1U<<0);    // DATA B 

    ...

     

    with (1U<<6) I accidentally overwrotte the maskbits of MessageBox 1 so that the message I want to receive seems to be  accepted by this MessageBox.

    The correction below solves the problem:

    _p_Handle->p_CAN->IF1CMD =  (1U<<7)     // WR
                               | (0U<<6)     // Write Mask Bits         <-----------------
                               | (1U<<5)     // Write Arbitration Bits
                               | (1U<<4)     // Write Control Bits
                               | (0U<<3)     // CtrlIntPnd
                               | (1U<<2)     // TxReqst
                               | (1U<<1)     // DATA A
                               | (1U<<0);    // DATA B 

     

    Thank you very much for your help!


    Best Regards

    Jens