Other Parts Discussed in Thread: TIMAC, , CC2650
Tool/software: TI-RTOS
platform:2630
sdk: timac 1.5.2
issue:can't run to main() after watchdog timeout.
test code is as follow:
call stack while watchdog reset is as follow:
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.
The call stack you give above is should be long before ICall is even started. What do you mean it would not start properly with this ICall_wait, do you mean this gives you the same call stack as above? If so, how do you read this out without having the debugger connected?
Also, could you share some insight on how this "epdWatchdogStart" function works and what it does?
M-W,
1. When the debugger is not connected, CC2630 also can NOT reset successfully.
2. The function is copied from attached demo code.
3. From debugging, we do see if remove the ICALL_WAIT, the chip can successful reset.
#include <stdbool.h> #include <stdint.h> #include <stdlib.h> #include <xdc/std.h> #include <xdc/runtime/Error.h> #include <xdc/runtime/System.h> #include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Clock.h> #include <ti/sysbios/family/arm/m3/Hwi.h> #include <ti/sysbios/knl/Semaphore.h> #include <ti/sysbios/family/arm/cc26xx/Power.h> #include <ti/drivers/PIN.h> #include <string.h> #include <inc/hw_ints.h> #include "ICall.h" #include "Macs.h" #include "MacStackMSG.h" #include <aon_event.h> #include <ioc.h> #include "Board.h" #include "watchdogp.h" #include "epdwatchdog.h" extern uint32_t halTime2Ticks(uint32 ms); WatchdogCC26XX_Object watchdogCC26XXObjects[CC26X2R1_LAUNCHXL_WATCHDOGCOUNT]; const WatchdogCC26XX_HWAttrs watchdogCC26XXHWAttrs[CC26X2R1_LAUNCHXL_WATCHDOGCOUNT] = { { .baseAddr = WDT_BASE, .reloadValue = WDT_TIMEOUT_MS /* Reload value in milliseconds */ }, }; const Watchdog_Config Watchdog_config[CC26X2R1_LAUNCHXL_WATCHDOGCOUNT] = { { .fxnTablePtr = &WatchdogCC26XX_fxnTable, .object = &watchdogCC26XXObjects[CC26X2R1_LAUNCHXL_WATCHDOG0], .hwAttrs = &watchdogCC26XXHWAttrs[CC26X2R1_LAUNCHXL_WATCHDOG0] }, }; const uint_least8_t Watchdog_count = CC26X2R1_LAUNCHXL_WATCHDOGCOUNT; /* Default Watchdog parameters structure */ const Watchdog_Params Watchdog_defaultParams = { NULL, /* callbackFxn */ Watchdog_RESET_ON, /* resetMode */ Watchdog_DEBUG_STALL_ON, /* debugStallMode */ NULL /* custom */ }; static bool isInitialized = false; /* * ======== Watchdog_clear ======== */ void Watchdog_clear(Watchdog_Handle handle) { handle->fxnTablePtr->watchdogClear(handle); } /* * ======== Watchdog_close ======== */ void Watchdog_close(Watchdog_Handle handle) { handle->fxnTablePtr->watchdogClose(handle); } /* * ======== Watchdog_control ======== */ int_fast16_t Watchdog_control(Watchdog_Handle handle, uint_fast16_t cmd, void *arg) { return (handle->fxnTablePtr->watchdogControl(handle, cmd, arg)); } /* * ======== Watchdog_init ======== */ void Watchdog_init(void) { uint_least8_t i; uint_fast32_t key; key = Hwi_disable(); if (!isInitialized) { isInitialized = (bool) true; /* Call each driver's init function */ for (i = 0; i < Watchdog_count; i++) { Watchdog_config[i].fxnTablePtr->watchdogInit((Watchdog_Handle)&(Watchdog_config[i])); } } Hwi_restore(key); } /* * ======== Watchdog_open ======== */ Watchdog_Handle Watchdog_open(uint_least8_t index, Watchdog_Params *params) { Watchdog_Handle handle = NULL; /* Verify driver index and state */ if (isInitialized && (index < Watchdog_count)) { /* If params are NULL use defaults */ if (params == NULL) { params = (Watchdog_Params *) &Watchdog_defaultParams; } handle = (Watchdog_Handle)&(Watchdog_config[index]); handle = handle->fxnTablePtr->watchdogOpen(handle, params); } return (handle); } /* * ======== Watchdog_Params_init ======== */ void Watchdog_Params_init(Watchdog_Params *params) { *params = Watchdog_defaultParams; } /* * ======== Watchdog_setReload ======== */ int_fast16_t Watchdog_setReload(Watchdog_Handle handle, uint32_t ticks) { return (handle->fxnTablePtr->watchdogSetReload(handle, ticks)); } /* * ======== Watchdog_convertMsToTicks ======== */ uint32_t Watchdog_convertMsToTicks(Watchdog_Handle handle, uint32_t milliseconds) { return (handle->fxnTablePtr->watchdogConvertMsToTicks(handle, milliseconds)); } /* Watchdog function table for CC26XX implementation */ const Watchdog_FxnTable WatchdogCC26XX_fxnTable = { WatchdogCC26XX_clear, WatchdogCC26XX_close, WatchdogCC26XX_control, WatchdogCC26XX_init, WatchdogCC26XX_open, WatchdogCC26XX_setReload, WatchdogCC26XX_convertMsToTicks }; /* Maximum allowable setReload value */ #define MAX_RELOAD_VALUE 0xFFFFFFFF #define WATCHDOG_DIV_RATIO 32 /* Watchdog division ratio */ #define MS_RATIO 1000 /* millisecond to second ratio */ /* * ======== WatchdogCC26XX_clear ======== */ void WatchdogCC26XX_clear(Watchdog_Handle handle) { WatchdogIntClear(); } /* * ======== WatchdogCC26XX_close ======== */ void WatchdogCC26XX_close(Watchdog_Handle handle) { /* * Not supported for CC26XX - Once the INTEN bit of the WDTCTL * register has been set, it can only be cleared by a hardware * reset. */ // DebugP_assert(false); } /* * ======== WatchdogCC26XX_control ======== * @pre Function assumes that the handle is not NULL */ int_fast16_t WatchdogCC26XX_control(Watchdog_Handle handle, uint_fast16_t cmd, void *arg) { /* No implementation yet */ return (Watchdog_STATUS_UNDEFINEDCMD); } /* * ======== Watchdog_init ======== */ void WatchdogCC26XX_init(Watchdog_Handle handle) { WatchdogCC26XX_Object *object = handle->object; object->isOpen = false; } /* * ======== WatchdogCC26XX_open ======== */ Watchdog_Handle WatchdogCC26XX_open(Watchdog_Handle handle, Watchdog_Params *params) { unsigned int key; // HwiP_Params hwiParams; WatchdogCC26XX_Object *object; /* get the pointer to the object and hwAttrs */ object = handle->object; /* disable preemption while checking if the WatchDog is open. */ key = Hwi_disable(); /* Check if the Watchdog is open already with the HWAttrs */ if (object->isOpen == true) { Hwi_restore(key); // DebugP_log1("Watchdog: Handle %x already in use.", (uintptr_t)handle); return (NULL); } object->isOpen = true; Hwi_restore(key); /* initialize the Watchdog object */ object->debugStallMode = params->debugStallMode; object->resetMode = params->resetMode; /* Construct Hwi object for Watchdog */ /* HwiP_Params_init(&hwiParams); hwiParams.arg = (uintptr_t)handle; */ /* setup callback function if defined */ if (params->callbackFxn != NULL) { Hwi_plug(INT_NMI_FAULT, (void *)params->callbackFxn); } /* initialize the watchdog hardware */ WatchdogCC26XX_initHw(handle); // DebugP_log1("Watchdog: handle %x opened" ,(uintptr_t)handle); /* return handle of the Watchdog object */ return (handle); } /* * ======== WatchdogCC26XX_setReload ======== */ int_fast16_t WatchdogCC26XX_setReload(Watchdog_Handle handle, uint32_t ticks) { unsigned int key; /* disable preemption while unlocking WatchDog registers */ key = Hwi_disable(); /* unlock the Watchdog configuration registers */ WatchdogUnlock(); /* make sure the Watchdog is unlocked before continuing */ while(WatchdogLockState() == WATCHDOG_LOCK_LOCKED) { } /* update the reload value */ WatchdogReloadSet(ticks); /* lock register access */ WatchdogLock(); Hwi_restore(key); // DebugP_log2("Watchdog: WDT with handle 0x%x has been set to " // "reload to 0x%x", (uintptr_t)handle, ticks); return (Watchdog_STATUS_SUCCESS); } /* * ======== WatchdogCC26XX_hwInit ======== * This function initializes the Watchdog hardware module. * * @pre Function assumes that the Watchdog handle is pointing to a hardware * module which has already been opened. */ void WatchdogCC26XX_initHw(Watchdog_Handle handle) { unsigned int key; uint32_t tickValue; WatchdogCC26XX_Object *object; WatchdogCC26XX_HWAttrs const *hwAttrs; /* get the pointer to the object and hwAttrs */ object = handle->object; hwAttrs = handle->hwAttrs; /* convert milliseconds to watchdog timer ticks */ tickValue = WatchdogCC26XX_convertMsToTicks(handle, hwAttrs->reloadValue); /* disable preemption while unlocking WatchDog registers */ key = Hwi_disable(); /* unlock the Watchdog configuration registers */ WatchdogUnlock(); /* make sure the Watchdog is unlocked before continuing */ while(WatchdogLockState() == WATCHDOG_LOCK_LOCKED) { } WatchdogReloadSet(tickValue); /* set reset mode */ if (object->resetMode == Watchdog_RESET_ON) { WatchdogResetEnable(); } else { WatchdogResetDisable(); } /* set debug stall mode */ if (object->debugStallMode == Watchdog_DEBUG_STALL_ON) { WatchdogStallEnable(); } else { WatchdogStallDisable(); } /* enable the Watchdog interrupt as a non-maskable interrupt */ WatchdogIntTypeSet(WATCHDOG_INT_TYPE_NMI); /* enable the Watchdog */ WatchdogEnable(); /* lock the Watchdog configuration registers */ WatchdogLock(); Hwi_restore(key); } /* * ======== WatchdogCC26XX_convertMsToTicks ======== * This function converts the input value from milliseconds to * Watchdog clock ticks. */ uint32_t WatchdogCC26XX_convertMsToTicks(Watchdog_Handle handle, uint32_t milliseconds) { uint32_t wdtTicks; wdtTicks = milliseconds*8; // wdtTicks = milliseconds; wdtTicks = halTime2Ticks(wdtTicks); return wdtTicks; } Watchdog_Handle watchdogHd = NULL; void epdWatchdogClear(void) { if(watchdogHd) { Watchdog_clear(watchdogHd); } } void epdWatchdogStart(void) { Watchdog_Params params; uint32_t timeout; Watchdog_init(); Watchdog_Params_init(¶ms); params.resetMode = Watchdog_RESET_ON; watchdogHd = Watchdog_open(0, ¶ms); if(NULL != watchdogHd) { timeout = WatchdogCC26XX_convertMsToTicks(watchdogHd, WDT_TIMEOUT_MS); Watchdog_setReload(watchdogHd, timeout); } }
No matter Run this device with the debugger attach. Properly start after watchdog timeout without I call wait. It would not start properly with I call wait.
Hi Morris,
I tested your code by taking the untouched stack example (<TIMAC SDK>/Projects/mac/Sample/cc26xx_RTOS/IAR Projects/Application/CC2650) and adding in your changes instead of calling the "msa_task()" which was originally done. I also added in turning on a LED right after enabling the watchdog to see if we are able to reset as intended (in theory it should blink if we get proper resets from the watchdog).
This resulted in the following task function:
Void taskFxn(UArg a0, UArg a1) { #if defined( USE_FPGA ) SysCtrlPowerEverything(); Power_setConstraint(Power_SB_DISALLOW); Power_setDependency(PERIPH_RFCORE, Power_GLOBAL); #endif /* Disallow shutting down JTAG, VIMS, SYSBUS during idle state * since TIMAC requires SYSBUS during idle. */ Power_setConstraint(Power_IDLE_PD_DISALLOW); /* Initialize ICall module */ ICall_init(); // #ifdef FEATURE_MAC_SECURITY CryptoCC26XX_Params CryptoCC26XXParams; extern CryptoCC26XX_Handle CryptoCC26XXHandle; CryptoCC26XX_init(); CryptoCC26XX_Params_init(&CryptoCC26XXParams); CryptoCC26XXHandle = CryptoCC26XX_open(Board_CRYPTO, false, &CryptoCC26XXParams); if (!CryptoCC26XXHandle) { Task_exit(); } Crypto_init(); /* * Copy the extended address from the CCFG area * Assumption: the memory in CCFG_IEEE_MAC_0 and CCFG_IEEE_MAC_1 * is contiguous and LSB first. */ memcpy(msa_ExtAddr, (uint8_t *)&(__ccfg.CCFG_IEEE_MAC_0), EXTADDR_LEN); /* Check to see if the CCFG IEEE is valid */ if(memcmp(msa_ExtAddr, dummyExtAddr, EXTADDR_LEN) == 0) { /* No, it isn't valid. Get the Primary IEEE Address */ memcpy(msa_ExtAddr, (uint8_t *)(FCFG1_BASE + EXTADDR_OFFSET), EXTADDR_LEN); } #endif // #ifdef NV_RESTORE /* Setup the NV driver */ NVOCTP_loadApiPtrs( &user1Cfg.nvFps ); if ( user1Cfg.nvFps.initNV ) { user1Cfg.nvFps.initNV( NULL ); } pfnMacCfgNvFps = &user1Cfg.nvFps; #endif // /* Start tasks of external images */ ICall_createRemoteTasks(); /* Kick off application */ PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH); PRCMPeripheralRunEnable(PRCM_PERIPH_GPIO); PRCMLoadSet(); while (!PRCMLoadGet()) { ; } Task_sleep(100000); epdWatchdogStart(); IOCPinTypeGpioOutput(IOID_6); while(1) { GPIOPinWrite(GPIO_PIN_6, 1); ICall_wait(ICALL_TIMEOUT_FOREVER); } }
I tested this out on a CC2650 launchpad and I did not see the problem you describe as the device was able to reset as expected. I assume you are seeing this problem on your own custom hardware, could you in this case reproduce it on a launchpad?
I had some problems to run it using your main file, this was related to "FEATURE_MAC_SECURITY" being defined in both the application and stack project, removing this define let me run the test. As you are not initializing the crypto in the example you provided, have you disabled this feature in both projects?
Hi M-W,
You tell me that you tested on a CC2650 and did not see the problem.
We tested on a CC2650 and did not see the problem we describe. The result is the same with you!
Only see the problem when we test on a CC2630. Would you please test on a CC2630?
Thanks,
Morris.Yang
Hi Morris,
There should be no difference between the CC2630 and CC2650, the later is the development platform for the former. The code should be binary compatible between the two devices when going from CC2630 -> CC2650.
In your test I assume the difference is that the CC2650 is a development platform and the CC2630 sits on custom hardware, is that correct?