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-Q1: When MCU SendsCAN data to TCAN4550-Q1, the Transimission Complete Interrupt is triggered about 760+ ms after the data is sent , it takes a very long delay

Part Number: TCAN4550-Q1
Other Parts Discussed in Thread: TCAN4550

Tool/software:

1. What do i want to do?

I want to configure the Transimission Complete Interrupt to nINT pin, and when data is sent out, I can get the TC Interrupt notification from nINT's IRQ_Handler. 

2. What is My Question?

1)  I use following code  (disable WDT, enable TC & RF0N  irq) to initize the tcan4550-q1, and configures IRQ linked to nINT pin

2)  Then using SPI to send data out.

3)  When SPI calling is over, it takes about 760ms +  for the nINT pin to become low  from high (which indicates the Transimmision Complete Interrupt happening)  

My Question :

the TC interrupt waits too long  to happen after sending data out, it should not be 760ms +,  what is the root cause ? please help me to check the configurations. thank you so much ...

following figure shows the big delay

a) following is init code 


/********************************************************************
function: board_canfd_ch1_cfg_init
discript:  
entrance: none.
return  : none
********************************************************************/
void board_tcan4550_cfg(uint8_t baud_nom, uint8_t baud_dat)
{
    TCAN4x5x_Device_ClearSPIERR();                              // Clear any SPI ERR flags that might be set as a result of our pin mux changing during MCU startup

    /* Step one attempt to clear all interrupts */
    // TCAN4x5x_Device_Interrupt_Enable dev_ie = {0};              // Initialize to 0 to all bits are set to 0.
    // TCAN4x5x_Device_ConfigureInterruptEnable(&dev_ie);          // Disable all non-MCAN related interrupts for simplicity

    TCAN4x5x_Device_Interrupts dev_ir = {0};                    // Setup a new MCAN IR object for easy interrupt checking
    TCAN4x5x_Device_ReadInterrupts(&dev_ir);                    // Request that the struct be updated with current DEVICE (not MCAN) interrupt values

    if (dev_ir.PWRON)                                           // If the Power On interrupt flag is set
    {
        TCAN4x5x_Device_ClearInterrupts(&dev_ir);               // Clear it because if it's not cleared within ~4 minutes, it goes to sleep
    }

    /* Configure the CAN bus speeds */
    TCAN4x5x_MCAN_Nominal_Timing_Simple TCANNomTiming = {0};
    TCANNomTiming.NominalBitRatePrescaler    = baud_list[baud_nom][0];
    TCANNomTiming.NominalTqBeforeSamplePoint = baud_list[baud_nom][1];
    TCANNomTiming.NominalTqAfterSamplePoint  = baud_list[baud_nom][2];

    TCAN4x5x_MCAN_Data_Timing_Simple TCANDataTiming = {0};
    TCANDataTiming.DataBitRatePrescaler      = baud_list[baud_dat][0];
    TCANDataTiming.DataTqBeforeSamplePoint   = baud_list[baud_dat][1];
    TCANDataTiming.DataTqAfterSamplePoint    = baud_list[baud_dat][2];

    /* Configure the MCAN core settings */
    TCAN4x5x_MCAN_CCCR_Config cccrConfig = {0};                 // Remember to initialize to 0, or you'll get random garbage!
    cccrConfig.FDOE = 1;                                        // CAN FD mode enable
    cccrConfig.BRSE = 1;                                        // CAN FD Bit rate switch enable
    cccrConfig.DAR  = 0;                                        // Disable automatic retransmission

    /* Configure the default CAN packet filtering settings */
    TCAN4x5x_MCAN_Global_Filter_Configuration gfc = {0};
    gfc.RRFE = 1;                                               // Reject remote frames (TCAN4x5x doesn't support this)
    gfc.RRFS = 1;                                               // Reject remote frames (TCAN4x5x doesn't support this)
    gfc.ANFE = TCAN4x5x_GFC_REJECT;                             // Default behavior if incoming message doesn't match a filter is to accept into RXFIO0 for extended ID messages (29 bit IDs)
    gfc.ANFS = TCAN4x5x_GFC_REJECT;                             // Default behavior if incoming message doesn't match a filter is to accept into RXFIO0 for standard ID messages (11 bit IDs)

    /* ************************************************************************
     * In the next configuration block, we will set the MCAN core up to have:
     *   - 1 SID filter element
     *   - 1 XID Filter element
     *   - 5 RX FIFO 0 elements
     *   - RX FIFO 0 supports data payloads up to 64 bytes
     *   - RX FIFO 1 and RX Buffer will not have any elements, but we still set their data payload sizes, even though it's not required
     *   - No TX Event FIFOs
     *   - 2 Transmit buffers supporting up to 64 bytes of data payload
     */
    TCAN4x5x_MRAM_Config MRAMConfiguration = {0};
    MRAMConfiguration.SIDNumElements = 8;                        // Standard ID number of elements, you MUST have a filter written to MRAM for each element defined
    MRAMConfiguration.XIDNumElements = 1;                        // Extended ID number of elements, you MUST have a filter written to MRAM for each element defined
    MRAMConfiguration.Rx0NumElements = 5;                        // RX0 Number of elements
    MRAMConfiguration.Rx0ElementSize = MRAM_32_Byte_Data;        // RX0 data payload size
    MRAMConfiguration.Rx1NumElements = 0;                        // RX1 number of elements
    MRAMConfiguration.Rx1ElementSize = MRAM_32_Byte_Data;        // RX1 data payload size
    MRAMConfiguration.RxBufNumElements = 0;                      // RX buffer number of elements
    MRAMConfiguration.RxBufElementSize = MRAM_32_Byte_Data;      // RX buffer data payload size
    MRAMConfiguration.TxEventFIFONumElements = 5;                // TX Event FIFO number of elements
    MRAMConfiguration.TxBufferNumElements = 5;                   // TX buffer number of elements
    MRAMConfiguration.TxBufferElementSize = MRAM_32_Byte_Data;   // TX buffer data payload size

    /* Configure the MCAN core with the settings above, the changes in this block are write protected registers,      *
     * so it makes the most sense to do them all at once, so we only unlock and lock once                             */

    TCAN4x5x_MCAN_EnableProtectedRegisters();                    // Start by making protected registers accessible
    TCAN4x5x_MCAN_ConfigureCCCRRegister(&cccrConfig);            // Enable FD mode and Bit rate switching
    TCAN4x5x_MCAN_ConfigureGlobalFilter(&gfc);                   // Configure the global filter configuration (Default CAN message behavior)
    TCAN4x5x_MCAN_ConfigureNominalTiming_Simple(&TCANNomTiming); // Setup nominal/arbitration bit timing
    TCAN4x5x_MCAN_ConfigureDataTiming_Simple(&TCANDataTiming);   // Setup CAN FD timing
    TCAN4x5x_MRAM_Clear();                                       // Clear all of MRAM (Writes 0's to all of it)
    TCAN4x5x_MRAM_Configure(&MRAMConfiguration);                 // Set up the applicable registers related to MRAM configuration
    TCAN4x5x_MCAN_DisableProtectedRegisters();                   // Disable protected write and take device out of INIT mode

    /* Set the interrupts we want to enable for MCAN */
    TCAN4x5x_MCAN_Interrupt_Enable mcan_ie = {0};                // Remember to initialize to 0, or you'll get random garbage!
    mcan_ie.RF0NE = 1;                                           // RX FIFO 0 new message interrupt enable

    TCAN4x5x_MCAN_ConfigureInterruptEnable(&mcan_ie);            // Enable the appropriate registers

    /* Setup filters, this filter will mark any message with ID 0x055 as a priority message */
    TCAN4x5x_MCAN_SID_Filter SID_ID = {0};
    SID_ID.SFT   = TCAN4x5x_SID_SFT_RANGE;                    // SFT: Standard filter type. Configured as a classic filter
    SID_ID.SFEC  = TCAN4x5x_SID_SFEC_PRIORITYSTORERX0;           // Standard filter element configuration, store it in RX fifo 0 as a priority message
    SID_ID.SFID1 = 0x00;                                         // SFID1 (Classic mode Filter)
    SID_ID.SFID2 = 0x1F;                                         // SFID2 (Classic mode Mask)
    TCAN4x5x_MCAN_WriteSIDFilter(0, &SID_ID);                    // Write to the MRAM


    /* Configure the TCAN4550 Non-CAN-related functions */
    TCAN4x5x_DEV_CONFIG devConfig = {0};                        // Remember to initialize to 0, or you'll get random garbage!
    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_DISABLED;  // Wake pin can be triggered by either edge (default)
    TCAN4x5x_Device_Configure(&devConfig);                      // Configure the device with the above configuration

    TCAN4x5x_Device_SetMode(TCAN4x5x_DEVICE_MODE_NORMAL);       // Set to normal mode, since configuration is done. This line turns on the transceiver

    TCAN4x5x_MCAN_ClearInterruptsAll();                         // Resets all MCAN interrupts (does NOT include any SPIERR interrupts)
	//TCAN4x5x_Device_ClearSPIERR();
}


