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.

TMS320F28P659DH-Q1: MCAN NOT WORKING IN 1MBPS

Part Number: TMS320F28P659DH-Q1
Other Parts Discussed in Thread: C2000WARE

Hi ALL,

reference ticket --- 

MCAN Interrupt is occur only once
https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1622361/tms320f28p659dh-q1-mcan-interrupt-is-occur-only-once/6258007

In my code, I changed the configuration to 250 kbps using the following settings:

bitTiming.nomRatePrescalar = 3U;
bitTiming.nomTimeSeg1 = 11U;
bitTiming.nomTimeSeg2 = 8U;
bitTiming.nomSynchJumpWidth = 4U;

However, it did not work.

My target is 1 Mbps bitrate. I used the following configuration:


SysCtl_setMCANClk(SYSCTL_MCANCLK_DIV_10, 1U);

 bitTiming.nomRatePrescalar = 0;
bitTiming.nomTimeSeg1 = 14;
bitTiming.nomTimeSeg2 = 5;
bitTiming.nomSynchJumpWidth = 2;
 

But this configuration also did not work.

Please refer to the code attached above for your reference.

Below is my processor card side configuration:

tcu1_processor_card_1:/home/petalinux# ip link set can1 down
ip link set can1 type can bitrate 1000000
ip link set can1 up

tcu1_processor_card_1:/home/petalinux# ip -details link show can1

4: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
link/can promiscuity 0 allmulti 0 minmtu 0 maxmtu 0
can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
bitrate 999999 sample-point 0.750
tq 50 prop-seg 7 phase-seg1 7 phase-seg2 5 sjw 2 brp 5
xilinx_can: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..256 brp_inc 1
clock 99999999 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size



Statistics output:
tcu1_processor_card_1:/home/petalinux# ip -details -statistics link show can1

4: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
link/can promiscuity 0 allmulti 0 minmtu 0 maxmtu 0
can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
bitrate 999999 sample-point 0.750
tq 50 prop-seg 7 phase-seg1 7 phase-seg2 5 sjw 2 brp 5
xilinx_can: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..256 brp_inc 1
clock 99999999
re-started bus-errors arbit-lost error-warn error-pass bus-off
0 129 0 4 4 4 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
RX: bytes packets errors dropped missed mcast
0 0 34 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 96 4 0 0


/* ================================================================
* mcan_debug.c – Working version for Linux SocketCAN
* 1 Mbps @ 75% Sample Point
* ================================================================ */

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "driverlib.h"
#include "device.h"
#include "FreeRTOS.h"
#include "BSP/uart/uart.h"
#include "libs/mcan/mcan.h"

volatile uint8_t mcan_flag = 0;
volatile uint32_t mcan_isr_count = 0;

/* ---------------- Configuration ---------------- */

#define MCAN_FIFO_1_NUM 8U
#define MCAN_FIFO_1_ELEM_SIZE MCAN_ELEM_SIZE_8BYTES
#define MCAN_TX_BUFF_ELEM_SIZE MCAN_ELEM_SIZE_8BYTES

#define MCAN_STD_ID_FILT_START_ADDR 0x0000U
#define MCAN_FIFO_1_START_ADDR 0x0100U
#define MCAN_TX_BUFF_START_ADDR 0x0200U

MCAN_TxBufElement txMsg;
MCAN_RxBufElement rxMsg;

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

MCAN_RxBufElement* MCAN_getLastRxMsg(void)
{
return &rxMsg;
}

