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.
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:
- 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
- Why does the example code above not work?