// Use this API to init TCAN4550
void board_tcan4550_init(uint8_t baud_nom,uint8_t baud_dat)
{
    tcan4550_spi_init(4);   // init SPI module

    uint16_t ver = TCAN4x5x_Device_ReadDeviceVersion();
    uint32_t id0 = TCAN4x5x_Device_ReadDeviceID0();
    uint32_t id1 = TCAN4x5x_Device_ReadDeviceID1();
    APP_LOG_INFO("CAN ID: 0x%08x.%08x, ver: 0x%04x", id0, id1, ver);

    board_tcan4550_cfg(BAUD_1000K, BAUD_4000K);
	
    /* enable all tx buffer interrupt */
    AHB_WRITE_32(REG_MCAN_TXBTIE, 0xffffffff);

	AHB_WRITE_32(0x800, 0x8004CA0);

    /* Enable irq */
    AHB_WRITE_32(0x10E0, 0x1);
	AHB_WRITE_32(0x1050, 0x0);
    AHB_WRITE_32(0x1054, 0x201);
    AHB_WRITE_32(0x1058, 0x201);
    AHB_WRITE_32(0x105C, 0x201);
    AHB_WRITE_32(0x0820, 0xFFFFFFFF);

	TCAN4x5x_Device_ClearSPIERR();
}

