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.

TMDS62LEVM: (NO RTOS) RTI Watchdog example code setup issue

Part Number: TMDS62LEVM
Other Parts Discussed in Thread: AM62L

Tool/software:

Hi,

When I am running the example code F:\Example\TI\freertos_sdk_am62lx_11_00_00_05\examples\drivers\watchdog\watchdog_interrupt\am62lx-evm\a53ss0-0_nortos. I have following two quesitons.

1. �after the example binary being loaded, I am seeing "PSCI Major version 1ock_set_rate: Failed to set freq with scmi_id = 273 rate = 32552" from uart print

SOC_ModuleClockFrequency gSocModulesClockFrequency[] = {
    { AM62LX_DEV_RTI0, AM62LX_DEV_RTI0_RTI_CLK, 32552 },

    { AM62LX_DEV_UART0, AM62LX_DEV_UART0_FCLK_CLK, 48000000 },

    { SOC_MODULES_END, SOC_MODULES_END, SOC_MODULES_END },
};

2. with expiration time set to 10000ms , should I expect the interrupt will be triggered around 10 seconds not immediately (currently it immediately triggers)?

{
        .callbackFxn        = NULL,
        .callbackFxnArgs    = NULL,
        .resetMode          = Watchdog_RESET_OFF,
        .debugStallMode     = Watchdog_DEBUG_STALL_ON,
        .windowSize         = Watchdog_WINDOW_100_PERCENT,
        .expirationTime     = 10000,
},

Thank you,

