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.

TMS320F28388D: CAN-FD BRS Enable

Part Number: TMS320F28388D


Hi.

I have a question regarding BRS setup.

If the value of "initParams.brsEnable" in line 221 is set to 0, it was confirmed that the communication operation is normal.

However, if the value of" initParams.brsEnable" is set to 1, the sending operation does not work. Please check if there are any wrong settings

//
// Included Files
//
#include "DSK2838x_Define.h"
#include "easy28x_bitfield_v9.4.h"


//
// Defines
//
#define MCAN_STD_ID_FILT_START_ADDR     (0x0U)
#define MCAN_STD_ID_FILTER_NUM          (32U)    //(1U)
#define MCAN_EXT_ID_FILT_START_ADDR     (0x14U)
#define MCAN_EXT_ID_FILTER_NUM          (1U)
#define MCAN_TX_BUFF_START_ADDR         (0x11U)
#define MCAN_TX_BUFF_SIZE               (10U)
#define MCAN_FIFO_1_START_ADDR          (0xc0U)
#define MCAN_FIFO_1_NUM                 (10U)
#define MCAN_TX_EVENT_START_ADDR        (0x100U)
#define MCAN_TX_EVENT_SIZE              (10U)
#define MCAN_EXT_ID_AND_MASK            (0x1FFFFFFFU)
#define MCAN_RX_BUFF_START_ADDR         (948U)
#define MCAN_FIFO_0_START_ADDR          (548U)
#define MCAN_FIFO_0_NUM                 (5U)
#define MCAN_MSG_INT                    (0x81200)

//
// Global Variables.
//
volatile uint32_t isrIntr0Flag = 1U;
volatile uint32_t isrIntr1Flag = 1U;
volatile uint16_t monEn = 0x0;
volatile unsigned long msgCount = 0;
volatile unsigned long error = 0;

//
// Function Prototype.
//
static void MCANConfig(void);
static void MCANIntrConfig(void);
__interrupt void MCANIntr0ISR(void);
__interrupt void MCANIntr1ISR(void);
__interrupt void cpu_timer0_isr(void);
int forcnt=0, testcnt=0, txtest=0, testNum=1;
uint32_t             txbto_val=0;
MCAN_TxBufElement    txMsg;
MCAN_RxBufElement    rxMsg;
uint32_t             time_250_cnt=0, test_data=0;
MCAN_RxNewDataStatus newData;
void setup_Variables(void);
// Main
void main(void)
{
    int i = 0;
    volatile uint32_t mode = 0U;

    //=============================================================
    // Initialize device clock and peripherals
    //-------------------------------------------------------------
    Device_init();//InitSysCtrl();
    //=============================================================

#if F2838xS_CPU1_CM || F2838xD_CPU1_CM || F2838xD_CPU1_CPU2_CM
    // CMCLK = 125MHz
    // Set up CMCLK to use AUXPLL as the clock source and set the clock divider to 1.
    // assumption : AUXPLLCLK is set to 125Mhz in InitSysCtrl();
    Device_bootCM(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
#endif
#if F2838xD_CPU1_CPU2 || F2838xD_CPU1_CPU2_CM
    // CMCLK = 125MHz
    // Set up CMCLK to use AUXPLL as the clock source and set the clock divider to 1.
    // assumption : AUXPLLCLK is set to 125Mhz in InitSysCtrl();
    Device_bootCPU2(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
#endif

    Device_initGPIO();//InitGpio();

#ifdef MCAN

    //
    // Allocated MCAN shared peripheral to C28x
    //
    SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_MCAN_A,0x0U);
    //
    // Setting the MCAN Clock.
    //
    SysCtl_setMCANClk(SYSCTL_MCANCLK_DIV_5);
    //
    // Configuring the GPIOs for MCAN.
    //
    GPIO_setPinConfig(DEVICE_GPIO_CFG_MCANRXA);
    GPIO_setPinConfig(DEVICE_GPIO_CFG_MCANTXA);
#endif


    //=============================================================
    // Disable CPU interrupts
    //-------------------------------------------------------------
    //DINT;
    //=============================================================

    //=============================================================
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    //-------------------------------------------------------------
    InitPieCtrl();
    //=============================================================

    //=============================================================
    // Disable CPU interrupts and clear all CPU interrupt flags
    //-------------------------------------------------------------
    IER = 0x0000;
    IFR = 0x0000;
    //=============================================================

    //=============================================================
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR)
    //-------------------------------------------------------------
    InitPieVectTable();
    //-------------------------------------------------------------
    // Map ISR functions
    EALLOW;
    PieVectTable.TIMER0_INT = &cpu_timer0_isr;
    EDIS;
    //Interrupt_register(INT_EQEP1, &eqepISR);
    //=============================================================

#ifdef EASYDSP
#if F2837xD_CPU1_CPU2 || F2838xS_CPU1_CM || F2838xD_CPU1_CM || F2838xD_CPU1_CPU2 || F2838xD_CPU1_CPU2_CM
    easyDSP_Boot_Sync();
#endif
    easyDSP_SCI_Init();
#endif

    //=============================================================
    // Initialize the Device Peripheral. For this example, only initialize the
    // Cpu Timers.
    //-------------------------------------------------------------
    InitCpuTimers();
    //-------------------------------------------------------------
    // Configure CPU-Timer 0, 1, and 2 to interrupt every second:
    // 200MHz CPU Freq, 1 second Period (in uSeconds)
    //-------------------------------------------------------------
    ConfigCpuTimer(&CpuTimer0, 200, 250);
    //-------------------------------------------------------------
    // To ensure precise timing, use write-only instructions to write to the
    // entire register. Therefore, if any of the configuration bits are changed
    // in ConfigCpuTimer and InitCpuTimers, the below settings must also be
    // be updated.
    //-------------------------------------------------------------
    CpuTimer0Regs.TCR.all = 0x4000;
    //=============================================================

    //=============================================================
    // Enable CPU int1 which is connected to CPU-Timer 0
    //-------------------------------------------------------------
    IER |= M_INT1;
    //-------------------------------------------------------------
    // Enable TINT0 in the PIE: Group 1 interrupt 7
    //-------------------------------------------------------------
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    //=============================================================

    Interrupt_enable(INT_TIMER0);

    //
    // Initialize message to transmit.
    //
    txMsg.id       = ((uint32_t)(0x11)); // Identifier Value.
    txMsg.rtr      = 0U; // Transmit data frame.
    txMsg.xtd      = 1U; // extended identifier
    txMsg.esi      = 0U; // ESI bit in CAN FD format depends only on error
                          // passive flag.
    txMsg.dlc      = 8U; // CAN FD: transmit frame has 12/16/20/24/32/48/64 data bytes
    txMsg.brs      = 1U; // CAN FD frames transmitted with bit rate
                      // switching.
    txMsg.fdf      = 1U; // Frame transmitted in CAN FD format.
    txMsg.efc      = 1U; // Store Tx events.
    txMsg.mm       = 0xAAU; // Message Marker.

    //
    // Data bytes.
    //
    for(i=0;i<64;i++)
    {
        txMsg.data[i]  = i;
    }

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


    for(;;)
    {

    }
}