void MCAN_initDriver(void)
{
int i;

/* Enable Transceiver */
GPIO_setDirectionMode(32, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(32, GPIO_PIN_TYPE_PULLUP);
GPIO_writePin(32, 0);
GPIO_setPinConfig(GPIO_32_GPIO32);

/* MCAN Clock = 20 MHz */
SysCtl_setMCANClk(SYSCTL_MCANCLK_DIV_10, 1U);

/* Configure CAN pins */
GPIO_setPinConfig(GPIO_45_MCANB_TX);
GPIO_setPinConfig(GPIO_44_MCANB_RX);
GPIO_setQualificationMode(44, GPIO_QUAL_ASYNC);

MCANIntrConfig();

for(i = 0; i < 64; i++)
rxMsg.data[i] = 0;

MCANConfig();

/* Enable RX FIFO interrupt */
MCAN_enableIntr(MCANB_DRIVER_BASE,
MCAN_INTR_SRC_RX_FIFO1_NEW_MSG,
1U);

MCAN_selectIntrLine(MCANB_DRIVER_BASE,
MCAN_INTR_SRC_RX_FIFO1_NEW_MSG,
MCAN_INTR_LINE_NUM_1);

MCAN_enableIntrLine(MCANB_DRIVER_BASE,
MCAN_INTR_LINE_NUM_1,
1U);
}

/* ------------------------------------------------ */

int MCAN_sendStdCAN(void)
{
uint16_t txData[4] = {0x11,0x22,0x33,0x44};
int i;

txMsg.id = ((uint32_t)0x123 << 18);
txMsg.rtr = 0;
txMsg.xtd = 0;
txMsg.esi = 0;
txMsg.dlc = 8;
txMsg.brs = 0;
txMsg.fdf = 0;
txMsg.efc = 0;
txMsg.mm = 0;

for(i=0;i<4;i++)
{
txMsg.data[i*2] = (uint8_t)(txData[i] & 0xFF);
txMsg.data[i*2+1] = (uint8_t)(txData[i] >> 8);
}

MCAN_writeMsgRam(MCANB_DRIVER_BASE,
MCAN_MEM_TYPE_BUF,
0,
&txMsg);

MCAN_txBufAddReq(MCANB_DRIVER_BASE,0);

return 0;
}

/* ------------------------------------------------ */

static void MCANConfig(void)
{
MCAN_InitParams initParams = {0};
MCAN_BitTimingParams bitTiming = {0};
MCAN_MsgRAMConfigParams ramCfg = {0};
MCAN_StdMsgIDFilterElement stdFilter = {0};

/* 1 Mbps configuration */
bitTiming.nomRatePrescalar = 0;
bitTiming.nomTimeSeg1 = 14;
bitTiming.nomTimeSeg2 = 5;
bitTiming.nomSynchJumpWidth = 2;

initParams.fdMode = 0;
initParams.brsEnable = 0;

/* Message RAM */

ramCfg.flssa = MCAN_STD_ID_FILT_START_ADDR;
ramCfg.lss = 1;

ramCfg.rxFIFO1startAddr = MCAN_FIFO_1_START_ADDR;
ramCfg.rxFIFO1size = MCAN_FIFO_1_NUM;
ramCfg.rxFIFO1waterMark = 1;
ramCfg.rxFIFO1ElemSize = MCAN_FIFO_1_ELEM_SIZE;

ramCfg.txStartAddr = MCAN_TX_BUFF_START_ADDR;
ramCfg.txBufNum = 1;
ramCfg.txBufElemSize = MCAN_TX_BUFF_ELEM_SIZE;

/* Accept Linux ID 0x7F4 */

stdFilter.sfid1 = 0x000;
stdFilter.sfid2 = 0x7FF;
stdFilter.sfec = 2; // store in FIFO1
stdFilter.sft = 2; // range filter

while(!MCAN_isMemInitDone(MCANB_DRIVER_BASE));

MCAN_setOpMode(MCANB_DRIVER_BASE,MCAN_OPERATION_MODE_SW_INIT);
while(MCAN_getOpMode(MCANB_DRIVER_BASE)!=MCAN_OPERATION_MODE_SW_INIT);

MCAN_init(MCANB_DRIVER_BASE,&initParams);
MCAN_setBitTime(MCANB_DRIVER_BASE,&bitTiming);
MCAN_msgRAMConfig(MCANB_DRIVER_BASE,&ramCfg);
MCAN_addStdMsgIDFilter(MCANB_DRIVER_BASE,0,&stdFilter);

MCAN_setOpMode(MCANB_DRIVER_BASE,MCAN_OPERATION_MODE_NORMAL);
while(MCAN_getOpMode(MCANB_DRIVER_BASE)!=MCAN_OPERATION_MODE_NORMAL);
}

/* ------------------------------------------------ */

static void MCANIntrConfig(void)
{
Interrupt_register(INT_MCANB_1,&MCAN_isr);
Interrupt_enable(INT_MCANB_1);
}

/* ------------------------------------------------ */

__interrupt void MCAN_isr(void)
{
uint32_t ir;
MCAN_RxFIFOStatus fs;

ir = MCAN_getIntrStatus(MCANB_DRIVER_BASE);

if(ir & MCAN_INTR_SRC_RX_FIFO1_NEW_MSG)
{
MCAN_getRxFIFOStatus(MCANB_DRIVER_BASE,&fs);

MCAN_readMsgRam(MCANB_DRIVER_BASE,
MCAN_MEM_TYPE_FIFO,
fs.getIdx,
MCAN_RX_FIFO_NUM_1,
&rxMsg);

MCAN_writeRxFIFOAck(MCANB_DRIVER_BASE,
MCAN_RX_FIFO_NUM_1,
fs.getIdx);

mcan_flag = 1;
}

MCAN_clearIntrStatus(MCANB_DRIVER_BASE,ir);
MCAN_clearInterrupt(MCANB_DRIVER_BASE,MCAN_INTR_LINE_NUM_1);

Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);

mcan_isr_count++;
}


