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.

DRA829J: RTI WWD on MCU2_0 won't trigger

Part Number: DRA829J

Hi, I'm trying to set up the R5 core MCU2_0 RTI WWD, but the settings don't seem to have any effect. I never get the reset nor the interrupt, regardless the configuration. Below is the code I'm using, based on PDK's rti_app_dwwd_v1.c example:

static void initWatchdog(void)
{
    rtiInterruptConfig();

    /* Set RTI clock source */
    HW_WR_FIELD32(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_WWD28_CLKSEL,
                                CSL_MAIN_CTRL_MMR_CFG0_WWD28_CLKSEL_CLK_SEL,
                                0x3u);

    uint32_t status;
    RTIDwwdGetStatus(CSL_RTI28_CFG_BASE, &status);
    RTIDwwdClearStatus(CSL_RTI28_CFG_BASE, status);

    int32_t result = RTIDwwdWindowConfig(CSL_RTI28_CFG_BASE,
                                         RTI_RTIDWWDRXNCTRL_DWWDRXN_INTERRUPT,
                                         10000u * 32u,
                                         RTI_RTIDWWDSIZECTRL_DWWDSIZE_100_PERCENT);
    ASSERT(CSL_PASS == result);

    result = RTIDwwdCounterEnable(CSL_RTI28_CFG_BASE);
    ASSERT(CSL_PASS == result);
}

static void rtiInterruptConfig(void)
{
    OsalRegisterIntrParams_t intParams;

    Osal_RegisterInterrupt_initParams(&intParams);

    intParams.corepacConfig.arg = (uintptr_t)NULL;
    intParams.corepacConfig.priority = 1u;
    intParams.corepacConfig.corepacEventNum = 0u;    /**< Not used */
    intParams.corepacConfig.isrRoutine = &rtiWwdIsr;
    intParams.corepacConfig.intVecNum = CSLR_R5FSS0_CORE0_INTR_RTI28_INTR_WWD_0;

    HwiP_Handle hHwiHandle;
    OsalInterruptRetCode_e osalRetVal = Osal_RegisterInterrupt(&intParams, &hHwiHandle);
    seASSERT(OSAL_INT_SUCCESS == osalRetVal);
}

