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.

TMS320F28P550SJ: F28P55: MCAN used as classic CAN with extend ID

Part Number: TMS320F28P550SJ
Other Parts Discussed in Thread: C2000WARE, TMS320F28075

Tool/software:

Hi Team/experts,

    I try to use MCAN module works as classic CAN with an extend ID.

    So I combined  "mcan_ex4_receive.c" and "mcan_ex9_transmit.c" in C2000Ware_5_04_00_00 and do some changes, it works with a standard ID (txMsg[loopCnt].xtd = 0U) in loopback mode(INTERNAL),but the ID

    received is not  equal to the ID I sent .

    for example :

    tx ID: 0x100000; rx ID:0x100008, 

    tx ID: 0x100001; rx ID:0x102008, 

    tx ID: 0x10000F; rx ID:0x11E008, 

    when I change txMsg[loopCnt].xtd to 1, it fails to communicate.

//
// Include Files
//
#include "driverlib.h"
#include "device.h"
#include "inc/stw_types.h"
#include "inc/stw_dataTypes.h"
#include <string.h>

#define NUM_OF_MSG                      (1U)
#define MCAN_STD_ID_FILTER_NUM          (1U)
#define MCAN_EXT_ID_FILTER_NUM          (1U)
#define MCAN_FIFO_0_NUM                 (0U)
#define MCAN_FIFO_0_ELEM_SIZE           (MCAN_ELEM_SIZE_64BYTES)
#define MCAN_FIFO_1_NUM                 (0U)
#define MCAN_FIFO_1_ELEM_SIZE           (MCAN_ELEM_SIZE_64BYTES)
#define MCAN_RX_BUFF_NUM                (10U)
#define MCAN_RX_BUFF_ELEM_SIZE          (MCAN_ELEM_SIZE_8BYTES)
#define MCAN_TX_BUFF_SIZE               (1U)
#define MCAN_TX_FQ_SIZE                 (0U)
#define MCAN_TX_BUFF_ELEM_SIZE          (MCAN_ELEM_SIZE_8BYTES)
#define MCAN_TX_EVENT_SIZE              (0U)

#define MCAN_STD_ID_FILT_START_ADDR     (0x0U)
#define MCAN_EXT_ID_FILT_START_ADDR     (MCAN_STD_ID_FILT_START_ADDR + ((MCAN_STD_ID_FILTER_NUM * MCANSS_STD_ID_FILTER_SIZE_WORDS * 4U)))
#define MCAN_FIFO_0_START_ADDR          (MCAN_EXT_ID_FILT_START_ADDR + ((MCAN_EXT_ID_FILTER_NUM * MCANSS_EXT_ID_FILTER_SIZE_WORDS * 4U)))
#define MCAN_FIFO_1_START_ADDR          (MCAN_FIFO_0_START_ADDR + (MCAN_getMsgObjSize(MCAN_FIFO_0_ELEM_SIZE) * 4U * MCAN_FIFO_0_NUM))
#define MCAN_RX_BUFF_START_ADDR         (MCAN_FIFO_1_START_ADDR + (MCAN_getMsgObjSize(MCAN_FIFO_1_ELEM_SIZE) * 4U * MCAN_FIFO_1_NUM))
#define MCAN_TX_BUFF_START_ADDR         (MCAN_RX_BUFF_START_ADDR + (MCAN_getMsgObjSize(MCAN_RX_BUFF_ELEM_SIZE) * 4U * MCAN_RX_BUFF_NUM))
#define MCAN_TX_EVENT_START_ADDR        (MCAN_TX_BUFF_START_ADDR + (MCAN_getMsgObjSize(MCAN_TX_BUFF_ELEM_SIZE) * 4U * (MCAN_TX_BUFF_SIZE + MCAN_TX_FQ_SIZE)))

int32_t     error = 0;
int32_t     error1 = 0;
int a = 1;
int32_t id = 0x100000U;
MCAN_RxBufElement rxMsg[NUM_OF_MSG], rxMsg1;
MCAN_TxBufElement txMsg[NUM_OF_MSG];
int32_t loopCnt = 0U;

static void MCANConfig(void);
static void MCANIntrConfig(void);
__interrupt void MCANIntr1ISR(void);

