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: Problem in reading register from SPI

Part Number: TCAN4550

Hi,

We are using TCAN4550 with ST MCU.

I am not able to read the register from SPI.

when I am trying to read the register it returning 0xffffffff.

What I am getting on hardware

VSUP Pin 24v
VIO Pin 3.3v
VCCOUT Pin 5V (for aprox 5 min after then 0 volt)
GND 0v
INH Pin left floating
WAKE Pin 24v
FLTR Pin floating
RST Pin pull down
OSC1 and OSC2 Pins 40 MHz clock (for 5 min after it becomes 0 volt)
nWKRQ Pin 0V for aprox 5 min then 3.3v
nINT Interrupt Pin 0V for aprox 5 min then 3.3v
GPO1 Pin 3.3v
GPO2 Pin floating
CANH and CANL Bus Pins 0 volt
SDO external pull up (3.3 v)
SCK external pull up (0 volt)
SDI external pull up (0 volt)

In code:

SPI data format

1 frame data length 8 bit

MSB first

I have just written a code to read register

I have written the code on the basis of code example given on TI's website

MX_SPI2_Init();   // initialize SPI

spi2_tx=0x41; // read opcode
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET); //chip select low

HAL_SPI_Transmit(&hspi2, &spi2_tx, 1, 5); //transmit  read opcode
while(HAL_SPI_GetState(&hspi2) == HAL_SPI_STATE_BUSY_TX);  //wait to transmit data

spi2_tx=0x10;
HAL_SPI_Transmit(&hspi2, &spi2_tx, 1, 5); //transmit  address MSB 8 bit
while(HAL_SPI_GetState(&hspi2) == HAL_SPI_STATE_BUSY_TX);   //wait to transmit data

spi2_tx=0x18;
HAL_SPI_Transmit(&hspi2, &spi2_tx, 1, 5); //transmit  address LSB 8 bit
while(HAL_SPI_GetState(&hspi2) == HAL_SPI_STATE_BUSY_TX);  //wait to transmit data

spi2_tx=0x1;
HAL_SPI_Transmit(&hspi2, &spi2_tx, 1, 5); // length of data to be that is 1 word
while(HAL_SPI_GetState(&hspi2) == HAL_SPI_STATE_BUSY_TX);  //wait to transmit data


spi2_tx=0x00;
while(HAL_SPI_GetState(&hspi2) == HAL_SPI_STATE_BUSY);  //wait until SPI line becomes idle
HAL_SPI_Transmit(&hspi2, &spi2_tx, 1, 5); // transmit 0x00
while(HAL_SPI_GetState(&hspi2) == HAL_SPI_STATE_BUSY);  //wait until SPI line becomes idle
HAL_SPI_Receive(&hspi2, &spi2_rx[0], 1, 5); // read 1 byte


HAL_SPI_Transmit(&hspi2, &spi2_tx, 1, 5); // transmit 0x00
while(HAL_SPI_GetState(&hspi2) == HAL_SPI_STATE_BUSY); //wait until SPI line becomes idle
HAL_SPI_Receive(&hspi2, &spi2_rx[1], 1, 5); // read 1 byte


HAL_SPI_Transmit(&hspi2, &spi2_tx, 1, 5);  // transmit 0x00
while(HAL_SPI_GetState(&hspi2) == HAL_SPI_STATE_BUSY);  //wait until SPI line becomes idle
HAL_SPI_Receive(&hspi2, &spi2_rx[2], 1, 5); // read 1 byte

HAL_SPI_Transmit(&hspi2, &spi2_tx, 1, 5);  // transmit 0x00
while(HAL_SPI_GetState(&hspi2) == HAL_SPI_STATE_BUSY);   //wait until SPI line becomes idle
HAL_SPI_Receive(&hspi2, &spi2_rx[3], 1, 5); // read 1 byte

HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET); //chip select high

 


Please help me where i am doing mistake.

Regards

