PROCESSOR-SDK-AM62X: M4 Watchdog

Part Number: PROCESSOR-SDK-AM62X

Tool/software:

Due to other priorities, I was unable to follow up on information provided by Anil in the thread (now locked):
https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1483103/processor-sdk-am62x-m4-watchdog

I have done so now.

My objective is to cause a reset when the M4 watchdog expires.  I have followed the information in that thread and have the watchdog expiring when I fail to use Watchdog_clear() to reset the watchdog down counter.  The problem is that the processor isn't resetting.

I have periodically dumped registers:

WDSTATUS 0
DWDCNTR 16d601
MCU_CTRL_MMR_CFG0_RST_CTRL 400fff
-----------------------------------
WDSTATUS 0
DWDCNTR 11e4e9
MCU_CTRL_MMR_CFG0_RST_CTRL 400fff
-----------------------------------
WDSTATUS 0
DWDCNTR cf357
MCU_CTRL_MMR_CFG0_RST_CTRL 400fff
-----------------------------------
WDSTATUS 0
DWDCNTR 8021d
MCU_CTRL_MMR_CFG0_RST_CTRL 400fff
-----------------------------------
WDSTATUS 0
DWDCNTR 31115
MCU_CTRL_MMR_CFG0_RST_CTRL 400fff
-----------------------------------
WDSTATUS 32
DWDCNTR 1fe2056
MCU_CTRL_MMR_CFG0_RST_CTRL 400fff


This shows the down counter decrementing and then wrapped around.  In the last capture, the status register shows that the watchdog has expired.

The dump also shows that the RST_CTRL_MCU_ESM_ERROR_RST_EN_Z bit (bit 17) of the register MCU_CTRL_MMR0 is clear, which means that the Reset of MCU by ESM is activated.

From TRM section 6.3.5.6 MCU ESM_ERRORz Reset, I gather that the ESM error is the correct bit to set in MCU_CTRL_MMR0.  That section says that the ESM Error Reset is issued when a MCU WDT timeout occurs.

What am I missing?  What else can prevent an MCU watchdog expiry from resetting the processor?