Dazong

  • Hello Dazong,

    Can you please clarify, the WDT works when you configurate at 25MZ clock selection ?

    If we feed the 25MHz clock to the WDT, then the expiration time can be configured to till 1.3sec. 

    To get the expired time of 10sec, you need to feed the WDT at 32KHz clock...

    Did you integrate all the WDT changes ?  Is it possible to share your project to reproduce the issue on my side ?

    Regards,

    Anil.

  • Hi Anil,

    With 25MHz, I got a expiration close to 1 second when set timoeout to 1000ms

    1. ti_drivers_open_close.c
    
    /* watchdog Driver Parameters */
    Watchdog_Params gWatchdogParams[CONFIG_WATCHDOG_NUM_INSTANCES] =
    {
        {
            .callbackFxn        = NULL,
            .callbackFxnArgs    = NULL,
            .resetMode          = Watchdog_RESET_OFF,
            .debugStallMode     = Watchdog_DEBUG_STALL_ON,
            .windowSize         = Watchdog_WINDOW_100_PERCENT,
            .expirationTime     = 1000,
        },
    };
    
    2. ti_drivers_config.c
    static Watchdog_HwAttrs gWatchdogHwAttrs[CONFIG_WATCHDOG_NUM_INSTANCES] =
    {
        {
            .instance        = WATCHDOG_INST_ID_0,
            .baseAddr        = CSL_RTI0_CFG_BASE,
            .wdtClkFrequency = 25000000U,
        },
    };
    
    3. ti_power_clock_config.c
    SOC_ModuleClockFrequency gSocModulesClockFrequency[] = {
        { AM62LX_DEV_RTI0, AM62LX_DEV_RTI0_RTI_CLK, 25000000 },
    
        { AM62LX_DEV_UART0, AM62LX_DEV_UART0_FCLK_CLK, 48000000 },
    
        { SOC_MODULES_END, SOC_MODULES_END, SOC_MODULES_END },
    };
    
    4. watchdog_interrupt_mode.c
    void watchdog_interrupt_main(void *args)
    {
        HwiP_Params             hwiPrms;
        int32_t                 status = SystemP_SUCCESS;
        static HwiP_Object       gRtiHwiObject;
        uint64_t curTime;
        /* Register interrupt */
        HwiP_Params_init(&hwiPrms);
        hwiPrms.intNum      = CONFIG_WDT0_INTR;
        hwiPrms.eventId     = CONFIG_WDT0_EVENT_ID;
        hwiPrms.callback    = &watchdogCallback;
        hwiPrms.isPulse     = 1U;
        status              = HwiP_construct(&gRtiHwiObject, &hwiPrms);
        
        curTime = ClockP_getTimeUsec();
    
        DebugP_assert(status == SystemP_SUCCESS);
    
        DebugP_log("Watchdog interrupt Mode Test Started ...\r\n");
    
        while (gWatchdogInt == 0);
        curTime = ClockP_getTimeUsec() - curTime;
    
        DebugP_log("%ld us\n", curTime);
    
        DebugP_log("Watchdog Driver NMI received\r\n");
    
        DebugP_log("All tests have passed!!\r\n");
    
    }
    
    Output:
    Watchdog interrupt Mode Test Started ...
    988698 us
             Watchdog Driver NMI received
    All tests have passed!!

    I think this proabably still related to our discussion regarding the input clk freq into the general periphrals.

    Thank you,

    Dazong

  • Hello Dazong,

    The Watchdog clock is configured properly by the ATF when we try to select a 25MHz clock.

    But changes to 32KHz, the ATF is making an error and this needs to be checked on my side ..

    If you share the example project with me, I can easily reproduce the issue at my side and let you know the status.

    Regards,

    Anil.

  • Hi Anil,

    As you know we are doing unit testing for all peripharals, another thing I noticed regarding the WDT driver is that the Watchdog_close() is empty.

    For the WDT we are testing it similar to a timer interrupt. Without wachdog_close(), seems I cannot really set the new "expirationTime". eg first time, test 1.25 sec, second time, test 500ms etc. From what I've tried, the wdt is only taking the first time passed in value, which is 1 sec in this case, as you can see from the log below. Will Ti be able to support this feature so we can test with different timeouts?

    	wwdt_config.expirationTime = get_arg_ulong(argv[2]);
    	info("expirationTime = %d\n", wwdt_config.expirationTime);
    	wwdt_config.windowSize = Watchdog_WINDOW_100_PERCENT;
    
    	wwdt_Init(&wwdt_config);
    	info("wdt int 1 = %d\n", gWatchdogInt);
        /* Register interrupt */
        HwiP_Params_init(&hwiPrms);
        hwiPrms.intNum      = CONFIG_WDT0_INTR;
        hwiPrms.eventId     = CONFIG_WDT0_EVENT_ID;
        hwiPrms.callback    = &watchdogCallback;
        hwiPrms.isPulse     = 1U;
        status              = HwiP_construct(&gRtiHwiObject, &hwiPrms);
        
        curTime = ClockP_getTimeUsec();
    
        DebugP_assert(status == SystemP_SUCCESS);
    
    	info("wdt int 2 = %d\n", gWatchdogInt);
        gWatchdogInt = 0;
    	while (gWatchdogInt == 0)
    	{
    		// do nothing
    	}
    
    	HwiP_destruct(&gRtiHwiObject);
    
    	info("wdt int 3 = %d\n", gWatchdogInt);
    
        curTime = ClockP_getTimeUsec() - curTime;
    
        info("%ld us\n", curTime);
    
    	Watchdog_close(wwdt_config.hwwdt);
    	wwdt_config.hwwdt = NULL;
    	Watchdog_deinit();
    	gWatchdogInt = 0;

    cmd:> wwdt_int 0 1250
    expirationTime = 1250
    wdt int 1 = 0
    wdt int 2 = 0
    +++++
    +++++
    wdt int 3 = 2
    1250908 us
    
    cmd:> wwdt_int 0 500
    expirationTime = 500
    wdt int 1 = 0
    +++++
    wdt int 2 = 1
    +++++
    +++++
    wdt int 3 = 2
    1252280 us
    
    cmd:>wwdt_int 0 300
    expirationTime = 300
    wdt int 1 = 0
    +++++
    wdt int 2 = 1
    +++++
    +++++
    wdt int 3 = 2
    1252281 us
    
    cmd:>

    Thank you,
    Dazong

  • For the WDT we are testing it similar to a timer interrupt. Without wachdog_close(), seems I cannot really set the new "expirationTime". eg first time, test 1.25 sec, second time, test 500ms etc. From what I've tried, the wdt is only taking the first time passed in value, which is 1 sec in this case, as you can see from the log below. Will Ti be able to support this feature so we can test with different timeouts?

    Hello Dazong ,

    The observed behavior is expected and correct.

    Once the Watchdog Timer (WDT) is started on the AM62L device:
    • It cannot be stopped.
    • The timeout (expire) value cannot be modified during runtime.

    This behavior is by design and aligns with the WDT implementation on the AM62L architecture.

    Changing the WDT Timeout

    If you need to change the WDT timeout value, the only method is:
    1.Write the new timeout value to a persistent location (e.g., external flash).
    2. Reset the SoC.
    3. On boot, during WDT initialization, read the stored timeout value and configure the WDT accordingly.

    There are no alternative methods to dynamically change the WDT timeout once it is active.

    Recommended Debug Guide

    For further information, configuration help, and debugging tips related to the WDT on Sitara AM6x MPU devices (including AM62L), refer to the following guide:

    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1414222/faq-am6442-watchdog-debug-and-configuration-guide-for-all-sitara-am6x-mpu-devices

    Regards,

    Anil.

  • Thank you Anil,

    Dazong

  • Hello Dazong ,

    To set the WDT clock frequency to 32KHz, try this clock ID  and see if it works or not.

            status = SOC_moduleClockEnable(AM62LX_DEV_RTI0, 1);
            DebugP_assertNoLog(status == SystemP_SUCCESS);
    
            status = SOC_moduleSetClockFrequency(AM62LX_DEV_RTI0,AM62LX_DEV_RTI0_RTI_CLK_PARENT_CLK_32K_RC_SEL_OUT0,32552);
            DebugP_assertNoLog(status == SystemP_SUCCESS);

    Regards,

    Anil.

  • Hi Anil,

    I am trying to change the WDT from interrupt to warm reset. based on example code, anything else I need to do besides change the reset_mode to reset on?

    Watchdog_Params gWatchdogParams[CONFIG_WATCHDOG_NUM_INSTANCES] =
    {
        {
            .callbackFxn        = NULL,
            .callbackFxnArgs    = NULL,
            .resetMode          = Watchdog_RESET_ON,
            .debugStallMode     = Watchdog_DEBUG_STALL_ON,
            .windowSize         = Watchdog_WINDOW_100_PERCENT,
            .expirationTime     = 10000,
        },
    };

    By only changing the resetMode to RESET_ON in example code, I am seeing the interrupt is not triggered.

    Thank you,

    Dazong

  • Hello Dazong,

    In the condition check below, add support for the AM62L (SOC_AM62LX) and see if it works or not. 

    Regards,

    Anil.

  • Hi Anil,

    I don't have these lines in the example code I have. If you can check the zip file I attached last week in this ticket.

    Thank you,

    Dazong

  • Looking at watchdog_rti.c and watchdog_soc.c file, are these causing the problem?

    if (retVal >= 0)
            {
                /* Configure the Watchdog driver. */
                 
                /* Bring watchdog out of reset */
                //Watchdog_reset(handle);
                
                /* if NMI interrupt mode is configured */
                if (ptrWatchdogMCB->params.resetMode == Watchdog_RESET_OFF)
                {
                     /* Clear the status flags */
                    HW_WR_REG32(ptrHwCfg->baseAddr + CSL_RTI_RTIWDSTATUS, WATCHDOG_CLEAR_STATUS);
                }
                else
                {                
                    /* Reset is not supported on AM64x.*/
                    /* Configure the SOC moule to trigger a warm reset upon watchdog reset */
                    //Watchdog_configureWarmReset(handle);
                 
                }
            }

    void Watchdog_configureWarmReset(Watchdog_Handle handle)
    {
        return;
    }

  • Hello Dazong,

    In the call today, we can discuss this issue.

    Regards,

    Anil. 

  • Hello Dazong,

    I have looked at the TRM and feel that WDT supports the AUO RESET the SOC after the WDT has expired.

    Please do one Testing and configure.resetMode = Watchdog_RESET_ON and comment on the line below

    Watchdog_clear(gWatchdogHandle[CONFIG_WDT0]) function and see if this works or not. 

    You have configured the expiration time is 10sec . So you need to select the 32KHZ mux selection.

    Please let me know the test results.

    Regards,
    Anil.
  • Hi Anil,

    We were able to confirm the SOC reset after WDT expired based on your suggestion (setting configure.resetMode = Watchdog_RESET_ON).

    However, we noted the following observations and would like to get your feedback on them:

    1) We were unable to figure out the exact code that initiates the SOC reset after the WDT expired. My assumption is that SOC_generateSwWarmResetMainDomain(void) defined in soc.c is getting called somewhere, but the breakpoint I set in the function was never reached before SOC restart. So, it's unclear what initiates the reset after WDT expires.

    2) After SOC reset, we tried to get the reason/what triggers the reset using the SOC_getWarmResetCauseMainDomain(void) function defined in soc.c, The function always returns 0 irrespective of the cause of the SOC reset. 

    But directly reading the Reset Cause Register (WKUP_CTRL_MMR_CFG5_RST_SRC at 0x43054010UL) after WDT expired and SOC restarts, returns 16 (bit 4 set - i.e. reset caused by MPU Watchdog 0).

    My observation is that the SOC_getWarmResetCauseMainDomain(void) function is reading a wrong register (0x43004010UL) instead of 0x43054010UL considering the values of the argument below:

     

    3) We also tried to pass a callback function to wwdt_config but the callback function is never reached before WDT expires and SOC reset.

    What do you think?

    Thanks,

    Simeon

  • Hello Simeon,

    The AM62L Watchdog Timer (WDT) works in two modes.

     Interrupt Mode :

    The WDT generates an interrupt after WDT expires. To enable this mode, the setting

    configure.resetMode should be set to Watchdog_RESET_OFF.

    In this mode, a user-defined callback is triggered when the WDT expires.

    However, this mode is not recommended because if the core hangs or hits an exception, the core will prioritize the exception and the WDT interrupt will not be serviced. As a result, the SoC will not recover, and the WDT becomes ineffective in such fault conditions.

    Reset Mode :

    In this mode, the WDT expiration triggers a hardware reset of the SoC.

    No API call is required for reset — the reset happens automatically inside the SoC Reset architecture .

    To use this mode, set configure.resetMode to Watchdog_RESET_ON.

    In this mode, even if a callback is registered, it will not be called because the hardware reset occurs immediately after the WDT expiry.

    So defining a callback in this mode has no effect.

    Please look at the image below, the WDT event is directly connected to the SOC RESET HW.

    So, when the WDT expires, the SOC will do the reset automatically and don't need any SW involvement .

     WDT register access:

    The correct register address to check Reset reason status is 0x43054010. The current SDK was using the wrong MMR macro for this reset register.

    I will raise a bug for this so it can be fixed in a future release.

    As a temporary workaround, you can directly use the correct address in your code or modify the driver as below , then recompile the driver and application.

    This will give proper Reset reason status .


    uint32_t SOC_getWarmResetCauseMainDomain(void)
    {
        uint32_t     resetCause = 0U;
    
        /* Read the Reset Cause Register bits */
        resetCause = CSL_REG32_RD(CSL_WKUP_CTRL_MMR0_DEVICE_MANAGEMENT_BASE + CSL_WKUP_CTRL_MMR_CFG5_RST_SRC);
    
        return resetCause;
    }

    Regards,

    Anil.

  • Thanks for the clarification, Anil.

    So, how do we pet/refresh the WDT when using Watchdog_RESET_ON mode, to prevent it from expiring and triggering a MPU reset?

    - Simeon

  • Hello Simeon,

    For example, if you have configured the Watchdog Timer (WDT) expiration time to 1 sec.

    Now, you can configure a timer interrupt to trigger every 500 milliseconds (configure Highest Priority Interrupt )

    In this timer interrupt routine, you can call the Watchdog_clear( ) API. This will reset the WDT counter and start it freshly.

    In this setup example, we are “feeding” the WDT keys every 500 milliseconds, which is within 50% of the WDT expiration time.

    Feeding the WDT at regular intervals depends on your software system’s timing.

    It is a good safety margin to clear the WDT within half the expiration period, but this interval can be adjusted based on your system’s behavior.

    You should analyze the software execution path and identify which API or task takes the most time.

    Based on that, configure the WDT expiration time accordingly, and make sure the WDT is cleared well before it expires.

    Regards,

    Anil