b) using following code to transmit data out

bool gwcp_spi2can_port_transmit(uint32_t can_id, uint8_t *p_data, uint8_t length)
{
	int buf_idx = 0;
	int ret = 0;
	TCAN4x5x_MCAN_TX_Header header = {0};

    header.DLC = len2dlc(length);
    header.ID  = can_id;
    header.XTD = 0;
    header.BRS = 1;
    header.FDF = 1;
	header.RTR = 0;

    ret = TCAN4x5x_MCAN_WriteTXBuffer(buf_idx, &header, p_data);

	TCAN4x5x_MCAN_TransmitBufferContents(buf_idx);

	return true;
}

  • Hello Nix,

    It is not clear from your logic analyzer plot when the CAN message actually completed the transmission.  It shows the time between when the message buffer was enabled for transmission and when the transmission complete interrupt occurred, but it does not actually shown when the message transmitted.

    Sometimes a message can't be transmitted immediately due to the CAN Protocol and the rules of arbitration.  I don't know what your CAN bus traffic looks like, or whether there are any additional CAN messages that could cause an arbitration delay to the message transmission. 

    I would suggest you try to monitor the CAN bus and determine the time from the End of the CAN Message transmission and the time of the Interrupt?

    The TCAN4550-Q1 uses the MCAN IP developed by Bosch for the CAN FD Controller.  More information about this IP and the TX Handling can be found in section 3.5 of the M_CAN User's Manual (Link).

    Regards,

    Jonathan

  • Hi, Jonathan, 

    thank you for your support.

    following figure shows the time when Data sent from CAN, it's very closed to SPI timing . and about 760ms later, the TC Interrupt happens

      

    And in addition, the big delay for TC interrupt  happens in every data transimission . 

    is there any way to commit the transimission  and interrupt  immediately

  • Hi, Jonathan, 

    i found the root cause that i configured the ILE register to wrong value.  

    thank you

  • Hi Nix,

    I'm glad you found the root cause and thanks for letting me know.

    Regards,

    Jonathan