void main()
{
    int i = 0;
    volatile uint32_t mode = 0U;
    uint32_t dataBytes = 8;

    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Initialize GPIO and unlock the GPIO configuration registers
    //
    Device_initGPIO();

    //
    // Configure the divisor for the MCAN bit-clock
    //
    SysCtl_setMCANClk(SYSCTL_MCANA, SYSCTL_MCANCLK_DIV_5);

    //
    // ISR Configuration.
    //
    MCANIntrConfig();

    //
    // Configure GPIO pins for MCANTX/MCANRX operation
    //
    GPIO_setPinConfig(DEVICE_GPIO_CFG_MCANRXA);
    GPIO_setPinConfig(DEVICE_GPIO_CFG_MCANTXA);

    //
    // Initialize message to receive
    //
    rxMsg[loopCnt].id = 0U;
    rxMsg[loopCnt].rtr = 0U;
    rxMsg[loopCnt].xtd = 0U;
    rxMsg[loopCnt].esi = 0U;
    rxMsg[loopCnt].rxts = 0U;   // Rx Timestamp
    rxMsg[loopCnt].dlc = 0U;
    rxMsg[loopCnt].brs = 0U;
    rxMsg[loopCnt].fdf = 0U;
    rxMsg[loopCnt].fidx = 0U;   // Filter Index
                                // (of matching Rx acceptance filter element)
    rxMsg[loopCnt].anmf = 0U;   // Accepted Non-matching Frame

    for(i = 0; i < dataBytes; i++)  // Initialize receive buffer to 0
    {
        rxMsg[loopCnt].data[i]  = 0;
    }
    
    
    txMsg[loopCnt].id       = ((uint32_t)(0x4)) << 18U; // STDID[28:18]
    txMsg[loopCnt].rtr      = 0U;   // RTR = 0 (Data frame)
    txMsg[loopCnt].xtd      = 0U;   // XTD = 0 (11-bit standard identifier)
    txMsg[loopCnt].esi      = 0U;
    txMsg[loopCnt].dlc      = 8U;  // 64 bytes
    txMsg[loopCnt].brs      = 1U;   // Bit-rate switching enabled
    txMsg[loopCnt].fdf      = 1U;   // Frame transmitted in CAN FD format
    txMsg[loopCnt].efc      = 1U;   // Store TX events
    txMsg[loopCnt].mm       = 0xAAU;
    txMsg[loopCnt].data[i]  = 0x1;
    for(i = 1; i < dataBytes; i++)
    {
        txMsg[loopCnt].data[i]  = txMsg[loopCnt].data[i-1] + 1;
    }
    i = 0;


    //
    // Configure the MCAN Module.
    //
    MCANConfig();

    //
    // Enable Interrupts.
    //
    MCAN_enableIntr(MCANA_DRIVER_BASE, MCAN_INTR_MASK_ALL, 1U);

    //
    // Select Interrupt Line.
    //
    MCAN_selectIntrLine(MCANA_DRIVER_BASE, MCAN_INTR_MASK_ALL, MCAN_INTR_LINE_NUM_1);

    //
    // Enable Interrupt Line.
    //
    MCAN_enableIntrLine(MCANA_DRIVER_BASE, MCAN_INTR_LINE_NUM_1, 1U);

    while(1)
    {
        //
        //  Adding delay of 1 second
        //
        
        txMsg[loopCnt].id       = id;//((uint32_t)(0x4)) << 18U; // STDID[28:18]
    txMsg[loopCnt].rtr      = 0U;   // RTR = 0 (Data frame)
    txMsg[loopCnt].xtd      = 0U;   // XTD = 0 (11-bit standard identifier)
    txMsg[loopCnt].esi      = 0U;
    txMsg[loopCnt].dlc      = 8U;  // 64 bytes
    txMsg[loopCnt].brs      = 1U;   // Bit-rate switching enabled
    txMsg[loopCnt].fdf      = 1U;   // Frame transmitted in CAN FD format
    txMsg[loopCnt].efc      = 1U;   // Store TX events
    txMsg[loopCnt].mm       = 0xAAU;
    txMsg[loopCnt].data[i]  = 0x1;
    for(i = 1; i < dataBytes; i++)
    {
        txMsg[loopCnt].data[i]  = txMsg[loopCnt].data[i-1] + 1;
    }
    i = 0;
    
     MCAN_writeMsgRam(MCANA_DRIVER_BASE, MCAN_MEM_TYPE_BUF, loopCnt,
                     &txMsg[loopCnt]);

    //
    // Add transmission request for Tx buffer 0
    //
    MCAN_txBufAddReq(MCANA_DRIVER_BASE, 0U);
    
        DEVICE_DELAY_US(1000000);

        //
        //  Message Handling Code goes here
        //
        
       


    }

    //
    // Stop Application.
    //
    asm("   ESTOP0");
}