I'm calling Board_unlockMMR() before configuring RTI.
I also tried setting the wwdt reaction to RTI_RTIDWWDRXNCTRL_DWWDRXN_RESET, but no change either.
Is there something I'm missing in the RTI WWD setup?

  • Hi,

    It appears that your current setup is using RTI28, which enables the MAIN domain RTI module, not the MCU RTI module. On J721E: MCU uses MCU RTI1 and MPU uses MAIN RTI0.

    To set up the RTI watchdog for the R5 MCU2_0 core, the RTI base address should be MCU_RTI1 (CSL_MCU_RTI1_CFG_BASE) instead of RTI28. The default CSL RTI example for J721E enables the MAIN domain RTI0 module. I have updated the example to use MCU_RTI1 for the R5 MCU2_0 core, and with this change, the interrupt is triggered successfully.  have attached the updated rti_app_dwwd_v1.c file for your reference.

    https://software-dl.ti.com/jacinto7/esd/processor-sdk-rtos-jacinto7/11_01_00_04/exports/docs/pdk_jacinto_11_01_00_17/docs/userguide/jacinto/modules/csl/csl_rti_example.html#csl-rti-example 

    rti_app_dwwd_v1.zip

    Regards,

    Karthik

  • That doesn't seem to solve the problem. 

    I set the rtiModule in all calls to CSL_MCU_RTI1_CFG_BASE as suggested and also adjusted the clock selection and interrupt to match MCU_RTI1, but I still don't see the RTI interrupt nor the reset (if using RTI_RTIDWWDRXNCTRL_DWWDRXN_INTERRUPT).

    I'm confused here, because in the Technical Reference Manual, it states the following:

    • RTI28 is dedicated to the first R5F CPU core in the Main domain (R5FSS0_CORE0)

    Isn't MCU2_0 the first R5F CPU core in the Main domain? This is how I understood the cores organization:

    MCU1_0 => First core in MCU domain
    MCU1_1 => Second core in MCU domain
    MCU2_0 => First core in MAIN domain
    MCU2_1 => Second core in MAIN domain
    MCU3_0 => Third core in MAIN domain
    MCU3_1 => Fourth core in MAIN domain

    If I'm running my code on MCU2_0, it sounds to me I should use RTI28.

  • Hi Anderson,
    Apologies for the confusion in my earlier response. I mistakenly interpreted the issue as RTI0-related, whereas RTI28 is indeed the correct RTI instance for the MCU2_0 core, as mentioned in the TRM.
    The default CSL RTI DWWD example in J721E uses the mpu1_0 and mcu1_0 cores for testing. I have updated the same example to use RTI28 for the R5 MCU2_0 core, and with this change, the interrupt is triggered successfully. I have attached the updated rti_app_dwwd_v1.c and rti_app_dwwd.h files for your reference. I hope this helps resolve your issue.

    Enable_RTI_For_MCU2_0_Core.zip

    Regards,

    Karthik

  • No worries, thanks for the update. However, the example you sent has very little differences from the code I initially posted. In fact only the clock RTI set function is different, but I tried both versions with the same results, still don't see the trigger. One important question: do we need to explicitly enable the RTI28 in the Linux device tree? It's not enabled by default from what I can see.

  • Hi Anderson,

    One important question: do we need to explicitly enable the RTI28 in the Linux device tree? It's not enabled by default from what I can see

    Could you please confirm whether the RTOS SDK or the Linux SDK is being used for this test?

    Regards,

    Karthik

  • RTOS SDK (FreeRTOS) running on MCU2_0.

  • Hi Anderson,

    The interrupt is being triggered successfully on my end, and I am not facing any issues while testing the CSL RTI DWWD example on J721E. Could you please share your rti_app_dwwd_v1.c and rti_app_dwwd.h files? I would like to verify them to help identify the possible root cause of the issue.

    Regards,

    Karthik

  • I'm not directly using the rti_app_dwwd_v1.c example. I wrote my own code based on that example, so I'm uploading it here. Our main() calls the BOARD_init() function at some point, which tries to initialize the watchdog as you'll see in the example. Please notice this code is not running on a J721E-EVM, but on our custom board that runs on DRA829J SoC.

    Important information about the code:

    • Proprietary parts were omitted.
    • OS_start() is missing because we handle RTOS scheduler initialization somewhere else.

    #include "sciclient.h"
    #include "ipc_rsctable.h"
    #include "ti/drv/ipc/ipc.h"
    #include "ti/csl/src/ip/rti/V0/rti.h"
    #include "ti/csl/csl_rti.h"
    #include "ti/csl/soc.h"
    
    
    /* MCU2_0 is connected to RTI28 address */
    #define SE_OS_RTI_WWD_BASE_ADDR     		(CSL_RTI28_CFG_BASE)
    #define SE_OS_RTI_WWD_INT_NUM               (CSLR_R5FSS0_CORE0_INTR_RTI28_INTR_WWD_0)
    #define SE_OS_RTI_WWD_REACTION              (RTI_RTIDWWDRXNCTRL_DWWDRXN_INTERRUPT)
    #define SE_OS_RTI_WWD_WINDOW_SIZE           (RTI_RTIDWWDSIZECTRL_DWWDSIZE_100_PERCENT)
    #define SE_OS_RTI_WWD_CLOCK_SOURCE_32KHZ    (3u)    /**< 32 KHz clock in the shit register */
    #define SE_OS_RTI_WWD_CLOCK_FREQ_KHZ        (32u)
    #define SE_OS_RTI_WWD_PRELOAD_VALUE         (10000u * SE_OS_RTI_WWD_CLOCK_FREQ_KHZ) /**< 10 sec */
    #define SE_OS_RTI_CTRL_MMR_CFG_BASE         (CSL_CTRL_MMR0_CFG0_BASE)
    #define SE_OS_RTI_CTRL_MMR_CLKSEL_OFFSET    (CSL_MAIN_CTRL_MMR_CFG0_WWD28_CLKSEL)
    #define SE_OS_RTI_RTI_CLK_SEL_FIELD_MASK    (CSL_MAIN_CTRL_MMR_CFG0_WWD28_CLKSEL_CLK_SEL_MASK)
    #define SE_OS_RTI_RTI_CLK_SEL_FIELD_SHIFT   (CSL_MAIN_CTRL_MMR_CFG0_WWD28_CLKSEL_CLK_SEL_SHIFT)
    
    // Prototypes
    static void initWatchdog(void);
    static void rtiInterruptConfig(void);
    static void rtiWwdIsr(uintptr_t handle);
    static void setRtiClockSource(void);
    
    
    void BOARD_init(void)
    {
        Sciclient_ConfigPrms_t config;
    
        Sciclient_configPrmsInit(&config);
        Sciclient_init(&config);
    
        /* Disable clocks first to ensure a clean state in case the board is coming from a reset */
        Board_moduleClockDeinitMcu();
        Board_moduleClockDeinitMain();
    
        Board_unlockMMR();
        Board_moduleClockInitMcu();
        Board_moduleClockInitMain();
    
        Ipc_loadResourceTable((void*)&ti_ipc_remoteproc_ResourceTable);
    
        OS_init();
    
        initWatchdog();
    }
    
    static void rtiInterruptConfig(void)
    {
        OsalRegisterIntrParams_t intParams;
    
        Osal_RegisterInterrupt_initParams(&intParams);
    
        intParams.corepacConfig.arg = (uintptr_t)NULL;
        intParams.corepacConfig.priority = 1u;
        intParams.corepacConfig.corepacEventNum = 0u;    /**< Not used */
        intParams.corepacConfig.isrRoutine = &rtiWwdIsr;
        intParams.corepacConfig.intVecNum = SE_OS_RTI_WWD_INT_NUM;
    
        HwiP_Handle hHwiHandle;
        OsalInterruptRetCode_e osalRetVal = Osal_RegisterInterrupt(&intParams, &hHwiHandle);
        ASSERT(OSAL_INT_SUCCESS == osalRetVal);
    }
    
    static void initWatchdog(void)
    {
        rtiInterruptConfig();
        setRtiClockSource();
    
        int32_t result = RTIDwwdWindowConfig(SE_OS_RTI_WWD_BASE_ADDR,
                                             SE_OS_RTI_WWD_REACTION,
                                             SE_OS_RTI_WWD_PRELOAD_VALUE,
                                             SE_OS_RTI_WWD_WINDOW_SIZE);
        ASSERT(CSL_PASS == result);
    
        result = RTIDwwdCounterEnable(SE_OS_RTI_WWD_BASE_ADDR);
        ASSERT(CSL_PASS == result);
    }
    
    static void rtiWwdIsr(uintptr_t handle)
    {
        uint32_t status;
    
        RTIDwwdGetStatus(SE_OS_RTI_WWD_BASE_ADDR, &status);
        RTIDwwdClearStatus(SE_OS_RTI_WWD_BASE_ADDR, status);
    
    	// Internal reset function
        reset();
    }
    
    static void setRtiClockSource(void)
    {
        volatile uint32_t *hwRegPtr;
    
        hwRegPtr = (uint32_t*)(SE_OS_RTI_CTRL_MMR_CFG_BASE + SE_OS_RTI_CTRL_MMR_CLKSEL_OFFSET);
        hwRegPtr[0] = (hwRegPtr[0] & (~SE_OS_RTI_RTI_CLK_SEL_FIELD_MASK)) | (SE_OS_RTI_WWD_CLOCK_SOURCE_32KHZ << SE_OS_RTI_RTI_CLK_SEL_FIELD_SHIFT);
    }

  • Hi Anderson,

    It seems like your configuration is correct. Please build your application in debug mode and set a break point through CCS to identify exactly where the code stops executing.

    Regards,

    Karthik