//
// This function will configure MCAN module.
//
static void MCANConfig(void)
{
    MCAN_RevisionId revId;
    MCAN_InitParams initParams;
    MCAN_ConfigParams configParams;
    MCAN_MsgRAMConfigParams    msgRAMConfigParams;
    MCAN_StdMsgIDFilterElement stdFiltelem;
    MCAN_ExtMsgIDFilterElement extFiltelem;
    MCAN_BitTimingParams       bitTimes;

    //
    // Initialize MCAN Init parameters.
    //
    initParams.fdMode            = 0x1U; // FD operation enabled.
    initParams.brsEnable         = 0x0U; // Bit rate switching for
                                         // transmissions enabled.
    initParams.txpEnable         = 0x1U; // Transmit pause disabled.
    initParams.efbi              = 0x0U; // Edge filtering disabled.
    initParams.pxhddisable       = 0x0U; // Protocol exception handling enabled.
    initParams.darEnable         = 0x1U; // Automatic retransmission of messages
                                         // not transmitted successfully enabled.
    initParams.wkupReqEnable     = 0x1U; // Wakeup request is enabled.
    initParams.autoWkupEnable    = 0x1U; // Auto-Wakeup is enabled.
    initParams.emulationEnable   = 0x1U; // Emulation/Debug Suspend is enabled.
    initParams.tdcEnable         = 0x1U; // Transmitter Delay Compensation is
                                         // enabled.
    initParams.wdcPreload        = 0xFFU; // Start value of the Message RAM
                                          // Watchdog Counter preload.

    //
    // Transmitter Delay Compensation parameters.
    //
    initParams.tdcConfig.tdcf    = 0xAU;
    initParams.tdcConfig.tdco    = 0x6U;

    //
    // Initialize MCAN Config parameters.
    //
    configParams.monEnable         = 0; // Bus Monitoring Mode is disabled.
    configParams.asmEnable         = 0x0U;  // Normal CAN operation.
    configParams.tsPrescalar       = 0x2U;  // Prescaler Value.
    configParams.tsSelect          = 0x2U;  // Timestamp counter value.
    configParams.timeoutSelect     = MCAN_TIMEOUT_SELECT_CONT;
    // Time-out counter source select.
    configParams.timeoutPreload    = 0xFFFFU; // Start value of the Timeout
                                              // Counter.
    configParams.timeoutCntEnable  = 0x0U; // Time-out Counter is disabled.
    configParams.filterConfig.rrfs = 0x1U; // Reject all remote frames with
                                           // 29-bit extended IDs.
    configParams.filterConfig.rrfe = 0x1U; // Reject all remote frames with
                                           // 11-bit standard IDs.
    configParams.filterConfig.anfe = 0x1U; // Accept in Rx FIFO 1.
    configParams.filterConfig.anfs = 0x1U; // Accept in Rx FIFO 1.

    //
    // 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;
    // Extended ID Filter List Start Address.
    msgRAMConfigParams.lse                  = MCAN_EXT_ID_FILTER_NUM;
    // List Size: Extended ID.
    msgRAMConfigParams.txStartAddr          = MCAN_TX_BUFF_START_ADDR;
    // Tx Buffers Start Address.
    msgRAMConfigParams.txBufNum             = MCAN_TX_BUFF_SIZE;
    // Number of Dedicated Transmit Buffers.
    msgRAMConfigParams.txFIFOSize           = MCAN_TX_BUFF_SIZE; // No Tx FIFO/Queue.
    msgRAMConfigParams.txBufMode            = 0U; //Tx FIFO operation
    msgRAMConfigParams.txBufElemSize        = MCAN_ELEM_SIZE_64BYTES;
    // Tx Buffer Element Size.
    msgRAMConfigParams.txEventFIFOStartAddr = MCAN_TX_EVENT_START_ADDR;
    // Tx Event FIFO Start Address.
    msgRAMConfigParams.txEventFIFOSize      = MCAN_TX_BUFF_SIZE;
    // Event FIFO Size.
    msgRAMConfigParams.txEventFIFOWaterMark = 3U;
    // Level for Tx Event FIFO watermark interrupt.
    msgRAMConfigParams.rxFIFO0startAddr     = MCAN_FIFO_0_START_ADDR;
    // Rx FIFO0 Start Address.
    msgRAMConfigParams.rxFIFO0size          = MCAN_FIFO_0_NUM;
    // Number of Rx FIFO elements.
    msgRAMConfigParams.rxFIFO0waterMark     = 3U; // Rx FIFO0 Watermark.
    msgRAMConfigParams.rxFIFO0OpMode        = 0U; // FIFO blocking mode.
    msgRAMConfigParams.rxFIFO1startAddr     = MCAN_FIFO_1_START_ADDR;
    // Rx FIFO1 Start Address.
    msgRAMConfigParams.rxFIFO1size          = MCAN_FIFO_1_NUM;
    // Number of Rx FIFO elements.
    msgRAMConfigParams.rxFIFO1waterMark     = 3U; // Level for Rx FIFO 1
                                                  // watermark interrupt.
    msgRAMConfigParams.rxFIFO1OpMode        = 0U; // FIFO blocking mode.
    msgRAMConfigParams.rxBufStartAddr       = MCAN_RX_BUFF_START_ADDR;
    // Rx Buffer Start Address.
    msgRAMConfigParams.rxBufElemSize        = MCAN_ELEM_SIZE_64BYTES;
    // Rx Buffer Element Size.
    msgRAMConfigParams.rxFIFO0ElemSize      = MCAN_ELEM_SIZE_64BYTES;
    // Rx FIFO0 Element Size.
    msgRAMConfigParams.rxFIFO1ElemSize      = MCAN_ELEM_SIZE_64BYTES;
    // Rx FIFO1 Element Size.

    //
    // Initialize Tx Buffer Configuration parameters.
    //
    stdFiltelem.sfid2              = 0x0U; // Standard Filter ID 2.
    stdFiltelem.sfid1              = 0x1U; // Standard Filter ID 1.
    stdFiltelem.sfec               = 0x7U; // Store into Rx Buffer or as
                           // debug message, configuration of SFT[1:0] ignored.
    stdFiltelem.sft                = 0x0U; // Range filter from SFID1 to SFID2.

    //
    // Initialize Tx Buffer Configuration parameters.
    //
    extFiltelem.efid2  = (0x9U << 16U);
    extFiltelem.efid2 |= 0xFFU;
    extFiltelem.efid1  = (0x0U << 16U);
    extFiltelem.efid1 |= 0xFFU;
    extFiltelem.efec   = 0x6U;
    extFiltelem.eft    = 0x0U;

    //
    // Initialize bit timings.
    //
    // Nominal = 1M  / Data = 2M
    bitTimes.nomRatePrescalar   = 0x4U; // Nominal Baud Rate Pre-scaler.
    bitTimes.nomTimeSeg1        = 0x4U; // Nominal Time segment before sample point.
    bitTimes.nomTimeSeg2        = 0x1U; // Nominal Time segment after sample point.
    bitTimes.nomSynchJumpWidth  = 0x0U; // Nominal (Re)Synchronization Jump Width Range.
    bitTimes.dataRatePrescalar  = 0x0U; // Data Baud Rate Pre-scaler.
    bitTimes.dataTimeSeg1       = 0x6U; // Data Time segment before sample point.
    bitTimes.dataTimeSeg2       = 0x1U; // Data Time segment after sample point.
    bitTimes.dataSynchJumpWidth = 0x0U; // Data (Re)Synchronization Jump Width.
    //
    // Get MCANSS Revision ID.
    //
    MCAN_getRevisionId(MCAN0_BASE, &revId);

    //
    // Wait for Memory initialization to be completed.
    //
    while(FALSE == MCAN_isMemInitDone(MCAN0_BASE));

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

    //
    // Wait till MCAN is not initialized.
    //
    while (MCAN_OPERATION_MODE_SW_INIT != MCAN_getOpMode(MCAN0_BASE));

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

    //
    // Configure MCAN module.
    //
    MCAN_config(MCAN0_BASE, &configParams);

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

    //
    // Set Extended ID Mask.
    //
    MCAN_setExtIDAndMask(MCAN0_BASE, MCAN_EXT_ID_AND_MASK);

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

    //
    // Configure Standard ID filter element
    //
    MCAN_addStdMsgIDFilter(MCAN0_BASE, 0U, &stdFiltelem);

    //
    // Configure Extended ID filter element
    //
    MCAN_addExtMsgIDFilter(MCAN0_BASE, 0U, &extFiltelem);

    //
    // Enable internal loopback mode
    //
    //MCAN_lpbkModeEnable(MCAN0_BASE, MCAN_LPBK_MODE_EXTERNAL, TRUE);

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

    while (MCAN_OPERATION_MODE_NORMAL != MCAN_getOpMode(MCAN0_BASE));
}