static void MCANConfig(void)
{
    MCAN_InitParams initParams;
    MCAN_MsgRAMConfigParams    msgRAMConfigParams;
    MCAN_StdMsgIDFilterElement stdFiltelem;
    MCAN_BitTimingParams       bitTimes;
    MCAN_ExtMsgIDFilterElement extFiltelem;

    //
    //  Initializing all structs to zero to prevent stray values
    //
    memset(&initParams, 0, sizeof(initParams));
    memset(&msgRAMConfigParams, 0, sizeof(msgRAMConfigParams));
    memset(&stdFiltelem, 0, sizeof(stdFiltelem));
    memset(&bitTimes, 0, sizeof(bitTimes));
    memset(&extFiltelem, 0, sizeof(extFiltelem));

    //
    // Configure MCAN initialization parameters
    //
    initParams.fdMode            = 0x0U; // FD operation enabled.
    initParams.brsEnable         = 0x0U; // Bit rate switching enabled
    
    initParams.tdcConfig.tdcf    = 0xAU;
     initParams.tdcConfig.tdco    = 0x6U;

    //
    // Initialize Message RAM Sections Configuration Parameters
    //
    msgRAMConfigParams.flssa                = MCAN_STD_ID_FILT_START_ADDR;
    // Standard ID Filter List Start Address.
    msgRAMConfigParams.lss                  = MCAN_STD_ID_FILTER_NUM;
    // List Size: Standard ID.
    msgRAMConfigParams.flesa                = MCAN_EXT_ID_FILT_START_ADDR;
    
    msgRAMConfigParams.lse                  = MCAN_EXT_ID_FILTER_NUM;
    
    msgRAMConfigParams.rxBufStartAddr       = MCAN_RX_BUFF_START_ADDR;
    // Rx Buffer Start Address.
    msgRAMConfigParams.rxBufElemSize        = MCAN_RX_BUFF_ELEM_SIZE;
    // Rx Buffer Element Size.
    
     msgRAMConfigParams.txStartAddr          = MCAN_TX_BUFF_START_ADDR;
    // Tx Buffers Start Address.

    msgRAMConfigParams.txBufNum             = MCAN_TX_BUFF_SIZE;
    // Number of Dedicated Transmit Buffers.

    msgRAMConfigParams.txBufMode            = 0U;

    msgRAMConfigParams.txFIFOSize           = MCAN_TX_FQ_SIZE; 
    // Number of Tx FIFO or Tx Queue Elements

    msgRAMConfigParams.txBufElemSize        = MCAN_TX_BUFF_ELEM_SIZE;
    // Tx Buffer Element Size.


    //
    // Initialize Rx Buffer Configuration parameters.
    //
    stdFiltelem.sfid2              = 0x0U; // Standard Filter ID 2.
    // Configuring received frame to be stored in buffer element 0
    stdFiltelem.sfid1              = 0x4U; // Standard Filter ID 1.
    // Confifuring frames with msg ID = 0x4U to be accepted by filter element
    stdFiltelem.sfec               = 0x7U; // Store into Rx Buffer
                                           // configuration of SFT[1:0] ignored
extFiltelem.efid2               = 0x0U;
extFiltelem.efid1               = 0x0U;
extFiltelem.efec                = 0x0U; 
extFiltelem.eft                 = 0x0U; 

    //
    // Initialize bit timings.
    //
    bitTimes.nomRatePrescalar   = 0xBU; // Nominal Baud Rate Pre-scaler
    bitTimes.nomTimeSeg1        = 0x2U; // Nominal Time segment before SP
    bitTimes.nomTimeSeg2        = 0x0U; // Nominal Time segment after SP
    bitTimes.nomSynchJumpWidth  = 0x0U; // Nominal SJW
    bitTimes.dataRatePrescalar  = 0x1U; // Data Baud Rate Pre-scaler
    bitTimes.dataTimeSeg1       = 0xAU; // Data Time segment before SP
    bitTimes.dataTimeSeg2       = 0x2U; // Data Time segment after SP
    bitTimes.dataSynchJumpWidth = 0x2U; // Data SJW

    //
    // Wait for memory initialization to happen.
    //
    while(FALSE == MCAN_isMemInitDone(MCANA_DRIVER_BASE))
    {
    }

    //
    // Put MCAN in SW initialization mode.
    //
    MCAN_setOpMode(MCANA_DRIVER_BASE, MCAN_OPERATION_MODE_SW_INIT);

    //
    // Wait till MCAN is not initialized.
    //
    while (MCAN_OPERATION_MODE_SW_INIT != MCAN_getOpMode(MCANA_DRIVER_BASE))
    {}

    //
    // Initialize MCAN module.
    //
    MCAN_init(MCANA_DRIVER_BASE, &initParams);

    //
    // Configure Bit timings.
    //
    MCAN_setBitTime(MCANA_DRIVER_BASE, &bitTimes);

    //
    // Configure Message RAM Sections
    //
    MCAN_msgRAMConfig(MCANA_DRIVER_BASE, &msgRAMConfigParams);

    //
    // Configure Standard ID filter element
    //
    MCAN_addStdMsgIDFilter(MCANA_DRIVER_BASE, 0U, &stdFiltelem);
    
    MCAN_addExtMsgIDFilter(MCANA_DRIVER_BASE, 0U, &extFiltelem);
    
     MCAN_lpbkModeEnable(MCANA_DRIVER_BASE,  MCAN_LPBK_MODE_INTERNAL, TRUE);

    //
    // Take MCAN out of the SW initialization mode
    //
    MCAN_setOpMode(MCANA_DRIVER_BASE, MCAN_OPERATION_MODE_NORMAL);

    while (MCAN_OPERATION_MODE_NORMAL != MCAN_getOpMode(MCANA_DRIVER_BASE))
    {

    }
}