Below is my mcan.h

#include <stdint.h>
#include <stdbool.h>
#include "driverlib.h"
#include "device.h"



// Standard 11-bit CAN ID (matches receiver RX_MSG_OBJ_ID = 1)
#define STD_CAN_ID 0x01
#define MSG_DATA_LENGTH 8 // 4 x 2-byte (uint16_t)


extern volatile uint8_t mcan_flag;

static void MCANConfig(void);
static void MCANIntrConfig(void);
__interrupt static void MCAN_isr(void);
void MCAN_initDriver(void);
int MCAN_sendStdCAN(void);
extern volatile uint8_t mcan_flag;
extern volatile uint32_t mcan_isr_count;

MCAN_RxBufElement* MCAN_getLastRxMsg(void);

//extern volatile uint32_t mcan_isr_count = 0; // Add this counter




below is my main.c
void main()

MCAN_initDriver();
MCAN_sendStdCAN();
DEVICE_DELAY_US(500000); // 500ms


MCAN_sendStdCAN();


/* In vTransDataTask — print ISR count every loop to confirm */
SYSTEM_LOG_UART(LOG, __func__,
"mcan_isr_count=%lu mcan_flag=%u\r\n",
mcan_isr_count, mcan_flag);

while (1)
if (mcan_flag)
{
mcan_flag = 0;

MCAN_RxBufElement *msg = MCAN_getLastRxMsg();

/* Cap DLC — valid CAN = 0 to 8 bytes */
uint16_t dlc = (msg->dlc <= 8U) ? msg->dlc : 8U;

char buf[32] = {0};
uint16_t i, pos = 0;
for (i = 0; i < dlc; i++)
pos += snprintf(buf + pos, sizeof(buf) - pos, "%02X ", msg->data[i]);

SYSTEM_LOG_UART(LOG, __func__,
"MCAN RX: ID=0x%03X DLC=%u Data= %s\r\n",
(unsigned int)(msg->id >> 18U),
(unsigned int)dlc,
buf);
}