// cpuTimer0ISR - CPU Timer0 ISR with interrupt counter
//int can_fd_test=0, can_fd_flag=0, can_tx_id=0x11, set_250_cnt=2;
__interrupt void cpu_timer0_isr(void)
{
    CpuTimer0.InterruptCount++;

    /*if(time_250_cnt++>=set_250_cnt)
    {
        time_250_cnt=0;
        if(can_fd_test==1)
        {
            txMsg.id       = ((uint32_t)(can_tx_id));
            if(can_tx_id++>=0x13) can_tx_id=0x11;
            txMsg.data[0] = test_data++;
            if(test_data>=100)  test_data=0;
            MCAN_writeMsgRam(MCAN0_BASE, MCAN_MEM_TYPE_BUF, 1U, &txMsg);
            MCAN_txBufAddReq(MCAN0_BASE,1U);
        }
    }*/


    MCAN_writeMsgRam(MCAN0_BASE, MCAN_MEM_TYPE_BUF, 1U, &txMsg);
    MCAN_txBufAddReq(MCAN0_BASE,1U);

    //
    // Read Message RAM.
    //
    MCAN_readMsgRam(MCAN0_BASE, MCAN_MEM_TYPE_FIFO, 0U, MCAN_RX_FIFO_NUM_1,
                    &rxMsg);
    MCAN_writeRxFIFOAck(MCAN0_BASE, MCAN_RX_FIFO_NUM_1, 0);

    // Acknowledge this interrupt to receive more interrupts from group 1
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

Please help. Thank you 

  • Hi,

    brs should be enabled along with fd mode. When it is enabled the data frame is transmitted with bit rate configured using bitTimes.data and the arbitration frame is trasnmitted with bit rate configured using bitTimes.nom

    Can you clarify on what do you mean by sending operation does not work. Is it not transmitting the frame at all on the bus or the bit rate switching is not happening?

    In you code at line 428 you are also missing a check for completion or successful transmission of frame before reading the received message.

    This could be the cause of reading an empty buffer. You are also writing ack to the fifo so it might be clearing the new data bit before correct reception.

    Regards,

    Yashwant

  • Hi,

    I am checking the communication operation through PCAN-view.

    If the brsEnable value is set to 1, the value is not displayed on the PCAN-view reception screen.

    When it is checked through the scope (CANH, CANL), the signal is not output and it maintains a low value.

    It seems that there is no transmission output.

    In the example provided (except for the internal loop), the BRS function was not used, 

    Can I get an example of using the BRS function?

  • Hi,

    We are validating the brs functionality using the external loopback example. Expect some delay in response.

    Regards,

    Yashwant 

  • Hi,

    May I know how the value is calculated? : TDCO and TDCF in the MCAN_TDCR

  • As listed in the TRM section "45.5.4 Transmitter Delay Compensation", when the delay compensation is enabled, the hardware measures the round trip delay using the dominant bit after FDF.

    The TDCO offset value is added to this measurement to arrive at the final SSP point within the bit time. The TDCF defines the minimum value of SSP to avoid any false TDC value due to glitches

  • Hi,

     I have tested the example with brs enabled with nominal bit rate of 500kbps, data bit rate of 1Mbps. It is working properly.

    Make sure your bit timing parameters are configured properly. Below are the parameters used by me.

    bitTimes.nomRatePrescalar = 0x3U; // Nominal Baud Rate Pre-scaler.
    bitTimes.nomTimeSeg1 = 0x9U; // Nominal Time segment before sample point.
    bitTimes.nomTimeSeg2 = 0x8U; // Nominal Time segment after sample point.
    bitTimes.nomSynchJumpWidth = 0x8U; // Nominal (Re)Synchronization Jump Width Range.
    bitTimes.dataRatePrescalar = 0x1U; // Data Baud Rate Pre-scaler.
    bitTimes.dataTimeSeg1 = 0x9U; // Data Time segment before sample point.
    bitTimes.dataTimeSeg2 = 0x8U; // Data Time segment after sample point.
    bitTimes.dataSynchJumpWidth = 0x8U; // Data (Re)Synchronization Jump Width.

    Attached is the code used and the bit timing calculator to calculate the bit time segment parameters.

    //#############################################################################
    //
    // FILE:   mcan_ex2_external_loopback.c
    //
    // TITLE:  MCAN External Loopback with Interrupt
    //
    //! \addtogroup driver_example_cm_list
    //! <h1> MCAN External Loopback with Interrupt </h1>
    //!
    //! This example shows the MCAN External Loopback functionality. The external
    //! loopback is done between two MCAN Controllers. As there is only one MCAN
    //! that exist this example can be changed to make MCAN Transmit or Receive
    //! based on define selected. The GPIOs of MCAN should be connected to a CAN
    //! Transceiver
    //!
    //! Selection of Mode : A define has to be selected to make the MCAN to
    //! transmit or receive.
    //!  - TRANSMIT - MCAN to Transmit messages.
    //!  - RECEIVE  - MCAN to Receive Messages.
    //!
    //! Run the example as with RECEIVE Define on one MCAN Controller before
    //! running it as Transmit.
    //!
    //! \b Hardware \b Required \n
    //!  - A C2000 board with CAN transceiver
    //!
    //! \b External \b Connections \n
    //!  Connect MCAN RX, TX of transmit to the MCAN RX, TX of receive
    //!  through a CAN tranxceiver.
    //!  - MCAN is on DEVICE_GPIO_PIN_CANRXA (MCANRXA)
    //!  - and DEVICE_GPIO_PIN_CANTXA (MCANTXA)
    //!
    //! \b Watch \b Variables \n
    //!  - isrIntr0Flag - The flag has initial value as no. of messages to be
    //!                   transmitted and its value decrements after a message is
    //!                   transmitted.
    //!  - isrIntr1Flag - The flag has initial value as no. of messages that are
    //!                   received and its value decrements after a message is
    //!                   successfully received.
    //!  - error - Checks if there is an error that occurred when the data was
    //!            sent using internal loopback
    //!
    //
    //#############################################################################
    //
    //
    // $Copyright: $
    //#############################################################################
    
    //
    // Include Files
    //
    #include "driverlib.h"
    #include "device.h"
    #include "inc/stw_types.h"
    #include "inc/stw_dataTypes.h"
    #include "inc/hw_types_mcan.h"
    
    //
    // Select one of the Modes.
    //
    //#define TRANSMIT
    //#define RECEIVE
    
    //
    // Defines.
    //
    #define NUM_OF_MSG                    (10U)
    #define MCAN_STD_ID_FILT_START_ADDR   (0U)
    #define MCAN_STD_ID_FILTER_NUM        (1U)
    #define MCAN_EXT_ID_FILT_START_ADDR   (48U)
    #define MCAN_EXT_ID_FILTER_NUM        (1U)
    #define MCAN_TX_EVENT_START_ADDR      (100U)
    #define MCAN_TX_EVENT_SIZE            (NUM_OF_MSG)
    #define MCAN_TX_EVENT_WATERMARK       (NUM_OF_MSG/2)
    #define MCAN_TX_BUFF_START_ADDR       (148U)
    #define MCAN_TX_BUFF_SIZE             (NUM_OF_MSG)
    #define MCAN_TX_FIFO_SIZE             (NUM_OF_MSG)
    #define MCAN_FIFO_0_START_ADDR        (548U)
    #define MCAN_FIFO_0_NUM               (NUM_OF_MSG)
    #define MCAN_FIFO_0_WATERMARK         (NUM_OF_MSG)
    #define MCAN_FIFO_1_START_ADDR        (748U)
    #define MCAN_FIFO_1_NUM               (NUM_OF_MSG)
    #define MCAN_FIFO_1_WATERMARK         (NUM_OF_MSG)
    #define MCAN_RX_BUFF_START_ADDR       (948U)
    #define MCAN_EXT_ID_AND_MASK          (0x1FFFFFFFU)
    #define MCAN_TS_PRESCALAR             (0xB0)
    
    #define MCAN_TX_BUFF_ELEM_SIZE       (MCAN_ELEM_SIZE_64Bytes)
    #define MCAN_RX_BUFF_ELEM_SIZE       (MCAN_ELEM_SIZE_64Bytes)
    #define MCAN_RX_FIFO0_ELEM_SIZE      (MCAN_ELEM_SIZE_64Bytes)
    #define MCAN_RX_FIFO1_ELEM_SIZE      (MCAN_ELEM_SIZE_64Bytes)
    
    //
    // Global Variables.
    //
    volatile uint32_t isrIntr0Flag = NUM_OF_MSG;
    volatile uint32_t isrIntr1Flag = NUM_OF_MSG;
    volatile uint32_t isrIntrTSFlag = 1U;
    int32_t     error = 0;
    MCAN_TxBufElement txMsg[NUM_OF_MSG];
    MCAN_RxBufElement rxMsg[NUM_OF_MSG], rxMsg1;
    MCAN_RxFIFOStatus RxFS;
    int32_t loopCnt = 0U;
    
    
    //
    // Function Prototype.
    //
    static void MCANConfig(void);
    static void MCANIntrConfig(void);
    __interrupt void MCANIntr0ISR(void);
    __interrupt void MCANIntr1ISR(void);
    
    void main()
    {
    #ifdef RECEIVE
        int32_t dataCnt;
    #endif
        int i = 0;
        uint32_t numOfMsg = NUM_OF_MSG;
        volatile uint32_t mode = 0U;
        uint32_t dataBytes = 8;
    
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Initialize GPIO and configure GPIO pins for CANTX/CANRX
        //
        Device_initGPIO();
    
        //
        // Allocated MCAN shared peripheral to C28x
        //
        SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_MCAN_A,0x0U);
    
        //
        // Setting the MCAN Clock.
        //
        SysCtl_setMCANClk(SYSCTL_MCANCLK_DIV_5);
    
        //
        // Configuring the GPIOs for MCAN.
        //
        GPIO_setPinConfig(DEVICE_GPIO_CFG_MCANRXA);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_MCANTXA);
    
        //
        // CrossBar and ISR Configuration.
        //
        MCANIntrConfig();
    
        //
        // Initialize message to transmit.
        //
        for(loopCnt = 0U ; loopCnt < numOfMsg ; loopCnt++)
        {
            txMsg[loopCnt].id       = (0x0);
            txMsg[loopCnt].id       = (loopCnt) << 18U;
            txMsg[loopCnt].id       |= (0xFF);
            txMsg[loopCnt].rtr      = 0U;
            txMsg[loopCnt].xtd      = 1U;
            txMsg[loopCnt].esi      = 0U;
            txMsg[loopCnt].dlc      = 15U;
            txMsg[loopCnt].brs      = 1U;
            txMsg[loopCnt].fdf      = 1U;
            txMsg[loopCnt].efc      = 1U;
            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;
        }
        for(loopCnt = 0U ; loopCnt < numOfMsg ; loopCnt++)
        {
            rxMsg[loopCnt].id = 0U;
            rxMsg[loopCnt].rtr = 0U;
            rxMsg[loopCnt].xtd = 0U;
            rxMsg[loopCnt].esi = 0U;
            rxMsg[loopCnt].rxts = 0U;
            rxMsg[loopCnt].dlc = 0U;
            rxMsg[loopCnt].brs = 0U;
            rxMsg[loopCnt].fdf = 0U;
            rxMsg[loopCnt].fidx = 0U;
            rxMsg[loopCnt].anmf = 0U;
            for(i = 0; i < dataBytes; i++)
            {
                rxMsg[loopCnt].data[i]  = 0;
            }
        }
    
        //
        // Configure the MCAN Module.
        //
        MCANConfig();
    
    #ifdef TRANSMIT
        //
        // This is transmitter side application.
        //
    
        //
        // Enable Interrupts.
        //
        MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_MASK_ALL,1);
        MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_SRC_RES_ADDR_ACCESS|
                        MCAN_INTR_SRC_TIMESTAMP_WRAPAROUND,0);
    
        //
        // Select Interrupt Line.
        //
        MCAN_selectIntrLine(MCAN0_BASE, MCAN_INTR_MASK_ALL,
                            MCAN_INTR_LINE_NUM_0);
    
        //
        // Enable Interrupt Line.
        //
        MCAN_enableIntrLine(MCAN0_BASE, MCAN_INTR_LINE_NUM_0, 1U);
    
        //
        // Enable Transmission interrupt.
        //
        for(loopCnt = 0U ; loopCnt < numOfMsg ; loopCnt++)
        {
            MCAN_txBufTransIntrEnable(MCAN0_BASE, loopCnt,1);
    
            //
            // Write message to Message RAM.
            //
            MCAN_writeMsgRam(MCAN0_BASE, MCAN_MEM_TYPE_BUF, loopCnt,
                             &txMsg[loopCnt]);
        }
    
        //
        // Add request for all transmission.
        //
        HWREG(MCAN0_BASE + MCAN_TXBAR) = 0x000003FF;
    
        //
        // Wait till the flag becomes zero and all the messages are transmitted.
        //
        while(isrIntr0Flag)
        {
        }
    #endif
    #ifdef RECEIVE
        //
        // This is receiver side application.
        //
    
        //
        // Enable Interrupts.
        //
        MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_MASK_ALL,1);
        MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_SRC_RES_ADDR_ACCESS|
                        MCAN_INTR_SRC_TIMESTAMP_WRAPAROUND,0);
    
        //
        // Select Interrupt Line.
        //
        MCAN_selectIntrLine(MCAN0_BASE, MCAN_INTR_MASK_ALL,
                            MCAN_INTR_LINE_NUM_1);
        //
        // Enable Interrupt Line.
        //
        MCAN_enableIntrLine(MCAN0_BASE, MCAN_INTR_LINE_NUM_1, 1U);
    
        //
        // Wait till the interrupt flag becomes zero.
        //
        while(isrIntr1Flag)
        {
        }
    
        for(loopCnt = 0U ; loopCnt < numOfMsg;loopCnt++)
        {
            MCAN_readMsgRam(MCAN0_BASE, MCAN_MEM_TYPE_FIFO, 0U,
                            MCAN_RX_FIFO_NUM_1, &rxMsg1);
            RxFS.num = MCAN_RX_FIFO_NUM_1;
            MCAN_getRxFIFOStatus(MCAN0_BASE, &RxFS);
    
            MCAN_writeRxFIFOAck(MCAN0_BASE, MCAN_RX_FIFO_NUM_1,
                                RxFS.getIdx);
            rxMsg[loopCnt] = rxMsg1;
        }
    
        for(loopCnt = 0U ; loopCnt < numOfMsg ; loopCnt++)
        {
    
            if (rxMsg[loopCnt].id  != txMsg[loopCnt].id)
            {
                error++;
            }
            if (rxMsg[loopCnt].rtr != txMsg[loopCnt].rtr)
            {
                error++;
            }
            if (rxMsg[loopCnt].xtd != txMsg[loopCnt].xtd)
            {
                error++;
            }
            if (rxMsg[loopCnt].esi != txMsg[loopCnt].esi)
            {
                error++;
            }
            if (rxMsg[loopCnt].dlc != txMsg[loopCnt].dlc)
            {
                error++;
            }
            if (rxMsg[loopCnt].brs != txMsg[loopCnt].brs)
            {
                error++;
            }
            if (rxMsg[loopCnt].fdf != txMsg[loopCnt].fdf)
            {
                error++;
            }
    
            if (loopCnt > 0)
            {
                if (rxMsg[loopCnt].rxts > rxMsg[loopCnt-1].rxts)
                {
                }
                else
                {
                    error++;
                }
            }
    
            for (dataCnt = 0U ; dataCnt < dataBytes ; dataCnt++)
            {
                if (rxMsg[loopCnt].data[dataCnt]!=
                    txMsg[loopCnt].data[dataCnt])
                {
                    error++;
                }
            }
        }
    #endif
        if (error != 0)
        {
            //
            // Stop if there is an error.
            //
            asm("   ESTOP0");
        }
    
        //
        // Stop Application.
        //
        asm("   ESTOP0");
    }
    
    static void MCANIntrConfig(void)
    {
        Interrupt_initModule();
        Interrupt_initVectorTable();
        Interrupt_register(INT_MCANSS0,&MCANIntr0ISR);
        Interrupt_enable(INT_MCANSS0);
    
        Interrupt_register(INT_MCANSS1,&MCANIntr1ISR);
        Interrupt_enable(INT_MCANSS1);
    
        Interrupt_enableMaster();
    }
    static void MCANConfig(void)
    {
        MCAN_RevisionId revId;
        MCAN_InitParams initParams;
        MCAN_ConfigParams configParams;
        MCAN_MsgRAMConfigParams    msgRAMConfigParams;
        MCAN_StdMsgIDFilterElement stdFiltelem;
        MCAN_ExtMsgIDFilterElement extFiltelem;
        MCAN_BitTimingParams       bitTimes;
    
        //
        // Initialize MCAN Init parameters.
        //
        initParams.fdMode            = 0x1U; // FD operation disabled.
        initParams.brsEnable         = 0x1U; // Bit rate switching for
                                             // transmissions enabled.
        initParams.txpEnable         = 0x1U; // Transmit pause enabled.
        initParams.efbi              = 0x0U; // Edge filtering disabled.
        initParams.pxhddisable       = 0x0U; // Protocol exception handling enabled.
        initParams.darEnable         = 0x1U; // Enable automatic retransmission of messages
                                             // that were not transmitted successfully.
        initParams.wkupReqEnable     = 0x1U; // Wakeup request is enabled.
        initParams.autoWkupEnable    = 0x1U; // Auto-Wakeup is enabled.
        initParams.emulationEnable   = 0x1U; // Emulation/Debug Suspend is enabled.
        initParams.tdcEnable         = 0x1U; // Transmitter Delay Compensation is
                                             // enabled.
        initParams.wdcPreload        = 0xFFU; // Start value of the Message RAM
                                              // Watchdog Counter preload.
    
        //
        // Transmitter Delay Compensation parameters.
        //
        initParams.tdcConfig.tdcf    = 0xAU;
        initParams.tdcConfig.tdco    = 0x6U;
    
        //
        // Initialize MCAN Config parameters.
        //
        configParams.monEnable       = 0x0U; // Bus Monitoring Mode is disabled.
        configParams.asmEnable       = 0x0U; // Normal CAN operation.
        configParams.tsPrescalar       = 0x2U; // Prescaler Value.
        configParams.tsSelect          = 0x2U; // Timestamp counter value.
        configParams.timeoutSelect     = MCAN_TIMEOUT_SELECT_CONT;
        // Time-out counter source select.
        configParams.timeoutPreload    = 0xFFFFU;// Start value of the Timeout
                                                 // Counter.
        configParams.timeoutCntEnable  = 0x0U; // Time-out Counter is disabled.
        configParams.filterConfig.rrfs = 0x1U; // Reject all remote frames with
                                               // 29-bit extended IDs.
        configParams.filterConfig.rrfe = 0x1U; // Reject all remote frames with
                                               // 11-bit standard IDs.
        configParams.filterConfig.anfe = 0x1U; // Accept in Rx FIFO 1.
        configParams.filterConfig.anfs = 0x1U; // Accept in Rx FIFO 1.
    
        //
        // 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;
        // Extended ID Filter List Start Address.
        msgRAMConfigParams.lse                  = MCAN_EXT_ID_FILTER_NUM;
        // List Size: Extended ID.
        msgRAMConfigParams.txStartAddr          = MCAN_TX_BUFF_START_ADDR;
        // Tx Buffers Start Address.
        msgRAMConfigParams.txBufNum             = MCAN_TX_BUFF_SIZE;
        // Number of Dedicated Transmit Buffers.
        msgRAMConfigParams.txFIFOSize           = MCAN_TX_FIFO_SIZE;
        // Tx FIFO/Queue.
        msgRAMConfigParams.txBufMode            = 0U;
        msgRAMConfigParams.txBufElemSize        = MCAN_ELEM_SIZE_64BYTES;
      // Tx Buffer Element Size.
        msgRAMConfigParams.txEventFIFOStartAddr = MCAN_TX_EVENT_START_ADDR;
        // Tx Event FIFO Start Address.
        msgRAMConfigParams.txEventFIFOSize      = MCAN_TX_BUFF_SIZE;
        // Event FIFO Size.
        msgRAMConfigParams.txEventFIFOWaterMark = MCAN_TX_EVENT_WATERMARK;
        // Level for Tx Event FIFO watermark interrupt.
        msgRAMConfigParams.rxFIFO0startAddr     = MCAN_FIFO_0_START_ADDR;
        // Rx FIFO0 Start Address.
        msgRAMConfigParams.rxFIFO0size          = MCAN_FIFO_0_NUM;
        // Number of Rx FIFO elements.
        msgRAMConfigParams.rxFIFO0waterMark     = MCAN_FIFO_0_WATERMARK;
        msgRAMConfigParams.rxFIFO0OpMode        = 0U;
        msgRAMConfigParams.rxFIFO1startAddr     = MCAN_FIFO_1_START_ADDR;
        // Rx FIFO1 Start Address.
        msgRAMConfigParams.rxFIFO1size          = MCAN_FIFO_1_NUM;
        // Number of Rx FIFO elements.
        msgRAMConfigParams.rxFIFO1waterMark     = MCAN_FIFO_1_WATERMARK;
        // Level for Rx FIFO 1 watermark interrupt.
        msgRAMConfigParams.rxFIFO1OpMode        = 0U; // FIFO blocking mode.
        msgRAMConfigParams.rxBufStartAddr       = MCAN_RX_BUFF_START_ADDR;
        // Rx Buffer Start Address.
        msgRAMConfigParams.rxBufElemSize        = MCAN_ELEM_SIZE_64BYTES;
        // Rx Buffer Element Size.
        msgRAMConfigParams.rxFIFO0ElemSize      = MCAN_ELEM_SIZE_64BYTES;
        // Rx FIFO0 Element Size.
        msgRAMConfigParams.rxFIFO1ElemSize      = MCAN_ELEM_SIZE_64BYTES;
        // Rx FIFO1 Element Size.
    
        //
        // Initialize Tx Buffer Configuration parameters.
        //
        stdFiltelem.sfid2              = 0x0U; // Standard Filter ID 2.
        stdFiltelem.sfid1              = 0x4U; // Standard Filter ID 1.
        stdFiltelem.sfec               = 0x7U; // Store into Rx Buffer or as
                               // debug message, configuration of SFT[1:0] ignored.
        stdFiltelem.sft                = 0x0U; // Range filter from SFID1 to SFID2.
    
        //
        // Initialize Tx Buffer Configuration parameters.
        //
        extFiltelem.efid2  = (0x9U << 18U);
        extFiltelem.efid2 |= 0xFFU;
        extFiltelem.efid1  = (0x0U << 18U);
        extFiltelem.efid1 |= 0xFFU;
        extFiltelem.efec   = 0x6U;
        extFiltelem.eft    = 0x0U;
    
        //
        // Initialize bit timings.
        //
        bitTimes.nomRatePrescalar   = 0x3U; // Nominal Baud Rate Pre-scaler.
        bitTimes.nomTimeSeg1        = 0x9U; // Nominal Time segment before sample point.
        bitTimes.nomTimeSeg2        = 0x8U; // Nominal Time segment after sample point.
        bitTimes.nomSynchJumpWidth  = 0x8U; // Nominal (Re)Synchronization Jump Width Range.
        bitTimes.dataRatePrescalar  = 0x1U; // Data Baud Rate Pre-scaler.
        bitTimes.dataTimeSeg1       = 0x9U; // Data Time segment before sample point.
        bitTimes.dataTimeSeg2       = 0x8U; // Data Time segment after sample point.
        bitTimes.dataSynchJumpWidth = 0x8U; // Data (Re)Synchronization Jump Width.
    
        //
        // Get MCANSS Revision ID
        //
        MCAN_getRevisionId(MCAN0_BASE, &revId);
        
        //
        // Wait for memory initialization to happen.
        //
        while(FALSE == MCAN_isMemInitDone(MCAN0_BASE))
        {
        }
    
        //
        // Put MCAN in SW initialization mode.
        //
        MCAN_setOpMode(MCAN0_BASE, MCAN_OPERATION_MODE_SW_INIT);
    
        //
        // Wait till MCAN is not initialized.
        //
        while (MCAN_OPERATION_MODE_SW_INIT != MCAN_getOpMode(MCAN0_BASE))
        {}
    
        //
        // Initialize MCAN module.
        //
        MCAN_init(MCAN0_BASE, &initParams);
    
        //
        // Configure MCAN module.
        //
        MCAN_config(MCAN0_BASE, &configParams);
    
        //
        // Disable external timeStamp overflow interrupt.
        //
        MCAN_extTSEnableIntr(MCAN0_BASE,1);
    
        //
        // Configure TimeStamp Counter.
        //
        MCAN_extTSCounterConfig(MCAN0_BASE, MCAN_TS_PRESCALAR);
    
        //
        // Configure Bit timings.
        //
        MCAN_setBitTime(MCAN0_BASE, &bitTimes);
    
        //
        // Set Extended ID Mask.
        //
        MCAN_setExtIDAndMask(MCAN0_BASE, MCAN_EXT_ID_AND_MASK);
    
        //
        // Configure Message RAM Sections
        //
        MCAN_msgRAMConfig(MCAN0_BASE, &msgRAMConfigParams);
    
        //
        // Configure Standard ID filter element
        //
        MCAN_addStdMsgIDFilter(MCAN0_BASE, 0U, &stdFiltelem);
    
        //
        // Configure Extended ID filter element
        //
        MCAN_addExtMsgIDFilter(MCAN0_BASE, 0U, &extFiltelem);
    
        //
        // Enable external counter.
        //
        MCAN_extTSCounterEnable(MCAN0_BASE, 1U);
    
        //
        // Take MCAN out of the SW initialization mode
        //
        MCAN_setOpMode(MCAN0_BASE, MCAN_OPERATION_MODE_NORMAL);
    
        while (MCAN_OPERATION_MODE_NORMAL != MCAN_getOpMode(MCAN0_BASE))
        {
    
        }
    }
    
    __interrupt void MCANIntr0ISR(void)
    {
        uint32_t intrStatus;
    
        intrStatus = MCAN_getIntrStatus(MCAN0_BASE);
        MCAN_clearIntrStatus(MCAN0_BASE, intrStatus);
    
        if (MCAN_INTR_SRC_TRANS_COMPLETE == (intrStatus &
             MCAN_INTR_SRC_TRANS_COMPLETE))
        {
            //
            // Decrement the flag after each message is transmitted.
            //
            isrIntr0Flag--;
        }
        else
        {
            //
            // Stop the application if error occurs.
            //
            asm("   ESTOP0");
        }
        HW_WR_FIELD32(MCAN0_BASE + MCAN_MCANSS_EOI,
                             MCAN_MCANSS_EOI,
                             0x1U);
        //
        // Acknowledge this interrupt located in group 9
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    
    }
    
    __interrupt void MCANIntr1ISR(void)
    {
        uint32_t intrStatus;
    
        intrStatus = MCAN_getIntrStatus(MCAN0_BASE);
        MCAN_clearIntrStatus(MCAN0_BASE, intrStatus);
        if(MCAN_INTR_SRC_RX_FIFO1_NEW_MSG ==
                (intrStatus & MCAN_INTR_SRC_RX_FIFO1_NEW_MSG))
        {
            //
            // Decrement the flag after each message is received.
            //
            isrIntr1Flag--;
        }
        else
        {
            //
            // Stop the application if error occurs.
            //
            asm("   ESTOP0");
        }
        HW_WR_FIELD32(MCAN0_BASE + MCAN_MCANSS_EOI,
                             MCAN_MCANSS_EOI,
                             0x2U);
        //
        // Acknowledge this interrupt located in group 9
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    }
    

    MCAN_BitTimingCalculator.xls

    Regards,

    Yashwant

  • Hi 

    Thanks for the reply.

    In the provided example(mcan_ex2_external_loopback.c), why does it not work when BRS is activated?
    baudrate: nominal=250k, data=2M

  • Please wait for the MCAN IP expert to respond.

  • (Re)Synchronization Jump width should be a non zero value.

  • Hi 

    The bitTime was corrected by referring to the Excel file (CAN Bit Timing Calculator.xls). When checking communication operation through PCAN view, receive operation is not working normally. Is there something wrong with the attached picture?

  • The value in the code should be taken from Row 49.

    Below are the parameters computed for 250kbps, 2Mbps. 

    -Yashwant

  • Hi.

    I tried changing the value referring to the value you mentioned, but it doesn't work.

    If you modify the example (mcan_ex2_external_loopback.c) to the value mentioned above, will the transmission work normally?