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.

TDA4VM-Q1: Modify j721e CAN Profiling Demo to use MCU MCAN0 and MAIN MCAN0 for mcu1_0

Part Number: TDA4VM-Q1
Other Parts Discussed in Thread: TDA4VM, TCAN1043, TCA6424A

I am working on a proof of concept that requires modifying the CAN Profiling demo. The main domain and mcu domain need to be configured to communicate directly using the CAN ports. The first step is to get the demo to work on both  mcu1_0 and mcu2_1 in external loopback mode. However, I am working on the J721e EVM with only the Common Processor Board and SOM, no GESI expansion board.

This is okay for running the demo on mcu1_0, since there are only two CAN ports in the mcu domain. Both MCU MCAN0 and MCU MCAN1 are exposed via headers at J31 and J30. However, the demo on mcu2_1 for the main domain is configured to use MCAN4 and MCAN9. These headers are only accessible via the GESI expansion board.

I would like to modify the demo for mcu2_1 to use MCAN0 and MCAN2, since they are exposed to the common processor board at headers J28 and J27. I have made the necessary additions to Can_Cfg, but am running into difficulty in CanApp_Startup. Based on the TRM, the following should be the correct PAD configurations/multiplexing for MCAN0 and MCAN2:

/* MAIN MCAN 0 Tx PAD configuration */
regVal = 0x60000U;
CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C20CU, regVal);
/* MAIN MCAN 0 Rx PAD configuration */
regVal = 0x60000U;
CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C208U, regVal);
/* MAIN MCAN 2 Tx PAD configuration */
regVal = 0x60003U;
CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C1F4U, regVal);
/* MAIN MCAN 2 Rx PAD configuration */
regVal = 0x60003U;
CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C1F0U, regVal);

But when I get to enabling these transceivers, I am confused as to what is happening. I understand that the following code is enabling output for certain GPIO pins, but I am having trouble understanding why:

/* Pin mux for CAN STB used in GESI board */
regVal = 0x20007U;
CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C0F4U, regVal);
/* Take MCAN transceiver out of STB mode for MCAN0 */
/* Set Pin direction to output */
regVal = CSL_REG32_RD(CSL_GPIO0_BASE + 0x38U);
regVal &= (~(1U << 0x1BU));
CSL_REG32_WR(CSL_GPIO0_BASE + 0x38U, regVal);
/* Drive Pin to Low */
Dio_WriteChannel(CAN_TRCV_MAIN_DOMAIN_4_9_11, STD_LOW);
/* Read Pin level */
dioPinLevel[0] = Dio_ReadChannel(CAN_TRCV_MAIN_DOMAIN_4_9_11);
/*Read back the pin levels to ensure transceiver is enabled*/
if (STD_LOW != dioPinLevel[0U])
{
    AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME
    " Error in Enabling CAN Transceiver Main Domain Inst 4,9,11!!!\n");
}
else
{
    AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME
    " Successfully Enabled CAN Transceiver Main Domain Inst 4,9,11!!!\n");
}

