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: CAN transmits not showing any data

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

Hi all,

I am working on implementing SPI-to-CAN-FD on a mmWave radar SoC (AWRL1432) using the TCAN4550-Q1 for automotive applications.

So far, we've implemented the functions in TCAN4x5x_SPI and verified that it can read/write to the TCAN4550 registers over SPI. 

However, when I try transmitting output over CAN-FD using the reference code provided in the TCAN4550_DEMO, no data is being sent; only the ID, ctrl, and CRC can be seen, followed by no acknowledgement.

Please see the waveform for a transmit below:

Testing on PCAN-Pro also shows similar: while transmits are registered, only ID is shown and data is shown to be 0.

Please see the TCAN4550_Initialization in the code below:

void TCAN4550_Initialize(void)
{
TCAN4x5x_Device_ClearSPIERR(); // Clear any SPI ERR flags that might be set as a result of our pin mux changing during MCU startup

TCAN4x5x_Device_EnableTestMode(TCAN4x5x_DEVICE_TEST_MODE_CONTROLLER);
int32_t debugVal = AHB_READ_32(REG_DEV_MODES_AND_PINS);

// 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}; // 500k arbitration with a 40 MHz crystal ((40E6 / 2) / (32 + 8) = 500E3)
TCANNomTiming.NominalBitRatePrescaler = 2;
TCANNomTiming.NominalTqBeforeSamplePoint = 32;
TCANNomTiming.NominalTqAfterSamplePoint = 8;

TCAN4x5x_MCAN_Data_Timing_Simple TCANDataTiming = {0}; // 2 Mbps CAN FD with a 40 MHz crystal (40E6 / (15 + 5) = 2E6)
TCANDataTiming.DataBitRatePrescaler = 1;
TCANDataTiming.DataTqBeforeSamplePoint = 15;
TCANDataTiming.DataTqAfterSamplePoint = 5;


TCAN4x5x_MCAN_CCCR_Config cccrConfig = {0}; // Remember to initialize to 0, or you'll get random garbage!
if(frameType == CANFDLLD_MCANFrameType_FD)
{
cccrConfig.FDOE = 1; // Enable CAN FD mode
cccrConfig.BRSE = 1; // CAN FD Bit rate switch enable
}
else
{
cccrConfig.FDOE = 0; // Enable CAN mode
cccrConfig.BRSE = 0; // CAN FD Bit rate switch disable

}
//cccrConfig.DAR = 1; // Disable automatic transmission

/* 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_ACCEPT_INTO_RXFIFO0; // 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_ACCEPT_INTO_RXFIFO0; // 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 = 1; // Standard ID number of elements
MRAMConfiguration.XIDNumElements = 1; // Extended ID number of elements
MRAMConfiguration.Rx0NumElements = 5; // RX0 Number of elements
MRAMConfiguration.Rx0ElementSize = MRAM_64_Byte_Data; // RX0 data payload size (Use the defines)
MRAMConfiguration.Rx1NumElements = 0; // RX1 number of elements
MRAMConfiguration.Rx1ElementSize = MRAM_64_Byte_Data; // RX1 data payload size (use the defines)
MRAMConfiguration.RxBufNumElements = 0; // RX buffer number of elements
MRAMConfiguration.RxBufElementSize = MRAM_64_Byte_Data; // RX buffer data payload size (use the defines)
MRAMConfiguration.TxEventFIFONumElements = 0; // TX Event FIFO number of elements
MRAMConfiguration.TxBufferNumElements = 2; // TX buffer number of elements
MRAMConfiguration.TxBufferElementSize = MRAM_64_Byte_Data; // TX buffer data payload size (use the defines)


// Configure the MCAN core with the settings above, these changes in this block all are protected write registers, so we just knock them out at once
TCAN4x5x_MCAN_EnableProtectedRegisters(); // Start by making protected registers accessible
TCAN4x5x_MCAN_ConfigureCCCRRegister(&cccrConfig); // Enable FD mode and Bit rate switching
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_CLASSIC; // 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 = 0x055; // SFID1 (Classic mode Filter)
SID_ID.SFID2 = 0x7FF; // SFID2 (Classic mode Mask)
TCAN4x5x_MCAN_WriteSIDFilter(0, &SID_ID); // Write to the MRAM


// Store ID 0x12345678 as a priority message
TCAN4x5x_MCAN_XID_Filter XID_ID = {0};
XID_ID.EFT = TCAN4x5x_XID_EFT_CLASSIC; // EFT
XID_ID.EFEC = TCAN4x5x_XID_EFEC_PRIORITYSTORERX0; // EFEC
XID_ID.EFID1 = 0x12345678; // EFID1 (Classic mode filter)
XID_ID.EFID2 = 0x1FFFFFFF; // EFID2 (Classic mode mask)
TCAN4x5x_MCAN_WriteXIDFilter(0, &XID_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_BOTH_EDGES;// 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)
}

Please see how I am sending a CAN-FD message below: 

void TCAN4550_Transmit_Schedule(uint32_t msg_id,
uint8_t *txmsg,
uint32_t len)
{
volatile uint32_t index = 0;

TCAN4x5x_MCAN_TX_Header header = {0}; // Remember to initialize to 0, or you'll get random garbage!
header.ID = msg_id; // Set the ID

header.EFC = 0;
header.MM = 0;
header.RTR = 0;
header.XTD = 0; // We are not using an extended ID in this example
header.ESI = 0; // Error state indicator

if(frameType == CANFDLLD_MCANFrameType_FD)
{
header.FDF = 1; // CAN FD frame enabled
header.BRS = 1; // Bit rate switch enable

header.DLC = MCAN_DLC_64B; // DLC is the remaining len?
TCAN4x5x_MCAN_WriteTXBuffer(0, &header, txmsg);
TCAN4x5x_MCAN_TransmitBufferContents(0);
uint32_t debugValue = AHB_READ_32(REG_DEV_IR);
}
...
}

*I tried setting the DLC to 64B as when I was sending the length (in bytes) of the txmsg, I was getting the same error.

When I read REG_DEV_IR, I get the following: 0x00000E0

Could you advise on what might be the issue?

Thank you,

Jin

  • Hi Jin,

    In the code you shared, I did not see the section where you created the message data to send.  What is the actual message contents you are writing into the TX Buffer?

    The demo code uses the following code to create the message to be sent.  You will need to create a data buffer to hold the message data contents and then set the DLC to correct size based on the number of data bytes you want to send.

        /*********************************************
         * Everything at this point is for TCAN4550  *
         *********************************************/
        Init_CAN();                                        // Run the main MCAN configuration sequence. The bulk of the configuration is in this!

        /* Define the CAN message we want to send*/
        TCAN4x5x_MCAN_TX_Header header = {0};            // Remember to initialize to 0, or you'll get random garbage!
        uint8_t data[4] = {0x55, 0x66, 0x77, 0x88};        // Define the data payload
        header.DLC = MCAN_DLC_4B;                        // Set the DLC to be equal to or less than the data payload (it is ok to pass a 64 byte data array into the WriteTXFIFO function if your DLC is 8 bytes, only the first 8 bytes will be read)
        header.ID = 0x144;                                // Set the ID
        header.FDF = 1;                                    // CAN FD frame enabled
        header.BRS = 1;                                    // Bit rate switch enabled
        header.EFC = 0;
        header.MM  = 0;
        header.RTR = 0;
        header.XTD = 0;                                    // We are not using an extended ID in this example
        header.ESI = 0;                                    // Error state indicator


        TCAN4x5x_MCAN_WriteTXBuffer(0, &header, data);    // This function actually writes the header and data payload to the TCAN's MRAM in the specified TX queue number. It returns the bit necessary to write to TXBAR,
                                                        // but does not necessarily require you to use it. In this example, we won't, so that we can send the data queued up at a later point.

        /* Let's make a different CAN message */
        data[0] = 0x11;
        data[1] = 0x22;
        data[2] = 0x33;
        data[3] = 0x44;                                    // Define the data payload

        header.DLC = MCAN_DLC_4B;                        // Set the DLC to be equal to or less than the data payload (it is ok to pass a 64 byte data array into the WriteTXFIFO function if your DLC is 8 bytes, only the first 8 bytes will be read)
        header.ID = 0x123;                                // Set the ID
        header.FDF = 1;                                    // CAN FD frame enabled
        header.BRS = 1;                                    // Bit rate switch enabled
        header.EFC = 0;
        header.MM  = 0;
        header.RTR = 0;
        header.XTD = 0;                                    // We are not using an extended ID in this example
        header.ESI = 0;                                    // Error state indicator

        TCAN4x5x_MCAN_WriteTXBuffer(1, &header, data);    // This line writes the data and header to TX FIFO 1
        TCAN4x5x_MCAN_TransmitBufferContents(1);        // Request that TX Buffer 1 be transmitted


        TCAN4x5x_MCAN_TransmitBufferContents(0);        // Now we can send the TX FIFO element 0 data that we had queued up earlier but didn't send.

    Regards,

    Jonathan

  • Hi Jonathan,

    Thanks for supporting. I am currently just testing with preset data (in Classic CAN) like in the TCAN4550_demo and getting the same CAN error:

  • Hi Jin,

    What are the other bits in your header structure?  You only show the header.DLC and header.ID fields.  What are you setting the FDF, BRS, EFC, MM, RTR, XTD and ESI bits of the header to?

    I'm wondering if the "NAK" you are seeing is really an error flag getting thrown due to some incompatible header or protocol setting or from some bit timing configuration mismatch with the TCAN4550 and the other CAN devices on the bus.

    Regards,

    Jonathan

  • Hi Jonathan, 

    The rest of the header bits are set as shown above in TCAN4550_Transmit Schedule():

    header.EFC = 0;
    header.MM = 0;
    header.RTR = 0;
    header.XTD = 0; // We are not using an extended ID in this example
    header.ESI = 0; // Error state indicator

    header.FDF = 0; // CAN FD frame disabled
    header.BRS = 0; // Bit rate switch disabled

    I am testing with just the TCAN4550 connected to PCAN-Pro/logic analyzer, if that is of any help.

    I am also currently setting up external loopback mode to further test on my end. 

    Thank you,

    Jin

  • Hi Jin,

    It does look like your control field and DLC value is not getting set correctly for a 4-byte data field. 

    How are you setting up external loopback?  Which register bits are you configuring?

    Regards,

    Jonathan