diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c index dacf193476..b3998d0370 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.c @@ -1,94 +1,168 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright 2016-2017 NXP + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of the copyright holder 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_smc.h" -#include "fsl_flash.h" +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.smc" +#endif + +typedef void (*smc_stop_ram_func_t)(void); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void); + +/******************************************************************************* + * Variables + ******************************************************************************/ +static uint32_t g_savedPrimask; + +/* + * The ram function code is: + * + * uint32_t i; + * for (i=0; i<0x8; i++) + * { + * __NOP(); + * } + * __DSB(); + * __WFI(); + * __ISB(); + * + * When entring the stop modes, the flash prefetch might be interrupted, thus + * the prefetched code or data might be broken. To make sure the flash is idle + * when entring the stop modes, the code is moved to ram. And delay for a while + * before WFI to make sure previous flash prefetch is finished. + * + * Only need to do like this when code is in flash, if code is in rom or ram, + * this is not necessary. + */ +static uint16_t s_stopRamFuncArray[] = { + 0x2000, /* MOVS R0, #0 */ + 0x2808, /* CMP R0, #8 */ + 0xD202, /* BCS.N */ + 0xBF00, /* NOP */ + 0x1C40, /* ADDS R0, R0, #1 */ + 0xE7FA, /* B.N */ + 0xF3BF, 0x8F4F, /* DSB */ + 0xBF30, /* WFI */ + 0xF3BF, 0x8F6F, /* ISB */ + 0x4770, /* BX LR */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void) +{ + uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U; + smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry; + stopRamFunc(); +} #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) +/*! + * brief Gets the SMC parameter. + * + * This function gets the SMC parameter including the enabled power mdoes. + * + * param base SMC peripheral base address. + * param param Pointer to the SMC param structure. + */ void SMC_GetParam(SMC_Type *base, smc_param_t *param) { - uint32_t reg = base->PARAM; + uint32_t reg = base->PARAM; param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK); - param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); - param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); + param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); + param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK); } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +/*! + * brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ void SMC_PreEnterStopModes(void) { - flash_prefetch_speculation_status_t speculationStatus = - { - kFLASH_prefetchSpeculationOptionDisable, /* Disable instruction speculation.*/ - kFLASH_prefetchSpeculationOptionDisable, /* Disable data speculation.*/ - }; - - __disable_irq(); + g_savedPrimask = DisableGlobalIRQ(); __ISB(); - - /* - * Before enter stop modes, the flash cache prefetch should be disabled. - * Otherwise the prefetch might be interrupted by stop, then the data and - * and instruction from flash are wrong. - */ - FLASH_PflashSetPrefetchSpeculation(&speculationStatus); } +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with ref SMC_PreEnterStopModes. + */ void SMC_PostExitStopModes(void) { - flash_prefetch_speculation_status_t speculationStatus = - { - kFLASH_prefetchSpeculationOptionEnable, /* Enable instruction speculation.*/ - kFLASH_prefetchSpeculationOptionEnable, /* Enable data speculation.*/ - }; - - FLASH_PflashSetPrefetchSpeculation(&speculationStatus); - - __enable_irq(); + EnableGlobalIRQ(g_savedPrimask); __ISB(); } +/*! + * brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Configures the system to RUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; reg = base->PMCTRL; /* configure Normal RUN mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) +/*! + * brief Configures the system to HSRUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeHsrun(SMC_Type *base) { uint8_t reg; @@ -96,13 +170,19 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base) reg = base->PMCTRL; /* configure High Speed RUN mode */ reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); + reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ +/*! + * brief Configures the system to WAIT power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ @@ -114,22 +194,29 @@ status_t SMC_SetPowerModeWait(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to Stop power mode. + * + * param base SMC peripheral base address. + * param option Partial Stop mode option. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) { uint8_t reg; #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO) - /* configure the Partial Stop mode in Noraml Stop mode */ + /* configure the Partial Stop mode in Normal Stop mode */ reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_PSTOPO_MASK; - reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK; + reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); base->STOPCTRL = reg; #endif /* configure Normal Stop mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ @@ -137,12 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter Stop mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -152,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) } } +/*! + * brief Configures the system to VLPR power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpr(SMC_Type *base #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) , bool wakeupMode #endif - ) +) { uint8_t reg; @@ -172,18 +263,24 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base else { /* remains in VLP mode on an interrupt */ - reg &= ~SMC_PMCTRL_LPWUI_MASK; + reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK; } #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /* configure VLPR mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } +/*! + * brief Configures the system to VLPW power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpw(SMC_Type *base) { /* configure VLPW mode */ @@ -196,14 +293,20 @@ status_t SMC_SetPowerModeVlpw(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to VLPS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlps(SMC_Type *base) { uint8_t reg; /* configure VLPS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ @@ -211,12 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter VLPS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -227,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) } #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to LLS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeLls(SMC_Type *base #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) , const smc_power_mode_lls_config_t *config #endif - ) +) { uint8_t reg; /* configure to LLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure LLS sub-mode*/ #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ @@ -267,12 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -284,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to VLLS power mode. + * + * param base SMC peripheral base address. + * param config The VLLS power mode configuration structure. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config) { uint8_t reg; @@ -296,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #endif { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enablePorDetectInVlls0) + if (true == config->enablePorDetectInVlls0) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK; #endif } else @@ -319,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t else if (config->subMode == kSMC_StopSub2) { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enableRam2InVlls2) + if (true == config->enableRam2InVlls2) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK; @@ -332,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK; #endif } } else { + /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */ } #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */ /* configure to VLLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure the VLLS sub-mode */ #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) reg = base->VLLSCTRL; reg &= ~SMC_VLLSCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); base->VLLSCTRL = reg; #else #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #else reg = base->STOPCTRL; reg &= ~SMC_STOPCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ #endif @@ -383,12 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h index 168ce83501..e5c318e1a1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_smc.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright 2016-2017 NXP + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of the copyright holder 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SMC_H_ @@ -36,15 +14,14 @@ /*! @addtogroup smc */ /*! @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.3. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) +/*! @brief SMC driver version 2.0.5. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5)) /*@}*/ /*! @@ -64,18 +41,14 @@ typedef enum _smc_power_mode_protection #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_AVLLS_MASK + | SMC_PMPROT_AVLLS_MASK #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_ALLS_MASK + | SMC_PMPROT_ALLS_MASK #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - | - SMC_PMPROT_AVLP_MASK + | SMC_PMPROT_AVLP_MASK #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - | - kSMC_AllowPowerModeHsrun + | kSMC_AllowPowerModeHsrun #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ ) /*!< Allow all power mode. */ } smc_power_mode_protection_t; @@ -85,7 +58,7 @@ typedef enum _smc_power_mode_protection */ typedef enum _smc_power_state { - kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ + kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */ kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */ kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */ @@ -107,7 +80,7 @@ typedef enum _smc_power_state typedef enum _smc_run_mode { kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ @@ -119,7 +92,7 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ @@ -148,7 +121,7 @@ typedef enum _smc_stop_submode */ typedef enum _smc_partial_stop_mode { - kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ + kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/ kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/ } smc_partial_stop_option_t; @@ -324,11 +297,7 @@ void SMC_PostExitStopModes(void); * * This function should be called before entering WAIT/VLPW modes. */ -static inline void SMC_PreEnterWaitModes(void) -{ - __disable_irq(); - __ISB(); -} +void SMC_PreEnterWaitModes(void); /*! * @brief Recovers after wake up from stop modes. @@ -336,11 +305,7 @@ static inline void SMC_PreEnterWaitModes(void) * This function should be called after wake up from WAIT/VLPW modes. * It is used with @ref SMC_PreEnterWaitModes. */ -static inline void SMC_PostExitWaitModes(void) -{ - __enable_irq(); - __ISB(); -} +void SMC_PostExitWaitModes(void); /*! * @brief Configures the system to RUN power mode. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_smc.c index 5c86e3366b..b3998d0370 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_smc.c @@ -1,94 +1,168 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_smc.h" -#include "fsl_flash.h" +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.smc" +#endif + +typedef void (*smc_stop_ram_func_t)(void); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void); + +/******************************************************************************* + * Variables + ******************************************************************************/ +static uint32_t g_savedPrimask; + +/* + * The ram function code is: + * + * uint32_t i; + * for (i=0; i<0x8; i++) + * { + * __NOP(); + * } + * __DSB(); + * __WFI(); + * __ISB(); + * + * When entring the stop modes, the flash prefetch might be interrupted, thus + * the prefetched code or data might be broken. To make sure the flash is idle + * when entring the stop modes, the code is moved to ram. And delay for a while + * before WFI to make sure previous flash prefetch is finished. + * + * Only need to do like this when code is in flash, if code is in rom or ram, + * this is not necessary. + */ +static uint16_t s_stopRamFuncArray[] = { + 0x2000, /* MOVS R0, #0 */ + 0x2808, /* CMP R0, #8 */ + 0xD202, /* BCS.N */ + 0xBF00, /* NOP */ + 0x1C40, /* ADDS R0, R0, #1 */ + 0xE7FA, /* B.N */ + 0xF3BF, 0x8F4F, /* DSB */ + 0xBF30, /* WFI */ + 0xF3BF, 0x8F6F, /* ISB */ + 0x4770, /* BX LR */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void) +{ + uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U; + smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry; + stopRamFunc(); +} #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) +/*! + * brief Gets the SMC parameter. + * + * This function gets the SMC parameter including the enabled power mdoes. + * + * param base SMC peripheral base address. + * param param Pointer to the SMC param structure. + */ void SMC_GetParam(SMC_Type *base, smc_param_t *param) { - uint32_t reg = base->PARAM; + uint32_t reg = base->PARAM; param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK); - param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); - param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); + param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); + param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK); } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +/*! + * brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ void SMC_PreEnterStopModes(void) { - flash_prefetch_speculation_status_t speculationStatus = - { - kFLASH_prefetchSpeculationOptionDisable, /* Disable instruction speculation.*/ - kFLASH_prefetchSpeculationOptionDisable, /* Disable data speculation.*/ - }; - - __disable_irq(); + g_savedPrimask = DisableGlobalIRQ(); __ISB(); - - /* - * Before enter stop modes, the flash cache prefetch should be disabled. - * Otherwise the prefetch might be interrupted by stop, then the data and - * and instruction from flash are wrong. - */ - FLASH_PflashSetPrefetchSpeculation(&speculationStatus); } +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with ref SMC_PreEnterStopModes. + */ void SMC_PostExitStopModes(void) { - flash_prefetch_speculation_status_t speculationStatus = - { - kFLASH_prefetchSpeculationOptionEnable, /* Enable instruction speculation.*/ - kFLASH_prefetchSpeculationOptionEnable, /* Enable data speculation.*/ - }; - - FLASH_PflashSetPrefetchSpeculation(&speculationStatus); - - __enable_irq(); + EnableGlobalIRQ(g_savedPrimask); __ISB(); } +/*! + * brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Configures the system to RUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; reg = base->PMCTRL; /* configure Normal RUN mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) +/*! + * brief Configures the system to HSRUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeHsrun(SMC_Type *base) { uint8_t reg; @@ -96,13 +170,19 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base) reg = base->PMCTRL; /* configure High Speed RUN mode */ reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); + reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ +/*! + * brief Configures the system to WAIT power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ @@ -114,22 +194,29 @@ status_t SMC_SetPowerModeWait(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to Stop power mode. + * + * param base SMC peripheral base address. + * param option Partial Stop mode option. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) { uint8_t reg; #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO) - /* configure the Partial Stop mode in Noraml Stop mode */ + /* configure the Partial Stop mode in Normal Stop mode */ reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_PSTOPO_MASK; - reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK; + reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); base->STOPCTRL = reg; #endif /* configure Normal Stop mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ @@ -137,12 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter Stop mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -152,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) } } +/*! + * brief Configures the system to VLPR power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpr(SMC_Type *base #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) , bool wakeupMode #endif - ) +) { uint8_t reg; @@ -172,18 +263,24 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base else { /* remains in VLP mode on an interrupt */ - reg &= ~SMC_PMCTRL_LPWUI_MASK; + reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK; } #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /* configure VLPR mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } +/*! + * brief Configures the system to VLPW power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpw(SMC_Type *base) { /* configure VLPW mode */ @@ -196,14 +293,20 @@ status_t SMC_SetPowerModeVlpw(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to VLPS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlps(SMC_Type *base) { uint8_t reg; /* configure VLPS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ @@ -211,12 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter VLPS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -227,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) } #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to LLS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeLls(SMC_Type *base #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) , const smc_power_mode_lls_config_t *config #endif - ) +) { uint8_t reg; /* configure to LLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure LLS sub-mode*/ #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ @@ -267,12 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -284,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to VLLS power mode. + * + * param base SMC peripheral base address. + * param config The VLLS power mode configuration structure. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config) { uint8_t reg; @@ -296,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #endif { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enablePorDetectInVlls0) + if (true == config->enablePorDetectInVlls0) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK; #endif } else @@ -319,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t else if (config->subMode == kSMC_StopSub2) { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enableRam2InVlls2) + if (true == config->enableRam2InVlls2) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK; @@ -332,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK; #endif } } else { + /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */ } #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */ /* configure to VLLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure the VLLS sub-mode */ #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) reg = base->VLLSCTRL; reg &= ~SMC_VLLSCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); base->VLLSCTRL = reg; #else #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #else reg = base->STOPCTRL; reg &= ~SMC_STOPCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ #endif @@ -383,12 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_smc.h index b901468e70..e5c318e1a1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_smc.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SMC_H_ @@ -36,15 +14,14 @@ /*! @addtogroup smc */ /*! @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.3. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) +/*! @brief SMC driver version 2.0.5. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5)) /*@}*/ /*! @@ -64,18 +41,14 @@ typedef enum _smc_power_mode_protection #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_AVLLS_MASK + | SMC_PMPROT_AVLLS_MASK #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_ALLS_MASK + | SMC_PMPROT_ALLS_MASK #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - | - SMC_PMPROT_AVLP_MASK + | SMC_PMPROT_AVLP_MASK #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - | - kSMC_AllowPowerModeHsrun + | kSMC_AllowPowerModeHsrun #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ ) /*!< Allow all power mode. */ } smc_power_mode_protection_t; @@ -85,7 +58,7 @@ typedef enum _smc_power_mode_protection */ typedef enum _smc_power_state { - kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ + kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */ kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */ kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */ @@ -107,7 +80,7 @@ typedef enum _smc_power_state typedef enum _smc_run_mode { kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ @@ -119,7 +92,7 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ @@ -148,7 +121,7 @@ typedef enum _smc_stop_submode */ typedef enum _smc_partial_stop_mode { - kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ + kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/ kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/ } smc_partial_stop_option_t; @@ -324,11 +297,7 @@ void SMC_PostExitStopModes(void); * * This function should be called before entering WAIT/VLPW modes. */ -static inline void SMC_PreEnterWaitModes(void) -{ - __disable_irq(); - __ISB(); -} +void SMC_PreEnterWaitModes(void); /*! * @brief Recovers after wake up from stop modes. @@ -336,11 +305,7 @@ static inline void SMC_PreEnterWaitModes(void) * This function should be called after wake up from WAIT/VLPW modes. * It is used with @ref SMC_PreEnterWaitModes. */ -static inline void SMC_PostExitWaitModes(void) -{ - __enable_irq(); - __ISB(); -} +void SMC_PostExitWaitModes(void); /*! * @brief Configures the system to RUN power mode. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_smc.c index 0018cf7dce..b3998d0370 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_smc.c @@ -1,60 +1,168 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_smc.h" +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.smc" +#endif + +typedef void (*smc_stop_ram_func_t)(void); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void); + +/******************************************************************************* + * Variables + ******************************************************************************/ +static uint32_t g_savedPrimask; + +/* + * The ram function code is: + * + * uint32_t i; + * for (i=0; i<0x8; i++) + * { + * __NOP(); + * } + * __DSB(); + * __WFI(); + * __ISB(); + * + * When entring the stop modes, the flash prefetch might be interrupted, thus + * the prefetched code or data might be broken. To make sure the flash is idle + * when entring the stop modes, the code is moved to ram. And delay for a while + * before WFI to make sure previous flash prefetch is finished. + * + * Only need to do like this when code is in flash, if code is in rom or ram, + * this is not necessary. + */ +static uint16_t s_stopRamFuncArray[] = { + 0x2000, /* MOVS R0, #0 */ + 0x2808, /* CMP R0, #8 */ + 0xD202, /* BCS.N */ + 0xBF00, /* NOP */ + 0x1C40, /* ADDS R0, R0, #1 */ + 0xE7FA, /* B.N */ + 0xF3BF, 0x8F4F, /* DSB */ + 0xBF30, /* WFI */ + 0xF3BF, 0x8F6F, /* ISB */ + 0x4770, /* BX LR */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void) +{ + uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U; + smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry; + stopRamFunc(); +} #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) +/*! + * brief Gets the SMC parameter. + * + * This function gets the SMC parameter including the enabled power mdoes. + * + * param base SMC peripheral base address. + * param param Pointer to the SMC param structure. + */ void SMC_GetParam(SMC_Type *base, smc_param_t *param) { - uint32_t reg = base->PARAM; + uint32_t reg = base->PARAM; param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK); - param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); - param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); + param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); + param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK); } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +/*! + * brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Configures the system to RUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; reg = base->PMCTRL; /* configure Normal RUN mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) +/*! + * brief Configures the system to HSRUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeHsrun(SMC_Type *base) { uint8_t reg; @@ -62,38 +170,53 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base) reg = base->PMCTRL; /* configure High Speed RUN mode */ reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); + reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ +/*! + * brief Configures the system to WAIT power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + __DSB(); __WFI(); + __ISB(); return kStatus_Success; } +/*! + * brief Configures the system to Stop power mode. + * + * param base SMC peripheral base address. + * param option Partial Stop mode option. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) { uint8_t reg; #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO) - /* configure the Partial Stop mode in Noraml Stop mode */ + /* configure the Partial Stop mode in Normal Stop mode */ reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_PSTOPO_MASK; - reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK; + reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); base->STOPCTRL = reg; #endif /* configure Normal Stop mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ @@ -101,10 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter Stop mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -114,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) } } +/*! + * brief Configures the system to VLPR power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpr(SMC_Type *base #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) , bool wakeupMode #endif - ) +) { uint8_t reg; @@ -134,42 +263,50 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base else { /* remains in VLP mode on an interrupt */ - reg &= ~SMC_PMCTRL_LPWUI_MASK; + reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK; } #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /* configure VLPR mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } +/*! + * brief Configures the system to VLPW power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpw(SMC_Type *base) { - /* Power mode transaction to VLPW can only happen in VLPR mode */ - if (kSMC_PowerStateVlpr != SMC_GetPowerModeState(base)) - { - return kStatus_Fail; - } - /* configure VLPW mode */ /* Set the SLEEPDEEP bit to enable deep sleep mode */ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + __DSB(); __WFI(); + __ISB(); return kStatus_Success; } +/*! + * brief Configures the system to VLPS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlps(SMC_Type *base) { uint8_t reg; /* configure VLPS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ @@ -177,10 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter VLPS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -191,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) } #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to LLS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeLls(SMC_Type *base #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) , const smc_power_mode_lls_config_t *config #endif - ) +) { uint8_t reg; /* configure to LLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure LLS sub-mode*/ #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ @@ -231,10 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -246,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to VLLS power mode. + * + * param base SMC peripheral base address. + * param config The VLLS power mode configuration structure. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config) { uint8_t reg; @@ -258,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #endif { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enablePorDetectInVlls0) + if (true == config->enablePorDetectInVlls0) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK; #endif } else @@ -281,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t else if (config->subMode == kSMC_StopSub2) { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enableRam2InVlls2) + if (true == config->enableRam2InVlls2) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK; @@ -294,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK; #endif } } else { + /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */ } #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */ /* configure to VLLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure the VLLS sub-mode */ #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) reg = base->VLLSCTRL; reg &= ~SMC_VLLSCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); base->VLLSCTRL = reg; #else #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #else reg = base->STOPCTRL; reg &= ~SMC_STOPCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ #endif @@ -345,10 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_smc.h index 5149f87e34..e5c318e1a1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/drivers/fsl_smc.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SMC_H_ @@ -36,16 +14,14 @@ /*! @addtogroup smc */ /*! @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.1. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! @brief SMC driver version 2.0.5. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5)) /*@}*/ /*! @@ -54,29 +30,25 @@ typedef enum _smc_power_mode_protection { #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-low-leakage Stop Mode. */ #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-leakage Stop Mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */ + kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-power Mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */ + kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High-speed Run mode. */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_AVLLS_MASK + | SMC_PMPROT_AVLLS_MASK #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_ALLS_MASK + | SMC_PMPROT_ALLS_MASK #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - | - SMC_PMPROT_AVLP_MASK + | SMC_PMPROT_AVLP_MASK #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - | - kSMC_AllowPowerModeHsrun + | kSMC_AllowPowerModeHsrun #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ ) /*!< Allow all power mode. */ } smc_power_mode_protection_t; @@ -86,7 +58,7 @@ typedef enum _smc_power_mode_protection */ typedef enum _smc_power_state { - kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ + kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */ kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */ kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */ @@ -107,10 +79,10 @@ typedef enum _smc_power_state */ typedef enum _smc_run_mode { - kSMC_RunNormal = 0U, /*!< normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */ + kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */ + kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ } smc_run_mode_t; @@ -120,12 +92,12 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */ + kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_StopVlls = 4U /*!< Very-Low-Leakage Stop mode. */ + kSMC_StopVlls = 4U /*!< Very-low-leakage Stop mode. */ #endif } smc_stop_mode_t; @@ -149,13 +121,13 @@ typedef enum _smc_stop_submode */ typedef enum _smc_partial_stop_mode { - kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ + kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/ kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/ } smc_partial_stop_option_t; /*! - * @brief SMC configuration status + * @brief SMC configuration status. */ enum _smc_status { @@ -190,7 +162,7 @@ typedef struct _smc_param #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO) /*! - * @brief SMC Low-Leakage Stop power mode config + * @brief SMC Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_lls_config { @@ -205,7 +177,7 @@ typedef struct _smc_power_mode_lls_config #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief SMC Very Low-Leakage Stop power mode config + * @brief SMC Very Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_vlls_config { @@ -242,10 +214,10 @@ extern "C" { * @brief Gets the SMC version ID. * * This function gets the SMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and feature specification number. * * @param base SMC peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) { @@ -257,10 +229,10 @@ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) /*! * @brief Gets the SMC parameter. * - * This function gets the SMC parameter, including the enabled power mdoes. + * This function gets the SMC parameter including the enabled power mdoes. * * @param base SMC peripheral base address. - * @param param Pointer to SMC param structure. + * @param param Pointer to the SMC param structure. */ void SMC_GetParam(SMC_Type *base, smc_param_t *param); #endif @@ -274,7 +246,7 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param); * system level initialization stage. See the reference manual for details. * This register can only write once after the power reset. * - * The allowed modes are passed as bit map, for example, to allow LLS and VLLS, + * The allowed modes are passed as bit map. For example, to allow LLS and VLLS, * use SMC_SetPowerModeProtection(kSMC_AllowPowerModeVlls | kSMC_AllowPowerModeVlps). * To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll). * @@ -289,13 +261,13 @@ static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedMod /*! * @brief Gets the current power mode status. * - * This function returns the current power mode stat. Once application - * switches the power mode, it should always check the stat to check whether it - * runs into the specified mode or not. An application should check + * This function returns the current power mode status. After the application + * switches the power mode, it should always check the status to check whether it + * runs into the specified mode or not. The application should check * this mode before switching to a different mode. The system requires that * only certain modes can switch to other specific modes. See the * reference manual for details and the smc_power_state_t for information about - * the power stat. + * the power status. * * @param base SMC peripheral base address. * @return Current power mode status. @@ -306,7 +278,37 @@ static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base) } /*! - * @brief Configure the system to RUN power mode. + * @brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with @ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void); + +/*! + * @brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with @ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void); + +/*! + * @brief Configures the system to RUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -315,7 +317,7 @@ status_t SMC_SetPowerModeRun(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) /*! - * @brief Configure the system to HSRUN power mode. + * @brief Configures the system to HSRUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -324,7 +326,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ /*! - * @brief Configure the system to WAIT power mode. + * @brief Configures the system to WAIT power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -332,7 +334,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); status_t SMC_SetPowerModeWait(SMC_Type *base); /*! - * @brief Configure the system to Stop power mode. + * @brief Configures the system to Stop power mode. * * @param base SMC peripheral base address. * @param option Partial Stop mode option. @@ -342,7 +344,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @param wakeupMode Enter Normal Run mode if true, else stay in VLPR mode. @@ -351,7 +353,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); status_t SMC_SetPowerModeVlpr(SMC_Type *base, bool wakeupMode); #else /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -360,7 +362,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /*! - * @brief Configure the system to VLPW power mode. + * @brief Configures the system to VLPW power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -368,7 +370,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); status_t SMC_SetPowerModeVlpw(SMC_Type *base); /*! - * @brief Configure the system to VLPS power mode. + * @brief Configures the system to VLPS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -379,7 +381,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @param config The LLS power mode configuration structure @@ -388,7 +390,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); status_t SMC_SetPowerModeLls(SMC_Type *base, const smc_power_mode_lls_config_t *config); #else /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -399,7 +401,7 @@ status_t SMC_SetPowerModeLls(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief Configure the system to VLLS power mode. + * @brief Configures the system to VLLS power mode. * * @param base SMC peripheral base address. * @param config The VLLS power mode configuration structure. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_smc.c index 0018cf7dce..b3998d0370 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_smc.c @@ -1,60 +1,168 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_smc.h" +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.smc" +#endif + +typedef void (*smc_stop_ram_func_t)(void); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void); + +/******************************************************************************* + * Variables + ******************************************************************************/ +static uint32_t g_savedPrimask; + +/* + * The ram function code is: + * + * uint32_t i; + * for (i=0; i<0x8; i++) + * { + * __NOP(); + * } + * __DSB(); + * __WFI(); + * __ISB(); + * + * When entring the stop modes, the flash prefetch might be interrupted, thus + * the prefetched code or data might be broken. To make sure the flash is idle + * when entring the stop modes, the code is moved to ram. And delay for a while + * before WFI to make sure previous flash prefetch is finished. + * + * Only need to do like this when code is in flash, if code is in rom or ram, + * this is not necessary. + */ +static uint16_t s_stopRamFuncArray[] = { + 0x2000, /* MOVS R0, #0 */ + 0x2808, /* CMP R0, #8 */ + 0xD202, /* BCS.N */ + 0xBF00, /* NOP */ + 0x1C40, /* ADDS R0, R0, #1 */ + 0xE7FA, /* B.N */ + 0xF3BF, 0x8F4F, /* DSB */ + 0xBF30, /* WFI */ + 0xF3BF, 0x8F6F, /* ISB */ + 0x4770, /* BX LR */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void) +{ + uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U; + smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry; + stopRamFunc(); +} #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) +/*! + * brief Gets the SMC parameter. + * + * This function gets the SMC parameter including the enabled power mdoes. + * + * param base SMC peripheral base address. + * param param Pointer to the SMC param structure. + */ void SMC_GetParam(SMC_Type *base, smc_param_t *param) { - uint32_t reg = base->PARAM; + uint32_t reg = base->PARAM; param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK); - param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); - param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); + param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); + param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK); } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +/*! + * brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Configures the system to RUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; reg = base->PMCTRL; /* configure Normal RUN mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) +/*! + * brief Configures the system to HSRUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeHsrun(SMC_Type *base) { uint8_t reg; @@ -62,38 +170,53 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base) reg = base->PMCTRL; /* configure High Speed RUN mode */ reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); + reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ +/*! + * brief Configures the system to WAIT power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + __DSB(); __WFI(); + __ISB(); return kStatus_Success; } +/*! + * brief Configures the system to Stop power mode. + * + * param base SMC peripheral base address. + * param option Partial Stop mode option. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) { uint8_t reg; #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO) - /* configure the Partial Stop mode in Noraml Stop mode */ + /* configure the Partial Stop mode in Normal Stop mode */ reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_PSTOPO_MASK; - reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK; + reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); base->STOPCTRL = reg; #endif /* configure Normal Stop mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ @@ -101,10 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter Stop mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -114,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) } } +/*! + * brief Configures the system to VLPR power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpr(SMC_Type *base #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) , bool wakeupMode #endif - ) +) { uint8_t reg; @@ -134,42 +263,50 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base else { /* remains in VLP mode on an interrupt */ - reg &= ~SMC_PMCTRL_LPWUI_MASK; + reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK; } #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /* configure VLPR mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } +/*! + * brief Configures the system to VLPW power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpw(SMC_Type *base) { - /* Power mode transaction to VLPW can only happen in VLPR mode */ - if (kSMC_PowerStateVlpr != SMC_GetPowerModeState(base)) - { - return kStatus_Fail; - } - /* configure VLPW mode */ /* Set the SLEEPDEEP bit to enable deep sleep mode */ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + __DSB(); __WFI(); + __ISB(); return kStatus_Success; } +/*! + * brief Configures the system to VLPS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlps(SMC_Type *base) { uint8_t reg; /* configure VLPS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ @@ -177,10 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter VLPS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -191,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) } #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to LLS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeLls(SMC_Type *base #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) , const smc_power_mode_lls_config_t *config #endif - ) +) { uint8_t reg; /* configure to LLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure LLS sub-mode*/ #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ @@ -231,10 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -246,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to VLLS power mode. + * + * param base SMC peripheral base address. + * param config The VLLS power mode configuration structure. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config) { uint8_t reg; @@ -258,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #endif { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enablePorDetectInVlls0) + if (true == config->enablePorDetectInVlls0) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK; #endif } else @@ -281,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t else if (config->subMode == kSMC_StopSub2) { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enableRam2InVlls2) + if (true == config->enableRam2InVlls2) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK; @@ -294,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK; #endif } } else { + /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */ } #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */ /* configure to VLLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure the VLLS sub-mode */ #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) reg = base->VLLSCTRL; reg &= ~SMC_VLLSCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); base->VLLSCTRL = reg; #else #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #else reg = base->STOPCTRL; reg &= ~SMC_STOPCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ #endif @@ -345,10 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_smc.h index 5149f87e34..e5c318e1a1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/drivers/fsl_smc.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SMC_H_ @@ -36,16 +14,14 @@ /*! @addtogroup smc */ /*! @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.1. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! @brief SMC driver version 2.0.5. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5)) /*@}*/ /*! @@ -54,29 +30,25 @@ typedef enum _smc_power_mode_protection { #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-low-leakage Stop Mode. */ #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-leakage Stop Mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */ + kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-power Mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */ + kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High-speed Run mode. */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_AVLLS_MASK + | SMC_PMPROT_AVLLS_MASK #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_ALLS_MASK + | SMC_PMPROT_ALLS_MASK #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - | - SMC_PMPROT_AVLP_MASK + | SMC_PMPROT_AVLP_MASK #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - | - kSMC_AllowPowerModeHsrun + | kSMC_AllowPowerModeHsrun #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ ) /*!< Allow all power mode. */ } smc_power_mode_protection_t; @@ -86,7 +58,7 @@ typedef enum _smc_power_mode_protection */ typedef enum _smc_power_state { - kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ + kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */ kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */ kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */ @@ -107,10 +79,10 @@ typedef enum _smc_power_state */ typedef enum _smc_run_mode { - kSMC_RunNormal = 0U, /*!< normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */ + kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */ + kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ } smc_run_mode_t; @@ -120,12 +92,12 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */ + kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_StopVlls = 4U /*!< Very-Low-Leakage Stop mode. */ + kSMC_StopVlls = 4U /*!< Very-low-leakage Stop mode. */ #endif } smc_stop_mode_t; @@ -149,13 +121,13 @@ typedef enum _smc_stop_submode */ typedef enum _smc_partial_stop_mode { - kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ + kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/ kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/ } smc_partial_stop_option_t; /*! - * @brief SMC configuration status + * @brief SMC configuration status. */ enum _smc_status { @@ -190,7 +162,7 @@ typedef struct _smc_param #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO) /*! - * @brief SMC Low-Leakage Stop power mode config + * @brief SMC Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_lls_config { @@ -205,7 +177,7 @@ typedef struct _smc_power_mode_lls_config #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief SMC Very Low-Leakage Stop power mode config + * @brief SMC Very Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_vlls_config { @@ -242,10 +214,10 @@ extern "C" { * @brief Gets the SMC version ID. * * This function gets the SMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and feature specification number. * * @param base SMC peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) { @@ -257,10 +229,10 @@ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) /*! * @brief Gets the SMC parameter. * - * This function gets the SMC parameter, including the enabled power mdoes. + * This function gets the SMC parameter including the enabled power mdoes. * * @param base SMC peripheral base address. - * @param param Pointer to SMC param structure. + * @param param Pointer to the SMC param structure. */ void SMC_GetParam(SMC_Type *base, smc_param_t *param); #endif @@ -274,7 +246,7 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param); * system level initialization stage. See the reference manual for details. * This register can only write once after the power reset. * - * The allowed modes are passed as bit map, for example, to allow LLS and VLLS, + * The allowed modes are passed as bit map. For example, to allow LLS and VLLS, * use SMC_SetPowerModeProtection(kSMC_AllowPowerModeVlls | kSMC_AllowPowerModeVlps). * To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll). * @@ -289,13 +261,13 @@ static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedMod /*! * @brief Gets the current power mode status. * - * This function returns the current power mode stat. Once application - * switches the power mode, it should always check the stat to check whether it - * runs into the specified mode or not. An application should check + * This function returns the current power mode status. After the application + * switches the power mode, it should always check the status to check whether it + * runs into the specified mode or not. The application should check * this mode before switching to a different mode. The system requires that * only certain modes can switch to other specific modes. See the * reference manual for details and the smc_power_state_t for information about - * the power stat. + * the power status. * * @param base SMC peripheral base address. * @return Current power mode status. @@ -306,7 +278,37 @@ static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base) } /*! - * @brief Configure the system to RUN power mode. + * @brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with @ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void); + +/*! + * @brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with @ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void); + +/*! + * @brief Configures the system to RUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -315,7 +317,7 @@ status_t SMC_SetPowerModeRun(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) /*! - * @brief Configure the system to HSRUN power mode. + * @brief Configures the system to HSRUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -324,7 +326,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ /*! - * @brief Configure the system to WAIT power mode. + * @brief Configures the system to WAIT power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -332,7 +334,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); status_t SMC_SetPowerModeWait(SMC_Type *base); /*! - * @brief Configure the system to Stop power mode. + * @brief Configures the system to Stop power mode. * * @param base SMC peripheral base address. * @param option Partial Stop mode option. @@ -342,7 +344,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @param wakeupMode Enter Normal Run mode if true, else stay in VLPR mode. @@ -351,7 +353,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); status_t SMC_SetPowerModeVlpr(SMC_Type *base, bool wakeupMode); #else /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -360,7 +362,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /*! - * @brief Configure the system to VLPW power mode. + * @brief Configures the system to VLPW power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -368,7 +370,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); status_t SMC_SetPowerModeVlpw(SMC_Type *base); /*! - * @brief Configure the system to VLPS power mode. + * @brief Configures the system to VLPS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -379,7 +381,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @param config The LLS power mode configuration structure @@ -388,7 +390,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); status_t SMC_SetPowerModeLls(SMC_Type *base, const smc_power_mode_lls_config_t *config); #else /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -399,7 +401,7 @@ status_t SMC_SetPowerModeLls(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief Configure the system to VLLS power mode. + * @brief Configures the system to VLLS power mode. * * @param base SMC peripheral base address. * @param config The VLLS power mode configuration structure. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_smc.c index 45382fdffe..b3998d0370 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_smc.c @@ -1,60 +1,168 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_smc.h" +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.smc" +#endif + +typedef void (*smc_stop_ram_func_t)(void); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void); + +/******************************************************************************* + * Variables + ******************************************************************************/ +static uint32_t g_savedPrimask; + +/* + * The ram function code is: + * + * uint32_t i; + * for (i=0; i<0x8; i++) + * { + * __NOP(); + * } + * __DSB(); + * __WFI(); + * __ISB(); + * + * When entring the stop modes, the flash prefetch might be interrupted, thus + * the prefetched code or data might be broken. To make sure the flash is idle + * when entring the stop modes, the code is moved to ram. And delay for a while + * before WFI to make sure previous flash prefetch is finished. + * + * Only need to do like this when code is in flash, if code is in rom or ram, + * this is not necessary. + */ +static uint16_t s_stopRamFuncArray[] = { + 0x2000, /* MOVS R0, #0 */ + 0x2808, /* CMP R0, #8 */ + 0xD202, /* BCS.N */ + 0xBF00, /* NOP */ + 0x1C40, /* ADDS R0, R0, #1 */ + 0xE7FA, /* B.N */ + 0xF3BF, 0x8F4F, /* DSB */ + 0xBF30, /* WFI */ + 0xF3BF, 0x8F6F, /* ISB */ + 0x4770, /* BX LR */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void) +{ + uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U; + smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry; + stopRamFunc(); +} #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) +/*! + * brief Gets the SMC parameter. + * + * This function gets the SMC parameter including the enabled power mdoes. + * + * param base SMC peripheral base address. + * param param Pointer to the SMC param structure. + */ void SMC_GetParam(SMC_Type *base, smc_param_t *param) { - uint32_t reg = base->PARAM; + uint32_t reg = base->PARAM; param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK); - param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); - param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); + param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); + param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK); } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +/*! + * brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Configures the system to RUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; reg = base->PMCTRL; /* configure Normal RUN mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) +/*! + * brief Configures the system to HSRUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeHsrun(SMC_Type *base) { uint8_t reg; @@ -62,13 +170,19 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base) reg = base->PMCTRL; /* configure High Speed RUN mode */ reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); + reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ +/*! + * brief Configures the system to WAIT power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ @@ -80,22 +194,29 @@ status_t SMC_SetPowerModeWait(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to Stop power mode. + * + * param base SMC peripheral base address. + * param option Partial Stop mode option. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) { uint8_t reg; #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO) - /* configure the Partial Stop mode in Noraml Stop mode */ + /* configure the Partial Stop mode in Normal Stop mode */ reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_PSTOPO_MASK; - reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK; + reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); base->STOPCTRL = reg; #endif /* configure Normal Stop mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ @@ -103,12 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter Stop mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -118,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) } } +/*! + * brief Configures the system to VLPR power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpr(SMC_Type *base #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) , bool wakeupMode #endif - ) +) { uint8_t reg; @@ -138,18 +263,24 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base else { /* remains in VLP mode on an interrupt */ - reg &= ~SMC_PMCTRL_LPWUI_MASK; + reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK; } #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /* configure VLPR mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } +/*! + * brief Configures the system to VLPW power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpw(SMC_Type *base) { /* configure VLPW mode */ @@ -162,14 +293,20 @@ status_t SMC_SetPowerModeVlpw(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to VLPS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlps(SMC_Type *base) { uint8_t reg; /* configure VLPS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ @@ -177,12 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter VLPS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -193,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) } #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to LLS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeLls(SMC_Type *base #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) , const smc_power_mode_lls_config_t *config #endif - ) +) { uint8_t reg; /* configure to LLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure LLS sub-mode*/ #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ @@ -233,12 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -250,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to VLLS power mode. + * + * param base SMC peripheral base address. + * param config The VLLS power mode configuration structure. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config) { uint8_t reg; @@ -262,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #endif { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enablePorDetectInVlls0) + if (true == config->enablePorDetectInVlls0) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK; #endif } else @@ -285,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t else if (config->subMode == kSMC_StopSub2) { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enableRam2InVlls2) + if (true == config->enableRam2InVlls2) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK; @@ -298,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK; #endif } } else { + /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */ } #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */ /* configure to VLLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure the VLLS sub-mode */ #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) reg = base->VLLSCTRL; reg &= ~SMC_VLLSCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); base->VLLSCTRL = reg; #else #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #else reg = base->STOPCTRL; reg &= ~SMC_STOPCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ #endif @@ -349,12 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_smc.h index 4148734a2a..e5c318e1a1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_smc.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SMC_H_ @@ -36,15 +14,14 @@ /*! @addtogroup smc */ /*! @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.2. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) +/*! @brief SMC driver version 2.0.5. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5)) /*@}*/ /*! @@ -53,29 +30,25 @@ typedef enum _smc_power_mode_protection { #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-low-leakage Stop Mode. */ #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-leakage Stop Mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */ + kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-power Mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */ + kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High-speed Run mode. */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_AVLLS_MASK + | SMC_PMPROT_AVLLS_MASK #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_ALLS_MASK + | SMC_PMPROT_ALLS_MASK #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - | - SMC_PMPROT_AVLP_MASK + | SMC_PMPROT_AVLP_MASK #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - | - kSMC_AllowPowerModeHsrun + | kSMC_AllowPowerModeHsrun #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ ) /*!< Allow all power mode. */ } smc_power_mode_protection_t; @@ -85,7 +58,7 @@ typedef enum _smc_power_mode_protection */ typedef enum _smc_power_state { - kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ + kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */ kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */ kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */ @@ -106,10 +79,10 @@ typedef enum _smc_power_state */ typedef enum _smc_run_mode { - kSMC_RunNormal = 0U, /*!< normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */ + kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */ + kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ } smc_run_mode_t; @@ -119,12 +92,12 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */ + kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_StopVlls = 4U /*!< Very-Low-Leakage Stop mode. */ + kSMC_StopVlls = 4U /*!< Very-low-leakage Stop mode. */ #endif } smc_stop_mode_t; @@ -148,13 +121,13 @@ typedef enum _smc_stop_submode */ typedef enum _smc_partial_stop_mode { - kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ + kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/ kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/ } smc_partial_stop_option_t; /*! - * @brief SMC configuration status + * @brief SMC configuration status. */ enum _smc_status { @@ -189,7 +162,7 @@ typedef struct _smc_param #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO) /*! - * @brief SMC Low-Leakage Stop power mode config + * @brief SMC Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_lls_config { @@ -204,7 +177,7 @@ typedef struct _smc_power_mode_lls_config #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief SMC Very Low-Leakage Stop power mode config + * @brief SMC Very Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_vlls_config { @@ -241,10 +214,10 @@ extern "C" { * @brief Gets the SMC version ID. * * This function gets the SMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and feature specification number. * * @param base SMC peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) { @@ -256,10 +229,10 @@ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) /*! * @brief Gets the SMC parameter. * - * This function gets the SMC parameter, including the enabled power mdoes. + * This function gets the SMC parameter including the enabled power mdoes. * * @param base SMC peripheral base address. - * @param param Pointer to SMC param structure. + * @param param Pointer to the SMC param structure. */ void SMC_GetParam(SMC_Type *base, smc_param_t *param); #endif @@ -273,7 +246,7 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param); * system level initialization stage. See the reference manual for details. * This register can only write once after the power reset. * - * The allowed modes are passed as bit map, for example, to allow LLS and VLLS, + * The allowed modes are passed as bit map. For example, to allow LLS and VLLS, * use SMC_SetPowerModeProtection(kSMC_AllowPowerModeVlls | kSMC_AllowPowerModeVlps). * To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll). * @@ -288,13 +261,13 @@ static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedMod /*! * @brief Gets the current power mode status. * - * This function returns the current power mode stat. Once application - * switches the power mode, it should always check the stat to check whether it - * runs into the specified mode or not. An application should check + * This function returns the current power mode status. After the application + * switches the power mode, it should always check the status to check whether it + * runs into the specified mode or not. The application should check * this mode before switching to a different mode. The system requires that * only certain modes can switch to other specific modes. See the * reference manual for details and the smc_power_state_t for information about - * the power stat. + * the power status. * * @param base SMC peripheral base address. * @return Current power mode status. @@ -305,7 +278,37 @@ static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base) } /*! - * @brief Configure the system to RUN power mode. + * @brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with @ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void); + +/*! + * @brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with @ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void); + +/*! + * @brief Configures the system to RUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -314,7 +317,7 @@ status_t SMC_SetPowerModeRun(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) /*! - * @brief Configure the system to HSRUN power mode. + * @brief Configures the system to HSRUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -323,7 +326,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ /*! - * @brief Configure the system to WAIT power mode. + * @brief Configures the system to WAIT power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -331,7 +334,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); status_t SMC_SetPowerModeWait(SMC_Type *base); /*! - * @brief Configure the system to Stop power mode. + * @brief Configures the system to Stop power mode. * * @param base SMC peripheral base address. * @param option Partial Stop mode option. @@ -341,7 +344,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @param wakeupMode Enter Normal Run mode if true, else stay in VLPR mode. @@ -350,7 +353,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); status_t SMC_SetPowerModeVlpr(SMC_Type *base, bool wakeupMode); #else /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -359,7 +362,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /*! - * @brief Configure the system to VLPW power mode. + * @brief Configures the system to VLPW power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -367,7 +370,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); status_t SMC_SetPowerModeVlpw(SMC_Type *base); /*! - * @brief Configure the system to VLPS power mode. + * @brief Configures the system to VLPS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -378,7 +381,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @param config The LLS power mode configuration structure @@ -387,7 +390,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); status_t SMC_SetPowerModeLls(SMC_Type *base, const smc_power_mode_lls_config_t *config); #else /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -398,7 +401,7 @@ status_t SMC_SetPowerModeLls(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief Configure the system to VLLS power mode. + * @brief Configures the system to VLLS power mode. * * @param base SMC peripheral base address. * @param config The VLLS power mode configuration structure. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_smc.c index 45382fdffe..b3998d0370 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_smc.c @@ -1,60 +1,168 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_smc.h" +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.smc" +#endif + +typedef void (*smc_stop_ram_func_t)(void); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void); + +/******************************************************************************* + * Variables + ******************************************************************************/ +static uint32_t g_savedPrimask; + +/* + * The ram function code is: + * + * uint32_t i; + * for (i=0; i<0x8; i++) + * { + * __NOP(); + * } + * __DSB(); + * __WFI(); + * __ISB(); + * + * When entring the stop modes, the flash prefetch might be interrupted, thus + * the prefetched code or data might be broken. To make sure the flash is idle + * when entring the stop modes, the code is moved to ram. And delay for a while + * before WFI to make sure previous flash prefetch is finished. + * + * Only need to do like this when code is in flash, if code is in rom or ram, + * this is not necessary. + */ +static uint16_t s_stopRamFuncArray[] = { + 0x2000, /* MOVS R0, #0 */ + 0x2808, /* CMP R0, #8 */ + 0xD202, /* BCS.N */ + 0xBF00, /* NOP */ + 0x1C40, /* ADDS R0, R0, #1 */ + 0xE7FA, /* B.N */ + 0xF3BF, 0x8F4F, /* DSB */ + 0xBF30, /* WFI */ + 0xF3BF, 0x8F6F, /* ISB */ + 0x4770, /* BX LR */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void) +{ + uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U; + smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry; + stopRamFunc(); +} #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) +/*! + * brief Gets the SMC parameter. + * + * This function gets the SMC parameter including the enabled power mdoes. + * + * param base SMC peripheral base address. + * param param Pointer to the SMC param structure. + */ void SMC_GetParam(SMC_Type *base, smc_param_t *param) { - uint32_t reg = base->PARAM; + uint32_t reg = base->PARAM; param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK); - param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); - param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); + param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); + param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK); } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +/*! + * brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Configures the system to RUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; reg = base->PMCTRL; /* configure Normal RUN mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) +/*! + * brief Configures the system to HSRUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeHsrun(SMC_Type *base) { uint8_t reg; @@ -62,13 +170,19 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base) reg = base->PMCTRL; /* configure High Speed RUN mode */ reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); + reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ +/*! + * brief Configures the system to WAIT power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ @@ -80,22 +194,29 @@ status_t SMC_SetPowerModeWait(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to Stop power mode. + * + * param base SMC peripheral base address. + * param option Partial Stop mode option. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) { uint8_t reg; #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO) - /* configure the Partial Stop mode in Noraml Stop mode */ + /* configure the Partial Stop mode in Normal Stop mode */ reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_PSTOPO_MASK; - reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK; + reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); base->STOPCTRL = reg; #endif /* configure Normal Stop mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ @@ -103,12 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter Stop mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -118,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) } } +/*! + * brief Configures the system to VLPR power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpr(SMC_Type *base #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) , bool wakeupMode #endif - ) +) { uint8_t reg; @@ -138,18 +263,24 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base else { /* remains in VLP mode on an interrupt */ - reg &= ~SMC_PMCTRL_LPWUI_MASK; + reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK; } #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /* configure VLPR mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } +/*! + * brief Configures the system to VLPW power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpw(SMC_Type *base) { /* configure VLPW mode */ @@ -162,14 +293,20 @@ status_t SMC_SetPowerModeVlpw(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to VLPS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlps(SMC_Type *base) { uint8_t reg; /* configure VLPS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ @@ -177,12 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter VLPS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -193,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) } #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to LLS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeLls(SMC_Type *base #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) , const smc_power_mode_lls_config_t *config #endif - ) +) { uint8_t reg; /* configure to LLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure LLS sub-mode*/ #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ @@ -233,12 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -250,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to VLLS power mode. + * + * param base SMC peripheral base address. + * param config The VLLS power mode configuration structure. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config) { uint8_t reg; @@ -262,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #endif { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enablePorDetectInVlls0) + if (true == config->enablePorDetectInVlls0) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK; #endif } else @@ -285,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t else if (config->subMode == kSMC_StopSub2) { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enableRam2InVlls2) + if (true == config->enableRam2InVlls2) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK; @@ -298,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK; #endif } } else { + /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */ } #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */ /* configure to VLLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure the VLLS sub-mode */ #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) reg = base->VLLSCTRL; reg &= ~SMC_VLLSCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); base->VLLSCTRL = reg; #else #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #else reg = base->STOPCTRL; reg &= ~SMC_STOPCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ #endif @@ -349,12 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_smc.h index 4148734a2a..e5c318e1a1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_smc.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SMC_H_ @@ -36,15 +14,14 @@ /*! @addtogroup smc */ /*! @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.2. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) +/*! @brief SMC driver version 2.0.5. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5)) /*@}*/ /*! @@ -53,29 +30,25 @@ typedef enum _smc_power_mode_protection { #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-low-leakage Stop Mode. */ #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-leakage Stop Mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */ + kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-power Mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */ + kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High-speed Run mode. */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_AVLLS_MASK + | SMC_PMPROT_AVLLS_MASK #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_ALLS_MASK + | SMC_PMPROT_ALLS_MASK #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - | - SMC_PMPROT_AVLP_MASK + | SMC_PMPROT_AVLP_MASK #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - | - kSMC_AllowPowerModeHsrun + | kSMC_AllowPowerModeHsrun #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ ) /*!< Allow all power mode. */ } smc_power_mode_protection_t; @@ -85,7 +58,7 @@ typedef enum _smc_power_mode_protection */ typedef enum _smc_power_state { - kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ + kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */ kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */ kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */ @@ -106,10 +79,10 @@ typedef enum _smc_power_state */ typedef enum _smc_run_mode { - kSMC_RunNormal = 0U, /*!< normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */ + kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */ + kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ } smc_run_mode_t; @@ -119,12 +92,12 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */ + kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_StopVlls = 4U /*!< Very-Low-Leakage Stop mode. */ + kSMC_StopVlls = 4U /*!< Very-low-leakage Stop mode. */ #endif } smc_stop_mode_t; @@ -148,13 +121,13 @@ typedef enum _smc_stop_submode */ typedef enum _smc_partial_stop_mode { - kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ + kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/ kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/ } smc_partial_stop_option_t; /*! - * @brief SMC configuration status + * @brief SMC configuration status. */ enum _smc_status { @@ -189,7 +162,7 @@ typedef struct _smc_param #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO) /*! - * @brief SMC Low-Leakage Stop power mode config + * @brief SMC Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_lls_config { @@ -204,7 +177,7 @@ typedef struct _smc_power_mode_lls_config #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief SMC Very Low-Leakage Stop power mode config + * @brief SMC Very Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_vlls_config { @@ -241,10 +214,10 @@ extern "C" { * @brief Gets the SMC version ID. * * This function gets the SMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and feature specification number. * * @param base SMC peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) { @@ -256,10 +229,10 @@ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) /*! * @brief Gets the SMC parameter. * - * This function gets the SMC parameter, including the enabled power mdoes. + * This function gets the SMC parameter including the enabled power mdoes. * * @param base SMC peripheral base address. - * @param param Pointer to SMC param structure. + * @param param Pointer to the SMC param structure. */ void SMC_GetParam(SMC_Type *base, smc_param_t *param); #endif @@ -273,7 +246,7 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param); * system level initialization stage. See the reference manual for details. * This register can only write once after the power reset. * - * The allowed modes are passed as bit map, for example, to allow LLS and VLLS, + * The allowed modes are passed as bit map. For example, to allow LLS and VLLS, * use SMC_SetPowerModeProtection(kSMC_AllowPowerModeVlls | kSMC_AllowPowerModeVlps). * To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll). * @@ -288,13 +261,13 @@ static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedMod /*! * @brief Gets the current power mode status. * - * This function returns the current power mode stat. Once application - * switches the power mode, it should always check the stat to check whether it - * runs into the specified mode or not. An application should check + * This function returns the current power mode status. After the application + * switches the power mode, it should always check the status to check whether it + * runs into the specified mode or not. The application should check * this mode before switching to a different mode. The system requires that * only certain modes can switch to other specific modes. See the * reference manual for details and the smc_power_state_t for information about - * the power stat. + * the power status. * * @param base SMC peripheral base address. * @return Current power mode status. @@ -305,7 +278,37 @@ static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base) } /*! - * @brief Configure the system to RUN power mode. + * @brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with @ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void); + +/*! + * @brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with @ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void); + +/*! + * @brief Configures the system to RUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -314,7 +317,7 @@ status_t SMC_SetPowerModeRun(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) /*! - * @brief Configure the system to HSRUN power mode. + * @brief Configures the system to HSRUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -323,7 +326,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ /*! - * @brief Configure the system to WAIT power mode. + * @brief Configures the system to WAIT power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -331,7 +334,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); status_t SMC_SetPowerModeWait(SMC_Type *base); /*! - * @brief Configure the system to Stop power mode. + * @brief Configures the system to Stop power mode. * * @param base SMC peripheral base address. * @param option Partial Stop mode option. @@ -341,7 +344,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @param wakeupMode Enter Normal Run mode if true, else stay in VLPR mode. @@ -350,7 +353,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); status_t SMC_SetPowerModeVlpr(SMC_Type *base, bool wakeupMode); #else /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -359,7 +362,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /*! - * @brief Configure the system to VLPW power mode. + * @brief Configures the system to VLPW power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -367,7 +370,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); status_t SMC_SetPowerModeVlpw(SMC_Type *base); /*! - * @brief Configure the system to VLPS power mode. + * @brief Configures the system to VLPS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -378,7 +381,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @param config The LLS power mode configuration structure @@ -387,7 +390,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); status_t SMC_SetPowerModeLls(SMC_Type *base, const smc_power_mode_lls_config_t *config); #else /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -398,7 +401,7 @@ status_t SMC_SetPowerModeLls(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief Configure the system to VLLS power mode. + * @brief Configures the system to VLLS power mode. * * @param base SMC peripheral base address. * @param config The VLLS power mode configuration structure. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_smc.c index 45382fdffe..b3998d0370 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_smc.c @@ -1,60 +1,168 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_smc.h" +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.smc" +#endif + +typedef void (*smc_stop_ram_func_t)(void); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void); + +/******************************************************************************* + * Variables + ******************************************************************************/ +static uint32_t g_savedPrimask; + +/* + * The ram function code is: + * + * uint32_t i; + * for (i=0; i<0x8; i++) + * { + * __NOP(); + * } + * __DSB(); + * __WFI(); + * __ISB(); + * + * When entring the stop modes, the flash prefetch might be interrupted, thus + * the prefetched code or data might be broken. To make sure the flash is idle + * when entring the stop modes, the code is moved to ram. And delay for a while + * before WFI to make sure previous flash prefetch is finished. + * + * Only need to do like this when code is in flash, if code is in rom or ram, + * this is not necessary. + */ +static uint16_t s_stopRamFuncArray[] = { + 0x2000, /* MOVS R0, #0 */ + 0x2808, /* CMP R0, #8 */ + 0xD202, /* BCS.N */ + 0xBF00, /* NOP */ + 0x1C40, /* ADDS R0, R0, #1 */ + 0xE7FA, /* B.N */ + 0xF3BF, 0x8F4F, /* DSB */ + 0xBF30, /* WFI */ + 0xF3BF, 0x8F6F, /* ISB */ + 0x4770, /* BX LR */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void) +{ + uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U; + smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry; + stopRamFunc(); +} #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) +/*! + * brief Gets the SMC parameter. + * + * This function gets the SMC parameter including the enabled power mdoes. + * + * param base SMC peripheral base address. + * param param Pointer to the SMC param structure. + */ void SMC_GetParam(SMC_Type *base, smc_param_t *param) { - uint32_t reg = base->PARAM; + uint32_t reg = base->PARAM; param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK); - param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); - param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); + param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); + param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK); } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +/*! + * brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Configures the system to RUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; reg = base->PMCTRL; /* configure Normal RUN mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) +/*! + * brief Configures the system to HSRUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeHsrun(SMC_Type *base) { uint8_t reg; @@ -62,13 +170,19 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base) reg = base->PMCTRL; /* configure High Speed RUN mode */ reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); + reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ +/*! + * brief Configures the system to WAIT power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ @@ -80,22 +194,29 @@ status_t SMC_SetPowerModeWait(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to Stop power mode. + * + * param base SMC peripheral base address. + * param option Partial Stop mode option. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) { uint8_t reg; #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO) - /* configure the Partial Stop mode in Noraml Stop mode */ + /* configure the Partial Stop mode in Normal Stop mode */ reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_PSTOPO_MASK; - reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK; + reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); base->STOPCTRL = reg; #endif /* configure Normal Stop mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ @@ -103,12 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter Stop mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -118,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) } } +/*! + * brief Configures the system to VLPR power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpr(SMC_Type *base #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) , bool wakeupMode #endif - ) +) { uint8_t reg; @@ -138,18 +263,24 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base else { /* remains in VLP mode on an interrupt */ - reg &= ~SMC_PMCTRL_LPWUI_MASK; + reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK; } #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /* configure VLPR mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } +/*! + * brief Configures the system to VLPW power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpw(SMC_Type *base) { /* configure VLPW mode */ @@ -162,14 +293,20 @@ status_t SMC_SetPowerModeVlpw(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to VLPS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlps(SMC_Type *base) { uint8_t reg; /* configure VLPS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ @@ -177,12 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter VLPS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -193,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) } #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to LLS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeLls(SMC_Type *base #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) , const smc_power_mode_lls_config_t *config #endif - ) +) { uint8_t reg; /* configure to LLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure LLS sub-mode*/ #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ @@ -233,12 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -250,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to VLLS power mode. + * + * param base SMC peripheral base address. + * param config The VLLS power mode configuration structure. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config) { uint8_t reg; @@ -262,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #endif { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enablePorDetectInVlls0) + if (true == config->enablePorDetectInVlls0) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK; #endif } else @@ -285,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t else if (config->subMode == kSMC_StopSub2) { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enableRam2InVlls2) + if (true == config->enableRam2InVlls2) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK; @@ -298,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK; #endif } } else { + /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */ } #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */ /* configure to VLLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure the VLLS sub-mode */ #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) reg = base->VLLSCTRL; reg &= ~SMC_VLLSCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); base->VLLSCTRL = reg; #else #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #else reg = base->STOPCTRL; reg &= ~SMC_STOPCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ #endif @@ -349,12 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_smc.h index 4148734a2a..e5c318e1a1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_smc.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SMC_H_ @@ -36,15 +14,14 @@ /*! @addtogroup smc */ /*! @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.2. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) +/*! @brief SMC driver version 2.0.5. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5)) /*@}*/ /*! @@ -53,29 +30,25 @@ typedef enum _smc_power_mode_protection { #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-low-leakage Stop Mode. */ #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-leakage Stop Mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */ + kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-power Mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */ + kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High-speed Run mode. */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_AVLLS_MASK + | SMC_PMPROT_AVLLS_MASK #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_ALLS_MASK + | SMC_PMPROT_ALLS_MASK #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - | - SMC_PMPROT_AVLP_MASK + | SMC_PMPROT_AVLP_MASK #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - | - kSMC_AllowPowerModeHsrun + | kSMC_AllowPowerModeHsrun #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ ) /*!< Allow all power mode. */ } smc_power_mode_protection_t; @@ -85,7 +58,7 @@ typedef enum _smc_power_mode_protection */ typedef enum _smc_power_state { - kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ + kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */ kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */ kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */ @@ -106,10 +79,10 @@ typedef enum _smc_power_state */ typedef enum _smc_run_mode { - kSMC_RunNormal = 0U, /*!< normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */ + kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */ + kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ } smc_run_mode_t; @@ -119,12 +92,12 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */ + kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_StopVlls = 4U /*!< Very-Low-Leakage Stop mode. */ + kSMC_StopVlls = 4U /*!< Very-low-leakage Stop mode. */ #endif } smc_stop_mode_t; @@ -148,13 +121,13 @@ typedef enum _smc_stop_submode */ typedef enum _smc_partial_stop_mode { - kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ + kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/ kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/ } smc_partial_stop_option_t; /*! - * @brief SMC configuration status + * @brief SMC configuration status. */ enum _smc_status { @@ -189,7 +162,7 @@ typedef struct _smc_param #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO) /*! - * @brief SMC Low-Leakage Stop power mode config + * @brief SMC Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_lls_config { @@ -204,7 +177,7 @@ typedef struct _smc_power_mode_lls_config #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief SMC Very Low-Leakage Stop power mode config + * @brief SMC Very Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_vlls_config { @@ -241,10 +214,10 @@ extern "C" { * @brief Gets the SMC version ID. * * This function gets the SMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and feature specification number. * * @param base SMC peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) { @@ -256,10 +229,10 @@ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) /*! * @brief Gets the SMC parameter. * - * This function gets the SMC parameter, including the enabled power mdoes. + * This function gets the SMC parameter including the enabled power mdoes. * * @param base SMC peripheral base address. - * @param param Pointer to SMC param structure. + * @param param Pointer to the SMC param structure. */ void SMC_GetParam(SMC_Type *base, smc_param_t *param); #endif @@ -273,7 +246,7 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param); * system level initialization stage. See the reference manual for details. * This register can only write once after the power reset. * - * The allowed modes are passed as bit map, for example, to allow LLS and VLLS, + * The allowed modes are passed as bit map. For example, to allow LLS and VLLS, * use SMC_SetPowerModeProtection(kSMC_AllowPowerModeVlls | kSMC_AllowPowerModeVlps). * To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll). * @@ -288,13 +261,13 @@ static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedMod /*! * @brief Gets the current power mode status. * - * This function returns the current power mode stat. Once application - * switches the power mode, it should always check the stat to check whether it - * runs into the specified mode or not. An application should check + * This function returns the current power mode status. After the application + * switches the power mode, it should always check the status to check whether it + * runs into the specified mode or not. The application should check * this mode before switching to a different mode. The system requires that * only certain modes can switch to other specific modes. See the * reference manual for details and the smc_power_state_t for information about - * the power stat. + * the power status. * * @param base SMC peripheral base address. * @return Current power mode status. @@ -305,7 +278,37 @@ static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base) } /*! - * @brief Configure the system to RUN power mode. + * @brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with @ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void); + +/*! + * @brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with @ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void); + +/*! + * @brief Configures the system to RUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -314,7 +317,7 @@ status_t SMC_SetPowerModeRun(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) /*! - * @brief Configure the system to HSRUN power mode. + * @brief Configures the system to HSRUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -323,7 +326,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ /*! - * @brief Configure the system to WAIT power mode. + * @brief Configures the system to WAIT power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -331,7 +334,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); status_t SMC_SetPowerModeWait(SMC_Type *base); /*! - * @brief Configure the system to Stop power mode. + * @brief Configures the system to Stop power mode. * * @param base SMC peripheral base address. * @param option Partial Stop mode option. @@ -341,7 +344,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @param wakeupMode Enter Normal Run mode if true, else stay in VLPR mode. @@ -350,7 +353,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); status_t SMC_SetPowerModeVlpr(SMC_Type *base, bool wakeupMode); #else /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -359,7 +362,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /*! - * @brief Configure the system to VLPW power mode. + * @brief Configures the system to VLPW power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -367,7 +370,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); status_t SMC_SetPowerModeVlpw(SMC_Type *base); /*! - * @brief Configure the system to VLPS power mode. + * @brief Configures the system to VLPS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -378,7 +381,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @param config The LLS power mode configuration structure @@ -387,7 +390,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); status_t SMC_SetPowerModeLls(SMC_Type *base, const smc_power_mode_lls_config_t *config); #else /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -398,7 +401,7 @@ status_t SMC_SetPowerModeLls(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief Configure the system to VLLS power mode. + * @brief Configures the system to VLLS power mode. * * @param base SMC peripheral base address. * @param config The VLLS power mode configuration structure. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_smc.c index 0018cf7dce..b3998d0370 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_smc.c @@ -1,60 +1,168 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_smc.h" +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.smc" +#endif + +typedef void (*smc_stop_ram_func_t)(void); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void); + +/******************************************************************************* + * Variables + ******************************************************************************/ +static uint32_t g_savedPrimask; + +/* + * The ram function code is: + * + * uint32_t i; + * for (i=0; i<0x8; i++) + * { + * __NOP(); + * } + * __DSB(); + * __WFI(); + * __ISB(); + * + * When entring the stop modes, the flash prefetch might be interrupted, thus + * the prefetched code or data might be broken. To make sure the flash is idle + * when entring the stop modes, the code is moved to ram. And delay for a while + * before WFI to make sure previous flash prefetch is finished. + * + * Only need to do like this when code is in flash, if code is in rom or ram, + * this is not necessary. + */ +static uint16_t s_stopRamFuncArray[] = { + 0x2000, /* MOVS R0, #0 */ + 0x2808, /* CMP R0, #8 */ + 0xD202, /* BCS.N */ + 0xBF00, /* NOP */ + 0x1C40, /* ADDS R0, R0, #1 */ + 0xE7FA, /* B.N */ + 0xF3BF, 0x8F4F, /* DSB */ + 0xBF30, /* WFI */ + 0xF3BF, 0x8F6F, /* ISB */ + 0x4770, /* BX LR */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void) +{ + uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U; + smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry; + stopRamFunc(); +} #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) +/*! + * brief Gets the SMC parameter. + * + * This function gets the SMC parameter including the enabled power mdoes. + * + * param base SMC peripheral base address. + * param param Pointer to the SMC param structure. + */ void SMC_GetParam(SMC_Type *base, smc_param_t *param) { - uint32_t reg = base->PARAM; + uint32_t reg = base->PARAM; param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK); - param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); - param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); + param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); + param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK); } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +/*! + * brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Configures the system to RUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; reg = base->PMCTRL; /* configure Normal RUN mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) +/*! + * brief Configures the system to HSRUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeHsrun(SMC_Type *base) { uint8_t reg; @@ -62,38 +170,53 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base) reg = base->PMCTRL; /* configure High Speed RUN mode */ reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); + reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ +/*! + * brief Configures the system to WAIT power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + __DSB(); __WFI(); + __ISB(); return kStatus_Success; } +/*! + * brief Configures the system to Stop power mode. + * + * param base SMC peripheral base address. + * param option Partial Stop mode option. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) { uint8_t reg; #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO) - /* configure the Partial Stop mode in Noraml Stop mode */ + /* configure the Partial Stop mode in Normal Stop mode */ reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_PSTOPO_MASK; - reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK; + reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); base->STOPCTRL = reg; #endif /* configure Normal Stop mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ @@ -101,10 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter Stop mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -114,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) } } +/*! + * brief Configures the system to VLPR power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpr(SMC_Type *base #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) , bool wakeupMode #endif - ) +) { uint8_t reg; @@ -134,42 +263,50 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base else { /* remains in VLP mode on an interrupt */ - reg &= ~SMC_PMCTRL_LPWUI_MASK; + reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK; } #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /* configure VLPR mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } +/*! + * brief Configures the system to VLPW power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpw(SMC_Type *base) { - /* Power mode transaction to VLPW can only happen in VLPR mode */ - if (kSMC_PowerStateVlpr != SMC_GetPowerModeState(base)) - { - return kStatus_Fail; - } - /* configure VLPW mode */ /* Set the SLEEPDEEP bit to enable deep sleep mode */ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + __DSB(); __WFI(); + __ISB(); return kStatus_Success; } +/*! + * brief Configures the system to VLPS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlps(SMC_Type *base) { uint8_t reg; /* configure VLPS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ @@ -177,10 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter VLPS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -191,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) } #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to LLS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeLls(SMC_Type *base #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) , const smc_power_mode_lls_config_t *config #endif - ) +) { uint8_t reg; /* configure to LLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure LLS sub-mode*/ #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ @@ -231,10 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -246,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to VLLS power mode. + * + * param base SMC peripheral base address. + * param config The VLLS power mode configuration structure. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config) { uint8_t reg; @@ -258,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #endif { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enablePorDetectInVlls0) + if (true == config->enablePorDetectInVlls0) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK; #endif } else @@ -281,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t else if (config->subMode == kSMC_StopSub2) { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enableRam2InVlls2) + if (true == config->enableRam2InVlls2) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK; @@ -294,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK; #endif } } else { + /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */ } #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */ /* configure to VLLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure the VLLS sub-mode */ #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) reg = base->VLLSCTRL; reg &= ~SMC_VLLSCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); base->VLLSCTRL = reg; #else #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #else reg = base->STOPCTRL; reg &= ~SMC_STOPCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ #endif @@ -345,10 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __WFI(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_smc.h index 5149f87e34..e5c318e1a1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_smc.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SMC_H_ @@ -36,16 +14,14 @@ /*! @addtogroup smc */ /*! @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.1. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! @brief SMC driver version 2.0.5. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5)) /*@}*/ /*! @@ -54,29 +30,25 @@ typedef enum _smc_power_mode_protection { #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-low-leakage Stop Mode. */ #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-leakage Stop Mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */ + kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-power Mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */ + kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High-speed Run mode. */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_AVLLS_MASK + | SMC_PMPROT_AVLLS_MASK #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_ALLS_MASK + | SMC_PMPROT_ALLS_MASK #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - | - SMC_PMPROT_AVLP_MASK + | SMC_PMPROT_AVLP_MASK #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - | - kSMC_AllowPowerModeHsrun + | kSMC_AllowPowerModeHsrun #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ ) /*!< Allow all power mode. */ } smc_power_mode_protection_t; @@ -86,7 +58,7 @@ typedef enum _smc_power_mode_protection */ typedef enum _smc_power_state { - kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ + kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */ kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */ kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */ @@ -107,10 +79,10 @@ typedef enum _smc_power_state */ typedef enum _smc_run_mode { - kSMC_RunNormal = 0U, /*!< normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */ + kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */ + kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ } smc_run_mode_t; @@ -120,12 +92,12 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */ + kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_StopVlls = 4U /*!< Very-Low-Leakage Stop mode. */ + kSMC_StopVlls = 4U /*!< Very-low-leakage Stop mode. */ #endif } smc_stop_mode_t; @@ -149,13 +121,13 @@ typedef enum _smc_stop_submode */ typedef enum _smc_partial_stop_mode { - kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ + kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/ kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/ } smc_partial_stop_option_t; /*! - * @brief SMC configuration status + * @brief SMC configuration status. */ enum _smc_status { @@ -190,7 +162,7 @@ typedef struct _smc_param #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO) /*! - * @brief SMC Low-Leakage Stop power mode config + * @brief SMC Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_lls_config { @@ -205,7 +177,7 @@ typedef struct _smc_power_mode_lls_config #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief SMC Very Low-Leakage Stop power mode config + * @brief SMC Very Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_vlls_config { @@ -242,10 +214,10 @@ extern "C" { * @brief Gets the SMC version ID. * * This function gets the SMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and feature specification number. * * @param base SMC peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) { @@ -257,10 +229,10 @@ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) /*! * @brief Gets the SMC parameter. * - * This function gets the SMC parameter, including the enabled power mdoes. + * This function gets the SMC parameter including the enabled power mdoes. * * @param base SMC peripheral base address. - * @param param Pointer to SMC param structure. + * @param param Pointer to the SMC param structure. */ void SMC_GetParam(SMC_Type *base, smc_param_t *param); #endif @@ -274,7 +246,7 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param); * system level initialization stage. See the reference manual for details. * This register can only write once after the power reset. * - * The allowed modes are passed as bit map, for example, to allow LLS and VLLS, + * The allowed modes are passed as bit map. For example, to allow LLS and VLLS, * use SMC_SetPowerModeProtection(kSMC_AllowPowerModeVlls | kSMC_AllowPowerModeVlps). * To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll). * @@ -289,13 +261,13 @@ static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedMod /*! * @brief Gets the current power mode status. * - * This function returns the current power mode stat. Once application - * switches the power mode, it should always check the stat to check whether it - * runs into the specified mode or not. An application should check + * This function returns the current power mode status. After the application + * switches the power mode, it should always check the status to check whether it + * runs into the specified mode or not. The application should check * this mode before switching to a different mode. The system requires that * only certain modes can switch to other specific modes. See the * reference manual for details and the smc_power_state_t for information about - * the power stat. + * the power status. * * @param base SMC peripheral base address. * @return Current power mode status. @@ -306,7 +278,37 @@ static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base) } /*! - * @brief Configure the system to RUN power mode. + * @brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with @ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void); + +/*! + * @brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with @ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void); + +/*! + * @brief Configures the system to RUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -315,7 +317,7 @@ status_t SMC_SetPowerModeRun(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) /*! - * @brief Configure the system to HSRUN power mode. + * @brief Configures the system to HSRUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -324,7 +326,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ /*! - * @brief Configure the system to WAIT power mode. + * @brief Configures the system to WAIT power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -332,7 +334,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); status_t SMC_SetPowerModeWait(SMC_Type *base); /*! - * @brief Configure the system to Stop power mode. + * @brief Configures the system to Stop power mode. * * @param base SMC peripheral base address. * @param option Partial Stop mode option. @@ -342,7 +344,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @param wakeupMode Enter Normal Run mode if true, else stay in VLPR mode. @@ -351,7 +353,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); status_t SMC_SetPowerModeVlpr(SMC_Type *base, bool wakeupMode); #else /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -360,7 +362,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /*! - * @brief Configure the system to VLPW power mode. + * @brief Configures the system to VLPW power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -368,7 +370,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); status_t SMC_SetPowerModeVlpw(SMC_Type *base); /*! - * @brief Configure the system to VLPS power mode. + * @brief Configures the system to VLPS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -379,7 +381,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @param config The LLS power mode configuration structure @@ -388,7 +390,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); status_t SMC_SetPowerModeLls(SMC_Type *base, const smc_power_mode_lls_config_t *config); #else /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -399,7 +401,7 @@ status_t SMC_SetPowerModeLls(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief Configure the system to VLLS power mode. + * @brief Configures the system to VLLS power mode. * * @param base SMC peripheral base address. * @param config The VLLS power mode configuration structure. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_smc.c index dacf193476..b3998d0370 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_smc.c @@ -1,94 +1,168 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright 2016-2017 NXP + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of the copyright holder 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_smc.h" -#include "fsl_flash.h" +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.smc" +#endif + +typedef void (*smc_stop_ram_func_t)(void); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void); + +/******************************************************************************* + * Variables + ******************************************************************************/ +static uint32_t g_savedPrimask; + +/* + * The ram function code is: + * + * uint32_t i; + * for (i=0; i<0x8; i++) + * { + * __NOP(); + * } + * __DSB(); + * __WFI(); + * __ISB(); + * + * When entring the stop modes, the flash prefetch might be interrupted, thus + * the prefetched code or data might be broken. To make sure the flash is idle + * when entring the stop modes, the code is moved to ram. And delay for a while + * before WFI to make sure previous flash prefetch is finished. + * + * Only need to do like this when code is in flash, if code is in rom or ram, + * this is not necessary. + */ +static uint16_t s_stopRamFuncArray[] = { + 0x2000, /* MOVS R0, #0 */ + 0x2808, /* CMP R0, #8 */ + 0xD202, /* BCS.N */ + 0xBF00, /* NOP */ + 0x1C40, /* ADDS R0, R0, #1 */ + 0xE7FA, /* B.N */ + 0xF3BF, 0x8F4F, /* DSB */ + 0xBF30, /* WFI */ + 0xF3BF, 0x8F6F, /* ISB */ + 0x4770, /* BX LR */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void) +{ + uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U; + smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry; + stopRamFunc(); +} #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) +/*! + * brief Gets the SMC parameter. + * + * This function gets the SMC parameter including the enabled power mdoes. + * + * param base SMC peripheral base address. + * param param Pointer to the SMC param structure. + */ void SMC_GetParam(SMC_Type *base, smc_param_t *param) { - uint32_t reg = base->PARAM; + uint32_t reg = base->PARAM; param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK); - param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); - param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); + param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); + param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK); } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +/*! + * brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ void SMC_PreEnterStopModes(void) { - flash_prefetch_speculation_status_t speculationStatus = - { - kFLASH_prefetchSpeculationOptionDisable, /* Disable instruction speculation.*/ - kFLASH_prefetchSpeculationOptionDisable, /* Disable data speculation.*/ - }; - - __disable_irq(); + g_savedPrimask = DisableGlobalIRQ(); __ISB(); - - /* - * Before enter stop modes, the flash cache prefetch should be disabled. - * Otherwise the prefetch might be interrupted by stop, then the data and - * and instruction from flash are wrong. - */ - FLASH_PflashSetPrefetchSpeculation(&speculationStatus); } +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with ref SMC_PreEnterStopModes. + */ void SMC_PostExitStopModes(void) { - flash_prefetch_speculation_status_t speculationStatus = - { - kFLASH_prefetchSpeculationOptionEnable, /* Enable instruction speculation.*/ - kFLASH_prefetchSpeculationOptionEnable, /* Enable data speculation.*/ - }; - - FLASH_PflashSetPrefetchSpeculation(&speculationStatus); - - __enable_irq(); + EnableGlobalIRQ(g_savedPrimask); __ISB(); } +/*! + * brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Configures the system to RUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; reg = base->PMCTRL; /* configure Normal RUN mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) +/*! + * brief Configures the system to HSRUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeHsrun(SMC_Type *base) { uint8_t reg; @@ -96,13 +170,19 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base) reg = base->PMCTRL; /* configure High Speed RUN mode */ reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); + reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ +/*! + * brief Configures the system to WAIT power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ @@ -114,22 +194,29 @@ status_t SMC_SetPowerModeWait(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to Stop power mode. + * + * param base SMC peripheral base address. + * param option Partial Stop mode option. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) { uint8_t reg; #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO) - /* configure the Partial Stop mode in Noraml Stop mode */ + /* configure the Partial Stop mode in Normal Stop mode */ reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_PSTOPO_MASK; - reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK; + reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); base->STOPCTRL = reg; #endif /* configure Normal Stop mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ @@ -137,12 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter Stop mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -152,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) } } +/*! + * brief Configures the system to VLPR power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpr(SMC_Type *base #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) , bool wakeupMode #endif - ) +) { uint8_t reg; @@ -172,18 +263,24 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base else { /* remains in VLP mode on an interrupt */ - reg &= ~SMC_PMCTRL_LPWUI_MASK; + reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK; } #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /* configure VLPR mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } +/*! + * brief Configures the system to VLPW power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpw(SMC_Type *base) { /* configure VLPW mode */ @@ -196,14 +293,20 @@ status_t SMC_SetPowerModeVlpw(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to VLPS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlps(SMC_Type *base) { uint8_t reg; /* configure VLPS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ @@ -211,12 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter VLPS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -227,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) } #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to LLS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeLls(SMC_Type *base #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) , const smc_power_mode_lls_config_t *config #endif - ) +) { uint8_t reg; /* configure to LLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure LLS sub-mode*/ #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ @@ -267,12 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -284,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to VLLS power mode. + * + * param base SMC peripheral base address. + * param config The VLLS power mode configuration structure. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config) { uint8_t reg; @@ -296,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #endif { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enablePorDetectInVlls0) + if (true == config->enablePorDetectInVlls0) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK; #endif } else @@ -319,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t else if (config->subMode == kSMC_StopSub2) { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enableRam2InVlls2) + if (true == config->enableRam2InVlls2) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK; @@ -332,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK; #endif } } else { + /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */ } #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */ /* configure to VLLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure the VLLS sub-mode */ #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) reg = base->VLLSCTRL; reg &= ~SMC_VLLSCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); base->VLLSCTRL = reg; #else #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #else reg = base->STOPCTRL; reg &= ~SMC_STOPCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ #endif @@ -383,12 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_smc.h index 168ce83501..e5c318e1a1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_smc.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright 2016-2017 NXP + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of the copyright holder 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SMC_H_ @@ -36,15 +14,14 @@ /*! @addtogroup smc */ /*! @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.3. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) +/*! @brief SMC driver version 2.0.5. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5)) /*@}*/ /*! @@ -64,18 +41,14 @@ typedef enum _smc_power_mode_protection #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_AVLLS_MASK + | SMC_PMPROT_AVLLS_MASK #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_ALLS_MASK + | SMC_PMPROT_ALLS_MASK #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - | - SMC_PMPROT_AVLP_MASK + | SMC_PMPROT_AVLP_MASK #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - | - kSMC_AllowPowerModeHsrun + | kSMC_AllowPowerModeHsrun #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ ) /*!< Allow all power mode. */ } smc_power_mode_protection_t; @@ -85,7 +58,7 @@ typedef enum _smc_power_mode_protection */ typedef enum _smc_power_state { - kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ + kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */ kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */ kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */ @@ -107,7 +80,7 @@ typedef enum _smc_power_state typedef enum _smc_run_mode { kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ @@ -119,7 +92,7 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ @@ -148,7 +121,7 @@ typedef enum _smc_stop_submode */ typedef enum _smc_partial_stop_mode { - kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ + kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/ kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/ } smc_partial_stop_option_t; @@ -324,11 +297,7 @@ void SMC_PostExitStopModes(void); * * This function should be called before entering WAIT/VLPW modes. */ -static inline void SMC_PreEnterWaitModes(void) -{ - __disable_irq(); - __ISB(); -} +void SMC_PreEnterWaitModes(void); /*! * @brief Recovers after wake up from stop modes. @@ -336,11 +305,7 @@ static inline void SMC_PreEnterWaitModes(void) * This function should be called after wake up from WAIT/VLPW modes. * It is used with @ref SMC_PreEnterWaitModes. */ -static inline void SMC_PostExitWaitModes(void) -{ - __enable_irq(); - __ISB(); -} +void SMC_PostExitWaitModes(void); /*! * @brief Configures the system to RUN power mode. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_smc.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_smc.c index 5c86e3366b..b3998d0370 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_smc.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_smc.c @@ -1,94 +1,168 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_smc.h" -#include "fsl_flash.h" +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.smc" +#endif + +typedef void (*smc_stop_ram_func_t)(void); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void); + +/******************************************************************************* + * Variables + ******************************************************************************/ +static uint32_t g_savedPrimask; + +/* + * The ram function code is: + * + * uint32_t i; + * for (i=0; i<0x8; i++) + * { + * __NOP(); + * } + * __DSB(); + * __WFI(); + * __ISB(); + * + * When entring the stop modes, the flash prefetch might be interrupted, thus + * the prefetched code or data might be broken. To make sure the flash is idle + * when entring the stop modes, the code is moved to ram. And delay for a while + * before WFI to make sure previous flash prefetch is finished. + * + * Only need to do like this when code is in flash, if code is in rom or ram, + * this is not necessary. + */ +static uint16_t s_stopRamFuncArray[] = { + 0x2000, /* MOVS R0, #0 */ + 0x2808, /* CMP R0, #8 */ + 0xD202, /* BCS.N */ + 0xBF00, /* NOP */ + 0x1C40, /* ADDS R0, R0, #1 */ + 0xE7FA, /* B.N */ + 0xF3BF, 0x8F4F, /* DSB */ + 0xBF30, /* WFI */ + 0xF3BF, 0x8F6F, /* ISB */ + 0x4770, /* BX LR */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +static void SMC_EnterStopRamFunc(void) +{ + uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U; + smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry; + stopRamFunc(); +} #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) +/*! + * brief Gets the SMC parameter. + * + * This function gets the SMC parameter including the enabled power mdoes. + * + * param base SMC peripheral base address. + * param param Pointer to the SMC param structure. + */ void SMC_GetParam(SMC_Type *base, smc_param_t *param) { - uint32_t reg = base->PARAM; + uint32_t reg = base->PARAM; param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK); - param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); - param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); + param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); + param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK); } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +/*! + * brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ void SMC_PreEnterStopModes(void) { - flash_prefetch_speculation_status_t speculationStatus = - { - kFLASH_prefetchSpeculationOptionDisable, /* Disable instruction speculation.*/ - kFLASH_prefetchSpeculationOptionDisable, /* Disable data speculation.*/ - }; - - __disable_irq(); + g_savedPrimask = DisableGlobalIRQ(); __ISB(); - - /* - * Before enter stop modes, the flash cache prefetch should be disabled. - * Otherwise the prefetch might be interrupted by stop, then the data and - * and instruction from flash are wrong. - */ - FLASH_PflashSetPrefetchSpeculation(&speculationStatus); } +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with ref SMC_PreEnterStopModes. + */ void SMC_PostExitStopModes(void) { - flash_prefetch_speculation_status_t speculationStatus = - { - kFLASH_prefetchSpeculationOptionEnable, /* Enable instruction speculation.*/ - kFLASH_prefetchSpeculationOptionEnable, /* Enable data speculation.*/ - }; - - FLASH_PflashSetPrefetchSpeculation(&speculationStatus); - - __enable_irq(); + EnableGlobalIRQ(g_savedPrimask); __ISB(); } +/*! + * brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +void SMC_PreEnterWaitModes(void) +{ + g_savedPrimask = DisableGlobalIRQ(); + __ISB(); +} + +/*! + * brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with ref SMC_PreEnterWaitModes. + */ +void SMC_PostExitWaitModes(void) +{ + EnableGlobalIRQ(g_savedPrimask); + __ISB(); +} + +/*! + * brief Configures the system to RUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; reg = base->PMCTRL; /* configure Normal RUN mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) +/*! + * brief Configures the system to HSRUN power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeHsrun(SMC_Type *base) { uint8_t reg; @@ -96,13 +170,19 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base) reg = base->PMCTRL; /* configure High Speed RUN mode */ reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); + reg |= ((uint8_t)kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ +/*! + * brief Configures the system to WAIT power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeWait(SMC_Type *base) { /* configure Normal Wait mode */ @@ -114,22 +194,29 @@ status_t SMC_SetPowerModeWait(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to Stop power mode. + * + * param base SMC peripheral base address. + * param option Partial Stop mode option. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) { uint8_t reg; #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO) - /* configure the Partial Stop mode in Noraml Stop mode */ + /* configure the Partial Stop mode in Normal Stop mode */ reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_PSTOPO_MASK; - reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_PSTOPO_MASK; + reg |= ((uint8_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); base->STOPCTRL = reg; #endif /* configure Normal Stop mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ @@ -137,12 +224,10 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter Stop mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -152,12 +237,18 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) } } +/*! + * brief Configures the system to VLPR power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpr(SMC_Type *base #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) , bool wakeupMode #endif - ) +) { uint8_t reg; @@ -172,18 +263,24 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base else { /* remains in VLP mode on an interrupt */ - reg &= ~SMC_PMCTRL_LPWUI_MASK; + reg &= ~(uint8_t)SMC_PMCTRL_LPWUI_MASK; } #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /* configure VLPR mode */ - reg &= ~SMC_PMCTRL_RUNM_MASK; - reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_RUNM_MASK; + reg |= ((uint8_t)kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); base->PMCTRL = reg; return kStatus_Success; } +/*! + * brief Configures the system to VLPW power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlpw(SMC_Type *base) { /* configure VLPW mode */ @@ -196,14 +293,20 @@ status_t SMC_SetPowerModeVlpw(SMC_Type *base) return kStatus_Success; } +/*! + * brief Configures the system to VLPS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlps(SMC_Type *base) { uint8_t reg; /* configure VLPS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* Set the SLEEPDEEP bit to enable deep sleep mode */ @@ -211,12 +314,10 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter VLPS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -227,27 +328,33 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base) } #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to LLS power mode. + * + * param base SMC peripheral base address. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeLls(SMC_Type *base #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) , const smc_power_mode_lls_config_t *config #endif - ) +) { uint8_t reg; /* configure to LLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure LLS sub-mode*/ #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ @@ -267,12 +374,10 @@ status_t SMC_SetPowerModeLls(SMC_Type *base /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } @@ -284,6 +389,13 @@ status_t SMC_SetPowerModeLls(SMC_Type *base #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) +/*! + * brief Configures the system to VLLS power mode. + * + * param base SMC peripheral base address. + * param config The VLLS power mode configuration structure. + * return SMC configuration error code. + */ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config) { uint8_t reg; @@ -296,12 +408,12 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #endif { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enablePorDetectInVlls0) + if (true == config->enablePorDetectInVlls0) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_PORPO_MASK; #endif } else @@ -319,7 +431,7 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t else if (config->subMode == kSMC_StopSub2) { /* configure whether the Por Detect work in Vlls0 mode */ - if (config->enableRam2InVlls2) + if (true == config->enableRam2InVlls2) { #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK; @@ -332,37 +444,38 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK; #else - base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK; + base->STOPCTRL &= ~(uint8_t)SMC_STOPCTRL_RAM2PO_MASK; #endif } } else { + /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */ } #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */ /* configure to VLLS mode */ reg = base->PMCTRL; - reg &= ~SMC_PMCTRL_STOPM_MASK; - reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); + reg &= ~(uint8_t)SMC_PMCTRL_STOPM_MASK; + reg |= ((uint8_t)kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); base->PMCTRL = reg; /* configure the VLLS sub-mode */ #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) reg = base->VLLSCTRL; reg &= ~SMC_VLLSCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); base->VLLSCTRL = reg; #else #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) reg = base->STOPCTRL; - reg &= ~SMC_STOPCTRL_LLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); + reg &= ~(uint8_t)SMC_STOPCTRL_LLSM_MASK; + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); base->STOPCTRL = reg; #else reg = base->STOPCTRL; reg &= ~SMC_STOPCTRL_VLLSM_MASK; - reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); + reg |= ((uint8_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); base->STOPCTRL = reg; #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ #endif @@ -383,12 +496,10 @@ status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t /* read back to make sure the configuration valid before enter stop mode */ (void)base->PMCTRL; - __DSB(); - __WFI(); - __ISB(); + SMC_EnterStopRamFunc(); /* check whether the power mode enter LLS mode succeed */ - if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) + if (0U != (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)) { return kStatus_SMC_StopAbort; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_smc.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_smc.h index b901468e70..e5c318e1a1 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_smc.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_smc.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o 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. - * - * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SMC_H_ @@ -36,15 +14,14 @@ /*! @addtogroup smc */ /*! @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.3. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) +/*! @brief SMC driver version 2.0.5. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 5)) /*@}*/ /*! @@ -64,18 +41,14 @@ typedef enum _smc_power_mode_protection #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_AVLLS_MASK + | SMC_PMPROT_AVLLS_MASK #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - | - SMC_PMPROT_ALLS_MASK + | SMC_PMPROT_ALLS_MASK #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - | - SMC_PMPROT_AVLP_MASK + | SMC_PMPROT_AVLP_MASK #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - | - kSMC_AllowPowerModeHsrun + | kSMC_AllowPowerModeHsrun #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ ) /*!< Allow all power mode. */ } smc_power_mode_protection_t; @@ -85,7 +58,7 @@ typedef enum _smc_power_mode_protection */ typedef enum _smc_power_state { - kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ + kSMC_PowerStateRun = 0x01U << 0U, /*!< 0000_0001 - Current power mode is RUN */ kSMC_PowerStateStop = 0x01U << 1U, /*!< 0000_0010 - Current power mode is STOP */ kSMC_PowerStateVlpr = 0x01U << 2U, /*!< 0000_0100 - Current power mode is VLPR */ kSMC_PowerStateVlpw = 0x01U << 3U, /*!< 0000_1000 - Current power mode is VLPW */ @@ -107,7 +80,7 @@ typedef enum _smc_power_state typedef enum _smc_run_mode { kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ @@ -119,7 +92,7 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ @@ -148,7 +121,7 @@ typedef enum _smc_stop_submode */ typedef enum _smc_partial_stop_mode { - kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ + kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/ kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/ kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/ } smc_partial_stop_option_t; @@ -324,11 +297,7 @@ void SMC_PostExitStopModes(void); * * This function should be called before entering WAIT/VLPW modes. */ -static inline void SMC_PreEnterWaitModes(void) -{ - __disable_irq(); - __ISB(); -} +void SMC_PreEnterWaitModes(void); /*! * @brief Recovers after wake up from stop modes. @@ -336,11 +305,7 @@ static inline void SMC_PreEnterWaitModes(void) * This function should be called after wake up from WAIT/VLPW modes. * It is used with @ref SMC_PreEnterWaitModes. */ -static inline void SMC_PostExitWaitModes(void) -{ - __enable_irq(); - __ISB(); -} +void SMC_PostExitWaitModes(void); /*! * @brief Configures the system to RUN power mode.