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.

TCAN4550: Data transmit wrong

Part Number: TCAN4550


Dear Team

TC4550 chip, using CAN FD mode
4M speed, only enable receive interrupt, no retransmission. Two device nodes are communicating.
Scenario 1:
Device node 0 sends request data
After receiving the request, Device Node 1 sends a data packet (67 bytes, which exceeds 64 bytes and is therefore divided into packets for transmission)
Node 0 received data and found unpacking errors (packet capture and simulation revealed that the first packet was correct, but the third to last data of the second packet was incorrect)
Packet capture: It was found that there was a problem with the second packet during packet capture. When the MCU sent data through SPI, packet capture was normal, but when it was sent to the bus stage through CAN, an error occurred
Approach:
Suspect that the interval between sending two packets is too short, but a delay of 500us is also useless.
Scenario 2:
Device node 0 sends request data
After receiving the request, Device Node 1 sends a data packet (less than 64 bytes)
Node 0 receives data unpacking normally
I don't know the reason yet, please ask TI engineers to assist. Thank you.

  • Hi Gabriel,

    Please provide the SPI and CAN message data logs showing the normal and abnormal data.

    Please also provide a list of all the final register values for the TCAN4550 so that I can review the configuration.

    Can you better explain your approach to handling multiple CAN packets?  Are you using a TX FIFO and creating multiple TX messages loading them both into the FIFO using two separate TX Buffer Elements?  Or are you trying to reuse the same TX buffer and loading the second message into the same TX buffer after the first packet has been transmitted?

    Regards,

    Jonathan

  • ,
    1.如附件所示
    2.最终配置log如下:

    === TCAN4550 Final Configuration Summary ===

    TCAN4550[D]: DEVICE_CONFIG: 0xC80004A0

    TCAN4550[D]: SWE_DIS: 0, WD_EN: 0, CLK_REF: 1, WAKE_CONFIG: 3

    TCAN4550[D]: CCCR: 0x00000340

    TCAN4550[D]: INIT: 0, CCE: 0, DAR: 1, FDOE: 1, BRSE: 1, NISO: 0

    TCAN4550[D]: NBTP: 0x02030601

    TCAN4550[D]: NBRP: 3, NTSEG1: 6, NTSEG2: 0, NSJW: 1

    TCAN4550[D]: DBTP: 0x00800622

    TCAN4550[D]: DBRP: 0, DTSEG1: 6, DTSEG2: 2, DSJW: 2

    TCAN4550[D]: GFC: 0x00000003

    TCAN4550[D]: RRFE: 0, RRFS: 0, ANFE: 0, ANFS: 3

    TCAN4550[D]: RXF0C: 0x8010000C

    TCAN4550[D]: RXF0S: 0x00000000 (F0FL: 0)

    TCAN4550[D]: TXBC: 0x4800048C

    TCAN4550[D]: DEV_IE: 0x87F628FF

    TCAN4550[D]: UVIOEN: 1, UVSUPEN: 1, CANBUSBATEN: 1, CANBUSGNDEN: 1, CANBUSOPETCAN4550[D]: MCAN_IE: 0x00000001

    TCAN4550[D]: RF0NE: 1, RF0WE: 0, RF0FE: 0, RF0LE: 0

    TCAN4550[D]: Device Mode: NORMAL

    TCAN4550[D]: Timing Configuration:

    TCAN4550[D]: Arbitration: 1000000 baud, Sample Point: 80.0%

    TCAN4550[D]: Data: 4000000 baud, Sample Point: 75.0%

    TCAN4550[D]: ================================================
    配置代码bsp_tcan4x5x.c
    3.代码配置了8个TX缓冲区,发送时循环调用发送的。而且bsp_tcan4x5x_send是调用了TCAN4x5x_MCAN_TransmitBufferContents直接发送,应该不会被覆盖。
    烦请帮忙分析下问题,谢谢TC4550发送问题相关log.doc

    #define TCAN_TX_BUFFER_COUNT       8     // 发送缓冲区数量,必须与MRAM配置一致
    #define TCAN_RX_FIFO0_COUNT        16    // RX FIFO0元素数量
    #define TCAN_MAX_DATA_LENGTH       64    // 最大数据长度 (CAN FD)
    
    
    void bsp_tcan4x5x_init(void) {
      TCAN4x5x_Debug(
          "\r\n====================================================\r\n");
      CanSpi_Init();
      CanSpi_Hw_Reset();
    
      TCAN4x5x_WDT_Timer_Enum wdt = TCAN4x5x_WDT_Read();
      TCAN4x5x_Debug("TCAN4x5x Watchdog Timer: %d, %s\n", wdt,
                     wdt == TCAN4x5x_WDT_60MS    ? "60ms"
                     : wdt == TCAN4x5x_WDT_600MS ? "600ms"
                     : wdt == TCAN4x5x_WDT_3S    ? "3S"
                                                 : "6S");
      /*
      TCAN4x5x Watchdog Timer: 0, 60ms
      */
      //  extern bool TCAN4x5x_WDT_Disable(void);
      if (!TCAN4x5x_WDT_Disable()) {
        TCAN4x5x_Debug("Failed to disable watchdog\n");
      }
    
      // extern uint16_t TCAN4x5x_Device_ReadDeviceVersion(void);
      uint16_t version = TCAN4x5x_Device_ReadDeviceVersion();
      TCAN4x5x_Debug("TCAN4x5x Device Version: 0x%04X\n", version);
    
      // void TCAN4x5x_Device_ReadConfig(TCAN4x5x_DEV_CONFIG *devCfg);
      TCAN4x5x_DEV_CONFIG devCfg;
      TCAN4x5x_Device_ReadConfig(&devCfg);
      TCAN4x5x_Debug("TCAN4x5x Device Config: 0x%08X\n", devCfg.word);
      TCAN4x5x_Debug("    SWE_DIS: %d\n", devCfg.SWE_DIS);
      TCAN4x5x_Debug("    DEVICE_RESET: %d\n", devCfg.DEVICE_RESET);
      TCAN4x5x_Debug("    WD_EN: %d\n", devCfg.WD_EN);
      TCAN4x5x_Debug("    nWKRQ_CONFIG: %d\n", devCfg.nWKRQ_CONFIG);
      TCAN4x5x_Debug("    INH_DIS: %d\n", devCfg.INH_DIS);
      TCAN4x5x_Debug("    GPIO1_CONFIG: %d\n", devCfg.GPIO1_CONFIG);
      TCAN4x5x_Debug("    FAIL_SAFE_EN: %d\n", devCfg.FAIL_SAFE_EN);
      TCAN4x5x_Debug("    WD_ACTION: %d\n", devCfg.WD_ACTION);
      TCAN4x5x_Debug("    WD_BIT_RESET: %d\n", devCfg.WD_BIT_RESET);
      TCAN4x5x_Debug("    nWKRQ_VOLTAGE: %d\n", devCfg.nWKRQ_VOLTAGE);
      TCAN4x5x_Debug("    GPO2_CONFIG: %d\n", devCfg.GPO2_CONFIG);
      TCAN4x5x_Debug("    CLK_REF: %d\n", devCfg.CLK_REF);
      TCAN4x5x_Debug("    WAKE_CONFIG: %d\n", devCfg.WAKE_CONFIG);
      Hw_System_RttLog_Flush();
      /*
      TCAN4x5x Device Config: 0xC8000468
        SWE_DIS: 0
        DEVICE_RESET: 0
        WD_EN: 1
        nWKRQ_CONFIG: 0
        INH_DIS: 0
        GPIO1_CONFIG: 0
        FAIL_SAFE_EN: 0
        WD_ACTION: 0
        WD_BIT_RESET: 0
        nWKRQ_VOLTAGE: 0
        GPO2_CONFIG: 0
        CLK_REF: 1
        WAKE_CONFIG: 3
      */
      // extern bool TCAN4x5x_Device_Configure(TCAN4x5x_DEV_CONFIG *devCfg);
      // SWE_DIS set to 1
      devCfg.SWE_DIS = 1;
      if (!TCAN4x5x_Device_Configure(&devCfg)) {
        TCAN4x5x_Debug("Failed to configure device\n");
      }
      // read again
      TCAN4x5x_Device_ReadConfig(&devCfg);
      TCAN4x5x_Debug("TCAN4x5x Device Config: 0x%08X\n", devCfg.word);
      TCAN4x5x_Debug("    SWE_DIS: %d\n", devCfg.SWE_DIS);
      TCAN4x5x_Debug("    DEVICE_RESET: %d\n", devCfg.DEVICE_RESET);
      TCAN4x5x_Debug("    WD_EN: %d\n", devCfg.WD_EN);
      TCAN4x5x_Debug("    nWKRQ_CONFIG: %d\n", devCfg.nWKRQ_CONFIG);
      TCAN4x5x_Debug("    INH_DIS: %d\n", devCfg.INH_DIS);
      TCAN4x5x_Debug("    GPIO1_CONFIG: %d\n", devCfg.GPIO1_CONFIG);
      TCAN4x5x_Debug("    FAIL_SAFE_EN: %d\n", devCfg.FAIL_SAFE_EN);
      TCAN4x5x_Debug("    WD_ACTION: %d\n", devCfg.WD_ACTION);
      TCAN4x5x_Debug("    WD_BIT_RESET: %d\n", devCfg.WD_BIT_RESET);
      TCAN4x5x_Debug("    nWKRQ_VOLTAGE: %d\n", devCfg.nWKRQ_VOLTAGE);
      TCAN4x5x_Debug("    GPO2_CONFIG: %d\n", devCfg.GPO2_CONFIG);
      TCAN4x5x_Debug("    CLK_REF: %d\n", devCfg.CLK_REF);
      TCAN4x5x_Debug("    WAKE_CONFIG: %d\n", devCfg.WAKE_CONFIG);
    
      // extern void TCAN4x5x_Device_ReadInterrupts(TCAN4x5x_Device_Interrupts *ir);
      TCAN4x5x_Device_Interrupts ir;
      TCAN4x5x_Device_ReadInterrupts(&ir);
      TCAN4x5x_Debug("TCAN4x5x Device Interrupts: 0x%08X\n", ir.word);
      TCAN4x5x_Debug("    VTWD: %d\n", ir.VTWD);
      TCAN4x5x_Debug("    M_CAN_INT: %d\n", ir.M_CAN_INT);
      TCAN4x5x_Debug("    SWERR: %d\n", ir.SWERR);
      TCAN4x5x_Debug("    SPIERR: %d\n", ir.SPIERR);
      TCAN4x5x_Debug("    CBF: %d\n", ir.CBF);
      TCAN4x5x_Debug("    CANERR: %d\n", ir.CANERR);
      TCAN4x5x_Debug("    WKRQ: %d\n", ir.WKRQ);
      TCAN4x5x_Debug("    GLOBALERR: %d\n", ir.GLOBALERR);
      TCAN4x5x_Debug("    CANDOM: %d\n", ir.CANDOM);
      TCAN4x5x_Debug("    RESERVED: %d\n", ir.RESERVED);
      TCAN4x5x_Debug("    CANTO: %d\n", ir.CANTO);
      TCAN4x5x_Debug("    RESERVED2: %d\n", ir.RESERVED2);
      TCAN4x5x_Debug("    FRAME_OVF: %d\n", ir.FRAME_OVF);
      TCAN4x5x_Debug("    WKERR: %d\n", ir.WKERR);
      TCAN4x5x_Debug("    LWU: %d\n", ir.LWU);
      TCAN4x5x_Debug("    CANINT: %d\n", ir.CANINT);
      TCAN4x5x_Debug("    ECCERR: %d\n", ir.ECCERR);
      TCAN4x5x_Debug("    RESERVED3: %d\n", ir.RESERVED3);
      TCAN4x5x_Debug("    WDTO: %d\n", ir.WDTO);
      TCAN4x5x_Debug("    TSD: %d\n", ir.TSD);
      TCAN4x5x_Debug("    PWRON: %d\n", ir.PWRON);
      TCAN4x5x_Debug("    UVIO: %d\n", ir.UVIO);
      TCAN4x5x_Debug("    UVSUP: %d\n", ir.UVSUP);
      TCAN4x5x_Debug("    SMS: %d\n", ir.SMS);
      TCAN4x5x_Debug("    CANBUSBAT: %d\n", ir.CANBUSBAT);
      TCAN4x5x_Debug("    CANBUSGND: %d\n", ir.CANBUSGND);
      TCAN4x5x_Debug("    CANBUSOPEN: %d\n", ir.CANBUSOPEN);
      TCAN4x5x_Debug("    CANLGND: %d\n", ir.CANLGND);
      TCAN4x5x_Debug("    CANHBAT: %d\n", ir.CANHBAT);
      TCAN4x5x_Debug("    CANHCANL: %d\n", ir.CANHCANL);
      TCAN4x5x_Debug("    CANBUSTERMOPEN: %d\n", ir.CANBUSTERMOPEN);
      TCAN4x5x_Debug("    CANBUSNORM: %d\n", ir.CANBUSNORM);
      Hw_System_RttLog_Flush();
      /*
      TCAN4x5x Device Interrupts: 0x00100000
        VTWD: 0
        M_CAN_INT: 0
        SWERR: 0
        SPIERR: 0
        CBF: 0
        CANERR: 0
        WKRQ: 0
        GLOBALERR: 0
        CANDOM: 0
        RESERVED: 0
        CANTO: 0
        RESERVED2: 0
        FRAME_OVF: 0
        WKERR: 0
        LWU: 0
        CANINT: 0
        ECCERR: 0
        RESERVED3: 0
        WDTO: 0
        TSD: 0
        PWRON: 1
        UVIO: 0
        UVSUP: 0
        SMS: 0
        CANBUSBAT: 0
        CANBUSGND: 0
        CANBUSOPEN: 0
        CANLGND: 0
        CANHBAT: 0
        CANHCANL: 0
        CANBUSTERMOPEN: 0
        CANBUSNORM: 0
      */
    
      // extern void
      // TCAN4x5x_Device_ReadInterruptEnable(TCAN4x5x_Device_Interrupt_Enable *ie);
      TCAN4x5x_Device_Interrupt_Enable ie;
      TCAN4x5x_Device_ReadInterruptEnable(&ie);
      TCAN4x5x_Debug("TCAN4x5x Device Interrupt Enable: 0x%08X\n", ie.word);
      TCAN4x5x_Debug("    RESERVED1: %d\n", ie.RESERVED1);
      TCAN4x5x_Debug("    CANDOMEN: %d\n", ie.CANDOMEN);
      TCAN4x5x_Debug("    RESERVED2: %d\n", ie.RESERVED2);
      TCAN4x5x_Debug("    CANTOEN: %d\n", ie.CANTOEN);
      TCAN4x5x_Debug("    RESERVED3: %d\n", ie.RESERVED3);
      TCAN4x5x_Debug("    FRAME_OVFEN: %d\n", ie.FRAME_OVFEN);
      TCAN4x5x_Debug("    WKERREN: %d\n", ie.WKERREN);
      TCAN4x5x_Debug("    LWUEN: %d\n", ie.LWUEN);
      TCAN4x5x_Debug("    CANINTEN: %d\n", ie.CANINTEN);
      TCAN4x5x_Debug("    ECCERREN: %d\n", ie.ECCERREN);
      TCAN4x5x_Debug("    RESERVED4: %d\n", ie.RESERVED4);
      TCAN4x5x_Debug("    WDTOEN: %d\n", ie.WDTOEN);
      TCAN4x5x_Debug("    TSDEN: %d\n", ie.TSDEN);
      TCAN4x5x_Debug("    PWRONEN: %d\n", ie.PWRONEN);
      TCAN4x5x_Debug("    UVIOEN: %d\n", ie.UVIOEN);
      TCAN4x5x_Debug("    UVSUPEN: %d\n", ie.UVSUPEN);
      TCAN4x5x_Debug("    SMSEN: %d\n", ie.SMSEN);
      TCAN4x5x_Debug("    CANBUSBATEN: %d\n", ie.CANBUSBATEN);
      TCAN4x5x_Debug("    CANBUSGNDEN: %d\n", ie.CANBUSGNDEN);
      TCAN4x5x_Debug("    CANBUSOPENEN: %d\n", ie.CANBUSOPENEN);
      TCAN4x5x_Debug("    CANLGNDEN: %d\n", ie.CANLGNDEN);
      TCAN4x5x_Debug("    CANHBATEN: %d\n", ie.CANHBATEN);
      TCAN4x5x_Debug("    CANHCANLEN: %d\n", ie.CANHCANLEN);
      TCAN4x5x_Debug("    CANBUSTERMOPENEN: %d\n", ie.CANBUSTERMOPENEN);
      TCAN4x5x_Debug("    CANBUSNORMEN: %d\n", ie.CANBUSNORMEN);
      /*
      TCAN4x5x Device Interrupt Enable: 0xFFFFFFFF
          RESERVED1: 255
          CANDOMEN: 1
          RESERVED2: 1
          CANTOEN: 1
          RESERVED3: 1
          FRAME_OVFEN: 1
          WKERREN: 1
          LWUEN: 1
          CANINTEN: 1
          ECCERREN: 1
          RESERVED4: 1
          WDTOEN: 1
          TSDEN: 1
          PWRONEN: 1
          UVIOEN: 1
          UVSUPEN: 1
          SMSEN: 1
          CANBUSBATEN: 1
          CANBUSGNDEN: 1
          CANBUSOPENEN: 1
          CANLGNDEN: 1
          CANHBATEN: 1
          CANHCANLEN: 1
          CANBUSTERMOPENEN: 1
          CANBUSNORMEN: 1
      */
    
      // TCAN4x5x_Device_Mode_Enum TCAN4x5x_Device_ReadMode(void);
      TCAN4x5x_Device_Mode_Enum mode = TCAN4x5x_Device_ReadMode();
      TCAN4x5x_Debug("TCAN4x5x Device Mode: %d, %s\n", mode,
                     mode == TCAN4x5x_DEVICE_MODE_NORMAL    ? "NORMAL"
                     : mode == TCAN4x5x_DEVICE_MODE_STANDBY ? "STANDBY"
                                                            : "SLEEP");
      /*
      TCAN4x5x Device Mode: 1, STANDBY
      */
      // extern bool TCAN4x5x_Device_SetMode(TCAN4x5x_Device_Mode_Enum modeDefine);
      // Set to NORMAL
      if (!TCAN4x5x_Device_SetMode(TCAN4x5x_DEVICE_MODE_NORMAL)) {
        TCAN4x5x_Debug("Failed to set device mode\n");
      }
      // read again
      mode = TCAN4x5x_Device_ReadMode();
      TCAN4x5x_Debug("TCAN4x5x Device Mode: %d, %s\n", mode,
                     mode == TCAN4x5x_DEVICE_MODE_NORMAL    ? "NORMAL"
                     : mode == TCAN4x5x_DEVICE_MODE_STANDBY ? "STANDBY"
                                                            : "SLEEP");
    
      // typedef enum { TCAN4x5x_DEVICE_TEST_MODE_NORMAL,
      // TCAN4x5x_DEVICE_TEST_MODE_PHY, TCAN4x5x_DEVICE_TEST_MODE_CONTROLLER }
      // TCAN4x5x_Device_Test_Mode_Enum;
      // extern TCAN4x5x_Device_Test_Mode_Enum TCAN4x5x_Device_ReadTestMode(void);
      TCAN4x5x_Device_Test_Mode_Enum testMode = TCAN4x5x_Device_ReadTestMode();
      TCAN4x5x_Debug("TCAN4x5x Device Test Mode: %d, %s\n", testMode,
                     testMode == TCAN4x5x_DEVICE_TEST_MODE_NORMAL ? "NORMAL"
                     : testMode == TCAN4x5x_DEVICE_TEST_MODE_PHY  ? "PHY"
                                                                  : "CONTROLLER");
      /*
      TCAN4x5x Device Test Mode: 0, NORMAL
      */
    
      // extern void TCAN4x5x_MCAN_ReadCCCRRegister(TCAN4x5x_MCAN_CCCR_Config
      // *cccrConfig);
      TCAN4x5x_MCAN_CCCR_Config cccrConfig;
      TCAN4x5x_MCAN_ReadCCCRRegister(&cccrConfig);
      TCAN4x5x_Debug("TCAN4x5x MCAN CCCR Config: 0x%08X\n", cccrConfig.word);
      TCAN4x5x_Debug("    reserved: %d\n", cccrConfig.reserved);
      TCAN4x5x_Debug("    ASM: %d\n", cccrConfig.ASM);
      TCAN4x5x_Debug("    reserved2: %d\n", cccrConfig.reserved2);
      TCAN4x5x_Debug("    CSR: %d\n", cccrConfig.CSR);
      TCAN4x5x_Debug("    MON: %d\n", cccrConfig.MON);
      TCAN4x5x_Debug("    DAR: %d\n", cccrConfig.DAR);
      TCAN4x5x_Debug("    TEST: %d\n", cccrConfig.TEST);
      TCAN4x5x_Debug("    FDOE: %d\n", cccrConfig.FDOE);
      TCAN4x5x_Debug("    BRSE: %d\n", cccrConfig.BRSE);
      TCAN4x5x_Debug("    reserved3: %d\n", cccrConfig.reserved3);
      TCAN4x5x_Debug("    PXHD: %d\n", cccrConfig.PXHD);
      TCAN4x5x_Debug("    EFBI: %d\n", cccrConfig.EFBI);
      TCAN4x5x_Debug("    TXP: %d\n", cccrConfig.TXP);
      TCAN4x5x_Debug("    NISO: %d\n", cccrConfig.NISO);
      /*
      TCAN4x5x MCAN CCCR Config: 0x00000000
          reserved: 0
          ASM: 0
          reserved2: 0
          CSR: 0
          MON: 0
          DAR: 0
          TEST: 0
          FDOE: 0
          BRSE: 0
          reserved3: 0
          PXHD: 0
          EFBI: 0
          TXP: 0
          NISO: 0
      */
      // extern bool TCAN4x5x_MCAN_EnableProtectedRegisters(void);
      // Attempts to enable CCCR.CCE and CCCR.INIT to allow writes to protected
      // registers, needed for MCAN configuration
      if (!TCAN4x5x_MCAN_EnableProtectedRegisters()) {
        TCAN4x5x_Debug("Failed to enable protected registers\n");
      }
      // read again
      TCAN4x5x_MCAN_ReadCCCRRegister(&cccrConfig);
      TCAN4x5x_Debug("TCAN4x5x MCAN CCCR Config: 0x%08X\n", cccrConfig.word);
      TCAN4x5x_Debug("    reserved(CCE << 1 | INIT): %d\n", cccrConfig.reserved);
      TCAN4x5x_Debug("    ASM: %d\n", cccrConfig.ASM);
      TCAN4x5x_Debug("    reserved2: %d\n", cccrConfig.reserved2);
      TCAN4x5x_Debug("    CSR: %d\n", cccrConfig.CSR);
      TCAN4x5x_Debug("    MON: %d\n", cccrConfig.MON);
      TCAN4x5x_Debug("    DAR: %d\n", cccrConfig.DAR);
      TCAN4x5x_Debug("    TEST: %d\n", cccrConfig.TEST);
      TCAN4x5x_Debug("    FDOE(FDF): %d\n", cccrConfig.FDOE);
      TCAN4x5x_Debug("    BRSE(BRS): %d\n", cccrConfig.BRSE);
      TCAN4x5x_Debug("    reserved3: %d\n", cccrConfig.reserved3);
      TCAN4x5x_Debug("    PXHD: %d\n", cccrConfig.PXHD);
      TCAN4x5x_Debug("    EFBI: %d\n", cccrConfig.EFBI);
      TCAN4x5x_Debug("    TXP: %d\n", cccrConfig.TXP);
      TCAN4x5x_Debug("    NISO: %d\n", cccrConfig.NISO);
      // if CSR not clear, you should set mode to NORMAL first
      // enable FDF and BRS, and disable CSR(Clock Stop Request)
      cccrConfig.FDOE = 1;
      cccrConfig.BRSE = 1;
      cccrConfig.CSR = 0;
      // 配置单次发送模式:禁用自动重传
      cccrConfig.DAR = 1;  // Disable Auto Retransmission - 单次发送不重传
      
      // extern bool TCAN4x5x_MCAN_ConfigureCCCRRegister(TCAN4x5x_MCAN_CCCR_Config
      // *cccr);
      if (!TCAN4x5x_MCAN_ConfigureCCCRRegister(&cccrConfig)) {
        TCAN4x5x_Debug("Failed to configure CCCR\n");
      }
      // read again
      TCAN4x5x_MCAN_ReadCCCRRegister(&cccrConfig);
      TCAN4x5x_Debug("TCAN4x5x MCAN CCCR Config: 0x%08X\n", cccrConfig.word);
      TCAN4x5x_Debug("    reserved(CCE << 1 | INIT): %d\n", cccrConfig.reserved);
      TCAN4x5x_Debug("    ASM: %d\n", cccrConfig.ASM);
      TCAN4x5x_Debug("    reserved2: %d\n", cccrConfig.reserved2);
      TCAN4x5x_Debug("    CSR: %d\n", cccrConfig.CSR);
      TCAN4x5x_Debug("    MON: %d\n", cccrConfig.MON);
      TCAN4x5x_Debug("    DAR: %d\n", cccrConfig.DAR);
      TCAN4x5x_Debug("    TEST: %d\n", cccrConfig.TEST);
      TCAN4x5x_Debug("    FDOE(FDF): %d\n", cccrConfig.FDOE);
      TCAN4x5x_Debug("    BRSE(BRS): %d\n", cccrConfig.BRSE);
      TCAN4x5x_Debug("    reserved3: %d\n", cccrConfig.reserved3);
      TCAN4x5x_Debug("    PXHD: %d\n", cccrConfig.PXHD);
      TCAN4x5x_Debug("    EFBI: %d\n", cccrConfig.EFBI);
      TCAN4x5x_Debug("    TXP: %d\n", cccrConfig.TXP);
      TCAN4x5x_Debug("    NISO: %d\n", cccrConfig.NISO);
      /*
      TCAN4x5x MCAN CCCR Config: 0x00000303
        reserved(CCE << 1 | INIT): 3
        ASM: 0
        reserved2: 0
        CSR: 0
        MON: 0
        DAR: 0
        TEST: 0
        FDOE(FDF): 1
        BRSE(BRS): 1
        reserved3: 0
        PXHD: 0
        EFBI: 0
        TXP: 0
        NISO: 0
      */
      // tcan4x5x_mcan_config(500000, 0.8f, 2000000, 0.8f);
      tcan4x5x_mcan_config(1000000, 0.8f, 4000000, 0.75f);
      // tcan4x5x_mcan_write_test();
    
    
    TCAN4x5x_Debug("\r\n=== TCAN4550 Final Configuration Summary ===\r\n");
    
    // 1. 设备配置寄存器
    TCAN4x5x_DEV_CONFIG final_dev_cfg;
    TCAN4x5x_Device_ReadConfig(&final_dev_cfg);
    TCAN4x5x_Debug("DEVICE_CONFIG: 0x%08X\r\n", final_dev_cfg.word);
    TCAN4x5x_Debug("  SWE_DIS: %d, WD_EN: %d, CLK_REF: %d, WAKE_CONFIG: %d\r\n", 
                   final_dev_cfg.SWE_DIS, final_dev_cfg.WD_EN, 
                   final_dev_cfg.CLK_REF, final_dev_cfg.WAKE_CONFIG);
    
    // 2. MCAN CCCR 寄存器
    TCAN4x5x_MCAN_CCCR_Config final_cccr;
    TCAN4x5x_MCAN_ReadCCCRRegister(&final_cccr);
    TCAN4x5x_Debug("CCCR: 0x%08X\r\n", final_cccr.word);
    TCAN4x5x_Debug("  INIT: %d, CCE: %d, DAR: %d, FDOE: %d, BRSE: %d, NISO: %d\r\n",
                   final_cccr.reserved & 1, (final_cccr.reserved >> 1) & 1,
                   final_cccr.DAR, final_cccr.FDOE, final_cccr.BRSE, final_cccr.NISO);
    
    // 3. 仲裁段定时寄存器 (NBTP)
    uint32_t nbtp_reg = AHB_READ_32(REG_MCAN_NBTP);
    TCAN4x5x_Debug("NBTP: 0x%08X\r\n", nbtp_reg);
    uint32_t nbrp = (nbtp_reg >> 16) & 0x1FF;
    uint32_t ntseg1 = (nbtp_reg >> 8) & 0xFF;
    uint32_t ntseg2 = (nbtp_reg >> 4) & 0x7;
    uint32_t nsjw = nbtp_reg & 0x7;
    TCAN4x5x_Debug("  NBRP: %d, NTSEG1: %d, NTSEG2: %d, NSJW: %d\r\n", 
                   nbrp, ntseg1, ntseg2, nsjw);
    
    // 4. 数据段定时寄存器 (DBTP)
    uint32_t dbtp_reg = AHB_READ_32(REG_MCAN_DBTP);
    TCAN4x5x_Debug("DBTP: 0x%08X\r\n", dbtp_reg);
    uint32_t dbrp = (dbtp_reg >> 16) & 0x1F;
    uint32_t dtseg1 = (dbtp_reg >> 8) & 0x1F;
    uint32_t dtseg2 = (dbtp_reg >> 4) & 0xF;
    uint32_t dsjw = dbtp_reg & 0xF;
    TCAN4x5x_Debug("  DBRP: %d, DTSEG1: %d, DTSEG2: %d, DSJW: %d\r\n",
                   dbrp, dtseg1, dtseg2, dsjw);
    
    // 5. 全局过滤器配置 (GFC)
    uint32_t gfc_reg = AHB_READ_32(REG_MCAN_GFC);
    TCAN4x5x_Debug("GFC: 0x%08X\r\n", gfc_reg);
    uint32_t rrfe = (gfc_reg >> 7) & 1;
    uint32_t rrfs = (gfc_reg >> 6) & 1;
    uint32_t anfe = (gfc_reg >> 3) & 0x3;
    uint32_t anfs = gfc_reg & 0x3;
    TCAN4x5x_Debug("  RRFE: %d, RRFS: %d, ANFE: %d, ANFS: %d\r\n",
                   rrfe, rrfs, anfe, anfs);
    
    // 6. RX FIFO 0 配置
    uint32_t rxf0c_reg = AHB_READ_32(REG_MCAN_RXF0C);
    TCAN4x5x_Debug("RXF0C: 0x%08X\r\n", rxf0c_reg);
    uint32_t rxf0s = AHB_READ_32(REG_MCAN_RXF0S);
    TCAN4x5x_Debug("RXF0S: 0x%08X (F0FL: %d)\r\n", rxf0s, (rxf0s >> 24) & 0x3F);
    
    // 7. TX Buffer 配置
    uint32_t txbc_reg = AHB_READ_32(REG_MCAN_TXBC);
    TCAN4x5x_Debug("TXBC: 0x%08X\r\n", txbc_reg);
    
    // 8. 设备中断使能
    TCAN4x5x_Device_Interrupt_Enable final_dev_ie;
    TCAN4x5x_Device_ReadInterruptEnable(&final_dev_ie);
    TCAN4x5x_Debug("DEV_IE: 0x%08X\r\n", final_dev_ie.word);
    TCAN4x5x_Debug("  UVIOEN: %d, UVSUPEN: %d, CANBUSBATEN: %d, CANBUSGNDEN: %d, CANBUSOPENEN: %d\r\n",
                   final_dev_ie.UVIOEN, final_dev_ie.UVSUPEN, 
                   final_dev_ie.CANBUSBATEN, final_dev_ie.CANBUSGNDEN, 
                   final_dev_ie.CANBUSOPENEN);
    
    // 9. MCAN 中断使能
    TCAN4x5x_MCAN_Interrupt_Enable final_mcan_ie;
    TCAN4x5x_MCAN_ReadInterruptEnable(&final_mcan_ie);
    TCAN4x5x_Debug("MCAN_IE: 0x%08X\r\n", final_mcan_ie.word);
    TCAN4x5x_Debug("  RF0NE: %d, RF0WE: %d, RF0FE: %d, RF0LE: %d\r\n",
                   final_mcan_ie.RF0NE, final_mcan_ie.RF0WE,
                   final_mcan_ie.RF0FE, final_mcan_ie.RF0LE);
    
    // 10. 工作模式
    TCAN4x5x_Device_Mode_Enum final_mode = TCAN4x5x_Device_ReadMode();
    TCAN4x5x_Debug("Device Mode: %s\r\n", 
                   final_mode == TCAN4x5x_DEVICE_MODE_NORMAL ? "NORMAL" :
                   final_mode == TCAN4x5x_DEVICE_MODE_STANDBY ? "STANDBY" : "SLEEP");
    
    // 11. 波特率计算信息
    TCAN4x5x_Debug("Timing Configuration:\r\n");
    TCAN4x5x_Debug("  Arbitration: %d baud, Sample Point: %.1f%%\r\n", 
                   1000000, 80.0f);
    TCAN4x5x_Debug("  Data: %d baud, Sample Point: %.1f%%\r\n", 
                   4000000, 75.0f);
    
    TCAN4x5x_Debug("================================================\r\n");
    
    
      is_busoff_or_error = false;
      busoff_or_error_count = 0;
    }
    
    static void tcan4x5x_mcan_config(uint32_t baud, float sample_point,
                                     uint32_t data_baud, float data_sample_point) {
      // 配置设备中断:仅开启必要的错误检测中断,关闭其他中断
      TCAN4x5x_Device_Interrupt_Enable ie = {0};
      ie.UVIOEN = 1;           // UVIO, Undervoltage on VIO
      ie.UVSUPEN = 1;          // UVSUP, Undervoltage on VSUP and VCCOUT
      ie.CANBUSBATEN = 1;      // CANBUSBAT, CAN Shorted to VBAT
      ie.CANBUSGNDEN = 1;      // CANBUSGND, CAN Shorted to GND
      ie.CANBUSOPENEN = 1;     // CANBUSOPEN, CAN Open fault
      // 关闭其他设备中断,只保留必要的错误检测
      TCAN4x5x_Device_ConfigureInterruptEnable(&ie);
      
      // Clear PWRON because if it's not cleared within ~4 minutes, it goes to sleep
      TCAN4x5x_Device_Interrupts ir = {0};
      TCAN4x5x_Device_ReadInterrupts(&ir);
      if (ir.PWRON) {
        TCAN4x5x_Device_ClearInterrupts(&ir);
        TCAN4x5x_Debug("Cleared PWRON interrupt\n");
      }
    
      // 40MHz Clock
      TCAN4x5x_MCAN_CCCR_Config cccr_config = {0};
      cccr_config.FDOE = 1;
      cccr_config.BRSE = 1;
      cccr_config.DAR = 1;  // 禁用自动重传,单次发送模式
      
      TCAN4x5x_MCAN_Nominal_Timing_Simple timing = {
          .NominalBitRatePrescaler = 4,
          .NominalTqBeforeSamplePoint =
              (int)roundf((10000000.0f / baud) * sample_point),
          .NominalTqAfterSamplePoint =
              (int)roundf((10000000.0f / baud) * (1 - sample_point))
      };
      TCAN4x5x_Debug("NominalTqBeforeSamplePoint: %d\n",
                     timing.NominalTqBeforeSamplePoint);
      TCAN4x5x_Debug("NominalTqAfterSamplePoint: %d\n",
                     timing.NominalTqAfterSamplePoint);
      
      TCAN4x5x_MCAN_Data_Timing_Simple data_timing = {
          .DataBitRatePrescaler = 1,
          .DataTqBeforeSamplePoint =
              (int)roundf((40000000 / data_baud) * data_sample_point),
          .DataTqAfterSamplePoint =
              (int)roundf((40000000 / data_baud) * (1 - data_sample_point))
      };
      TCAN4x5x_Debug("DataTqBeforeSamplePoint: %d\n",
                     data_timing.DataTqBeforeSamplePoint);
      TCAN4x5x_Debug("DataTqAfterSamplePoint: %d\n",
                     data_timing.DataTqAfterSamplePoint);
      
      // 配置全局过滤器:接受所有标准帧和扩展帧到RXFIFO0
      TCAN4x5x_MCAN_Global_Filter_Configuration global_filter = {0};
      global_filter.RRFE = 1;  // 拒绝远程帧
      global_filter.RRFS = 1;
      global_filter.ANFE = TCAN4x5x_GFC_ACCEPT_INTO_RXFIFO0;  // 接受所有扩展帧到RXFIFO0
      global_filter.ANFS = TCAN4x5x_GFC_ACCEPT_INTO_RXFIFO0;  // 接受所有标准帧到RXFIFO0
      
      // 使用宏定义配置MRAM大小
      TCAN4x5x_MRAM_Config mram_config = {
          .SIDNumElements = 1,
          .XIDNumElements = 1,
          .Rx0NumElements = TCAN_RX_FIFO0_COUNT,  // 使用宏定义
          .Rx0ElementSize = MRAM_64_Byte_Data,
          .Rx1NumElements = 0,
          .Rx1ElementSize = MRAM_64_Byte_Data,
          .RxBufNumElements = 0,
          .RxBufElementSize = MRAM_64_Byte_Data,
          .TxEventFIFONumElements = 0,
          .TxBufferNumElements = TCAN_TX_BUFFER_COUNT,  // 使用宏定义
          .TxBufferElementSize = MRAM_64_Byte_Data,
      };
    
      TCAN4x5x_MCAN_EnableProtectedRegisters();
      TCAN4x5x_MCAN_ConfigureCCCRRegister(&cccr_config);
      TCAN4x5x_MCAN_ConfigureGlobalFilter(&global_filter);
      TCAN4x5x_MCAN_ConfigureNominalTiming_Simple(&timing);
      TCAN4x5x_MCAN_ConfigureDataTiming_Simple(&data_timing);
      TCAN4x5x_MRAM_Clear();
      TCAN4x5x_MRAM_Configure(&mram_config);
      TCAN4x5x_MCAN_DisableProtectedRegisters();
    
      // 配置MCAN中断:仅开启接收中断
      TCAN4x5x_MCAN_Interrupt_Enable mcan_ie = {0};
      mcan_ie.RF0NE = 1; // 仅启用RX FIFO 0新消息中断
      // 关闭其他所有MCAN中断
      TCAN4x5x_MCAN_ConfigureInterruptEnable(&mcan_ie);
    
      // 配置标准ID过滤器
      TCAN4x5x_MCAN_SID_Filter std_filter = {0};
      std_filter.SFT = TCAN4x5x_SID_SFT_CLASSIC;
      std_filter.SFEC = TCAN4x5x_SID_SFEC_PRIORITYSTORERX0;
      std_filter.SFID1 = 0;
      std_filter.SFID2 = 0;
      TCAN4x5x_MCAN_WriteSIDFilter(0, &std_filter);
      
      // 配置扩展ID过滤器
      TCAN4x5x_MCAN_XID_Filter ext_filter = {0};
      ext_filter.EFT = TCAN4x5x_XID_EFT_CLASSIC;
      ext_filter.EFEC = TCAN4x5x_XID_EFEC_PRIORITYSTORERX0;
      ext_filter.EFID1 = 0;
      ext_filter.EFID2 = 0;
      TCAN4x5x_MCAN_WriteXIDFilter(0, &ext_filter);
    
      /* Configure the TCAN4550 Non-CAN-related functions */
      TCAN4x5x_DEV_CONFIG devConfig = {0};
      devConfig.SWE_DIS =
          0; // Keep Sleep Wake Error Enabled (it's a disable bit, not an enable)
      devConfig.DEVICE_RESET = 0; // Not requesting a software reset
      devConfig.WD_EN = 0;        // Watchdog disabled
      devConfig.nWKRQ_CONFIG = 0; // Mirror INH function (default)
      devConfig.INH_DIS = 0;      // INH enabled (default)
      devConfig.GPIO1_GPO_CONFIG =
          TCAN4x5x_DEV_CONFIG_GPO1_MCAN_INT1; // MCAN nINT 1 (default)
      devConfig.FAIL_SAFE_EN = 0;             // Failsafe disabled (default)
      devConfig.GPIO1_CONFIG =
          TCAN4x5x_DEV_CONFIG_GPIO1_CONFIG_GPO; // GPIO set as GPO (Default)
      devConfig.WD_ACTION =
          TCAN4x5x_DEV_CONFIG_WDT_ACTION_nINT; // Watchdog set an interrupt
                                               // (default)
      devConfig.WD_BIT_RESET = 0;              // Don't reset the watchdog
      devConfig.nWKRQ_VOLTAGE = 0; // Set nWKRQ to internal voltage rail (default)
      devConfig.GPO2_CONFIG =
          TCAN4x5x_DEV_CONFIG_GPO2_NO_ACTION; // GPO2 has no behavior (default)
      devConfig.CLK_REF = 1; // Input crystal is a 40 MHz crystal (default)
      devConfig.WAKE_CONFIG =
          TCAN4x5x_DEV_CONFIG_WAKE_BOTH_EDGES; // Wake pin can be triggered by
                                               // either edge (default)
      TCAN4x5x_Device_Configure(&devConfig);
    
      TCAN4x5x_Device_SetMode(TCAN4x5x_DEVICE_MODE_NORMAL);
      TCAN4x5x_MCAN_ClearInterruptsAll();
      
      TCAN4x5x_Debug("TCAN4x5x configured: RX interrupt only, single transmission, filters enabled\n");
    }
    
    /**
     * @brief 发送函数
     */
    bool bsp_tcan4x5x_send(uint32_t id, uint8_t *data, uint8_t len, bool is_extended)
    {
        if (len > 64) return false;
        
        TCAN4x5x_MCAN_TX_Header tx_header = {
            .ID = id,
            .RTR = 0,
            .XTD = 1,
            .ESI = 0,
            .DLC = TCAN4x5x_MCAN_BytesToDLC(len),
            .BRS = 1,  // 启用比特率切换 (FD模式)
            .FDF = 1,  // CAN FD帧
            .reserved = 0,
            .EFC = 0,
            .MM = 0,
        };
    
        // 使用循环缓冲区索引
        uint8_t buffer_index = g_tx_buffer_index;
        g_tx_buffer_index = (g_tx_buffer_index + 1) % TCAN_TX_BUFFER_COUNT;
        
        // 写入TX缓冲区并发送
        if (!TCAN4x5x_MCAN_WriteTXBuffer(buffer_index, &tx_header, data)) {
            return false;
        }
        
        return TCAN4x5x_MCAN_TransmitBufferContents(buffer_index);
    }
    
    /**
     * @brief 简化的处理函数 - 只处理接收中断
     */
    void bsp_tcan4x5x_data_process(void)
    {
        TCAN4x5x_MCAN_Interrupts mcan_ir = {0};
            // 清除中断标志
            mcan_ir.RF0N = 1;
            TCAN4x5x_MCAN_ClearInterrupts(&mcan_ir);
            
            TCAN4x5x_MCAN_RX_Header rx_header = {0};
            uint8_t frame_data[64] = {0};
            
            //读到的不是实际长度,待分析原因
            uint8_t bytes = TCAN4x5x_MCAN_ReadNextFIFO(RXFIFO0, &rx_header, frame_data);
            
            if (bytes > 0) {
                callback_func(rx_header.ID, frame_data, bytes);
            }
    }

  • Hi Song,

    I need a little more time to review these files and I follow up with you tomorrow.

    Regards,

    Jonathan

  • Hi Jonathan,
    It seems that I have figured out the reason. When sending multiple packets consecutively, the last packet was sent without meeting the 64-byte requirement, which caused the issue.
    Was it because the CAN FD did not support sending packets with a length less than 64 bytes (variable length)? This was my first time using CAN FD.

  • Hi Song,

    A Classic CAN message or packet has a maximum data payload of 8-bytes.  

    A CAN FD message or packet has a maximum data payload of 64-bytes.

    The DLC value will determine how many bytes are transmitted in a message. But take note that the DLC is only a 4-bit field, you can't support any unique byte value between 0 and 64 because you only have 16 possible values for the DLC field.  Therefore you need to set the DLC value according to the following table.

    DLC Indicator DLC (Binary) Classic CAN Bytes CAN FD Bytes
    0 0000 0 0
    1 0001 1 1
    2 0010 2 2
    3 0011 3 3
    4 0100 4 4
    5 0101 5 5
    6 0110 6 6
    7 0111 7 7
    8 1000 8 8
    9 1001 8 12
    10 1010 8 16
    11 1011 8 20
    12 1100 8 24
    13 1101 8 32
    14 1110 8 48
    15 1111 8 64

    If you need to send more than 64 data bytes, you will need to break the data into more than one CAN FD message or packet.  For example, if you need to send 67 data bytes you could send the first message with 64-bytes and a DLC=15, and then a second message with 3-bytes with a DLC=3.

    Regards,

    Jonathan