Could you please help me identify what might be wrong with my configuration?

 

  • Hi Saravanan,

    MCAN Configuration Issue: Bit Timing Mismatch and Bus Errors

    Your MCAN interrupt fires only once because there's a bit timing mismatch between your TMS320F28P659DH-Q1 and the Linux Xilinx CAN controller, causing persistent bus errors that prevent successful communication.

    The Core Problem

    Your Linux statistics reveal the issue clearly: 129 bus-errors, 96 TX errors, 34 RX errors, and 4 bus-off events [1]. This indicates the two nodes cannot communicate reliably due to timing incompatibility, not a software configuration error in your ISR.

    Bit Timing Analysis

    Let me verify your calculations:

    Parameter Your TI Config Linux Config
    Clock 20 MHz (200 MHz ÷ 10) 100 MHz
    Prescaler 1 (nomRatePrescalar=0) 5
    TSEG1 14 14 (prop-seg + phase-seg1)
    TSEG2 5 5
    Total TQ 20 (1+14+5) 20
    Bitrate 20 MHz ÷ 20 = 1 Mbps ✓ 1 Mbps ✓
    Sample Point (1+14)/20 = 75% ✓ 75% ✓

    Your bit timing math is actually correct [2]. The sample points match at 75%, so the configuration itself isn't the problem.

    Root Cause: Physical Layer Issues

    Since the timing parameters are mathematically correct but you're seeing bus errors, the issue is hardware-related:

    1. CAN Transceiver Propagation Delay: If the transceiver delay exceeds TSEG1, bit errors occur at the sample point [3]. At 1 Mbps, this is critical.

    2. Bus Termination: CAN requires 120Ω termination resistors at both ends of the bus. Missing or incorrect termination causes reflections that appear as bus errors [4].

    3. Physical Wiring: At 1 Mbps, bus length must be under 40 meters with proper twisted-pair differential wiring [4].

    Debugging Steps

    Add this diagnostic code to read MCAN registers directly when issues occur:

    // Read these registers when communication fails
    uint32_t ir_reg = HWREG(MCANB_DRIVER_BASE + MCAN_O_IR);
    uint32_t rxf1s_reg = HWREG(MCANB_DRIVER_BASE + MCAN_O_RXF1S);
    uint32_t rxf1c_reg = HWREG(MCANB_DRIVER_BASE + MCAN_O_RXF1C);
    uint32_t ecr_reg = HWREG(MCANB_DRIVER_BASE + MCAN_O_ECR);  // Error counters
    uint32_t psr_reg = HWREG(MCANB_DRIVER_BASE + MCAN_O_PSR);  // Protocol status
    
    SYSTEM_LOG_UART(LOG, __func__,
        "IR=0x%08X RXF1S=0x%08X RXF1C=0x%08X ECR=0x%08X PSR=0x%08X\r\n",
        ir_reg, rxf1s_reg, rxf1c_reg, ecr_reg, psr_reg);
    

    Critical check: If MCAN_RXF1C reads 0x00000000, your FIFO1 is disabled despite configuration, which would prevent new message interrupts [5].

    ISR Verification

    Your ISR clearing sequence is correct—you're calling all four required steps [6]:

    1. MCAN_writeRxFIFOAck() - releases FIFO element
    2. MCAN_clearIntrStatus() - clears peripheral flags (W1C register) [7]
    3. MCAN_clearInterrupt() - clears interrupt line
    4. Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11) - clears PIE

    Recommended Actions

    1. Verify termination: Measure resistance between CAN_H and CAN_L with power off—should read ~60Ω (two 120Ω in parallel)

    2. Check transceiver: Confirm GPIO32 is driving low (your code looks correct), and verify the transceiver part number supports 1 Mbps

    3. Use oscilloscope: Capture CAN_H and CAN_L signals to verify proper differential signaling (typically 2V differential swing)

    4. Test at lower speed: Try 250 kbps first to rule out physical layer issues:

    // 250 kbps @ 75% sample point with 20 MHz clock
    bitTiming.nomRatePrescalar = 3;  // BRP = 4
    bitTiming.nomTimeSeg1 = 14;
    bitTiming.nomTimeSeg2 = 5;
    bitTiming.nomSynchJumpWidth = 4;
    

    And on Linux: ip link set can1 type can bitrate 250000

    1. Reference C2000Ware examples: Version 6.00.01.00 includes new MCAN examples for F28003x that can serve as working reference implementations [8].

    If the lower bitrate works, the issue is signal integrity at 1 Mbps. If it still fails, focus on termination and wiring. Could you share the CAN transceiver part number and confirm whether you have termination resistors installed at both bus ends?


    References:

    1. [User's Linux ip statistics output]
    2. TMS320F28P65x Technical Reference Manual - MCAN Bit Timing
    3. C2000 MCAN Academy - Sample Point and Transmitter Delay
    4. C2000 CAN Academy - Physical Layer Requirements
    5. TI E2E Forum - MCAN RX FIFO Configuration Issue
    6. TI E2E Forum - Interrupt Clearing Sequence
    7. TMS320F28P65x Technical Reference Manual - MCAN_IR Register
    8. C2000Ware 6.00.01.00 Release Notes