hal_ti/simplelink/source/ti/drivers/power/PowerCC26XX.c

1395 lines
46 KiB
C

/*
* Copyright (c) 2015-2018, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* ======== PowerCC26XX.c ========
*/
#include <stdbool.h>
#include <ti/drivers/dpl/ClockP.h>
#include <ti/drivers/dpl/DebugP.h>
#include <ti/drivers/dpl/HwiP.h>
#include <ti/drivers/dpl/SwiP.h>
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC26XX.h>
#include <ti/devices/DeviceFamily.h>
#include DeviceFamily_constructPath(inc/hw_types.h)
#include DeviceFamily_constructPath(inc/hw_prcm.h)
#include DeviceFamily_constructPath(inc/hw_nvic.h)
#include DeviceFamily_constructPath(inc/hw_aon_wuc.h)
#include DeviceFamily_constructPath(inc/hw_aon_rtc.h)
#include DeviceFamily_constructPath(inc/hw_memmap.h)
#include DeviceFamily_constructPath(inc/hw_ccfg.h)
#include DeviceFamily_constructPath(inc/hw_rfc_pwr.h)
#include DeviceFamily_constructPath(driverlib/sys_ctrl.h)
#include DeviceFamily_constructPath(driverlib/pwr_ctrl.h)
#include DeviceFamily_constructPath(driverlib/prcm.h)
#include DeviceFamily_constructPath(driverlib/aon_wuc.h)
#include DeviceFamily_constructPath(driverlib/aon_ioc.h)
#include DeviceFamily_constructPath(driverlib/aon_rtc.h)
#include DeviceFamily_constructPath(driverlib/aon_event.h)
#include DeviceFamily_constructPath(driverlib/aux_wuc.h)
#include DeviceFamily_constructPath(driverlib/osc.h)
#include DeviceFamily_constructPath(driverlib/cpu.h)
#include DeviceFamily_constructPath(driverlib/vims.h)
#include DeviceFamily_constructPath(driverlib/rfc.h)
#include DeviceFamily_constructPath(driverlib/sys_ctrl.h)
#include DeviceFamily_constructPath(driverlib/driverlib_release.h)
#include DeviceFamily_constructPath(driverlib/setup.h)
#include DeviceFamily_constructPath(driverlib/ccfgread.h)
static unsigned int configureXOSCHF(unsigned int action);
static unsigned int nopResourceHandler(unsigned int action);
static unsigned int configureRFCoreClocks(unsigned int action);
static void switchXOSCHFclockFunc(uintptr_t arg0);
static void lfClockReadyCallback(uintptr_t arg);
static void disableLfClkQualifiersEnableClkLoss();
static void emptyClockFunc(uintptr_t arg);
static int_fast16_t notify(uint_fast16_t eventType);
/* RCOSC calibration functions functions */
extern void PowerCC26XX_doCalibrate(void);
extern bool PowerCC26XX_initiateCalibration(void);
extern void PowerCC26XX_auxISR(uintptr_t arg);
extern void PowerCC26XX_RCOSC_clockFunc(uintptr_t arg);
/* Externs */
extern const PowerCC26XX_Config PowerCC26XX_config;
/* Module_State */
PowerCC26XX_ModuleState PowerCC26XX_module = {
.notifyList = { NULL }, /* list of registered notifications */
.constraintMask = 0, /* the constraint mask */
.clockObj = { 0 }, /* Clock object for scheduling wakeups */
.xoscClockObj = { 0 }, /* Clock object for XOSC_HF switching */
.lfClockObj = { 0 }, /* Clock object for LF clock check */
.calClockStruct = { 0 }, /* Clock object for RCOSC calibration */
.hwiStruct = { 0 }, /* hwi object for calibration */
.nDeltaFreqCurr = 0, /* RCOSC calibration variable */
.nCtrimCurr = 0, /* RCOSC calibration variable */
.nCtrimFractCurr = 0, /* RCOSC calibration variable */
.nCtrimNew = 0, /* RCOSC calibration variable */
.nCtrimFractNew = 0, /* RCOSC calibration variable */
.nRtrimNew = 0, /* RCOSC calibration variable */
.nRtrimCurr = 0, /* RCOSC calibration variable */
.nDeltaFreqNew = 0, /* RCOSC calibration variable */
.bRefine = false, /* RCOSC calibration variable */
.state = Power_ACTIVE, /* current transition state */
.xoscPending = false, /* is XOSC_HF activation in progress? */
.calLF = false, /* calibrate RCOSC_LF? */
.hwiState = 0, /* calibration AUX ISR state */
.busyCal = false, /* already busy calibrating */
.calStep = 1, /* current calibration step */
.firstLF = true, /* is this first LF calibration? */
.enablePolicy = false, /* default value is false */
.initialized = false, /* whether Power_init has been called */
#if defined(DeviceFamily_CC26X0R2)
.emulatorAttached = false, /* emulator attached during boot */
#endif
.constraintCounts = { 0, 0, 0, 0, 0, 0, 0 },
.resourceCounts = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
.resourceHandlers = {
configureRFCoreClocks,
configureXOSCHF,
nopResourceHandler
}, /* special resource handler functions */
.policyFxn = NULL /* power policyFxn */
};
/* resource database */
const PowerCC26XX_ResourceRecord resourceDB[PowerCC26XX_NUMRESOURCES] = {
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_PERIPH, PRCM_PERIPH_TIMER0 }, /* PERIPH_GPT0 */
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_PERIPH, PRCM_PERIPH_TIMER1 }, /* PERIPH_GPT1 */
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_PERIPH, PRCM_PERIPH_TIMER2 }, /* PERIPH_GPT2 */
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_PERIPH, PRCM_PERIPH_TIMER3 }, /* PERIPH_GPT3 */
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_SERIAL, PRCM_PERIPH_SSI0 }, /* PERIPH_SSI0 */
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_PERIPH, PRCM_PERIPH_SSI1 }, /* PERIPH_SSI1 */
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_SERIAL, PRCM_PERIPH_UART0 }, /* PERIPH_UART0 */
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_SERIAL, PRCM_PERIPH_I2C0 }, /* PERIPH_I2C0 */
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_PERIPH, PRCM_PERIPH_TRNG }, /* PERIPH_TRNG */
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_PERIPH, PRCM_PERIPH_GPIO }, /* PERIPH_GPIO */
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_PERIPH, PRCM_PERIPH_UDMA }, /* PERIPH_UDMA */
{ PowerCC26XX_PERIPH | PowerCC26XX_DOMAIN_PERIPH, PRCM_PERIPH_CRYPTO }, /* PERIPH_CRYPTO */
{ PowerCC26XX_PERIPH | PowerCC26XX_PERIPH_UDMA, PRCM_PERIPH_I2S }, /* PERIPH_I2S */
{ PowerCC26XX_SPECIAL | PowerCC26XX_DOMAIN_RFCORE, 0 }, /* PERIPH_RFCORE */
{ PowerCC26XX_SPECIAL | PowerCC26XX_NOPARENT, 1 }, /* XOSC_HF */
{ PowerCC26XX_DOMAIN | PowerCC26XX_NOPARENT, PRCM_DOMAIN_PERIPH }, /* DOMAIN_PERIPH */
{ PowerCC26XX_DOMAIN | PowerCC26XX_NOPARENT, PRCM_DOMAIN_SERIAL }, /* DOMAIN_SERIAL */
{ PowerCC26XX_DOMAIN | PowerCC26XX_NOPARENT, PRCM_DOMAIN_RFCORE }, /* DOMAIN_RFCORE */
{ PowerCC26XX_SPECIAL | PowerCC26XX_NOPARENT, 2 } /* DOMAIN_SYSBUS */
};
/* ****************** Power APIs ******************** */
/*
* ======== Power_disablePolicy ========
* Do not run the configured policy
*/
bool Power_disablePolicy(void)
{
bool enablePolicy = PowerCC26XX_module.enablePolicy;
PowerCC26XX_module.enablePolicy = false;
return (enablePolicy);
}
/*
* ======== Power_enablePolicy ========
* Run the configured policy
*/
void Power_enablePolicy(void)
{
PowerCC26XX_module.enablePolicy = true;
}
/*
* ======== Power_getConstraintMask ========
* Get a bitmask indicating the constraints that have been registered with
* Power.
*/
uint_fast32_t Power_getConstraintMask(void)
{
return (PowerCC26XX_module.constraintMask);
}
/*
* ======== Power_getDependencyCount ========
* Get the count of dependencies that are currently declared upon a resource.
*/
int_fast16_t Power_getDependencyCount(uint_fast16_t resourceId)
{
DebugP_assert(resourceId < PowerCC26XX_NUMRESOURCES);
return ((int_fast16_t)PowerCC26XX_module.resourceCounts[resourceId]);
}
/*
* ======== Power_getTransitionLatency ========
* Get the transition latency for a sleep state. The latency is reported
* in units of microseconds.
*/
uint_fast32_t Power_getTransitionLatency(uint_fast16_t sleepState,
uint_fast16_t type)
{
uint32_t latency = 0;
if (type == Power_RESUME) {
if (sleepState == PowerCC26XX_STANDBY) {
latency = PowerCC26XX_RESUMETIMESTANDBY;
}
}
else {
if (sleepState == PowerCC26XX_STANDBY) {
latency = PowerCC26XX_TOTALTIMESTANDBY;
}
}
return (latency);
}
/*
* ======== Power_getTransitionState ========
* Get the current sleep transition state.
*/
uint_fast16_t Power_getTransitionState(void)
{
return (PowerCC26XX_module.state);
}
/*
* ======== Power_idleFunc ========
* Function needs to be plugged into the idle loop.
* It calls the configured policy function if the
* 'enablePolicy' flag is set.
*/
void Power_idleFunc()
{
if (PowerCC26XX_module.enablePolicy) {
if (PowerCC26XX_module.policyFxn != NULL) {
(*(PowerCC26XX_module.policyFxn))();
}
}
}
/*
* ======== Power_init ========
*/
int_fast16_t Power_init()
{
ClockP_Params clockParams;
uint32_t ccfgLfClkSrc;
uint32_t timeout;
/* if this function has already been called, just return */
if (PowerCC26XX_module.initialized) {
return (Power_SOK);
}
#if defined(DeviceFamily_CC26X0R2)
/* check to see if the JTAG_PD is on, meaning the emulator was attached during boot and */
/* that the user is in an active debug session */
PowerCC26XX_module.emulatorAttached = (HWREG(AON_WUC_BASE + AON_WUC_O_PWRSTAT) & AON_WUC_PWRSTAT_JTAG_PD_ON) == AON_WUC_PWRSTAT_JTAG_PD_ON;
#endif
/* set module state field 'initialized' to true */
PowerCC26XX_module.initialized = true;
/* set the module state enablePolicy field */
PowerCC26XX_module.enablePolicy = PowerCC26XX_config.enablePolicy;
/* copy the Power policy function to module state */
PowerCC26XX_module.policyFxn = PowerCC26XX_config.policyFxn;
/* construct the Clock object for scheduling of wakeups */
/* initiated and started by the power policy */
ClockP_Params_init(&clockParams);
clockParams.period = 0;
clockParams.startFlag = false;
clockParams.arg = 0;
ClockP_construct(&PowerCC26XX_module.clockObj, &emptyClockFunc,
0, &clockParams);
/* construct the Clock object for XOSC_HF switching */
/* initiated and started by Power module when activating XOSC_HF */
ClockP_construct(&PowerCC26XX_module.xoscClockObj, &switchXOSCHFclockFunc,
0, &clockParams);
/* construct the Clock object for disabling LF clock quailifiers */
/* one shot, auto start, first expires at 100 msec */
ClockP_construct(&PowerCC26XX_module.lfClockObj, &lfClockReadyCallback,
0, &clockParams);
(*(PowerCC26XX_config.calibrateFxn))(PowerCC26XX_SETUP_CALIBRATE);
DRIVERLIB_ASSERT_CURR_RELEASE();
/* read the LF clock source from CCFG */
ccfgLfClkSrc = CCFGRead_SCLK_LF_OPTION();
/* check if should calibrate RCOSC_LF */
if (PowerCC26XX_config.calibrateRCOSC_LF) {
/* verify RCOSC_LF is the LF clock source */
if (ccfgLfClkSrc == CCFGREAD_SCLK_LF_OPTION_RCOSC_LF) {
PowerCC26XX_module.calLF = true;
}
}
/*
* if LF source is RCOSC_LF or XOSC_LF: assert DISALLOW_STANDBY constraint
* and start a timeout to check for activation
*/
if ((ccfgLfClkSrc == CCFGREAD_SCLK_LF_OPTION_RCOSC_LF) ||
(ccfgLfClkSrc == CCFGREAD_SCLK_LF_OPTION_XOSC_LF)) {
/* disallow STANDBY pending LF clock quailifier disabling */
Power_setConstraint(PowerCC26XX_DISALLOW_STANDBY);
/* determine timeout */
if (ccfgLfClkSrc == CCFGREAD_SCLK_LF_OPTION_RCOSC_LF) {
timeout = PowerCC26XX_INITIALWAITRCOSC_LF;
}
else {
timeout = PowerCC26XX_INITIALWAITXOSC_LF;
}
/* start the Clock object */
ClockP_setTimeout(ClockP_handle(&PowerCC26XX_module.lfClockObj),
(timeout / ClockP_tickPeriod));
ClockP_start(ClockP_handle(&PowerCC26XX_module.lfClockObj));
}
/*
* else, if the LF clock source is external, can disable clock qualifiers
* now; no need to assert DISALLOW_STANDBY or start the Clock object
*/
else if (ccfgLfClkSrc == CCFGREAD_SCLK_LF_OPTION_EXTERNAL_LF) {
/* Disable clock qualifiers and enable clock loss */
disableLfClkQualifiersEnableClkLoss();
}
/*
* else, user has requested LF to be derived from XOSC_HF
*/
else if(ccfgLfClkSrc == CCFGREAD_SCLK_LF_OPTION_XOSC_HF_DLF)
{
/* disallow standby */
Power_setConstraint(PowerCC26XX_DISALLOW_STANDBY);
/* wait for the XOSC_HF to power up if it's not ready.. */
if(OSCClockSourceGet(OSC_SRC_CLK_LF) == OSC_XOSC_HF)
{
/* XOSC_HF is ready. Simply disable clock qualifiers and enable clock loss */
disableLfClkQualifiersEnableClkLoss(NULL);
}
else
{
/* XOSC_HF is not ready yet, schedule clock to check again later */
timeout = PowerCC26XX_INITIALWAITXOSC_HF / ClockP_tickPeriod;
/* start the Clock object */
ClockP_setTimeout(ClockP_handle(&PowerCC26XX_module.lfClockObj),
(timeout / ClockP_tickPeriod));
ClockP_start(ClockP_handle(&PowerCC26XX_module.lfClockObj));
}
}
/* if VIMS RAM is configured as GPRAM: set retention constraint */
if (!CCFGRead_DIS_GPRAM()) {
Power_setConstraint(PowerCC26XX_RETAIN_VIMS_CACHE_IN_STANDBY);
}
return (Power_SOK);
}
/*
* ======== Power_registerNotify ========
* Register a function to be called on a specific power event.
*
*/
int_fast16_t Power_registerNotify(Power_NotifyObj * pNotifyObj,
uint_fast16_t eventTypes, Power_NotifyFxn notifyFxn, uintptr_t clientArg)
{
int_fast16_t status = Power_SOK;
/* check for NULL pointers */
if ((pNotifyObj == NULL) || (notifyFxn == NULL)) {
status = Power_EINVALIDPOINTER;
}
else {
/* fill in notify object elements */
pNotifyObj->eventTypes = eventTypes;
pNotifyObj->notifyFxn = notifyFxn;
pNotifyObj->clientArg = clientArg;
/* place notify object on event notification queue */
List_put(&PowerCC26XX_module.notifyList, (List_Elem*)pNotifyObj);
}
return (status);
}
/*
* ======== Power_releaseConstraint ========
* Release a previously declared constraint.
*/
int_fast16_t Power_releaseConstraint(uint_fast16_t constraintId)
{
unsigned int key;
uint8_t count;
DebugP_assert(constraintId < PowerCC26XX_NUMCONSTRAINTS);
key = HwiP_disable();
/* get the count of the constraint */
count = PowerCC26XX_module.constraintCounts[constraintId];
DebugP_assert(count != 0);
count--;
/* save the updated count */
PowerCC26XX_module.constraintCounts[constraintId] = count;
if (count == 0) {
PowerCC26XX_module.constraintMask &= ~(1 << constraintId);
}
HwiP_restore(key);
return (Power_SOK);
}
/*
* ======== Power_releaseDependency ========
* Release a previously declared dependency.
*/
int_fast16_t Power_releaseDependency(uint_fast16_t resourceId)
{
uint8_t parent;
uint8_t count;
uint32_t id;
unsigned int key;
/* assert resourceId is valid */
DebugP_assert(resourceId < PowerCC26XX_NUMRESOURCES);
/* disable interrupts */
key = HwiP_disable();
/* read and decrement the reference count */
count = PowerCC26XX_module.resourceCounts[resourceId];
DebugP_assert(count != 0);
count--;
/* save the reference count */
PowerCC26XX_module.resourceCounts[resourceId] = count;
/* if this was the last dependency being released.., */
if (count == 0) {
/* deactivate this resource ... */
id = resourceDB[resourceId].driverlibID;
/* is resource a peripheral?... */
if (resourceDB[resourceId].flags & PowerCC26XX_PERIPH) {
PRCMPeripheralRunDisable(id);
PRCMPeripheralSleepDisable(id);
PRCMPeripheralDeepSleepDisable(id);
PRCMLoadSet();
while (!PRCMLoadGet()) {
;
}
}
/* else, does resource require a special handler?... */
else if (resourceDB[resourceId].flags & PowerCC26XX_SPECIAL) {
/* call the special handler */
PowerCC26XX_module.resourceHandlers[id](PowerCC26XX_DISABLE);
}
/* else resource is a power domain */
else {
PRCMPowerDomainOff(id);
while (PRCMPowerDomainStatus(id) != PRCM_DOMAIN_POWER_OFF) {
;
}
}
/* propagate release up the dependency tree ... */
/* check for a first parent */
parent = resourceDB[resourceId].flags & PowerCC26XX_PARENTMASK;
/* if 1st parent, make recursive call to release that dependency */
if (parent < PowerCC26XX_NUMRESOURCES) {
Power_releaseDependency(parent);
}
}
/* re-enable interrupts */
HwiP_restore(key);
return (Power_SOK);
}
/*
* ======== Power_setConstraint ========
* Declare an operational constraint.
*/
int_fast16_t Power_setConstraint(uint_fast16_t constraintId)
{
unsigned int key;
DebugP_assert(constraintId < PowerCC26XX_NUMCONSTRAINTS);
/* disable interrupts */
key = HwiP_disable();
/* set the specified constraint in the constraintMask */
PowerCC26XX_module.constraintMask |= 1 << constraintId;
/* increment the specified constraint count */
PowerCC26XX_module.constraintCounts[constraintId]++;
/* re-enable interrupts */
HwiP_restore(key);
return (Power_SOK);
}
/*
* ======== Power_setDependency ========
* Declare a dependency upon a resource.
*/
int_fast16_t Power_setDependency(uint_fast16_t resourceId)
{
uint8_t parent;
uint8_t count;
uint32_t id;
unsigned int key;
DebugP_assert(resourceId < PowerCC26XX_NUMRESOURCES);
/* disable interrupts */
key = HwiP_disable();
/* read and increment reference count */
count = PowerCC26XX_module.resourceCounts[resourceId]++;
/* if resource was NOT activated previously ... */
if (count == 0) {
/* propagate set up the dependency tree ... */
/* check for a first parent */
parent = resourceDB[resourceId].flags & PowerCC26XX_PARENTMASK;
/* if first parent, make recursive call to set that dependency */
if (parent < PowerCC26XX_NUMRESOURCES) {
Power_setDependency(parent);
}
/* now activate this resource ... */
id = resourceDB[resourceId].driverlibID;
/* is resource a peripheral?... */
if (resourceDB[resourceId].flags & PowerCC26XX_PERIPH) {
PRCMPeripheralRunEnable(id);
PRCMPeripheralSleepEnable(id);
PRCMPeripheralDeepSleepEnable(id);
PRCMLoadSet();
while (!PRCMLoadGet()) {
;
}
}
/* else, does resource require a special handler?... */
else if (resourceDB[resourceId].flags & PowerCC26XX_SPECIAL) {
/* call the special handler */
PowerCC26XX_module.resourceHandlers[id](PowerCC26XX_ENABLE);
}
/* else resource is a power domain */
else {
PRCMPowerDomainOn(id);
while (PRCMPowerDomainStatus(id) != PRCM_DOMAIN_POWER_ON) {
;
}
}
}
/* re-enable interrupts */
HwiP_restore(key);
return (Power_SOK);
}
/*
* ======== Power_setPolicy ========
* Set the Power policy function
*/
void Power_setPolicy(Power_PolicyFxn policy)
{
PowerCC26XX_module.policyFxn = policy;
}
/*
* ======== Power_shutdown ========
*/
int_fast16_t Power_shutdown(uint_fast16_t shutdownState,
uint_fast32_t shutdownTime)
{
int_fast16_t status = Power_EFAIL;
unsigned int constraints;
unsigned int hwiKey;
/* disable interrupts */
hwiKey = HwiP_disable();
/* check if there is a constraint to prohibit shutdown */
constraints = Power_getConstraintMask();
if (constraints & (1 << PowerCC26XX_DISALLOW_SHUTDOWN)) {
status = Power_ECHANGE_NOT_ALLOWED;
}
/* OK to shutdown ... */
else if (PowerCC26XX_module.state == Power_ACTIVE) {
/* set new transition state to entering shutdown */
PowerCC26XX_module.state = Power_ENTERING_SHUTDOWN;
/* signal all clients registered for pre-shutdown notification */
status = notify(PowerCC26XX_ENTERING_SHUTDOWN);
/* check for any error */
if (status != Power_SOK) {
PowerCC26XX_module.state = Power_ACTIVE;
HwiP_restore(hwiKey);
return (status);
}
/* now proceed with shutdown sequence ... */
/* If the JTAG_PD is on, make sure that the DUT reboots without
* stopping for halt-in-boot when it enters shutdown. */
#if defined(DeviceFamily_CC26X0R2)
uint32_t aonSysctrlResetctl;
if((HWREG(AON_WUC_BASE + AON_WUC_O_PWRSTAT) & AON_WUC_PWRSTAT_JTAG_PD_ON) &&
(!PowerCC26XX_module.emulatorAttached)) {
/* set BOOT_DET = b10.
* The next time the device enters shutdown the
* device will start booting immediately because the JTAG_PD is already on.
* However since since BOOT_DET == b10, the boot code will run not wait
* for a GPIO interrupt, but rather run to completion and branch to the
* flash image with the JTAG_PD turned off.
*/
aonSysctrlResetctl = HWREG( AON_SYSCTL_BASE + AON_SYSCTL_O_RESETCTL ) &
~( AON_SYSCTL_RESETCTL_BOOT_DET_1_CLR_M | AON_SYSCTL_RESETCTL_BOOT_DET_0_CLR_M |
AON_SYSCTL_RESETCTL_BOOT_DET_1_SET_M | AON_SYSCTL_RESETCTL_BOOT_DET_0_SET_M );
/* To get BOOT_DET = b10, set BOOT_DET_1_SET and BOOT_DET_0_CLR*/
HWREG(AON_SYSCTL_BASE + AON_SYSCTL_O_RESETCTL) = aonSysctrlResetctl |
(AON_SYSCTL_RESETCTL_BOOT_DET_0_CLR | AON_SYSCTL_RESETCTL_BOOT_DET_1_SET);
}
#endif
/* 1. Switch HF, MF, and LF clocks to source from RCOSC_HF */
if (OSCClockSourceGet(OSC_SRC_CLK_HF) != OSC_RCOSC_HF) {
/* 1.1. Source HF and MF from RCOSC_HF */
OSCClockSourceSet(OSC_SRC_CLK_HF | OSC_SRC_CLK_MF, OSC_RCOSC_HF);
while (!OSCHfSourceReady());
OSCHfSourceSwitch();
}
/* 1.2. Source LF from RCOSC_LF */
OSCClockSourceSet(OSC_SRC_CLK_LF, OSC_RCOSC_LF);
while (OSCClockSourceGet(OSC_SRC_CLK_LF) != OSC_RCOSC_LF);
/* 2. Make sure DMA and CRYTO clocks are off in deep-sleep */
PRCMPeripheralDeepSleepDisable(PRCM_PERIPH_CRYPTO);
PRCMPeripheralDeepSleepDisable(PRCM_PERIPH_UDMA);
PRCMLoadSet();
while (!PRCMLoadGet()) {
;
}
/* 3. Power OFF AUX and disconnect from bus */
AUXWUCPowerCtrl(AUX_WUC_POWER_OFF);
/* 4. Remove AUX force ON */
HWREG(AON_WUC_BASE + AON_WUC_O_AUXCTL) &=
~AON_WUC_AUXCTL_AUX_FORCE_ON;
/*
* 5. Reset AON event source IDs to avoid pending events powering
* on MCU/AUX
*/
HWREG(AON_EVENT_BASE + AON_EVENT_O_MCUWUSEL) = 0x3F3F3F3F;
HWREG(AON_EVENT_BASE + AON_EVENT_O_AUXWUSEL) = 0x003F3F3F;
/* sync AON */
SysCtrlAonSync();
/*
* 6. Enable shutdown - this latches the IOs, so configuration of
* IOCFGx registers must be done prior to this
*/
AONWUCShutDownEnable();
/* 7. Sync AON */
SysCtrlAonSync();
/* 8. Wait until AUX powered off */
while (AONWUCPowerStatusGet() & AONWUC_AUX_POWER_ON);
/* 9. Request to power off MCU when go to deep sleep */
PRCMMcuPowerOff();
/*
* 10. Turn off power domains inside MCU VD (BUS, FL_BUS, RFC,
* CPU)
*/
PRCMPowerDomainOff(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL |
PRCM_DOMAIN_PERIPH | PRCM_DOMAIN_CPU | PRCM_DOMAIN_VIMS);
/* 11. Deep sleep to activate shutdown */
PRCMDeepSleep();
}
else {
status = Power_EBUSY;
}
/* NOTE: if shutdown succeeded, should never get here */
/* return failure status */
PowerCC26XX_module.state = Power_ACTIVE;
/* re-enable interrupts */
HwiP_restore(hwiKey);
/* if get here, failed to shutdown, return error code */
return (status);
}
/*
* ======== Power_sleep ========
*/
int_fast16_t Power_sleep(uint_fast16_t sleepState)
{
int_fast16_t status = Power_SOK;
int_fast16_t notifyStatus = Power_SOK;
int_fast16_t lateNotifyStatus = Power_SOK;
unsigned int xosc_hf_active = false;
uint_fast16_t postEventLate;
uint32_t poweredDomains = 0;
uint_fast16_t preEvent;
uint_fast16_t postEvent;
unsigned int constraints;
bool retainCache = false;
uint32_t modeVIMS;
unsigned int swiKey;
#if defined(DeviceFamily_CC26X0R2)
/* has JTAG_PD been turned AFTER boot due to TCK noise? */
if((HWREG(AON_WUC_BASE + AON_WUC_O_PWRSTAT) & AON_WUC_PWRSTAT_JTAG_PD_ON) && (!PowerCC26XX_module.emulatorAttached))
{
/* notify all subscribers */
notify(PowerCC26XX_JTAG_PD_TURNED_ON);
}
#endif
/* first validate the sleep code */
if (sleepState != PowerCC26XX_STANDBY) {
status = Power_EINVALIDINPUT;
}
else {
/* check to make sure Power is not busy with another transition */
if (PowerCC26XX_module.state == Power_ACTIVE) {
/* set transition state to entering sleep */
PowerCC26XX_module.state = Power_ENTERING_SLEEP;
}
else {
status = Power_EBUSY;
}
if (status == Power_SOK) {
/* setup sleep vars */
preEvent = PowerCC26XX_ENTERING_STANDBY;
postEvent = PowerCC26XX_AWAKE_STANDBY;
postEventLate = PowerCC26XX_AWAKE_STANDBY_LATE;
/* disable Task scheduling; allow Swis and Hwis for notifications */
PowerCC26XX_schedulerDisable();
/* signal all clients registered for pre-sleep notification */
status = notify(preEvent);
/* check for any error */
if (status != Power_SOK) {
PowerCC26XX_module.state = Power_ACTIVE;
PowerCC26XX_schedulerRestore();
return (status);
}
/* now disable Swi scheduling */
swiKey = SwiP_disable();
/* 1. Freeze the IOs on the boundary between MCU and AON */
AONIOCFreezeEnable();
/* 2. If XOSC_HF is active, force it off */
if(OSCClockSourceGet(OSC_SRC_CLK_HF) == OSC_XOSC_HF) {
xosc_hf_active = true;
configureXOSCHF(PowerCC26XX_DISABLE);
}
/* 3. Allow AUX to power down */
AONWUCAuxWakeupEvent(AONWUC_AUX_ALLOW_SLEEP);
/* 4. Make sure writes take effect */
SysCtrlAonSync();
/* now proceed to transition to Power_STANDBY ... */
/* 5. Query and save domain states before powering them off */
if (Power_getDependencyCount(PowerCC26XX_DOMAIN_RFCORE)) {
poweredDomains |= PRCM_DOMAIN_RFCORE;
}
if (Power_getDependencyCount(PowerCC26XX_DOMAIN_SERIAL)){
poweredDomains |= PRCM_DOMAIN_SERIAL;
}
if (Power_getDependencyCount(PowerCC26XX_DOMAIN_PERIPH)) {
poweredDomains |= PRCM_DOMAIN_PERIPH;
}
/* 6. Gate running deep sleep clocks for Crypto and DMA */
if (Power_getDependencyCount(PowerCC26XX_PERIPH_CRYPTO)) {
PRCMPeripheralDeepSleepDisable(
resourceDB[PowerCC26XX_PERIPH_CRYPTO].driverlibID);
}
if (Power_getDependencyCount(PowerCC26XX_PERIPH_UDMA)) {
PRCMPeripheralDeepSleepDisable(
resourceDB[PowerCC26XX_PERIPH_UDMA].driverlibID);
}
/* 7. Make sure clock settings take effect */
PRCMLoadSet();
/* 8. Request power off of domains in the MCU voltage domain */
PRCMPowerDomainOff(poweredDomains | PRCM_DOMAIN_CPU);
/* 9. Request uLDO during standby */
PRCMMcuUldoConfigure(true);
/* query constraints to determine if cache should be retained */
constraints = Power_getConstraintMask();
if (constraints & (1 << PowerCC26XX_RETAIN_VIMS_CACHE_IN_STANDBY)) {
retainCache = true;
}
/* 10. If don't want VIMS retention in standby, disable it now... */
if (retainCache == false) {
/* 10.1 Get the current VIMS mode */
do {
modeVIMS = VIMSModeGet(VIMS_BASE);
} while (modeVIMS == VIMS_MODE_CHANGING);
/* 10.2 If in a cache mode, turn VIMS off */
if (modeVIMS == VIMS_MODE_ENABLED) {
/* 10.3 Now turn off the VIMS */
VIMSModeSet(VIMS_BASE, VIMS_MODE_OFF);
}
/* 10.4 Now disable retention */
PRCMCacheRetentionDisable();
}
/* 11. Setup recharge parameters */
SysCtrlSetRechargeBeforePowerDown(XOSC_IN_HIGH_POWER_MODE);
/* 12. Make sure all writes have taken effect */
SysCtrlAonSync();
/* 13. Invoke deep sleep to go to STANDBY */
PRCMDeepSleep();
/* 14. If didn't retain VIMS in standby, re-enable retention now */
if (retainCache == false) {
/* 14.1 If previously in a cache mode, restore the mode now */
if (modeVIMS == VIMS_MODE_ENABLED) {
VIMSModeSet(VIMS_BASE, modeVIMS);
}
/* 14.2 Re-enable retention */
PRCMCacheRetentionEnable();
}
/* 15. Start forcing on power to AUX */
AONWUCAuxWakeupEvent(AONWUC_AUX_WAKEUP);
/* 16. Start re-powering power domains */
PRCMPowerDomainOn(poweredDomains);
/* 17. Restore deep sleep clocks of Crypto and DMA */
if (Power_getDependencyCount(PowerCC26XX_PERIPH_CRYPTO)) {
PRCMPeripheralDeepSleepEnable(
resourceDB[PowerCC26XX_PERIPH_CRYPTO].driverlibID);
}
if (Power_getDependencyCount(PowerCC26XX_PERIPH_UDMA)) {
PRCMPeripheralDeepSleepEnable(
resourceDB[PowerCC26XX_PERIPH_UDMA].driverlibID);
}
/* 18. Make sure clock settings take effect */
PRCMLoadSet();
/* 19. Release request for uLDO */
PRCMMcuUldoConfigure(false);
/* 20. Set transition state to EXITING_SLEEP */
PowerCC26XX_module.state = Power_EXITING_SLEEP;
/* 21. Wait until all power domains are back on */
while (PRCMPowerDomainStatus(poweredDomains) !=
PRCM_DOMAIN_POWER_ON) {
;
}
/* 22. Wait for the RTC shadow values to be updated so that
* the early notification callbacks can read out valid RTC values
*/
SysCtrlAonSync();
/*
* 23. Signal clients registered for early post-sleep notification;
* this should be used to initialize any timing critical or IO
* dependent hardware
*/
notifyStatus = notify(postEvent);
/* 24. Disable IO freeze and ensure RTC shadow value is updated */
AONIOCFreezeDisable();
SysCtrlAonSync();
/* 25. Wait for AUX to power up */
while(!(AONWUCPowerStatusGet() & AONWUC_AUX_POWER_ON)) {};
/* 26. If XOSC_HF was forced off above, initiate switch back */
if (xosc_hf_active == true) {
configureXOSCHF(PowerCC26XX_ENABLE);
}
/* 27. Re-enable interrupts */
CPUcpsie();
/*
* 28. Signal all clients registered for late post-sleep
* notification
*/
lateNotifyStatus = notify(postEventLate);
/*
* 29. Now clear the transition state before re-enabling
* scheduler
*/
PowerCC26XX_module.state = Power_ACTIVE;
/* 30. Re-enable Swi scheduling */
SwiP_restore(swiKey);
/* 31. Adjust recharge parameters */
SysCtrlAdjustRechargeAfterPowerDown(PowerCC26XX_config.vddrRechargeMargin);
/* re-enable Task scheduling */
PowerCC26XX_schedulerRestore();
/* if there was a notification error, set return status */
if ((notifyStatus != Power_SOK) ||
(lateNotifyStatus != Power_SOK)) {
status = Power_EFAIL;
}
}
}
return (status);
}
/*
* ======== Power_unregisterNotify ========
* Unregister for a power notification.
*
*/
void Power_unregisterNotify(Power_NotifyObj * pNotifyObj)
{
unsigned int key;
/* remove notify object from its event queue */
key = HwiP_disable();
/* remove notify object from its event queue */
List_remove(&PowerCC26XX_module.notifyList, (List_Elem *)pNotifyObj);
HwiP_restore(key);
}
/* ****************** CC26XX specific APIs ******************** */
/*
* ======== PowerCC26XX_calibrate ========
* Plug this function into the PowerCC26XX_Config structure
* if calibration is needed.
*/
bool PowerCC26XX_calibrate(unsigned int arg)
{
bool retVal = false;
ClockP_Params clockParams;
switch (arg) {
case PowerCC26XX_SETUP_CALIBRATE:
/*
* If RCOSC calibration is enabled, construct a Clock object for
* delays. Set timeout to '1' Clock tick period for the minimal
* delay. The object will explicitly started by Power module when
* appropriate
*/
ClockP_Params_init(&clockParams);
clockParams.period = 0;
clockParams.startFlag = false;
clockParams.arg = 0;
ClockP_construct(&PowerCC26XX_module.calClockStruct,
&PowerCC26XX_RCOSC_clockFunc, 1, &clockParams);
/* construct the Hwi */
HwiP_construct(&PowerCC26XX_module.hwiStruct,
44, PowerCC26XX_auxISR, NULL);
break;
case PowerCC26XX_INITIATE_CALIBRATE:
retVal = PowerCC26XX_initiateCalibration();
break;
case PowerCC26XX_DO_CALIBRATE:
PowerCC26XX_doCalibrate();
break;
}
return (retVal);
}
/*
* ======== PowerCC26XX_doWFI ========
*/
void PowerCC26XX_doWFI(void)
{
__asm(" wfi");
}
/*
* ======== PowerCC26XX_getClockHandle ========
*/
ClockP_Handle PowerCC26XX_getClockHandle()
{
return ((ClockP_Handle)&PowerCC26XX_module.clockObj);
}
/*
* ======== PowerCC26XX_noCalibrate ========
* Plug this function into the PowerCC26XX config structure if calibration
* is not needed.
*/
bool PowerCC26XX_noCalibrate(unsigned int arg)
{
return (0);
}
/*
* ======== PowerCC26XX_getXoscStartupTime ========
* Get the estimated crystal oscillator startup time
*/
uint32_t PowerCC26XX_getXoscStartupTime(uint32_t timeUntilWakeupInMs)
{
return (OSCHF_GetStartupTime(timeUntilWakeupInMs));
}
/*
* ======== PowerCC26XX_injectCalibration ========
* Explicitly trigger RCOSC calibration
*/
bool PowerCC26XX_injectCalibration(void)
{
if ((*(PowerCC26XX_config.calibrateFxn))(PowerCC26XX_INITIATE_CALIBRATE)) {
/* here if AUX SMPH was available, start calibration now ... */
(*(PowerCC26XX_config.calibrateFxn))(PowerCC26XX_DO_CALIBRATE);
return (true);
}
return (false);
}
/*
* ======== PowerCC26XX_isStableXOSC_HF ========
* Check if XOSC_HF has stabilized.
*/
bool PowerCC26XX_isStableXOSC_HF(void)
{
bool ready = true;
unsigned int key;
key = HwiP_disable();
/* only query if HF source is ready if there is a pending change */
if (PowerCC26XX_module.xoscPending) {
ready = OSCHfSourceReady();
}
HwiP_restore(key);
return (ready);
}
/*
* ======== PowerCC26XX_switchXOSC_HF ========
* Switch to enable XOSC_HF.
* May only be called when using the PowerCC26XX_SWITCH_XOSC_HF_MANUALLY
* constraint.
* May only be called after ensuring the XOSC_HF is stable by calling
* PowerCC26XX_isStableXOSC_HF().
*/
void PowerCC26XX_switchXOSC_HF(void)
{
/* This function is just a veneer to call the static callback function for
* the XOSC_HF clock. This way, if the switching does fail because a constraint
* stopped it from switching, a clock will be scheduled into the future to try
* again. This could happen if there is an ongoing operation from another bus
* master that reads from flash such as SPI or AES DMA operations.
*/
switchXOSCHFclockFunc((uintptr_t) NULL);
}
/* * * * * * * * * * * internal and support functions * * * * * * * * * * */
/*
* ======== emptyClockFunc ========
* Clock function used by power policy to schedule early wakeups.
*/
static void emptyClockFunc(uintptr_t arg)
{
}
/*
* ======== disableLfClkQualifiersEnableClkLoss ========
* Function used to disable LF clock qualifiers and enable clock loss
*/
static void disableLfClkQualifiersEnableClkLoss()
{
/* Disable the LF clock qualifiers */
DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
DDI_0_OSC_CTL0_BYPASS_XOSC_LF_CLK_QUAL_M |
DDI_0_OSC_CTL0_BYPASS_RCOSC_LF_CLK_QUAL_M,
DDI_0_OSC_CTL0_BYPASS_RCOSC_LF_CLK_QUAL_S, 0x3);
/* Enable clock loss detection */
OSCClockLossEventEnable();
}
/*
* ======== lfClockReadyCallback ========
* Clock function callback used to check if the LF clock is ready
*/
static void lfClockReadyCallback(uintptr_t arg)
{
uint32_t ccfgLfClkSrc;
uint32_t sourceLF;
uint32_t timeout;
/* query LF clock source */
sourceLF = OSCClockSourceGet(OSC_SRC_CLK_LF);
/* is LF source either RCOSC_LF or XOSC_LF yet? */
if ((sourceLF == OSC_RCOSC_LF) || (sourceLF == OSC_XOSC_LF)) {
/* Disable clock qualifiers and enable clock loss */
disableLfClkQualifiersEnableClkLoss();
/* now finish by releasing the standby disallow constraint */
Power_releaseConstraint(PowerCC26XX_DISALLOW_STANDBY);
}
/* is LF source XOSC_HF yet? */
else if(sourceLF == OSC_XOSC_HF)
{
/* Disable clock qualifiers and enable clock loss */
disableLfClkQualifiersEnableClkLoss();
/* Keep PowerCC26XX_DISALLOW_STANDBY set, not allowed to enter standby
* when LF clock is sourced from from XOSC_HF
*/
}
/* not yet, LF still derived from RCOSC_HF, restart clock to check back later */
else {
/* read the LF clock source from CCFG */
ccfgLfClkSrc = CCFGRead_SCLK_LF_OPTION();
/* determine retry timeout */
if (ccfgLfClkSrc == CCFGREAD_SCLK_LF_OPTION_RCOSC_LF) {
timeout = PowerCC26XX_RETRYWAITRCOSC_LF;
}
else if(ccfgLfClkSrc == CCFGREAD_SCLK_LF_OPTION_XOSC_LF){
timeout = PowerCC26XX_RETRYWAITXOSC_LF;
}
else {
/* ccfgLfClkSrc == CCFGREAD_SCLK_LF_OPTION_XOSC_HF_DLF */
timeout = PowerCC26XX_RETRYWAITXOSC_HF;
}
/* retrigger LF Clock to fire again */
ClockP_setTimeout(ClockP_handle(&PowerCC26XX_module.lfClockObj),
(timeout / ClockP_tickPeriod));
ClockP_start(ClockP_handle(&PowerCC26XX_module.lfClockObj));
}
}
/*
* ======== nopResourceFunc ========
* special resource handler
*/
static unsigned int nopResourceHandler(unsigned int action)
{
return (0);
}
/*
* ======== notify ========
* Send notifications to registered clients.
* Note: Task scheduling is disabled when this function is called.
*/
static int_fast16_t notify(uint_fast16_t eventType)
{
int_fast16_t notifyStatus;
Power_NotifyFxn notifyFxn;
uintptr_t clientArg;
List_Elem *elem;
/* if queue is empty, return immediately */
if (!List_empty(&PowerCC26XX_module.notifyList)) {
/* point to first client notify object */
elem = List_head(&PowerCC26XX_module.notifyList);
/* walk the queue and notify each registered client of the event */
do {
if (((Power_NotifyObj *)elem)->eventTypes & eventType) {
/* pull params from notify object */
notifyFxn = ((Power_NotifyObj *)elem)->notifyFxn;
clientArg = ((Power_NotifyObj *)elem)->clientArg;
/* call the client's notification function */
notifyStatus = (int_fast16_t)(*(Power_NotifyFxn)notifyFxn)(
eventType, 0, clientArg);
/* if client declared error stop all further notifications */
if (notifyStatus != Power_NOTIFYDONE) {
return (Power_EFAIL);
}
}
/* get next element in the notification queue */
elem = List_next(elem);
} while (elem != NULL);
}
return (Power_SOK);
}
/*
* ======== configureRFCoreClocks ========
* Special dependency function for controlling RF core clocks.
*/
static unsigned int configureRFCoreClocks(unsigned int action)
{
if (action == PowerCC26XX_ENABLE) {
RFCClockEnable();
}
else {
RFCClockDisable();
}
return (0);
}
/*
* ======== switchXOSCHFclockFunc ========
* Clock function used for delayed switching to XOSC_HF.
*/
static void switchXOSCHFclockFunc(uintptr_t arg0)
{
bool readyToCal;
uint32_t timeout;
unsigned int key;
key = HwiP_disable();
/* if pending switch has already been made, just send out notifications */
if (PowerCC26XX_module.xoscPending == false) {
/* initiate RCOSC calibration */
readyToCal = (*(PowerCC26XX_config.calibrateFxn))(PowerCC26XX_INITIATE_CALIBRATE);
/* notify clients that were waiting for a switch notification */
notify(PowerCC26XX_XOSC_HF_SWITCHED);
/* if ready to start first cal measurment, do it now */
if (readyToCal == true) {
(*(PowerCC26XX_config.calibrateFxn))(PowerCC26XX_DO_CALIBRATE);
}
}
/* else, if HF ready to switch and we are allowed to, do it now ... */
else if (!(Power_getConstraintMask() & (1 << PowerCC26XX_DISALLOW_XOSC_HF_SWITCHING)) && OSCHfSourceReady()) {
OSCHF_AttemptToSwitchToXosc();
PowerCC26XX_module.xoscPending = false;
/* initiate RCOSC calibration */
readyToCal = (*(PowerCC26XX_config.calibrateFxn))(PowerCC26XX_INITIATE_CALIBRATE);
/* now notify clients that were waiting for a switch notification */
notify(PowerCC26XX_XOSC_HF_SWITCHED);
/* if ready to start first cal measurment, do it now */
if (readyToCal == true) {
(*(PowerCC26XX_config.calibrateFxn))(PowerCC26XX_DO_CALIBRATE);
}
}
/* else, wait some more, then see if can switch ... */
else {
/* calculate wait timeout in units of ticks */
timeout = PowerCC26XX_RETRYWAITXOSC_HF / ClockP_tickPeriod;
if (timeout == 0) {
timeout = 1; /* wait at least 1 tick */
}
/* re-start Clock object with retry timeout */
ClockP_setTimeout(
ClockP_handle(&PowerCC26XX_module.xoscClockObj), timeout);
ClockP_start(ClockP_handle(&PowerCC26XX_module.xoscClockObj));
}
HwiP_restore(key);
}
/*
* ======== configureXOSCHF ========
*/
static unsigned int configureXOSCHF(unsigned int action)
{
uint32_t timeout;
if (action == PowerCC26XX_ENABLE && OSCClockSourceGet(OSC_SRC_CLK_HF) != OSC_XOSC_HF) {
OSCHF_TurnOnXosc();
PowerCC26XX_module.xoscPending = true;
/* Unless it is disallowed, estimate the required stabilisation
* time and start a clock.
* When the clock times out, the callback will try and switch to
* the XOSC_HF. If the XOSC_HF is not ready yet, the callback
* will start a new clock to try again.
*/
if (!(Power_getConstraintMask() & (1 << PowerCC26XX_SWITCH_XOSC_HF_MANUALLY))) {
/* calculate wait timeout in units of ticks */
timeout = PowerCC26XX_INITIALWAITXOSC_HF / ClockP_tickPeriod;
if (timeout == 0) {
timeout = 1; /* wait at least 1 tick */
}
/* start Clock object with initial timeout */
ClockP_stop(ClockP_handle(&PowerCC26XX_module.xoscClockObj));
ClockP_setTimeout(ClockP_handle(&PowerCC26XX_module.xoscClockObj),
timeout);
ClockP_start(ClockP_handle(&PowerCC26XX_module.xoscClockObj));
}
}
/* when release XOSC_HF, auto switch to RCOSC_HF */
else {
OSCHF_SwitchToRcOscTurnOffXosc();
}
return (0);
}