Thanks,
    Steve

  • I added the printing of the MCU_MMR0_RST_STAT register.  It starts off as 1 (Reset deasserted) and remains 1 even as WDSTATUS indicates a watchdog timeout.

  • Hello Steve,

    I am looking at your queries and you may expect reply in one or two days .

    Regards,

    Anil.

  • Hello Steve,

    Can you please confirm did you integrate the ESM module into your application to reset the SOC ?

    I feel that the ESM integration is not done in your application.

    If you follow the FAQ below then all steps are available.

    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1283237/faq-am64x-am62x-how-to-reset-the-soc-when-wdt-timer-expires-in-am64x-and-am62x

    Regards,

    Anil.

  • Hi Anil.

    I am initializing the ESM:


    SDL_DPL_init(&dpl_interface);
    SDL_ESM_init(SDL_ESM_INST_WKUP_ESM0, &esmInitConfig, SDL_ESM_callback, &apparg);


    I have confirmed that both routines are returning SDL_PASS.  dpl_interface is the same as in examples/sdl/dpl/dpl_interface.c.

    I do wonder about the config that is passed to SDL_ESM_init().  In the UC1 sample code (both in the MCU+ SDK and the zip file attached to the FAQ), it has:

    SDL_ESM_config RTI_Test_esmInitConfig_wkup =
    {
    .esmErrorConfig = {0u, 3u}, /* Self test error config */
    .enableBitmap = {0xffffffffu, 0xff0fffffu, 0x7fffffffu, 0x00000007u,
    },
    /**< All events enable: except timer and self test events, and Main ESM output */
    /* Temporarily disabling vim compare error as well*/
    .priorityBitmap = {0xffffffffu, 0xff0fffffu, 0x7fffffffu, 0x00000007u,
    },
    /**< All events high priority: except timer, selftest error events, and Main ESM output */
    .errorpinBitmap = {0xffffffffu, 0xff0fffffu, 0x7fffffffu, 0x00000007u,
    },
    /**< All events high priority: except timer, selftest error events, and Main ESM output */
    };


    For each of the bitmaps, this is setting 3x32 + 3 = 99 bits.  However, Table 10-3 in the TRM has only 91 interrupts.  Also, the comments about the bits (vim compare, self test, etc), don't seem to match entries in that table.  So I am not understanding the chosen bit values.

    I'm really only interested in a reset when the watchdog timer (ID 85) expires, so I tried setting the bit fields to:

    .enableBitmap = {0x0u, 0x0u, 0x00200000u, },

    However, this made no difference in terms of getting the device to reset when a watchdog expiry occurred.

    In order to help determine that the ESM was initialized, I added the call:

    SDL_ESM_getStaticRegisters(SDL_ESM_INST_WKUP_ESM0, &staticRegs);

    It too returns SDL_PASS and I see the following register values:

    PID = 0x6fe04900
    INFO = 0x80000103
    EN = 0xf
    ERR_EN_SET = 0x7
    ERR_EN_CLR = 0x7
    LOW_PRI = 0xffffffff
     HI_PRI = 0xffffffff
     LOW = 0x0
    HI = 0x0
    PIN_CTRL = 0x0
    PIN_CNTR_PRE = 0x30d40
    PWMH_PIN_CNTR_PRE = 0x186a0
    PWML_PIN_CNTR_PRE = 0x186a0

    I'm not seeing anything obviously wrong in those.

    Regards,
        Steve

  • Hello Steve,

    Use the config below to route WDT events to the MCU ESM module and, by default, I have enabled to route MAIN ESM events to WKUP ESM.

    If you don't monitor these MAIN ESM events from the MCU core, then in the below config where ever 0x7 value is replaced with a 0x00 value.

    SDL_ESM_config RTI_Test_esmInitConfig_wkup =
    {
        .esmErrorConfig = {0u, 3u}, /* Self test error config */
        .enableBitmap = {0x00000007u, 0x00000000u, 0x00200000u, 0x00000000u,
                    },
         /**< All events enable: except timer and self test  events, and Main ESM output */
        /* Temporarily disabling vim compare error as well*/
        .priorityBitmap = {0x00000007u, 0x00000000u, 0x00200000u, 0x00000000u,
                            },
        /**< All events high priority: except timer, selftest error events, and Main ESM output */
        .errorpinBitmap = {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                          },
        /**< All events high priority: except timer, selftest error events, and Main ESM output */
    };
    

    Next, we need to configure the MMR register to make the SOC Reset after the Watchdog expires, as described below.

         /* Unlock CONTROL MMR registers */
         SOC_controlModuleUnlockMMR(SOC_DOMAIN_ID_WKUP, rstPartition);
    
    
         ctrl_addr = (volatile uint32_t *)(0x43018170);
    
         *ctrl_addr &= (~(1<<17));
    
    
         /* Lock CONTROL MMR registers */
         SOC_controlModuleLockMMR(SOC_DOMAIN_ID_WKUP, rstPartition);

    Please try the above steps and let me know if you face any issues ...

    Regards,

    Anil.

  • Hi Anil.

    I am doing that, but in a FreeRTOS environment.

    SOC_controlModuleUnlockMMR(SOC_DOMAIN_ID_WKUP, rstPartition);

    Baseaddress = (uint32_t) AddrTranslateP_getLocalAddr(CSL_WKUP_CTRL_MMR0_CFG0_BASE);

    reg = HW_RD_REG32(Baseaddress + CSL_WKUP_CTRL_MMR_CFG0_RST_CTRL);
    DebugP_log("CSL_WKUP_CTRL_MMR_CFG0_RST_CTRL was %x\n\r", reg);

    CSL_REG32_FINS(Baseaddress + CSL_WKUP_CTRL_MMR_CFG0_RST_CTRL, WKUP_CTRL_MMR_CFG0_RST_CTRL_MAIN_ESM_ERROR_RST_EN_Z, 0);

    reg = HW_RD_REG32(Baseaddress + CSL_WKUP_CTRL_MMR_CFG0_RST_CTRL);
    DebugP_log("CSL_WKUP_CTRL_MMR_CFG0_RST_CTRL at %x now %x\n\r", Baseaddress + CSL_WKUP_CTRL_MMR_CFG0_RST_CTRL, reg);

    SOC_controlModuleLockMMR(SOC_DOMAIN_ID_WKUP, rstPartition);

    This shows:

    CSL_WKUP_CTRL_MMR_CFG0_RST_CTRL was 200ff
    CSL_WKUP_CTRL_MMR_CFG0_RST_CTRL at c3018170 now ff

    Then I:

    SDL_ESM_config esmInitConfig =
    {
    .esmErrorConfig = {0u, 3u}, /* Self test error config */
    .enableBitmap = {0x00000007u, 0x00000000u, 0x00200000u, 0x00000000u,
    },
    /**< All events enable: except timer and self test events, and Main ESM output */
    /* Temporarily disabling vim compare error as well*/
    .priorityBitmap = {0x00000007u, 0x00000000u, 0x00200000u, 0x00000000u,
    },
    /**< All events high priority: except timer, selftest error events, and Main ESM output */
    .errorpinBitmap = {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
    },
    /**< All events high priority: except timer, selftest error events, and Main ESM output */
    };
    /* Need to call this before any SDL functions */
    sdlret = SDL_DPL_init(&dpl_interface);
    if (sdlret != SDL_PASS)
    {
    DebugP_logError("SDL_DPL_Init failed\n\r");
    }

    /* Initialize WKUP ESM module */
    status = SDL_ESM_init(SDL_ESM_INST_WKUP_ESM0, &esmInitConfig,
    SDL_ESM_callback, &apparg);
    if (status != SDL_PASS)
    {
    DebugP_logError("SDL_ESM_Init failed\n\r");
    }

    No failures are reported.
    The esmInitConfig shown here is the one you indicated just above.  As I noted earlier, I've tried different configuration without a difference in operation.

    I am also able to retrieve the ESM registers to help demonstrate that the ESM is initialized:

    status = SDL_ESM_getStaticRegisters(SDL_ESM_INST_WKUP_ESM0, &staticRegs);
    if (status != SDL_PASS) {
    DebugP_logError("SDL_ESM_getStaticRegisters failed\n\r");
    }

    After that:

    for(instCnt = 0U; instCnt < CONFIG_WATCHDOG_NUM_INSTANCES; instCnt++)
    {
    gWatchdogHandle[instCnt] = NULL;
    }

    /* Open all instances */
    for(instCnt = 0U; instCnt < CONFIG_WATCHDOG_NUM_INSTANCES; instCnt++)
    {
    gWatchdogParams[instCnt].expirationTime = timeout_ms;
    gWatchdogHandle[instCnt] = Watchdog_open(instCnt, &gWatchdogParams[instCnt]);
    if(NULL == gWatchdogHandle[instCnt])
    {
    DebugP_logError("Watchdog open failed for instance %d !!!\r\n", instCnt);
    status = SystemP_FAILURE;
    break;
    }

    /*
    * When first enabled, the watchdog counts down from the default
    * preload value. In order to get it to start over from the count that
    * corresponds to the above timeout_ms (setup by Watchdog_open()), we
    * need to call Watchdog_clear().
    */
    Watchdog_clear(gWatchdogHandle[instCnt]);
    }

    if(SystemP_FAILURE == status)
    {
    Watchdog_driversClose(); /* Exit gracefully */
    }

    At this point, I expect the watchdog to expire and reset the device.  While I see it expire, there is no reset:

    ===========================================
    RTI_RTIDWDCTRL a98559da
    RTI_RTIINTFLAG 0
    RTI_RTIDWDCTRL a98559da
    RTI_RTIDWDPRLD 12
    RTI_RTIWDSTATUS 0
    RTI_RTIDWDCNTR 25ffb
    RTI_RTIWWDRXNCTRL 5
    ===========================================
    RTI_RTIDWDCTRL a98559da
    RTI_RTIINTFLAG 0
    RTI_RTIDWDCTRL a98559da
    RTI_RTIDWDPRLD 12
    RTI_RTIWDSTATUS 0
    RTI_RTIDWDCNTR 1e1fa
    RTI_RTIWWDRXNCTRL 5
    Doing Watchdog_clear()
    ===========================================
    RTI_RTIDWDCTRL a98559da
    RTI_RTIINTFLAG 0
    RTI_RTIDWDCTRL a98559da
    RTI_RTIDWDPRLD 12
    RTI_RTIWDSTATUS 0
    RTI_RTIDWDCNTR 163c8
    RTI_RTIWWDRXNCTRL 5
    ===========================================
    RTI_RTIDWDCTRL a98559da
    RTI_RTIINTFLAG 0
    RTI_RTIDWDCTRL a98559da
    RTI_RTIDWDPRLD 12
    RTI_RTIWDSTATUS 0
    RTI_RTIDWDCNTR e591
    RTI_RTIWWDRXNCTRL 5
    ===========================================
    RTI_RTIDWDCTRL a98559da
    RTI_RTIINTFLAG 0
    RTI_RTIDWDCTRL a98559da
    RTI_RTIDWDPRLD 12
    RTI_RTIWDSTATUS 0
    RTI_RTIDWDCNTR 6756
    RTI_RTIWWDRXNCTRL 5
    ===========================================
    RTI_RTIDWDCTRL a98559da
    RTI_RTIINTFLAG 0
    RTI_RTIDWDCTRL a98559da
    RTI_RTIDWDPRLD 12
    RTI_RTIWDSTATUS 32
    RTI_RTIDWDCNTR 1ffe930
    RTI_RTIWWDRXNCTRL 5

    Regards,
        Steve

  • Hello Steve,

    When you call the watchdog_clear API, the WDT counter starts freshly, and again you need to wait for the same expiry time.

    After calling the watchdog_driver_open and waiting for the expiry time, then only the WDT reset should happen. 

    I feel that there is a problem with the WDT code in your setup.

    Can you please share your example project ?

    Regards,

    Anil.

  • When you call the watchdog_clear API, the WDT counter starts freshly, and again you need to wait for the same expiry time.

    After calling the watchdog_driver_open and waiting for the expiry time, then only the WDT reset should happen. 

    The register dumps are several seconds apart.  You can see the watchdog expiry eventually as the RTI_RTIWDSTATUS register goes from 0 to 32.

    I can't share project but will create a simple one that only implements the watchdog.

    Regards,
         Steve

  • Can you please share your example project ?

    I've created a simple version based on the hello_world example.  It includes watchdog_rti.c and watchdog_soc.c which are in the MCU+ SDK but not included in the M4 library binary.  I am building them with my application so that I can use an unmodified SDK.

    Regards,
        Steve

    watchdog.tar

  • Hello Steve,

    Code wise, everything is fine except the change below.

        /* Reset Src belongs to partition 6 of the CTRL MMR */
        uint32_t     rstPartition = 6U, baseAddr;
        
        /* Unlock CONTROL MMR registers */
        SOC_controlModuleUnlockMMR(SOC_DOMAIN_ID_MCU, rstPartition);
    
        baseAddr = (uint32_t) AddrTranslateP_getLocalAddr(CSL_MCU_CTRL_MMR0_CFG0_BASE);
    
    
        CSL_REG32_FINS(baseAddr + CSL_MCU_CTRL_MMR_CFG0_RST_CTRL,
                       CSL_MCU_CTRL_MMR_CFG0_RST_CTRL_MCU_ESM_ERROR_RST_EN_Z_MASK, 0);
    
                   
        SOC_controlModuleUnlockMMR(SOC_DOMAIN_ID_MCU, rstPartition);
    

    We need to be control the MCU MMR register to make the SOC Reset from the MCU ESM Module.

    Can you please add the above change in your setup  and see if it works or not ?

    If the suggestion above does not work out, I can reproduce the issue at my side.

    Please share test results.

    Regards,

    Anil.

  • Hi Ani.

    We need to be control the MCU MMR register to make the SOC Reset from the MCU ESM Module.

    That's different than what's done in the example code which sets the WKUP RST_CTRL register (address 43018170) rather than the MCU RST_CTRL register (address 04518170):

    ctrl_addr = (volatile uint32_t *)(0x43018170);

    *ctrl_addr &= (~(1<<17));


    I added code to also set the MCU RST_CTRL register, but found that the RST_CTRL_MCU_ESM_ERROR_RST_EN_Z bit was already clear.

    Baseaddress = (uint32_t) AddrTranslateP_getLocalAddr(CSL_MCU_CTRL_MMR0_CFG0_BASE);
    DebugP_log("Translated address %x\n\r", CSL_MCU_CTRL_MMR0_CFG0_BASE);

    reg = HW_RD_REG32(Baseaddress + CSL_MCU_CTRL_MMR_CFG0_RST_CTRL);
    DebugP_log("CSL_MCU_CTRL_MMR_CFG0_RST_CTRL was %x\n\r", reg);
    CSL_REG32_FINS(Baseaddress + CSL_MCU_CTRL_MMR_CFG0_RST_CTRL,
    MCU_CTRL_MMR_CFG0_RST_CTRL_MCU_ESM_ERROR_RST_EN_Z, 0);

    reg = HW_RD_REG32(Baseaddress + CSL_MCU_CTRL_MMR_CFG0_RST_CTRL);
    DebugP_log("CSL_MCU_CTRL_MMR_CFG0_RST_CTRL at %x now %x\n\r",
    Baseaddress + CSL_MCU_CTRL_MMR_CFG0_RST_CTRL, reg);

    This produces:

    Translated address 4500000
    CSL_MCU_CTRL_MMR_CFG0_RST_CTRL was 400fff
    CSL_MCU_CTRL_MMR_CFG0_RST_CTRL at 84518170 now 400fff
    Translated address 43000000
    CSL_WKUP_CTRL_MMR_CFG0_RST_CTRL was 200ff
    CSL_WKUP_CTRL_MMR_CFG0_RST_CTRL at c3018170 now ff

    Regards,
        Steve

  • Hello Steve,

    I can reproduce the issue at my side and will update the status by Friday this week.

    Regards,

    Anil.