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.

AM2634: AM2634 - WWDT de-initialization functions do nothing

Part Number: AM2634

When handling a fault (e.g. handling divide by 0 trap from within undefine_instruction_handler), we want to disable the watchdog for a specific core, write some persistent information, and reboot (either by warm reset or by re-enabling the watchdog and not petting)

However, this was not working, so we investigated the SDK source. Appears that the APIs for Watchdog_close, Watchdog_deinit literally do nothing. See image 1 below.image.png

Similarly, tried refactoring to this (implementing Watchdog_close in terms of Watchdog_open but with different parameters), but that also does not seem to stop the generation of warmresets.

void Watchdog_close(Watchdog_Handle handle) {
    Watchdog_Config* ptrWatchdogConfig;
    ptrWatchdogConfig            = (Watchdog_Config*)handle;
    Watchdog_MCB* ptrWatchdogMCB = (Watchdog_MCB*)ptrWatchdogConfig->object;

    if (ptrWatchdogConfig->object == NULL) {
        return;
    }

    const Watchdog_Params close_params = {
        .resetMode       = Watchdog_RESET_OFF,
        .debugStallMode  = Watchdog_DEBUG_STALL_OFF,
        .windowSize      = Watchdog_WINDOW_100_PERCENT,
        .expirationTime  = 1000,
        .callbackFxn     = NULL,
        .callbackFxnArgs = NULL,
    };

    Watchdog_open_handle(handle, &close_params);

    ptrWatchdogMCB->state = Watchdog_DriverState_UNINIT;
    return;
}

static int32_t Watchdog_open_handle(Watchdog_Handle handle, const Watchdog_Params* params) {    
    Watchdog_Config*  ptrWatchdogConfig;
    Watchdog_MCB*     ptrWatchdogMCB;
    Watchdog_HwAttrs* ptrHwCfg;
    int32_t           retVal = 0;
    uint32_t          preloadMaxValue;
    uint64_t          preloadValueTmp;
    /* Get the Watchdog Configuration: */
    ptrWatchdogConfig = (Watchdog_Config*)handle;

    /* Get the hardware configuration: */
    ptrHwCfg = (Watchdog_HwAttrs*)ptrWatchdogConfig->hwAttrs;

    /* Get the Watchdog Driver Object */
    ptrWatchdogMCB = (Watchdog_MCB*)ptrWatchdogConfig->object;

    /* Initialize the memory: */
    memset((void*)ptrWatchdogMCB, 0, sizeof(Watchdog_MCB));

    /* Store the WDT parameters */
    if (params == NULL) {
        /* No params passed in, so use the defaults */
        Watchdog_paramsInitDefaults(&(ptrWatchdogMCB->params));
    } else {
        /* Copy the params contents */
        ptrWatchdogMCB->params = *params;
    }

    /* Calculate preload value from the expiration time */
    /* Expiration time (in millisecond)/1000 = (preload value + 1)*(2^13)/RTICLK */
    preloadValueTmp =
        ((uint64_t)(ptrHwCfg->wdtClkFrequency)) * ((uint64_t)ptrWatchdogMCB->params.expirationTime) / 1000;
    /* Pre load is 12 bit value in register and actual value should be multiplied by 2^13) */
    preloadMaxValue = (1 << (12 + 13)) - 1;
    if (preloadValueTmp > preloadMaxValue) {
        retVal = SystemP_FAILURE;
    }

    if (retVal == SystemP_FAILURE) {
        return retVal;
    }

    /* 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 {
        /* Configure the SOC moule to trigger a warm reset upon watchdog reset */
        Watchdog_configureWarmReset(handle);
    }

    uint32_t preloadValue;
    uint32_t dwwdPreloadVal_l;
    /* CSL API needs shifted value but doesnot do -1 while programming.
     * So updating the preload value.
     */
    preloadValue = ((uint32_t)(preloadValueTmp) >> RTI_DWWDPRLD_MULTIPLIER_SHIFT) - 1;
    preloadValue = preloadValue << RTI_DWWDPRLD_MULTIPLIER_SHIFT;

    /* Clear the status flags */
    HW_WR_REG32(ptrHwCfg->baseAddr + CSL_RTI_RTIWDSTATUS, WATCHDOG_CLEAR_STATUS);

    /* Configure window in which watch-dog should be serviced */
    Watchdog_setWindowSize(handle, ptrWatchdogMCB->params.windowSize);

    /* Set the preload value */
    dwwdPreloadVal_l = (preloadValue >> ((uint32_t)RTI_DWWDPRLD_MULTIPLIER_SHIFT));
    if ((uint32_t)CSL_RTI_RTIDWDPRLD_DWDPRLD_MAX > dwwdPreloadVal_l) {
        /* Initialize DWD Expiration Period */
        HW_WR_FIELD32(ptrHwCfg->baseAddr + CSL_RTI_RTIDWDPRLD, CSL_RTI_RTIDWDPRLD_DWDPRLD, dwwdPreloadVal_l);
    }

    /* Configure the reset mode    */
    Watchdog_setReaction(handle, ptrWatchdogMCB->params.resetMode);

    /* Configure the stall mode */
    HW_WR_FIELD32(ptrHwCfg->baseAddr + CSL_RTI_RTIGCTRL, CSL_RTI_RTIGCTRL_COS, ptrWatchdogMCB->params.debugStallMode);

    /* Enable DWWD by writing pre-defined value '0xA98559DA' to RTIDWDCTRL */
    HW_WR_REG32(ptrHwCfg->baseAddr + CSL_RTI_RTIDWDCTRL, CSL_RTI_RTIDWDCTRL_DWDCTRL_ENABLE);

    /* Mark the driver to be operational */
    ptrWatchdogMCB->state = Watchdog_DriverState_OPERATIONAL;

    return retVal;
}

Watchdog_Handle Watchdog_open(uint8_t index, Watchdog_Params* params) {
    Watchdog_Handle handle = NULL;
    int32_t         status = SystemP_SUCCESS;

    /* Check index */
    if (index >= gWatchdogConfigNum) {
        status = SystemP_FAILURE;
    } else {
        handle = (Watchdog_Handle) & (gWatchdogConfig[index]);
    }

    if (status != SystemP_SUCCESS || handle == NULL) {
        return NULL;
    }

    status = Watchdog_open_handle(handle, params);
    if (status != SystemP_SUCCESS) {
        return NULL;
    }

    return handle;
}

 

3 Question:

  1. What are we doing wrong? What is the proper way to temporarily disable the WWDT? Clearly it is not the HAL/SDK since the APIs do nothing
  2. Why does the example code above not work?