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: Interrupt to MCU

Part Number: TCAN4550


Hi,

I downloaded the datasheet of the TCAN4550 and also the sample- user code that TI provided.

However, I have doubts regarding the interrupt management.

As I understood correctly, there's the nINT pin that is always enabled and it is a OR of all the interrupts.

Then, there is interrupt from the 2 GPIOS.

GPIO 1 can only trigger interrupt from MCAN_INT_1

GPIO 2 can only trigger interrupt from MCAN_INT_0

In the sample code provided, the GPIO 1 is configured for MCAN_INT_1 and GPIO 2 is configured for NO ACTION. Then, the function TCAN4x5x_Device_Configure is called.

But earlier, in the function TCAN4x5x_MCAN_ConfigureInterruptEnable the M_INT_0 is enabled, also writing in the multiplexer register.

So, the final configuration is:

- GPIO 1 works for MCAN_INT_1

- But it is enabled only MCAN_INT_0

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};	// 250k arbitration with a 40 MHz crystal ((40E6 / 4) / (32 + 8) = 500E3)
	TCANNomTiming.NominalBitRatePrescaler = 4;
	TCANNomTiming.NominalTqBeforeSamplePoint = 32;
	TCANNomTiming.NominalTqAfterSamplePoint = 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 = 0;										// CAN FD mode disabled
	cccrConfig.BRSE = 0;										// CAN FD Bit rate switch disable

	/* 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:
	 *   - 0 SID filter element
	 *   - 0 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
	 *   - 10 Transmit buffers supporting up to 8 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 = 0;						// Extended ID number of elements, you MUST have a filter written to MRAM for each element defined
	MRAMConfiguration.Rx0NumElements = MAX_LENGTH_FIFO;						// RX0 Number of elements
	MRAMConfiguration.Rx0ElementSize = MRAM_8_Byte_Data;		// RX0 data payload size
	MRAMConfiguration.Rx1NumElements = 0;						// RX1 number of elements
	MRAMConfiguration.Rx1ElementSize = MRAM_8_Byte_Data;		// RX1 data payload size
	MRAMConfiguration.RxBufNumElements = 0;						// RX buffer number of elements
	MRAMConfiguration.RxBufElementSize = MRAM_8_Byte_Data;		// RX buffer data payload size
	MRAMConfiguration.TxEventFIFONumElements = 0;				// TX Event FIFO number of elements
	MRAMConfiguration.TxBufferNumElements = MAX_LENGTH_FIFO;					// TX buffer number of elements
	MRAMConfiguration.TxBufferElementSize = MRAM_8_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);			// dON'T 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

How could work the GPIO? I'm expecting it never triggers. Am I missing something? 

If I enable MCAN_INT_0 (from register 0x105C) I should use the GPIO2.

On the other hand, if I enable MCAN_INT_1 (from 0x105C) I should use the GPIO1.

Is my understood correct?

  • Hi Marco,

    The GPO interrupt output functionality for TCAN4550 is not used in this demo code. The configurations for GPIO1 and GPO2 are left as their default values (0b01 and 0b00) during device configuration. As you stated, the nINT pin on TCAN4550 is used to indicate when any unmasked interrupt bit is set. This will include any enabled interrupt from MCAN_INT_0 or MCAN_INT_1. This interrupt output is what is used by the demo code to recognize when an interrupt has occurred. This pin is mapped to MCU pin 2.3. The interrupt vector (bottom of main.c) for this pin allows for the incrementing of an interrupt counter variable. 

    If you wanted to use the GPO pins to get information on the present interrupts more quickly (without having to do a SPI read), you can configure them to indicate these certain interrupt conditions. The demo code treats all interrupts the same until the interrupt registers can be read via SPI. Additionally, the only mcan interrupt that is enabled in this demo is RF0NE (new message in FIFO0 ), so the GPOs would not have much unique information to indicate in this example.

    Let me know if you have any more questions.

    Regards,
    Eric Schott

  • Hi Eric,

    thanks for the answers. Now it is everything more clear.

    So, just to be sure,  for example if I enable only the RF0NE interrupt by registers, then the behaviour of nINT pin should be the same as a GPO configured to trigger on RFONE? I mean, when nINT pin triggers I already know that there's an incoming message. (in this particular case)

    In other words, nINT pin is the OR of all the enabled interrupts?

    Thanks,

    Marco.

  • Hi Marco,

    Yes, you are correct here. The nINT pin will indicate when any of the enable interrupts are set. This includes both device interrupts and mcan interrupts. The GPOs can be used to convey extra information. This could be used to set priority on handling certain interrupts by having the MCU respond differently when nINT is set or when nINT and GPIO1 is set for example. If this extra priority layer not needed, the nINT pin can be used to indicate any and all of the desired interrupts. 

    Regards,
    Eric Schott

  • Hi Eric,

    many thanks for all information provided.

    Regards,

    Marco.