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: STM32 MCU can send data through TCAN4550, but cannot receive data

Part Number: TCAN4550

Tool/software:

HI TI team,

I am using the official TCAN demo, and the contents of the initialized Init_CAN() are as follows. At present, I am sending data to TCAN4550 through MCU SPI. TCAN4550 can forward it to other devices and the devices can also receive it. But the interrupt pin of TCAN4550 is not pulled down for CAN data sent by other devices. In the initialization phase, the interrupt pin will report multiple interrupts to interact with the MCU to complete initialization, so the interrupt pin is working normally.

/*
 * Configure the TCAN4550
 */
void
Init_CAN(void)
{
    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

    //设置波特率500KB classic CAN not CAN FD
    TCAN4x5x_Set_Baudrate(500,500);

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

    /* Configure the default CAN packet filtering settings */
    TCAN4x5x_MCAN_Global_Filter_Configuration gfc = {0};
    gfc.RRFE = 0;      //1                                         // Reject remote frames (TCAN4x5x doesn't support this)
    gfc.RRFS = 0;      //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 reject for extended ID messages (29 bit IDs)
    gfc.ANFS = TCAN4x5x_GFC_REJECT;                // Default behavior if incoming message doesn't match a filter is to reject for standard ID messages (11 bit IDs)
//  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 = 0;                       // Standard ID number of elements, you MUST have a filter written to MRAM for each element defined
    MRAMConfiguration.XIDNumElements = 8; //1 aizj                      // Extended ID number of elements, you MUST have a filter written to MRAM for each element defined
    MRAMConfiguration.Rx0NumElements = 32; //2 aizj     // RX0 Number of elements RemoteFrame <32;STD 64
    MRAMConfiguration.Rx0ElementSize = MRAM_64_Byte_Data;       // RX0 data payload size
    MRAMConfiguration.Rx1NumElements = 0;                       // RX1 number of elements
    MRAMConfiguration.Rx1ElementSize = MRAM_64_Byte_Data;       // RX1 data payload size
    MRAMConfiguration.RxBufNumElements = 64;                        // RX buffer number of elements
    MRAMConfiguration.RxBufElementSize = MRAM_64_Byte_Data;     // RX buffer data payload size
    MRAMConfiguration.TxEventFIFONumElements = 0;               // TX Event FIFO number of elements
    MRAMConfiguration.TxBufferNumElements = 8;//2;                  // TX buffer number of elements
    MRAMConfiguration.TxBufferElementSize = MRAM_64_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 = 0;                                            // RX FIFO 0 new message interrupt enable
    mcan_ie.RF0WE = 1;
    mcan_ie.RF0FE =1;
    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;//TCAN4x5x_SID_SFT_RANGE;//TCAN4x5x_SID_SFT_DUALID;//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 = 0x55;                                        // 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 */
/* {0x00258001,0x00258002, 0x00258003, 0x00258004, 0x00198001, 0x00198002, 0x00198003, 0x00198004}*/
    uint32_t ExFilter[] = {0x00258001,0x00258002, 0x00258003, 0x00258004, 0x00198001, 0x00198002, 0x00198003, 0x00198004};
    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.EFID2 = 0x1FFFFFFF;                                  // EFID2 (Classic mode mask)
    for(int i=0; i< sizeof(ExFilter)/sizeof(ExFilter[0]);i++){
        XID_ID.EFID1 = ExFilter[i];                                  // EFID1 (Classic mode filter)
        TCAN4x5x_MCAN_WriteXIDFilter(i, &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)
}
  • HI TI team,
    The complete initialization and sending, receiving code is as follows:
    ======================================================================================================>
    Init_CAN();
            /* 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[8] = {0x55, 0x66, 0x77, 0x88};     // Define the data payload
            header.DLC = MCAN_DLC_8B;                       // 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_8B;                       // 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.

            while (1)
            {
            #if 1
                if (TCAN_Int_Cnt > 0 )
                {
                    TCAN_Int_Cnt--;
                    TCAN4x5x_Device_Interrupts dev_ir = {0};            // Define a new Device IR object for device (non-CAN) interrupt checking
                    TCAN4x5x_MCAN_Interrupts mcan_ir = {0};             // Setup a new MCAN IR object for easy interrupt checking
                    TCAN4x5x_Device_ReadInterrupts(&dev_ir);            // Read the device interrupt register
                    TCAN4x5x_MCAN_ReadInterrupts(&mcan_ir);             // Read the interrupt register

                    if (dev_ir.SPIERR)                                  // If the SPIERR flag is set
                        TCAN4x5x_Device_ClearSPIERR();                  // Clear the SPIERR flag
                    if (mcan_ir.RF0W || mcan_ir.RF0F){//RF0N    if (mcan_ir.RF0N)       // If a new message in RX FIFO 0
                        TCAN4x5x_MCAN_RX_Header MsgHeader = {0};        // Initialize to 0 or you'll get garbage
                        uint8_t ret = CANIF_MAX_CANSTD_DATA;                           // Used since the ReadNextFIFO function will return how many bytes of data were read
                        uint8_t dataPayload[64] = {0};                  // Used to store the received data

                        while(ret >= CANIF_MAX_CANSTD_DATA){
                            TCAN4x5x_MCAN_ClearInterrupts(&mcan_ir);        // Clear any of the interrupt bits that are set.
                            ret = TCAN4x5x_MCAN_ReadNextFIFO( RXFIFO0, &MsgHeader, dataPayload);    // This will read the next element in the RX FIFO 0
                        }
                    }
                }
            #else
                if (TCAN_Int_Cnt > 0 )
                {
                    TCAN_Int_Cnt--;
                    TCAN4x5x_Device_Interrupts dev_ir = {0};            // Define a new Device IR object for device (non-CAN) interrupt checking
                    TCAN4x5x_MCAN_Interrupts mcan_ir = {0};             // Setup a new MCAN IR object for easy interrupt checking
                    TCAN4x5x_Device_ReadInterrupts(&dev_ir);            // Read the device interrupt register
                    TCAN4x5x_MCAN_ReadInterrupts(&mcan_ir);             // Read the interrupt register

                    if (dev_ir.SPIERR)                                  // If the SPIERR flag is set
                        TCAN4x5x_Device_ClearSPIERR();                  // Clear the SPIERR flag

                    if (mcan_ir.RF0N)                                   // If a new message in RX FIFO 0
                    {
                        TCAN4x5x_MCAN_RX_Header MsgHeader = {0};        // Initialize to 0 or you'll get garbage
                        uint8_t numBytes = 0;                           // Used since the ReadNextFIFO function will return how many bytes of data were read
                        uint8_t dataPayload[64] = {0};                  // Used to store the received data

                        TCAN4x5x_MCAN_ClearInterrupts(&mcan_ir);        // Clear any of the interrupt bits that are set.

                        numBytes = TCAN4x5x_MCAN_ReadNextFIFO( RXFIFO0, &MsgHeader, dataPayload);   // This will read the next element in the RX FIFO 0

                        // numBytes will have the number of bytes it transfered in it. Or you can decode the DLC value in MsgHeader.DLC
                        // The data is now in dataPayload[], and message specific information is in the MsgHeader struct.
                        if (MsgHeader.ID == 0x0AA)      // Example of how you can do an action based off a received address
                        {
                            // Do something
                        }
                    }
                }
            #endif
            }
  • The nINT pin is working normally because if I manually pull down the nINT, the STM32 MCU can receive interrupts

  • I captured the waveform of the initialization part of the code above, and I can see that the interrupt nINT can be triggered normally after resetting the chip, but the subsequent data reception cannot notify the MCU

  • During the initialization process, the two data frames sent by the above code can be received by other devices

  • So I want to know under what abnormal circumstances does TCAN4550 not pull down the nINT pin after receiving a CAN message?

  • My hardware environment here is flying from the demo board on the left to the STM32 board on the right. Could it be that the demo board requires some configuration to make nINT work properly?

  • Some messages can be received, but some cannot, so I suspect it may be a problem with the filter settings. I want to know how to receive all incoming messages without filtering any messages. How can I configure it in Init_CAN()

  • Hi Zhicheng,

    So I want to know under what abnormal circumstances does TCAN4550 not pull down the nINT pin after receiving a CAN message?

    The nINT pin is the Logical OR of all enabled interrupt bits reflected in registers 0x0820 and 0x0824.  Note that register 0x0824 is a read only copy of register 0x1050. 

    To get the nINT pin to reflect a set bit such as the reception of a new message, we simply need to enable the interrupt bits properly.

    From your MRAM configuration, it looks like you are using RX FIFO 0 to receive your messages.  However, it doesn't appear that the RX FIFO 0 New Message Interrupt Enable is being set and that line is commented out, and otherwise would be set to 0 (disabled).

      TCAN4x5x_MRAM_Config MRAMConfiguration = {0};
        MRAMConfiguration.SIDNumElements = 0;                       // Standard ID number of elements, you MUST have a filter written to MRAM for each element defined
        MRAMConfiguration.XIDNumElements = 8; //1 aizj                      // Extended ID number of elements, you MUST have a filter written to MRAM for each element defined
        MRAMConfiguration.Rx0NumElements = 32; //2 aizj     // RX0 Number of elements RemoteFrame <32;STD 64
        MRAMConfiguration.Rx0ElementSize = MRAM_64_Byte_Data;       // RX0 data payload size
        MRAMConfiguration.Rx1NumElements = 0;                       // RX1 number of elements
        MRAMConfiguration.Rx1ElementSize = MRAM_64_Byte_Data;       // RX1 data payload size
        MRAMConfiguration.RxBufNumElements = 64;                        // RX buffer number of elements
        MRAMConfiguration.RxBufElementSize = MRAM_64_Byte_Data;     // RX buffer data payload size
        MRAMConfiguration.TxEventFIFONumElements = 0;               // TX Event FIFO number of elements
        MRAMConfiguration.TxBufferNumElements = 8;//2;                  // TX buffer number of elements
        MRAMConfiguration.TxBufferElementSize = MRAM_64_Byte_Data;  // TX buffer data payload size
      /* 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 = 0;                                            // RX FIFO 0 new message interrupt enable
        mcan_ie.RF0WE = 1;
        mcan_ie.RF0FE =1;
        TCAN4x5x_MCAN_ConfigureInterruptEnable(&mcan_ie);           // Enable the appropriate registers

    In order to receive a new message Interrupt from RX FIFO 0, the following bits need to be set:

    RF0NE=1 (0x1054[0])

    RF0NL=0 (if using Interrupt line 0 which is default) or =1 (if using Interrupt line 1) (0x1058[0])

    EINT0=1 (if using Interrupt line 0) or EINT1=1 (if using Interrupt line 1) Enabling both is ok, but the line used for 0x1058 needs to be enabled. (0x105C[1:0])

    Configuring those bits should allow any new message received into the RX FIFO 0 to be reflected on the RF0N bit in the MCAN Interrupt Register (0x1050[0] and 0x0824[0]).

    Some messages can be received, but some cannot, so I suspect it may be a problem with the filter settings. I want to know how to receive all incoming messages without filtering any messages. How can I configure it in Init_CAN()

    The Global Filter Configuration register (0x1080) can be configured to accept all non-matching frames.  By default all non-matching frames will be stored into RX FIFO 0, so you will want to configure this register to accept instead of reject non-matching frames. 

    The configuration code shows the device is configured to reject instead of accept, so you will want to comment out the "reject' lines and uncomment the "accept" lines of code.

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

    Regards,

    Jonathan

  • Hi Zhicheng,

    As a follow up I would suggest the following documents for additional information on how to configure the TCAN4550.

    TCAN45xx Software User's Guide (Link)

    M_CAN User's Manual (Link)

    TCAN455x Clock Optimization and Design Guidelines Application Report (Link)

    Regards,

    Jonathan

  • Hi Jonathan,

    This is very useful. We can now receive CAN messages, but there is an issue where when TCAN4550 receives a frame of message, it will pull down the nINT pin to notify the MCU to retrieve the packet. The MCU also responds to the interrupt and retrieves the packet, but after the MCU retrieves the packet, nINT does not pull up, but keeps pulling down. This leads to the problem that TCAN4550 receives the second frame message and nINT remains low, making it impossible for MCU to trigger interrupts to retrieve packets

  • Hi Jonathan,

    The waveform below shows the timing sequence of TCAN4550 receiving a frame of message and forwarding it to MCU. It can be seen that after MCU reads the message, nINT remains at a low level


    The MCU has cleared the IR interrupt after reading the TCAN4550 data.But we still can't raise nINT. The code for the clear IR register is as follows:

  • Hi Jonathan,

    After encountering the issue where nINT cannot be pulled high, I found that when nINT cannot be pulled high, the SPIERR bit of the 0x820 register is set to 1. Therefore, after adding a clear SPIERR bit operation in the following locations of your demo code, nINT can now be pulled up normally. But there must be a problem with this. Why do I always set the SPIERR bit to 1 every time I receive a package.

  • Hi Jonathan,

    thanks a lot for your help. This is Yang (I contacted you in webex). I am also looking at this issue and find this similar post:https://e2e.ti.com/support/interface-group/interface/f/interface-forum/981125/tcan4550-nint-latches-active-for-unclear-reason-possibly-wup-related 

    So, I asked Mr. Zhang to check 0h0820 & 0h0824 if the device goes into sleep mode, please correct me or if you have more comments. thanks a lot.

    Best regards,

    Yang

  • Hi Zhicheng and Yang,

    SPI Errors are generally due to an incorrect number of SPI clock pulses detected while the nCS pin is low. The device uses a FIFO to handle the frequency domain transition between the SPI clock frequency and the OSC clock frequency and an incorrect number of clock pulses can result in errors with passing data into and out of this FIFO

    Because the device uses 32-bit words for the registers and MRAM, the device will count the number of clock pulses to make sure that it is an exact multiple of 32.  If there are to few or to many pulses, this could cause the data transmitted to be incorrect and the SPIERR flag is set.

    The device also verifies that the number of clock pulses matches the number of data bits expected in the transaction which can vary with the Length field.  For a single register read/write, the Length Field should be set to 0x01.  The TCAN4550 will then expect a total of 64 SPI Clock pulses while the nCS pin is low.

    Multiple consecutive register or MRAM locations can be accessed by setting a larger value for the Length field.  For example if the Length field is set to 0x02, a total of 96 SPI Clock pulses would be expected. 

    However, the Length field should never be set to 0x00.  I looked back at your previous logic analyzer plot and found that you have a SPI Write (0x61 op code) that has the Length Field set to 0x00. This would result in a SPI Error because there would not be an extra 32 data bits clocked into the FIFO that is not expected.

    Can you verify your code is correctly setting the Length field to 0x01 during SPI Writes and see if this resolves the SPI Errors you are seeing?

    Regards,

    Jonathan

  • Hi Jonathan,

    Did the specification sheet explain this issue? After I changed it to 0x01, SPIERR did indeed disappear.

  • Hi Zhicheng,

    Yes, the SPI Errors are related to an incorrect number of SPI Clock pulses, or data bits because each SPI Clock pulse represents a single Data bit.  Therefore, an incorrect number of clock pulses results in an incorrect number of data bits with either too few, or too many bits, and this can cause doubt about the validity of the data.  Therefore this is considered and Error and the attempt is to prevent corrupting the register configuration with bad values.

    Regards,

    Jonathan