Could someone point me in the right direction to understanding how these GPIO pins interact with the MCAN pins? The rest of the file seems to be geared toward communicating with the GESI board over I2C, is that what these pins are being used for?

  • I am now trying to configure the external loopback demo for mcu1_0 to transmit from MCU MCAN0 and receive on MAIN MCAN0. I understand that the GPIO pins are used for the enable and standby lines.

    However, even now that I have switched out all of the MCU MCAN1 receive code for MAIN MCAN0, my build does not work. It compiles fine and seems to run on the board, but no transmission occurs. I believe my issue is with configuring the mailboxes.

    Can_Cfg.c:

    /* HW Filter structure for all configsets */
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_HwFilterType
        CanConfigSet_CanHardwareObject_3_CanHwFilter_0 =
    {
        177U,  /*CanHwFilterCode*/
        4294967295U,  /*Filter Mask*/
    };
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_HwFilterType
        CanConfigSet_CanHardwareObject_4_CanHwFilter_0 =
    {
        176U,  /*CanHwFilterCode*/
        4294967295U,  /*Filter Mask*/
    };
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_HwFilterType
        CanConfigSet_CanHardwareObject_5_CanHwFilter_0 =
    {
        192U,  /*CanHwFilterCode*/
        4294967295U,  /*Filter Mask*/
    };
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_HwFilterType
        CanConfigSet_CanHardwareObject_6_CanHwFilter_0 =
    {
        193U,  /*CanHwFilterCode*/
        4294967295U,  /*Filter Mask*/
    };
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_HwFilterType
        CanConfigSet_CanHardwareObject_8_CanHwFilter_0 =
    {
        192U,  /*CanHwFilterCode*/
        4294967295U,  /*Filter Mask*/
    };
    
    /*List of the HW Filter structures */
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_HwFilterType
        *CanConfigSet_CanHardwareObject_3_HwFilterConfigList[]=
    {
        &CanConfigSet_CanHardwareObject_3_CanHwFilter_0,
    };
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_HwFilterType
        *CanConfigSet_CanHardwareObject_4_HwFilterConfigList[]=
    {
        &CanConfigSet_CanHardwareObject_4_CanHwFilter_0,
    };
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_HwFilterType
        *CanConfigSet_CanHardwareObject_5_HwFilterConfigList[]=
    {
        &CanConfigSet_CanHardwareObject_5_CanHwFilter_0,
    };
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_HwFilterType
        *CanConfigSet_CanHardwareObject_6_HwFilterConfigList[]=
    {
        &CanConfigSet_CanHardwareObject_6_CanHwFilter_0,
    };
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_HwFilterType
        *CanConfigSet_CanHardwareObject_8_HwFilterConfigList[]=
    {
        &CanConfigSet_CanHardwareObject_8_CanHwFilter_0,
    };
    
    
    /* All the Mailbox objects(MB's) will be defined here for all config sets */
        CAN_CONFIG_DATA_SECTION_NON_CONST static Can_MailboxType
        CanConfigSet_CanHardwareObject_0 =
    {
        0U,  /*  CanHandleType 0=Full, 1=Basic */
        1U,  /* CanIdType 0=standard 1=Extended 2=Mixed*/
    	0U,  /* HwHandle i.e Mailbox - Hw object in the controller */
    
    
        12U,   /* Length of the Mailbox */
        CAN_MAILBOX_DIRECTION_TX,  /* CanObjectType - Direction of Mailbox*/
        &CanConfigSet_PC_CanController_0,  /* Controller */
    	NULL_PTR,  /* List of HW Filter structs */
        0U,   /* Hw Filter Count */
        204U,   /* Padding value for CAN FD message */
    	(boolean)FALSE,   /* CanHardwareObjectUsesPolling */
    };
    	CAN_CONFIG_DATA_SECTION_NON_CONST static Can_MailboxType
        CanConfigSet_CanHardwareObject_1 =
    {
        0U,  /*  CanHandleType 0=Full, 1=Basic */
        1U,  /* CanIdType 0=standard 1=Extended 2=Mixed*/
    	0U,  /* HwHandle i.e Mailbox - Hw object in the controller */
    
    
        12U,   /* Length of the Mailbox */
        CAN_MAILBOX_DIRECTION_TX,  /* CanObjectType - Direction of Mailbox*/
        &CanConfigSet_PC_CanController_0,  /* Controller */
    	NULL_PTR,  /* List of HW Filter structs */
        0U,   /* Hw Filter Count */
        204U,   /* Padding value for CAN FD message */
    	(boolean)FALSE,   /* CanHardwareObjectUsesPolling */
    };
    	CAN_CONFIG_DATA_SECTION_NON_CONST static Can_MailboxType
        CanConfigSet_CanHardwareObject_2 =
    {
        0U,  /*  CanHandleType 0=Full, 1=Basic */
        1U,  /* CanIdType 0=standard 1=Extended 2=Mixed*/
    	0U,  /* HwHandle i.e Mailbox - Hw object in the controller */
    
    
        12U,   /* Length of the Mailbox */
        CAN_MAILBOX_DIRECTION_TX,  /* CanObjectType - Direction of Mailbox*/
        &CanConfigSet_PC_CanController_2,  /* Controller */
    	NULL_PTR,  /* List of HW Filter structs */
        0U,   /* Hw Filter Count */
        204U,   /* Padding value for CAN FD message */
    	(boolean)FALSE,   /* CanHardwareObjectUsesPolling */
    };
    		CAN_CONFIG_DATA_SECTION_NON_CONST static Can_MailboxType
        CanConfigSet_CanHardwareObject_3 =
    {
        0U,  /*  CanHandleType 0=Full, 1=Basic */
        0U,  /* CanIdType 0=standard 1=Extended 2=Mixed*/
    	0U,  /* HwHandle i.e Mailbox - Hw object in the controller */
    
    
        12U,   /* Length of the Mailbox */
        CAN_MAILBOX_DIRECTION_RX,  /* CanObjectType - Direction of Mailbox*/
        &CanConfigSet_PC_CanController_0,  /* Controller */
        CanConfigSet_CanHardwareObject_3_HwFilterConfigList,  /* List of HW Filter structs */
        1U, /* Hw Filter Count */
        0U,   /* Padding value for CAN FD message */
    	(boolean)FALSE,   /* CanHardwareObjectUsesPolling */
    };
    	CAN_CONFIG_DATA_SECTION_NON_CONST static Can_MailboxType
        CanConfigSet_CanHardwareObject_4 =
    {
        0U,  /*  CanHandleType 0=Full, 1=Basic */
        1U,  /* CanIdType 0=standard 1=Extended 2=Mixed*/
    	0U,  /* HwHandle i.e Mailbox - Hw object in the controller */
    
    
        12U,   /* Length of the Mailbox */
        CAN_MAILBOX_DIRECTION_RX,  /* CanObjectType - Direction of Mailbox*/
        &CanConfigSet_PC_CanController_2,  /* Controller */
        CanConfigSet_CanHardwareObject_4_HwFilterConfigList,  /* List of HW Filter structs */
        1U, /* Hw Filter Count */
        0U,   /* Padding value for CAN FD message */
    	(boolean)FALSE,   /* CanHardwareObjectUsesPolling */
    };
    		CAN_CONFIG_DATA_SECTION_NON_CONST static Can_MailboxType
        CanConfigSet_CanHardwareObject_5 =
    {
        0U,  /*  CanHandleType 0=Full, 1=Basic */
        1U,  /* CanIdType 0=standard 1=Extended 2=Mixed*/
    	1U,  /* HwHandle i.e Mailbox - Hw object in the controller */
    
    
        12U,   /* Length of the Mailbox */
        CAN_MAILBOX_DIRECTION_RX,  /* CanObjectType - Direction of Mailbox*/
        &CanConfigSet_PC_CanController_0,  /* Controller */
        CanConfigSet_CanHardwareObject_5_HwFilterConfigList,  /* List of HW Filter structs */
        1U, /* Hw Filter Count */
        0U,   /* Padding value for CAN FD message */
    	(boolean)FALSE,   /* CanHardwareObjectUsesPolling */
    };
    	CAN_CONFIG_DATA_SECTION_NON_CONST static Can_MailboxType
        CanConfigSet_CanHardwareObject_6 =
    {
        0U,  /*  CanHandleType 0=Full, 1=Basic */
        0U,  /* CanIdType 0=standard 1=Extended 2=Mixed*/
    	0U,  /* HwHandle i.e Mailbox - Hw object in the controller */
    
    
        12U,   /* Length of the Mailbox */
        CAN_MAILBOX_DIRECTION_RX,  /* CanObjectType - Direction of Mailbox*/
        &CanConfigSet_PC_CanController_2,  /* Controller */
        CanConfigSet_CanHardwareObject_6_HwFilterConfigList,  /* List of HW Filter structs */
        1U, /* Hw Filter Count */
        0U,   /* Padding value for CAN FD message */
    	(boolean)FALSE,   /* CanHardwareObjectUsesPolling */
    };
    
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_MailboxType
        CanConfigSet_CanHardwareObject_7 =
    {
        0U,  /*  CanHandleType 0=Full, 1=Basic */
        0U,  /* CanIdType 0=standard 1=Extended 2=Mixed*/
    	0U,  /* HwHandle i.e Mailbox - Hw object in the controller */
    
    
        1U,   /* Length of the Mailbox */
        CAN_MAILBOX_DIRECTION_TX,  /* CanObjectType - Direction of Mailbox*/
        &CanConfigSet_PC_CanController_2,  /* Controller */
    	NULL_PTR,  /* List of HW Filter structs */
        0U,   /* Hw Filter Count */
        0U,   /* Padding value for CAN FD message */
    	(boolean)FALSE,   /* CanHardwareObjectUsesPolling */
    };
    
    CAN_CONFIG_DATA_SECTION_NON_CONST static Can_MailboxType
        CanConfigSet_CanHardwareObject_8 =
    {
        0U,  /*  CanHandleType 0=Full, 1=Basic */
        0U,  /* CanIdType 0=standard 1=Extended 2=Mixed*/
    	0U,  /* HwHandle i.e Mailbox - Hw object in the controller */
    
    
        1U,   /* Length of the Mailbox */
        CAN_MAILBOX_DIRECTION_RX,  /* CanObjectType - Direction of Mailbox*/
        &CanConfigSet_PC_CanController_2,  /* Controller */
        CanConfigSet_CanHardwareObject_8_HwFilterConfigList,  /* List of HW Filter structs */
        1U, /* Hw Filter Count */
        0U,   /* Padding value for CAN FD message */
    	(boolean)FALSE,   /* CanHardwareObjectUsesPolling */
    };

    I swapped out any MCU MCAN1 identifiers for MAIN MCAN0, but am not confident that this is correct. I did not change any of the filters. Could someone point me to the resource for understanding how to configure the mailbox hardware objects? Or the steps for converting the mcu1_0 external loopback demo to transmit on MCU MCAN0 and receive on MAIN MCAN0?

  • The end goal is to convert the mcu1_0 external loopback can profiling demo to use MAIN MCAN0 as the receiving transceiver rather than MCU MCAN1. I have tried followed the steps in this related post:

    1. Register interrupts for the instance to be used White check mark

    CAN_CONFIG_DATA_SECTION_CONST const struct Can_ControllerStruct_PC
        CanConfigSet_PC_CanController_2 =
    {
        CanConf_CanController_CanController_2,      /* Id as provided by GUI */
        (boolean)TRUE,   /* Contoller is used=1 or not_used=0*/
        0x2708000U, /* Can Controller Base Address */
    
    
        CAN_TX_RX_PROCESSING_INTERRUPT,  /* Can Rx Processing Type */
        CAN_TX_RX_PROCESSING_INTERRUPT,  /* Can Tx Processing Type */
        (boolean)TRUE,/* BusOff  TRUE = Interrupt FALSE = Polling */
    	CAN_CONTROLLER_INSTANCE_MCAN0,  /* Controller Instance */
    
    
    	(boolean)TRUE,  /* CAN FD Mode Enable */
    };
    // ...
    /** \brief MCAN0 Controller Instance ISR */
    FUNC(void, CAN_CODE) Can_2_Int0ISR(void)
    {
    Can_IntISR_Function(CAN_CONTROLLER_INSTANCE_MCAN0, 0x2708000U);
    }

    2. Modify configuration to add config for controller and mailboxes for that controller (loop back is functional at this point) Question

    Not sure how to configure the fields of the Can_MailboxType struct other than the definition found here.

    3. Configure pinmux for Tx and Rx. White check mark

    /* MAIN MCAN 0 Tx PAD configuration */
    regVal = 0x60000U;
    CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C20CU, regVal);
    /* MAIN MCAN 0 Rx PAD configuration */
    regVal = 0x60000U;
    CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C208U, regVal);

    4. Configure Transceiver. White check mark

    /* Configure SOC_PADCONFIG_143 set it to '1' to take
       MCAN transceiver out of STB mode */
    I2C_Params      i2cParams;
    I2C_Handle      handle = NULL;
    uint8           dataToSlave[4];
    /*
     * Configuring TCA6424 IO Exp 2 with addr 0x22
     * This io expander is controlled by i2c0
     * For Main MCAN2 P13 and P14 should be set to 0, This should route the MCAN2 STB line to transciver.
     * For Main MCAN0 P06 and P07 should be set to 1.
     */
     /* I2c PinMux */
    /* I2C0_SDL */
    regVal = 0x40000U;
    CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C220U, regVal);
    /* I2C0_SDA */
    regVal = 0x40000U;
    CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C224U, regVal);
    /* I2C initialization */
    I2C_init();
    I2C_Params_init(&i2cParams);
    i2cParams.transferMode = I2C_MODE_BLOCKING;
    i2cParams.bitRate = I2C_400kHz;
    i2cParams.transferCallbackFxn = NULL;
    
    handle = I2C_open(0U, &i2cParams);
    
    dataToSlave[0] = TCA6424_REG_CONFIG0 | TCA6424_CMD_AUTO_INC;
    dataToSlave[1] = 0x0U;
    SetupI2CTransfer(handle, 0x22, &dataToSlave[0], 2, NULL, 0);
    
    dataToSlave[0] = TCA6424_REG_INPUT0 | TCA6424_CMD_AUTO_INC;
    dataToSlave[1] = 0x0U;
    dataToSlave[2] = 0x0U;
    dataToSlave[3] = 0x0U;
    SetupI2CTransfer(handle, 0x22, &dataToSlave[0], 1, &dataToSlave[1], 3);
    
    /* Set P06 and P07 to 1.
     * Set P13 and P14 to 0.
     */
    dataToSlave[0] = TCA6424_REG_OUTPUT0 | TCA6424_CMD_AUTO_INC;
    dataToSlave[1] |= 0xC0;
    dataToSlave[2] &= ~(0x18);
    SetupI2CTransfer(handle, 0x22, &dataToSlave[0], 1, &dataToSlave[1], 3);

    I have made multiple modifications and iterations and the program still gets stuck waiting on the CanIf_TxConfirmationSemaphore to be released. I do have jumpers connecting CAN_H, CAN_L, and GND from J30 to J27 on the common processing board.

    Attached are the source files that I have touched (profiling/can: main_rtos.c, can_profile.h, can_profile.c; profiling/can/soc/j721e/mcu1_0: CanApp_Startup.h, CanApp_Startup.c; mcal_config/Can_Demo_Cfg/output/generated/soc/j721e/mcu1_0: include/Can_Cfg.h, src/Can_Cfg.c). Most of my modifications are escaped with preprocessor if statements and my MY_CAN_SIC_MOD flag.

    can_profile_app_mcu1_0_modified.zip

  • Joseph

    I'm assuming you are using the latest SDK for TDA4VM.

    However, the demo on mcu2_1 for the main domain is configured to use MCAN4 and MCAN9. These headers are only accessible via the GESI expansion board.

    The demo should also configure the transceivers for MCAN0 and MCAN2 as well which are there on the Common Processor board.

    CanApp_EnableTransceivers() in the file mcusw/mcuss_demos/profiling/can/soc/j721e/mcu2_1/CanApp_Startup.c configures MCAN0, MCAN2 on the Common Processor board. It also configures MCAN4, MCAN5, MCAN6, MCAN7, MCAN9 and MCAN11 (on the GESI card) as the transceivers of all these MCANs are driven by the same signal.

    I have made the necessary additions to Can_Cfg, but am running into difficulty in CanApp_Startup. Based on the TRM, the following should be the correct PAD configurations/multiplexing for MCAN0 and MCAN2:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /* MAIN MCAN 0 Tx PAD configuration */
    regVal = 0x60000U;
    CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C20CU, regVal);
    /* MAIN MCAN 0 Rx PAD configuration */
    regVal = 0x60000U;
    CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C208U, regVal);
    /* MAIN MCAN 2 Tx PAD configuration */
    regVal = 0x60003U;
    CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C1F4U, regVal);
    /* MAIN MCAN 2 Rx PAD configuration */
    regVal = 0x60003U;
    CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C1F0U, regVal);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    This is already there in the CanApp_PlatformInit() function in mcusw/mcuss_demos/profiling/can/soc/j721e/mcu2_1/CanApp_Startup.c. This configures pinmux for MCAN0 and MCAN2's Tx and Rx signals as well.

    But when I get to enabling these transceivers, I am confused as to what is happening. I understand that the following code is enabling output for certain GPIO pins, but I am having trouble understanding why:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /* Pin mux for CAN STB used in GESI board */
    regVal = 0x20007U;
    CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C0F4U, regVal);
    /* Take MCAN transceiver out of STB mode for MCAN0 */
    /* Set Pin direction to output */
    regVal = CSL_REG32_RD(CSL_GPIO0_BASE + 0x38U);
    regVal &= (~(1U << 0x1BU));
    CSL_REG32_WR(CSL_GPIO0_BASE + 0x38U, regVal);
    /* Drive Pin to Low */
    Dio_WriteChannel(CAN_TRCV_MAIN_DOMAIN_4_9_11, STD_LOW);
    /* Read Pin level */
    dioPinLevel[0] = Dio_ReadChannel(CAN_TRCV_MAIN_DOMAIN_4_9_11);
    /*Read back the pin levels to ensure transceiver is enabled*/
    if (STD_LOW != dioPinLevel[0U])
    {
    AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME
    " Error in Enabling CAN Transceiver Main Domain Inst 4,9,11!!!\n");
    }
    else
    {
    AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME

    The EN and nSTB pins to the MCAN0 and MCAN2's transceivers are coming from an I2C controlled GPIO expander (TCA6424ARGJR) and 2:1 MUXes (SN74CB3Q3257PWR). This piece of code configures them appropriately.

    Could someone point me in the right direction to understanding how these GPIO pins interact with the MCAN pins? The rest of the file seems to be geared toward communicating with the GESI board over I2C, is that what these pins are being used for?

    For normal functioning of MCAN for using TCAN1043 transceivers, the EN should be HIGH and STB should HIGH (nSTB should be LOW). These signals could be driven by direct SoC GPIOs or could be routed via some other circuitry (in this case GPIO expanders) on the board.

    Regards

    Karan

  • Joseph

    The end goal is to convert the mcu1_0 external loopback can profiling demo to use MAIN MCAN0 as the receiving transceiver rather than MCU MCAN1.

    From MCU1_0 are you able to send from MCU MCAN0 and receive on MCU MCAN1?

    If so and then you plan to receive on MCAN0 then you need to register the interrupt for MCAN0 and also program an interrupt router in between. Interrupts from MCAN0 are not directly routed to MCU1_0. You need to use TISCI_RM_IRQ_SET API to do so.

    Refer CanApp_InterruptConfig() in mcusw/mcal_drv/mcal/examples/Can/soc/j721e/mcu1_0/CanApp_Startup.c for an example. Also refer this FAQ:

    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/931985/faq-tda4vm-routing-interrupts-via-the-interrupt-router 

    1. Register interrupts for the instance to be used 

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    CAN_CONFIG_DATA_SECTION_CONST const struct Can_ControllerStruct_PC
    CanConfigSet_PC_CanController_2 =
    {
    CanConf_CanController_CanController_2, /* Id as provided by GUI */
    (boolean)TRUE, /* Contoller is used=1 or not_used=0*/
    0x2708000U, /* Can Controller Base Address */
    CAN_TX_RX_PROCESSING_INTERRUPT, /* Can Rx Processing Type */
    CAN_TX_RX_PROCESSING_INTERRUPT, /* Can Tx Processing Type */
    (boolean)TRUE,/* BusOff TRUE = Interrupt FALSE = Polling */
    CAN_CONTROLLER_INSTANCE_MCAN0, /* Controller Instance */
    (boolean)TRUE, /* CAN FD Mode Enable */
    };
    // ...
    /** \brief MCAN0 Controller Instance ISR */
    FUNC(void, CAN_CODE) Can_2_Int0ISR(void)
    {
    Can_IntISR_Function(CAN_CONTROLLER_INSTANCE_MCAN0, 0x2708000U);

    This piece of code will not register the interrupt. Function CanApp_InterruptConfig() in mcusw/mcuss_demos/profiling/can/soc/j721e/mcu2_1/CanApp_Startup.c will register interrupts.

    2. Modify configuration to add config for controller and mailboxes for that controller (loop back is functional at this point) 

    Not sure how to configure the fields of the Can_MailboxType struct other than the definition found here.

    You should have Rx mailbox setup for the MCAN which you want to receive on and Tx for the one you plan to send from. All this has to be in this config file:

    mcuss_demos/mcal_config/Can_Demo_Cfg/output/generated/soc/j721e/<core>/src/Can_Cfg.c

    Regards

    Karan

    Regards

    Karan

  • Thank you for the informative response, interrupt routing is something that I forgot to implement. Will I need to do a similar thing for I2C0? I cannot get the MAIN MCAN0 TCAN1043 transceiver enabled. It is connected through a GPIO expander at address 0x22 on the I2C0 bus. From what I can gather in the datasheet, the following code should be enabling and setting P06 and P07 to high on the TCA6424A:

    /*
     * Configuring TCA6424 IO Exp 2 with addr 0x22
     * This io expander is controlled by i2c0
     * For Main MCAN0 P06 and P07 should be set to 1, This should route the MCAN0 EN and STB line to transciver.
     */
    /* I2c PinMux */
    /* I2C0_SDL */
    regVal = 0x40000U;
    CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C220U, regVal);
    /* I2C0_SDA */
    regVal = 0x40000U;
    CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + 0x1C224U, regVal);
    /* I2C initialization */
    I2C_init();
    I2C_Params_init(&i2cParams);
    i2cParams.transferMode = I2C_MODE_BLOCKING;
    i2cParams.bitRate = I2C_400kHz;
    i2cParams.transferCallbackFxn = NULL;
    
    handle = I2C_open(0U, &i2cParams);
    
    dataToSlave[0] = TCA6424_REG_CONFIG0;
    dataToSlave[1] = 0x0U;
    SetupI2CTransfer(handle, 0x22, &dataToSlave[0], 2, NULL, 0);
    
    dataToSlave[0] = TCA6424_REG_INPUT0 | TCA6424_CMD_AUTO_INC;
    dataToSlave[1] = 0x0U;
    dataToSlave[2] = 0x0U;
    dataToSlave[3] = 0x0U;
    SetupI2CTransfer(handle, 0x22, &dataToSlave[0], 1, &dataToSlave[1], 3);
    
    /* Set P06 and P07 to 1.
     */
    dataToSlave[0] = TCA6424_REG_OUTPUT0;
    dataToSlave[1] |= 0xC0;
    SetupI2CTransfer(handle, 0x22, &dataToSlave[0], 2, NULL, 0);
    
    dataToSlave[0] = TCA6424_REG_INPUT0;
    dataToSlave[1] = 0x0U;
    SetupI2CTransfer(handle, 0x22, &dataToSlave[0], 1, &dataToSlave[1], 1);
    if (0xC0U != (dataToSlave[1] & 0xC0U))
    {
        AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME
        " Error in Enabling CAN Transceiver MAIN MCAN0!!! TCA6424_REG_INPUT0: %x\n",
        dataToSlave[1]);
    }
    else
    {
        AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME
        " Successfully Enabled CAN Transceiver MAIN MCAN0!!!\n");
    }

    With the following helper function:

    void SetupI2CTransfer(I2C_Handle handle,  uint32 slaveAddr,
                          uint8 *writeData, uint32 numWriteBytes,
                          uint8 *readData,  uint32 numReadBytes)
    {
        bool status;
        I2C_Transaction i2cTransaction;
    
        I2C_transactionInit(&i2cTransaction);
        i2cTransaction.slaveAddress = slaveAddr;
        i2cTransaction.writeBuf = (uint8 *)&writeData[0];
        i2cTransaction.writeCount = numWriteBytes;
        i2cTransaction.readBuf = (uint8 *)&readData[0];
        i2cTransaction.readCount = numReadBytes;
        status = I2C_transfer(handle, &i2cTransaction);
        if(FALSE == status)
        {
            AppUtils_Printf(MSG_NORMAL, "\n Data Transfer failed. \n");
        }
    }

    Can mcu1_0 use I2C0?

  • Joseph

    Thank you for the informative response, interrupt routing is something that I forgot to implement. Will I need to do a similar thing for I2C0?

    No need to configure the interrupt router for the I2C0 usage from MCU2_1.

    For setting up the transceiver please use the existing SDK function, I see some deltas between what is there in the SDK and what you have quoted.

    Path to CanApp_EnableTransceivers() is "mcusw/mcuss_demos/profiling/can/soc/j721e/mcu2_1/CanApp_Startup.c".

    1. Can you confirm how do you make sure that the MAIN MCAN0 TCAN1043 is not enabled? Do you probe the EN and STB pins?

    2. What is your boot flow? How are you loading this application and what is running on the other cores when you run this? I've seen issues in enabling this transceiver when using SD boot with SPL/u-boot flow booting to Linux Kernel on A72. Reason for this is that we are trying to configure the IO expander which Linux also tries to configure when probing the SD card.  But if you are not booting Linux on A72, it shouldn't be an issue.

    Regards

    Karan

  • I am running this program on mcu1_0 and need to use I2C from there. I tried using the existing SDK function, but it did not work. I will revert it for further troubleshooting.

    1) Yes, I am probing the EN and STB pins. The pins for MCU MCAN0's TCAN1043 are high, but the pins for MAIN MCAN0's are not.

    2) My boot flow is using JTAG and CCS, so I am not booting Linux.

  • I also do not understand what this code is doing:

    /* Set P06 and P07 to 1.
     * Set P13 and P14 to 0.
     */
    dataToSlave[0] = TCA6424_REG_OUTPUT0 | TCA6424_CMD_AUTO_INC;
    dataToSlave[1] |= 0xC0;
    dataToSlave[2] &= ~(0x18);
    SetupI2CTransfer(handle, 0x22, &dataToSlave[0], 1, &dataToSlave[1], 3);


    Doesn't the fourth argument hold the buffer for read data? If so, how is this writing any more than the register address?

  • From my understanding of the documentation, the relevant fields of the tisci_msg_rm_irq_set_req struct to change based on this example code are: src_id, src_index, dst_id, and dst_host_irq. Could you provide more information on how to configure each of these fields? Below is the code that I am using to try and route interrupts from MCU_MCAN0 to R5FSS0_CORE1:

    (Running external loopback on mcu2_1 from MCAN0 to MCU_MCAN0)

    void CanApp_InterruptConfig(void)
    {
        uint32 idx;
        OsalRegisterIntrParams_t    intrPrms;
        OsalInterruptRetCode_e      osalRetVal;
        HwiP_Handle hwiHandle;
        struct tisci_msg_rm_irq_set_req     rmIrqReq;
        struct tisci_msg_rm_irq_set_resp    rmIrqResp;
        Int32 retVal;
        const Can_ConfigType *Can_ConfigPtr;
    
    #if (STD_ON == CAN_VARIANT_PRE_COMPILE)
        Can_ConfigPtr = &CAN_INIT_CONFIG_PC;
    #else
        Can_ConfigPtr = &CanConfigSet;
    #endif
    
        for (idx = 0U; idx < Can_ConfigPtr->CanMaxControllerCount; idx++)
        {
            /* If the CAN instance is not in MAIN domain, the interrupt router will
                have to be configured */
            if ((CAN_CONTROLLER_INSTANCE_MCU_MCAN0 ==
                CanConfigSet_CanController_List_PC[idx]->CanControllerInst))
            {
                CanApp_IntNumbers[idx]          = APP_MCU_MCAN_0_INT0; // CSLR_R5FSS0_INTROUTER0_IN_MCU_MCAN0_MCANSS_MCAN_LVL_INT_0 (336U)
                rmIrqReq.valid_params           = TISCI_MSG_VALUE_RM_DST_ID_VALID;
                rmIrqReq.valid_params          |= TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID;
                rmIrqReq.src_id                 = TISCI_DEV_MCU_MCAN0;
                rmIrqReq.global_event           = 0U;
                /* Src Index 0 - mcanss_ext_ts_rollover_lvl_int,
                   Src Index 1 - mcanss_mcan_lvl_int Line 0,
                   Src Index 2 - mcanss_mcan_lvl_int Line 1 */
                rmIrqReq.src_index              = 1U;
                rmIrqReq.dst_id                 = TISCI_DEV_R5FSS0_CORE1;
                rmIrqReq.dst_host_irq           = APP_MCU_MCAN_0_INT0; // CSLR_R5FSS0_INTROUTER0_IN_MCU_MCAN0_MCANSS_MCAN_LVL_INT_0 (336U)
                rmIrqReq.ia_id                  = 0U;
                rmIrqReq.vint                   = 0U;
                rmIrqReq.vint_status_bit_index  = 0U;
                rmIrqReq.secondary_host         = TISCI_MSG_VALUE_RM_UNUSED_SECONDARY_HOST;
                retVal = Sciclient_rmIrqSet(
                             &rmIrqReq, &rmIrqResp, APP_SCICLIENT_TIMEOUT);
                if(CSL_PASS != retVal)
                {
                    AppUtils_Printf(MSG_NORMAL,
                    "CAN_APP: Error in SciClient Interrupt Params Configuration!!!\n");
                }
            }
    
            /* Set the destination interrupt */
            Osal_RegisterInterrupt_initParams(&intrPrms);
            intrPrms.corepacConfig.arg          = (uintptr_t)CanApp_Isr[idx];
            intrPrms.corepacConfig.isrRoutine   = &CanApp_CanXIsr;
            intrPrms.corepacConfig.priority     = 1U;
            intrPrms.corepacConfig.corepacEventNum = 0U; /* NOT USED ? */
            intrPrms.corepacConfig.intVecNum        = CanApp_IntNumbers[idx];
    
            osalRetVal = Osal_RegisterInterrupt(&intrPrms, &hwiHandle);
            if(OSAL_INT_SUCCESS != osalRetVal)
            {
                AppUtils_Printf(MSG_NORMAL, MSG_APP_NAME
                                " Error %d !!!\n");
                break;
            }
        }
    
        return;
    }

    This seems correct based on these diagrams in the TRM:

    I believe that want to route interrupts from:

    MCU_MCAN0_MCANSS_MCAN_LVL_INT_0 (R5FSS0_INTRTR0_IN_335) => R5FSS0_INTR_IN_[511:256] (R5FSS0_INTROUTER0_OUTL_[255:0])

    Is this correct? It is throwing the "CAN_APP: Error in SciClient Interrupt Params Configuration!!!" error.

  • Joseph

    Could you provide more information on how to configure each of these fields?

    You can find more details here.

    https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/rm/rm_irq.html#pub-rm-irq-route-set

    I believe that want to route interrupts from:

    MCU_MCAN0_MCANSS_MCAN_LVL_INT_0 (R5FSS0_INTRTR0_IN_335) => R5FSS0_INTR_IN_[511:256] (R5FSS0_INTROUTER0_OUTL_[255:0])

    Is this correct?

    The full chain would be:

    MCU_MCAN0_MCANSS_MCAN_LVL_INT_0 (MCU MCAN0) => R5FSS0_INTRTR0_IN_335 (Interrupt Router Input Index) => R5FSS0_INTRTR0_OUT_[0:255] => MCU2_1 (rmIrqReq.dst_host_irq between 256:511)

    So the rmIrqReq.dst_host_irq is the interrupt number of the MCU2_1. This should be a free IRQ in the system (not registered already) and should be between 256:511 as these are the IRQs connected to the interrupt router.

    I see you programing the rmIrqReq.dst_host_irq as 336 which is input to the Interrupt Router, the rmIrqReq.dst_host_irq is not the input to the router but the input IRQ to the core. Can you try a different number for rmIrqReq.dst_host_irq between 256:511, make sure that this is a free IRQ in the system.

    Regards

    Karan

  • The issue was that while 336 was also within the output range, it was already in use. I looped through the possible outputs until I found one that was unused; it happened to be 384. Thank you for your help!