Imran Aftab

  • Imran,

    I'll look into this and have a response for you tomorrow, but one question: when you send SPI transactions, is it always in 8-bit packets? The TCAN4550-Q1 SPI design requires 32-bit SPI transactions to be read correctly.

    Regards,

  • Hi Eric,

    Yes, SPI format configuration I have done for 8 bit. But I am sending the data in multiple of 32 bit (8 bits of packet four times).

    And I have done this as per given in the example on TI, here is that function

    void
    AHB_READ_BURST_START(uint16_t address, uint8_t words)
    {
    // Set the CS low to start the transaction
    GPIO_setOutputLowOnPin(SPI_CS_GPIO_PORT, SPI_CS_GPIO_PIN);
    EUSCI_B_SPI_transmitData(SPI_HW_ADDR, AHB_READ_OPCODE);

    // Send the 16-bit address
    WAIT_FOR_TRANSMIT;
    EUSCI_B_SPI_transmitData(SPI_HW_ADDR, HWREG8(&address + 1));
    WAIT_FOR_TRANSMIT;
    EUSCI_B_SPI_transmitData(SPI_HW_ADDR, HWREG8(&address));

    // Send the number of words to read
    WAIT_FOR_TRANSMIT;
    EUSCI_B_SPI_transmitData(SPI_HW_ADDR, words);

    }

    uint32_t
    AHB_READ_BURST_READ(void)
    {
    uint8_t readData;
    uint8_t readData1;
    uint8_t readData2;
    uint8_t readData3;
    uint32_t returnData;

    WAIT_FOR_IDLE;
    EUSCI_B_SPI_transmitData(SPI_HW_ADDR, 0x00); // pause after this
    WAIT_FOR_IDLE;

    readData = HWREG8(SPI_HW_ADDR + OFS_UCBxRXBUF);
    EUSCI_B_SPI_transmitData(SPI_HW_ADDR, 0x00);


    WAIT_FOR_IDLE;
    readData1 = HWREG8(SPI_HW_ADDR + OFS_UCBxRXBUF);
    EUSCI_B_SPI_transmitData(SPI_HW_ADDR, 0x00);

    WAIT_FOR_IDLE;
    readData2 = HWREG8(SPI_HW_ADDR + OFS_UCBxRXBUF);
    EUSCI_B_SPI_transmitData(SPI_HW_ADDR, 0x00);

    WAIT_FOR_IDLE;
    readData3 = HWREG8(SPI_HW_ADDR + OFS_UCBxRXBUF);


    returnData = (((uint32_t)readData) << 24) | (((uint32_t)readData1 << 16)) | (((uint32_t)readData2) << 8) | readData3;
    return returnData;
    }

    void
    AHB_READ_BURST_END(void)
    {
    WAIT_FOR_IDLE;
    GPIO_setOutputHighOnPin(SPI_CS_GPIO_PORT, SPI_CS_GPIO_PIN);
    }

    Here in these functions also they are sending 32 bit data in multiples of 8 bits.

    And I have written the code in this way only. 

    Please have a look and let me know if I have done any mistake.

    Regards

    Imran Aftab

  • Hi Eric,

    Please review my schematic also.

    TOP Drv Card MCU V-7-TI-CAN-CNTRL.pdf

  • Imran,

    Thanks for the information, this looks right, I just wanted to verify the burst writing. And from the voltage present on all of the pins on your device, it looks like the device is in standby mode, so the SPI should be active and able to be read. That 5 minute duration where the voltages on some of the pins drop to 0 is the SWE timer running out and putting the device into sleep mode.

    The schematic you shared looks correct, can you share the part number for the crystal used on the OSC1 and OSC2 pins? And what capacitance value do you have on the filter pin?

    Are you ever able to read any SPI data, or is it always 0xFFFFFFFF? And is there any way you can share waveforms of your SPI signals?

    Regards,

  • Hi Eric,

    crystal Part number:- ECS-400-18-33-JGN-TR

    Filter capacitor value:- 0.33uF

    Are you ever able to read any SPI data, or is it always 0xFFFFFFFF?

    Its always 0xFFFFFFFF.

    Waveform:-

    On MISO , MOSI waveform is straight line.

    and on SCK when I am sending data then it becomes low-high-low only once. 

    Regards,

    Imran Aftab

  • Imran,

    If your SPI clock is only going low-high-low then that means the SPI transaction isn't completing and something is stopping it. Is there something happening that would be causing an interrupt or reset on the MCU? Where is the nINT pin connected on the MCU?

    Regards,

  • Hi Eric,

    Is there something happening that would be causing an interrupt or reset on the MCU?

    No, I have written the code for only this one. So, no other task is going on.

     Where is the nINT pin connected on the MCU?

    It is connected with MCU.

    Regards,

    Imran Aftab

  • Imran,

    I think what is happening is the nINT is stuck low and is causing your MCU to stop at the beginning of the SPI transaction. Is it possible to disconnect the nINT pin from the MCU and try SPI transactions then?

    Regards,

  • Hi Eric

    It started working thanks for help.

    But now I am facing some other issue.

    I am able to read device ID(0x0000 and 0x0004) correctly

    And even I am able to write and read Test register (0x0808) perfectly.

    But when I am reading Interrupts register (0x0820) then I am getting 0x00500089

    and when I am reading status register (0x000C) then I am getting 0x0030000A.

    That means there is error with SPI. Why it is so, even I am able to read and write the registers.

    And one more thing I have noticed I am able to read and write with PPHA=0 and CPHA=1 both configuration of SPI.

    Regards

    Imran Aftab

  • Hi Eric,

    Although I was getting error for SPI in interrupt register. 

    And as I was able to read and write the data so I tried to transmit the data on CAN. But on receiver end I am not getting Interrupt on nINT pin.

    here is the code:-

    for receiver:-

    Configuration:-

    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
    HAL_Delay(200);
    /* 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

    //printmsg("PWRON %x",dev_ir.PWRON);

    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;

    /* 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

    /* 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, 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_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 = 0; // 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 = 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 = 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 = 0x123; // SFID1 (Classic mode Filter)
    SID_ID.SFID2 = 0x7FF; // SFID2 (Classic mode Mask)
    if(TCAN4x5x_MCAN_WriteSIDFilter(0, &SID_ID)) // Write to the MRAM
    {
    printmsg("SPID True\n");
    }

    else{
    printmsg("SPID False\n");
    }
    /* 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)


    }

    Configuration for transmitter:-

    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

    //printmsg("PWRON %x",dev_ir.PWRON);

    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;

    /* 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

    /* 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, 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_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 = 0; // 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 = 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 = 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)

    }

    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 = 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(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.

    And am getting this data on CANL pin on transmission of data when I checked with Oscilloscope:-

    I am accepting that on receiver end I will get interrupt from nINT then I will read the data. Am I correct or There is some other procedure of receiving the data?  

  • Hi Imram,

    I'm a colleague of Eric's and will jump into this thread while he is currently out of the office. 

    First regarding your SPI communication, I'm surprised you see successful communication with both SPI Modes (CPHA = 1/0).  The TCAN4550 requires MODE 0 (CPOL = 0, CPHA = 0), so you should use this mode.  And if you are seeing a SPIERR flag, then you generally have an issue where the device is seeing either too many or too few clock cycles as compared to the data.  Sometimes this is caused by a setup and hold issue if the PCB traces and any wires are of different lengths.  Another reason is poor signal integrity that can cause reflections large enough to be interpreted as an additional clock edge.  Is it possible to use your scope to verify the SPI signals have proper timing and quality?

    Regarding the receiver, your idea is generally correct.  However, any interrupt flag that is set and enabled will also pull the nINT pin low and if some other flag has already set the nINT pin low, you won't necessarily know if a new message has arrived until the you read the registers to determine what flags were set and whether one of them was the result of a new message.  It is possible to use the GPIO1 as an additional interrupt pin if it is configured as an output and set for the MCAN_INT mode.  The GPO2 is also another dedicated output pin that can be configured for MCAN Interrupts.  This will allow for a dedicated interrupt line to be used for received messages and MCAN specific interrupts and avoid them getting masked by other device related flags that may get set. 

    I see that the last bit of the messages are at a lower voltage than the rest of the bits.  This is consistent with an acknowledge (ACK) from the Receiver node.  Another observation I have is that it does not appear that the transmitter is re-transmitting the message in a continuous loop.  Unless you have disabled this feature, the transmitter will generally try to resend a failed message that was not acknowledged by another node.  Therefore the larger ACK bit and the lack of continuous transmission leads me to believe that the receiving node is acknowledging the message properly.  I think you have configured the device to place the message into the RX FIFO 0, unless you made a specific filter for the message you are sending.

    Have you tried to read the RX FIFO 0 or the appropriate RX Buffer if you expect it to be filtered and determine if the message has indeed arrived?  You can also read register 0x0824 to see if any of the MCAN Interrupts including the related RX Message bits have been set.

    Regards,

    Jonathan

  • Hi Jonathan,

    Here is my waveform of SPI:-

    SDI

    Chip Select

    SDO

    SCK

    Is it ok?

    Regards

    Imran Aftab

     

  • Hi Imran,

    Is this for a single register read or write?  Or for multiple registers? 

    I see the chip select line transitioning from low to high 6 additional times between the initial and final transition.  If this is for a single register read/write then this is a problem.  The Chip Select line must stay low for the entire SPI transaction that contains a multiple of 32 bits (clock cycles).  If the chip select line transitions with either too few or too many clock cycles then it will generate a SPI Error.  However, a single register read or write will require 64 bits because the Write/Read OpCode (0x41 or 0x61), Address, and Number of Words will require 32 bits, followed by the 32 bits of actual data.

    From my understanding of your SPI function earlier in this thread, you are sending 8 bits (one byte) of data at a time.  This is fine and very common.  However, I would expect this to be 8 bytes (or 64 bits) for a single register transaction.  If your waveforms are for a single register write/read, then I would expect the Chip Select to transition low 8 times, one for each byte, assuming the chip select was toggling after each byte.  Your waveform only shows it toggling low 7 times, so this would indicate a byte of data is missing somewhere within the total transaction and this would also be a problem.

    But if this is for multiple register Write/Read transactions, then there is not enough resolution to determine if there are any issues with the signal integrity.  Preferably I would like to see the chip select, clock and data lines in the same plot and only for a single register write or read transaction.  This would allow us to count the number of clock cycles between the chip select transitions to make sure it is a multiple of 32 and also determine where the clock edges are placed relative to the data bits.  This can tell us if there may be any incorrectly sampled bits, and any noise that might generate an error.

    Also, what is your SPI data rate?

    If these plots are for a single register, what is the address and data value you are using?  If it is for multiple registers, can you capture just a single register and let me know what the bytes are (Read/Write, address, number of words, and data bytes) so that I can check them more closely for errors?

    Thanks and Regards,

    Jonathan

  • Hi Jonathan,

    Thanks for your reply.

    Here is the waveform of single register read.

    Register address 0x0000 (ID register)  

    And I am getting correct value i.e. 0x4e414354 as per datasheet.

    SDO

    SDI

    Chip Select

    SCK

    Regards

    Imran Aftab

  • Hi Imran,

    The signals look a little noisy that most likely is coming from some cross talk with other SPI signals and or some reflections. But that could also be partly from the scope probes.  There is room for improvement, but if you are writing and reading the correct values, then it is most likely ok. 

    Are you still getting the SPI Error Flag?  Previously you mentioned the status registers 0x0820 = 0x00500089, and 0x000C = 0x0030000A. 

    Bit 21 of 0x000C indicates the SPI transfer did not end on a byte boundary, meaning that there was an extra clock cycle counted by the device which could either be a clock pulse from the MCU, or a reflection that crossed the voltage threshold that caused the device to count it as a clock cycle.

    There is still not enough resolution in your plots for me to determine where the issue is.  I don't think this will be possible through the forum.

    So if you are still getting the SPI error flag even after clearing it, then you will need to use multiple scope probes to look at both the SCLK and MOSI signals at the same time and zoom in to allow you to verify there is only a single clock cycle per bit while the chip select line is low.  Also, you need to check that there are not any reflections or cross talk that could be crossing the voltage high/low thresholds that could be causing extra clock cycles to be counted.

    You might want to add some series resistors such as 33ohms to the signals that could help reduce the amplitude of the crosstalk and reflections in the signal.  Also make sure the scope probes are properly grounded to reduce any inductance from the probes that could be appearing in the scope plots that would create measurement error.

    Regards,

    Jonathan

  • Hi Jonathan,

    Thanks for your suggestion to check CAN message reception with GPIO2 pin. I tried its working.

    I was connecting two boards with aprox 50 cm long wire, then it was working.

    But because of my application need. I connected with long wire of aprox 5 meter in my case I may need to even longer wire for real scenario. But with 5 meter long wire its not working. When I am sending data other device is not able to receive.

    When I checked with the oscilloscope as I use to connect the long wire, CANL and CANH start giving noise small amount. But this does not happen with smaller wire.

    I am sending data at 500 kbps.

    Here is my configuration of TCAN:-

    void Init_CAN(uint16_t unique_ID, uint16_t global_ID)
    {
    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

    //printmsg("PWRON %x",dev_ir.PWRON);

    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}; // 500kbps CAN FD with a 40 MHz crystal (40E6 / (15 + 5) = 2E6)
    TCANDataTiming.DataBitRatePrescaler = 2;
    TCANDataTiming.DataTqBeforeSamplePoint = 32;
    TCANDataTiming.DataTqAfterSamplePoint = 8;

    /* 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

    /* 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 = 1; // 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_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 = 0; // 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 = 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 = 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_DUALID; // 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 = unique_ID; // SFID1 (Classic mode Filter)
    SID_ID.SFID2 = global_ID; // 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_MCAN_INT0; // 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)

    }

    And Should I decrease the speed? Then please let me know how to calculate the configuration values. I am having some doubt with the calculation of configuration values.

  • Hi Imran,

    I'm glad we are making some progress and that you can now see some improvement on the reception of the messages.  With your description of the problem, I think that the problem most likely is more related to the hardware setup and not so much the configuration settings.  The TCAN4550 was designed to support a data rate of greater than 5 Mbps across a 40 meter long wiring harness.  Since you are only operating at 500 kbps across a much shorter cable with noticeable noise when looking at the signals with your oscilloscope, I think that we need to improve the signal quality instead of trying to lower the data rate.

    Are you using the TCAN4550 EVM for your evaluation or are you using a custom board?  If it is a custom board, I could review the schematics if you would like, and we can share those through direct email if you would like.

    What type of wire are you using?  Is it twisted pair.  CAN and CAN FD is designed to operate over twisted pair wire with 120 ohm impedance. 

    Do you have 120 ohm termination resistors at each end of the cable?  These are required by the CAN Standard and the device driver expects to see the approximately 60 ohm load.  If the termination value is missing or of a different value, then the voltage levels could be incorrect for proper data reception.  Also, the termination resistance is required to reduce or eliminate reflections on the bus that can create the noise you are describing.  In an ideal system, the twisted pair wire has a controlled impedance of 120 ohms, and the 120 ohm termination resistors prevent any reflections when the signal reaches the end of the cable.  If the cable impedance and termination resistors are not matched, then some amount of signal energy is reflected back down the cable which mixes with the rest of the signal and results in noise and bit errors.

    I suspect that some form of impedance mismatch in your system is resulting in reflected noise and causing your problems.  This is consistent with your description that the problem gets worse when the cable length is greater.  But I can't be certain without more information.  If you can share the scope plots, schematics, etc. I can help make some more specific suggestions on how to improve the signal.

    If you do not want to share that info on this forum, let me know and I can contract you through email using the email address registered to your profile.

    Regards,

    Jonathan

  • Jonathan,

    Thanks for your response.

    Right now I am not using twisted pair cable.

    Please give me your email ID. I will share schematic.

    Regards,

    Imran

  • Hi Imran,

    I will send you an email that you can reply to with any schematics and other information that you would like me to review.

    CAN and CAN FD signals are differential and require a balanced transmission of the two signals for error free communication.  Twisted pair wire helps ensure the two signals maintain this balance and arrive at the same time.  Also, any length mismatch between two single ended wires will cause a longer propagation delay in one of the signals and the receiver will not be able to recover the the data properly.  Switching to a twisted pair wire will greatly improve your results.

    Regards,

    Jonathan

  • And one more issue I observed.

    That, if i send two frame of data without any gap. then receptor controller receives only one data. 

    For example:-

    uint8_t temp[] = {0x22, 0x02, 0x03};
    CAN_Transmit(0xff, temp, 3);

    temp[0] = 0x22;

    CAN_Transmit(0xff, temp, 3);

    So, the receiver receives the 1st CAN transmitted data.

    And suppose I give some delay like 10 ms then both data receiver use to receive.

    My CAN transmitter function

    void CAN_Transmit(uint16_t ID, uint8_t *data, uint8_t size)
    {

    TCAN4x5x_MCAN_TX_Header header = {0}; // Remember to initialize to 0, or you'll get random garbage!
    header.DLC = size; // 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 = ID; // 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); 
    TCAN4x5x_MCAN_TransmitBufferContents(0); 

    }

    Regards,

    Imran

  • Hi Imran,

    Is your receiver configured to receive the messages into a RX buffer, or a RX FIFO?  The issue may or may not be related to the same signal integrity issues we have already discussed, but if they are not related, then I will need to know whether you using a buffer or FIFO so that I can make some suggestions.

    Regards,

    Jonathan

  • Hi Jonathan,

    I have used RX FIFO.

    Here is my configuration

    TCAN4x5x_MRAM_Config MRAMConfiguration = {0};
    MRAMConfiguration.SIDNumElements = 1; // 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_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 = 0; // 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 = 2; // TX buffer number of elements
    MRAMConfiguration.TxBufferElementSize = MRAM_64_Byte_Data; // TX buffer data payload size

    Regards,

    Imran

  • Hi Imran,

    Are you reading the status registers and or getting any errors when you are receiving fewer messages than you are sending?

    Could you read the values of the following registers for both test cases (with and without your delay between messages)?  If an error is happening, then it might be getting logged and we can compare the status registers between the two cases to help us determine what the fault might be.

    0x000C (Status Register)

    0x0820 (Interrupts Register)

    0x0824 (MCAN Interrupts Register)

    0x1040 (Error Count Register)

    0x1044 (Protocol Status Register)

    0x1050 (Interrupt Register)

    If you are using RX FIFO 0:

    0x10A4 (RX FIFO 0 Status Register)

    0x10A8 (RX FIFO 0 Acknowledge Register)

    If you are using RX FIFO 1:

    0x10B4 (RX FIFO 1 Status Register)

    0x10B8 (RX FIFO 0 Acknowledge Register)

    Regards,

    Jonathan

  • Hi Jonathan,

    After discussed on mail communication was working well.

    If I use 7 nodes then it works fine but as I increases the number of nodes to 8 or 9 then communication stops working properly,

    Sometime node 1 and node 2 able to communicate but the node which is far that's not able to communicate. 

    We have made some changes in the termination resister. And we have used in all the nodes.

    So, I am sending you schematic on mail. Please check let us know how to resolve the issue.

    Regards

    Imran Aftab

     

  • Hi Imran,

    I'm glad that our prior communication has been successful.  This issue should be fairly straight forward to resolve. 

    The issue is that you cannot use termination on every node.  The termination resistors are only intended to be placed at the first and last node which are at the end if the wiring harness connecting all of the nodes.  This is specified in the CAN standard and CAN transceivers are designed to support this type of load which is effectively 60 ohms (or two 120 ohm resistances in parallel).  If you use the termination resistance at every node (such as 9 in your current case) you will have an effective load of nine 120 ohm resistors in parallel which will be too great of a load for the transceivers to drive signals at the required voltage levels which is resulting in failed communication between the nodes.

    What you need to do, is to remove the termination resistors from all nodes except the first and last node.  This should resolve the issue and all nodes should then be able to communicate properly.

    Regards,

    Jonathan

  • Hi Jonathan,

    Thanks for response after correcting termination resistor system is working fine with 10 nodes. And we will test it with more nodes later.

    But now I observed one more issue.

    When ever I start the system and nodes start sending the data in the very beginning, at that time some node does not transmit the data and when it sends again the data then it sends the previous one. And some time it sends data after some delay.

    How can I resolve this issue please help me.

  • Hi Imran,

    I'm glad to hear you have the system working fine with 10 nodes!

    I have a few thoughts since you say this happens when you "start the system and nodes start sending the data in the very beginning".  I'm not sure if there are any system level issues going on, but there are a few things that the TCAN4550 might be doing at this time.  It sounds like this is a system level startup issue with some nodes becoming active before others are ready based on your description.  I'm assuming that this is just an issue around the startup and not a persistent issue after the system has started.

    The M_CAN controller inside the TCAN4550 will try to transmit a message (TX Buffer Element) when requested by a write to the corresponding TX Buffer Add Request bit in the TX Buffer Add Request (TXBAR) register.  The controller will then set and corresponding bit for the TX Buffer in the TX Buffer Request Pending (TXBRP) register and try to send the message. Once this message is transmitted it monitors the bus for an Acknowledge from other nodes on the bus.  If another node on the bus acknowledges the message and no errors are detected, then the controller will clear the bit in the TXBRP register and sets the corresponding bit for the TX Buffer in the TX Buffer Transmission Occurred (TXBTO) register.  And if you have setup the TX Event FIFO, the successful transmission will be logged in a TX Event Element which will be reflected in the TX Event FIFO Status (TXEFS) register.

    But if the message transmission was not successful either due to errors or failure by another node on the bus to acknowledge the reception of the message, the controller will try to resend the message until it is successful.  So, when you say this issue happens at the very beginning when you start up the system, I am thinking that some nodes will start to transmit messages before other nodes are ready which could result in the unsuccessful transmission and cause the node to resend the messages again until other nodes on the bus are ready to acknowledge the message as a success.

    So, I would suggest you could try to monitor the various TX registers such as the TXBRP, TXBTO and TXEFS register to see if messages are failing to send for an extended period of time. 

    And you could also try to disable the automatic retransmission of messages through the DAR (bit 6) in the CCCR register (0x1018).  If you set the DAR bit to '1', the automatic retransmission will be disabled.  If you disable this feature, you should not see any nodes re-sending data from a failed or non-acknowledged message.  This could prevent the retransmission of data you are seeing, but it also means that the MCU will have to manually send the messages that failed to send by monitoring the registers I have mentioned to ensure all of it's messages get transmitted successfully.  But this may allow you some additional control over when certain messages are sent and how to handle failed transmissions.

    Another idea is to add some additional delay to the node's boot sequence before messages are transmitted to allow other nodes more time to boot themselves and hopefully this places them in a state where they are able to receive and acknowledge messages and prevent any message from not being acknowledged the first time it is sent.

    Regards,

    Jonathan

  • Hi Jonathan,

    Thanks for your reply.

    I also thought the same reason behind this issue. And I tried the last solution which you have provided, delay before transmission of first data but it did not work.

    I will check other solutions and I will get back to you.

    Regards,

    Imran

  • Hi Jonathan, 

    As you suggested me to check all the status register.

    After initialization I am getting this value:-

    0x000C value = 30000a
    0x0820 value = 4a8
    0x0824 value = 10000
    0x1040 value = 0
    0x1044 value = 70f
    0x1050 value = 10000
    0x10A4 value = 0
    0x10A8 value = 10000

    And after transmission of data, I am getting these values:-

    0x000C value = 8
    0x0820 value = 4a0
    0x0824 value = 10000
    0x1040 value = 0
    0x1044 value = 70f
    0x1050 value = 10000
    0x10A4 value = 10100
    0x10A8 value = 10000

    But data transmission and reception is working perfectly.

    Sometimes in continuous testing it gets hanged when I send data just after startup.

    So, what should I do?

    Regards

    Imran Aftab

     

  • Hi Imran,

    Thanks for the register values.  There are a couple of bits that caught my attention that may be an important clue to solving this issue.  Can you check one more register for me and tell me the value of register 0x0800 (the Modes of Operation register)? 

    The following bits caught my attention:

    After initialization I am getting this value:-

    0x000C value = 30000a

    [1] SPI Error Interrupt --> Unmasked SPI error set

    [20] Invalid_Command --> Invalid SPI command received

    [21] SPI_END_ERROR --> SPI transfer did not end on a byte boundary


    0x0820 value = 4a8

    [3] SPIERR --> SPI Error

    [5] CANERR --> CAN Error, the Logical OR of CANSLNT and CANDOM faults.

    [7] GLOBALERR --> Global Error (Any Fault) which is set because other fault bits have been set in this register

    [10] CANSLNT --> CAN Silent (see section 8.4.5 Failsafe Feature for a description)


    There are two things of interest here.  The first is the SPI Errors.  This tells us that there was an error with at least one of the SPI transactions in your initialization sequence and that the device did not detect the proper number of bits (or clock cycles) to have an the data end on a byte boundary.  It either detected extra clock cycles that could come from noise or some other source, or it could have missed a clock cycles.  This is important because when this occurs the TCAN4550 will ignore that transaction and if the MCU does not repeat that Failed SPI transaction, then whatever bits that were being written will remain unchanged.  This could lead to an unknown configuration state and result in communication errors.  If a SPI Error occurred when trying to receive or send a CAN message, then this could be the cause of your observations.

    Note that at the beginning of every SPI transaction the TCAN4550 will output the register bits 0x0820[7:0] which include the SPIERR bit [3].  Therefore it is possible for the MCU to monitor this bit on the next SPI transaction and determine if the previous SPI transaction was successful or failed and then determine if it needs to be re-attempted.  This is a bit more involved, but this is the intent behind providing this information on every SPI transaction and it could help mitigate errors like this.

    If you get repeated SPI errors, there may be some other configuration adjustments needed on the SPI bus to make the communication more reliable.

    The second interesting point is the CAN Silent (CANSLNT) Error.  This is used in the TCAN4550's Failsafe Feature as described in section 8.4.5 of the datasheet.  There are three failure mechanisms that cause the device to use the failsafe feature.  The third mechanism is when the device is in standby or normal mode and the CANSLNT flag persists for tINACTIVE the device enters sleep mode.  Examples of events that could create this CLKIN or Crystal stops working, processor is no longer working and not able to exercise the SPI bus, a go-to-sleep command comes in and the processor is not ale to receive it or is not able to respond.  There is a figure called Normal and Standby Failsafe Feature that shows this in a block diagram.

    Are you enabling the Failsafe feature?  I've asked you for the value of register 0x0800 which includes the FAILSAFE_EN bit [13].  When the device "hangs" up during your testing, does the value of this register change such as in the value of the MODE_SEL bits which may show if the device is changing modes?  If you are unable to read this register while it is hung up, then the device has most likely entered Sleep Mode.

    If you have enabled the Failsafe feature, I am wondering if there could be a SPI Error that is causing the CANSLNT fault which in turn is putting the device to sleep.  Or perhaps one of the other causes for this are occurring.

    By default this feature is disabled, so if you have enabled it, you could try to leave it disabled and see if you still have the same issues with the device communication failing or getting hung up.

    Regards,

    Jonathan

  • Hi Jonathan, 

    Thanks for your support.

    As you asked the value of 0x0800.

    So, it is here, Address 0x0800, value = c84004a0.

    As I am in quarantine, so I will soon provide you the value for status register when it is hanged as I resume the office again. 

    Regards

    Imran Aftab

  • Imran,

    Are there any updates to share?

    Regards,

  • Hi Eric,

    Thanks for asking,

    I will get back to you in few days.

     

    Regards,
    Imran