//
// This function will configure X-BAR for MCAN interrupts.
//
static void MCANIntrConfig(void)
{

    Interrupt_initModule();
    Interrupt_initVectorTable();

    Interrupt_register(INT_MCANA_1,&MCANIntr1ISR);
    Interrupt_enable(INT_MCANA_1);

    Interrupt_enableGlobal();

}

//
// This is Interrupt Service Routine for MCAN interrupt 1.
//
__interrupt void MCANIntr1ISR(void)
{
    uint32_t intrStatus;
    MCAN_RxNewDataStatus newData;

    intrStatus = MCAN_getIntrStatus(MCANA_DRIVER_BASE);

    //
    // Clear the interrupt Status.
    //
    MCAN_clearIntrStatus(MCANA_DRIVER_BASE, intrStatus);

    //
    //  Clearing the interrupt lineNum
    //
    MCAN_clearInterrupt(MCANA_DRIVER_BASE, 0x2);

    //
    //  Check to see if the interrupt is caused by a message being
    //  received in dedicated RX Buffers
    //
    if((MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG & intrStatus) == MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG)
    {
        //
        // Read the NewData registers
        //
        MCAN_getNewDataStatus(MCANA_DRIVER_BASE, &newData);

        //  If message is received in buffer element 0
        if((newData.statusLow & (1UL << 0U)) != 0)
        {
            MCAN_readMsgRam(MCANA_DRIVER_BASE, MCAN_MEM_TYPE_BUF, 0U,
                          0, &rxMsg1);

            rxMsg[loopCnt] = rxMsg1;
        }

        //
        //  Clearing the NewData registers
        //
        MCAN_clearNewDataStatus(MCANA_DRIVER_BASE, &newData);
    }
    else
    {
        error++;

        //
        //  Interrupt handling for other interrupt sources goes here
        //

    }

    //
    // Acknowledge this interrupt located in group 9
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}

    what I realy want is a extend Id (29 bit) without any masks or filters,receive as it's sent.

Best Regards,

Zane

  • Hi Zane,

    Thanks for reaching out. It appears that we have a thread with the same question, we will resort to this thread to continue debug and address the issue.

    Best Regards,

    Zackary Fleenor

  • Hey Zane,

    On line 99 and 142 of the code you sent the tx/rxMsg configuration is using xtd = 0, designating a standard 11-bit identifier.

    Extended Identifier (xtd)
    0 = 11-bit standard identifier
    1 = 29-bit extended identifier

    When you say 

        when I change txMsg[loopCnt].xtd to 1, it fails to communicate.

    What is the failure signature here? How does it fail to communicate?

    Do you have a CAN Analyzer, Logic Analyzer, Oscope, or similar tool to examine the CAN bus itself and verify the data sent on the line?

    Best Regards,

    Zackary Fleenor

  • Hey Fleenor,

       The original issue is fixed by this "#define MCAN_EXT_ID_AND_MASK            (0x00000000U)" ,datas and ID are receiced correctly.

       Then I  closed the loopback mode by block this sentence ( "// MCAN_lpbkModeEnable(MCANA_DRIVER_BASE, MCAN_LPBK_MODE_INTERNAL,

       TRUE);") and programed the same firmware into two CPUs and connect them by wires, it can't received data, 

       In the interrupt "intrStatus"  got a value 0x08000000U , which means "Protocol Error in Arbitration Phase interrupt".

       Is there any setting is missing?

        Best Regards,

    Darcy Liu

  • Hey Darcy,

    When you say:

    programed the same firmware into two CPUs and connect them by wires

    Does this mean you programmed this to two different launchpads together? Or literally two cpu cores on the same device?

    Have you set the S4 CAN Routing Switch down (ON)  to route it to the CAN Transceiver instead of the boosterpack headers?

    Best Regards,

    Zackary Fleenor

  • Hi Fleenor,

    It's two identical boards with all peripheral circuit, I am not using a launchpad.

    Here are  signals I tested :

    picture 1 / 2 are tested in loopback mode (MCAN_lpbkModeEnable(MCANA_DRIVER_BASE, MCAN_LPBK_MODE_EXTERN, TRUE))

    picture 3 / 4 shows signals of normal mode (just by blocking MCAN_lpbkModeEnable(MCANA_DRIVER_BASE, MCAN_LPBK_MODE_EXTERN, TRUE))

      

    Best Regards,

      Darcy Liu

  • Hey Darcy,

    Thanks for this information.

    1) Can you provide more details on the board implementation?

    1a) What CAN transceivers are used?

    1b) Can you provide a schematic for review?

    2) Can you check the equivalent code on the Launchpad?

    3) Can you also provide scope shots of the CAN_H/CAN_L signals?

    The scope shots you provided do not look like accurate CAN signals. Please refer to the app note below regarding debugging the CAN bus.

    https://www.ti.com/lit/an/slyt529/slyt529.pdf

    Best Regards,

    Zackary Fleenor

  • Hey Fleenor,

       Thank you for the patience.

       CAN transceivers is HVDA551QDRQ1,schematic is attached below, also I got a scope shots of the CAN_H/CAN_L signals,it doesn't looks right compared which our previous product which use a TMS320F28075 as MCU.

       If a loopback mode can  works,does it means the code is correct and someting wrong with the hardware?

    Best Regards,

     Darcy Liu

  • Hey Darcy,

    I agree with your assessment, SW + Loopback seems to be working but these "HW" signals are not compliant with the CAN standards.

    The schematic you provided doesn't show any termination resistors, is this correct?

    If not, this is likely a probable root cause of your issue. A termination resistor or split termination (if possible) is needed for proper physical layer implementation (refer to the app note below).

    https://www.ti.com/lit/an/slla270/slla270.pdf

    If needed we can loop in the necessary expert from the CAN Transceiver team supporting th HVDA551QDRQ1.

    Best Regards,

    Zackary Fleenor

  • Hey Fleenor,

       Thank you very much for your help,when  the termination resistor added signal become correct.

        One more thing about mcan, when I try to clear the RAM for MCANA in " f28p55x_codestartbranch.asm" by adding this code(in picture),

        After I programmed the MCU,it can't be programmed anymore. Is there anything wrong with the code?

  • Hey Darcy,

    What do you mean by: 

    After I programmed the MCU,it can't be programmed anymore

    I don't see anything glaringly wrong with the code at the moment.

    Is there any reason you can't use the MCAN_msgRAMConfig() and MCAN_isMemInitDone() API's for this?

    Best Regards,

    Zackary Fleenor

  • Hey Fleenor,

       Program can't be loaded in to the MCU I mentioned

      If MCAN_msgRAMConfig() and MCAN_isMemInitDone()  can clear the Ram,it's OK for me.

    Best Regards,

     Darcy Liu

  • Hey Darcy,

    I have some threads open internally to get additional information to address your concern regarding MCAN MSG RAM clearing. Please allow us a few more days to provide a response.

    Best Regards,

    Zackary Fleenor