Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
fsl_smc.c
00001 /* 00002 * Copyright (c) 2015, Freescale Semiconductor, Inc. 00003 * Copyright 2016-2017 NXP 00004 * All rights reserved. 00005 * 00006 * SPDX-License-Identifier: BSD-3-Clause 00007 */ 00008 00009 #include "fsl_smc.h" 00010 #include "fsl_common.h" 00011 00012 /******************************************************************************* 00013 * Definitions 00014 ******************************************************************************/ 00015 /* Component ID definition, used by tools. */ 00016 #ifndef FSL_COMPONENT_ID 00017 #define FSL_COMPONENT_ID "platform.drivers.smc" 00018 #endif 00019 00020 typedef void (*smc_stop_ram_func_t)(void); 00021 00022 /******************************************************************************* 00023 * Prototypes 00024 ******************************************************************************/ 00025 static void SMC_EnterStopRamFunc(void); 00026 00027 /******************************************************************************* 00028 * Variables 00029 ******************************************************************************/ 00030 static uint32_t g_savedPrimask; 00031 00032 /* 00033 * The ram function code is: 00034 * 00035 * uint32_t i; 00036 * for (i=0; i<0x8; i++) 00037 * { 00038 * __NOP(); 00039 * } 00040 * __DSB(); 00041 * __WFI(); 00042 * __ISB(); 00043 * 00044 * When entring the stop modes, the flash prefetch might be interrupted, thus 00045 * the prefetched code or data might be broken. To make sure the flash is idle 00046 * when entring the stop modes, the code is moved to ram. And delay for a while 00047 * before WFI to make sure previous flash prefetch is finished. 00048 * 00049 * Only need to do like this when code is in flash, if code is in rom or ram, 00050 * this is not necessary. 00051 */ 00052 static uint16_t s_stopRamFuncArray[] = { 00053 0x2000, /* MOVS R0, #0 */ 00054 0x2808, /* CMP R0, #8 */ 00055 0xD202, /* BCS.N */ 00056 0xBF00, /* NOP */ 00057 0x1C40, /* ADDS R0, R0, #1 */ 00058 0xE7FA, /* B.N */ 00059 0xF3BF, 0x8F4F, /* DSB */ 00060 0xBF30, /* WFI */ 00061 0xF3BF, 0x8F6F, /* ISB */ 00062 0x4770, /* BX LR */ 00063 }; 00064 00065 /******************************************************************************* 00066 * Code 00067 ******************************************************************************/ 00068 static void SMC_EnterStopRamFunc(void) 00069 { 00070 uint32_t ramFuncEntry = ((uint32_t)(s_stopRamFuncArray)) + 1U; 00071 smc_stop_ram_func_t stopRamFunc = (smc_stop_ram_func_t)ramFuncEntry; 00072 stopRamFunc(); 00073 } 00074 00075 #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) 00076 /*! 00077 * brief Gets the SMC parameter. 00078 * 00079 * This function gets the SMC parameter including the enabled power mdoes. 00080 * 00081 * param base SMC peripheral base address. 00082 * param param Pointer to the SMC param structure. 00083 */ 00084 void SMC_GetParam(SMC_Type *base, smc_param_t *param) 00085 { 00086 uint32_t reg = base->PARAM; 00087 param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK); 00088 param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK); 00089 param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK); 00090 param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK); 00091 } 00092 #endif /* FSL_FEATURE_SMC_HAS_PARAM */ 00093 00094 /*! 00095 * brief Prepares to enter stop modes. 00096 * 00097 * This function should be called before entering STOP/VLPS/LLS/VLLS modes. 00098 */ 00099 void SMC_PreEnterStopModes(void) 00100 { 00101 g_savedPrimask = DisableGlobalIRQ(); 00102 __ISB(); 00103 } 00104 00105 /*! 00106 * brief Recovers after wake up from stop modes. 00107 * 00108 * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. 00109 * It is used with ref SMC_PreEnterStopModes. 00110 */ 00111 void SMC_PostExitStopModes(void) 00112 { 00113 EnableGlobalIRQ(g_savedPrimask); 00114 __ISB(); 00115 } 00116 00117 /*! 00118 * brief Prepares to enter wait modes. 00119 * 00120 * This function should be called before entering WAIT/VLPW modes. 00121 */ 00122 void SMC_PreEnterWaitModes(void) 00123 { 00124 g_savedPrimask = DisableGlobalIRQ(); 00125 __ISB(); 00126 } 00127 00128 /*! 00129 * brief Recovers after wake up from stop modes. 00130 * 00131 * This function should be called after wake up from WAIT/VLPW modes. 00132 * It is used with ref SMC_PreEnterWaitModes. 00133 */ 00134 void SMC_PostExitWaitModes(void) 00135 { 00136 EnableGlobalIRQ(g_savedPrimask); 00137 __ISB(); 00138 } 00139 00140 /*! 00141 * brief Configures the system to RUN power mode. 00142 * 00143 * param base SMC peripheral base address. 00144 * return SMC configuration error code. 00145 */ 00146 status_t SMC_SetPowerModeRun(SMC_Type *base) 00147 { 00148 uint8_t reg; 00149 00150 reg = base->PMCTRL; 00151 /* configure Normal RUN mode */ 00152 reg &= ~SMC_PMCTRL_RUNM_MASK; 00153 reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT); 00154 base->PMCTRL = reg; 00155 00156 return kStatus_Success; 00157 } 00158 00159 #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) 00160 /*! 00161 * brief Configures the system to HSRUN power mode. 00162 * 00163 * param base SMC peripheral base address. 00164 * return SMC configuration error code. 00165 */ 00166 status_t SMC_SetPowerModeHsrun(SMC_Type *base) 00167 { 00168 uint8_t reg; 00169 00170 reg = base->PMCTRL; 00171 /* configure High Speed RUN mode */ 00172 reg &= ~SMC_PMCTRL_RUNM_MASK; 00173 reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT); 00174 base->PMCTRL = reg; 00175 00176 return kStatus_Success; 00177 } 00178 #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ 00179 00180 /*! 00181 * brief Configures the system to WAIT power mode. 00182 * 00183 * param base SMC peripheral base address. 00184 * return SMC configuration error code. 00185 */ 00186 status_t SMC_SetPowerModeWait(SMC_Type *base) 00187 { 00188 /* configure Normal Wait mode */ 00189 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; 00190 __DSB(); 00191 __WFI(); 00192 __ISB(); 00193 00194 return kStatus_Success; 00195 } 00196 00197 /*! 00198 * brief Configures the system to Stop power mode. 00199 * 00200 * param base SMC peripheral base address. 00201 * param option Partial Stop mode option. 00202 * return SMC configuration error code. 00203 */ 00204 status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option) 00205 { 00206 uint8_t reg; 00207 00208 #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO) 00209 /* configure the Partial Stop mode in Normal Stop mode */ 00210 reg = base->STOPCTRL; 00211 reg &= ~SMC_STOPCTRL_PSTOPO_MASK; 00212 reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT); 00213 base->STOPCTRL = reg; 00214 #endif 00215 00216 /* configure Normal Stop mode */ 00217 reg = base->PMCTRL; 00218 reg &= ~SMC_PMCTRL_STOPM_MASK; 00219 reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT); 00220 base->PMCTRL = reg; 00221 00222 /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */ 00223 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; 00224 00225 /* read back to make sure the configuration valid before enter stop mode */ 00226 (void)base->PMCTRL; 00227 SMC_EnterStopRamFunc(); 00228 00229 /* check whether the power mode enter Stop mode succeed */ 00230 if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) 00231 { 00232 return kStatus_SMC_StopAbort ; 00233 } 00234 else 00235 { 00236 return kStatus_Success; 00237 } 00238 } 00239 00240 /*! 00241 * brief Configures the system to VLPR power mode. 00242 * 00243 * param base SMC peripheral base address. 00244 * return SMC configuration error code. 00245 */ 00246 status_t SMC_SetPowerModeVlpr(SMC_Type *base 00247 #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) 00248 , 00249 bool wakeupMode 00250 #endif 00251 ) 00252 { 00253 uint8_t reg; 00254 00255 reg = base->PMCTRL; 00256 #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) 00257 /* configure whether the system remains in VLP mode on an interrupt */ 00258 if (wakeupMode) 00259 { 00260 /* exits to RUN mode on an interrupt */ 00261 reg |= SMC_PMCTRL_LPWUI_MASK; 00262 } 00263 else 00264 { 00265 /* remains in VLP mode on an interrupt */ 00266 reg &= ~SMC_PMCTRL_LPWUI_MASK; 00267 } 00268 #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ 00269 00270 /* configure VLPR mode */ 00271 reg &= ~SMC_PMCTRL_RUNM_MASK; 00272 reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT); 00273 base->PMCTRL = reg; 00274 00275 return kStatus_Success; 00276 } 00277 00278 /*! 00279 * brief Configures the system to VLPW power mode. 00280 * 00281 * param base SMC peripheral base address. 00282 * return SMC configuration error code. 00283 */ 00284 status_t SMC_SetPowerModeVlpw(SMC_Type *base) 00285 { 00286 /* configure VLPW mode */ 00287 /* Set the SLEEPDEEP bit to enable deep sleep mode */ 00288 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; 00289 __DSB(); 00290 __WFI(); 00291 __ISB(); 00292 00293 return kStatus_Success; 00294 } 00295 00296 /*! 00297 * brief Configures the system to VLPS power mode. 00298 * 00299 * param base SMC peripheral base address. 00300 * return SMC configuration error code. 00301 */ 00302 status_t SMC_SetPowerModeVlps(SMC_Type *base) 00303 { 00304 uint8_t reg; 00305 00306 /* configure VLPS mode */ 00307 reg = base->PMCTRL; 00308 reg &= ~SMC_PMCTRL_STOPM_MASK; 00309 reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT); 00310 base->PMCTRL = reg; 00311 00312 /* Set the SLEEPDEEP bit to enable deep sleep mode */ 00313 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; 00314 00315 /* read back to make sure the configuration valid before enter stop mode */ 00316 (void)base->PMCTRL; 00317 SMC_EnterStopRamFunc(); 00318 00319 /* check whether the power mode enter VLPS mode succeed */ 00320 if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) 00321 { 00322 return kStatus_SMC_StopAbort ; 00323 } 00324 else 00325 { 00326 return kStatus_Success; 00327 } 00328 } 00329 00330 #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) 00331 /*! 00332 * brief Configures the system to LLS power mode. 00333 * 00334 * param base SMC peripheral base address. 00335 * return SMC configuration error code. 00336 */ 00337 status_t SMC_SetPowerModeLls(SMC_Type *base 00338 #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ 00339 (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) 00340 , 00341 const smc_power_mode_lls_config_t *config 00342 #endif 00343 ) 00344 { 00345 uint8_t reg; 00346 00347 /* configure to LLS mode */ 00348 reg = base->PMCTRL; 00349 reg &= ~SMC_PMCTRL_STOPM_MASK; 00350 reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT); 00351 base->PMCTRL = reg; 00352 00353 /* configure LLS sub-mode*/ 00354 #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) 00355 reg = base->STOPCTRL; 00356 reg &= ~SMC_STOPCTRL_LLSM_MASK; 00357 reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); 00358 base->STOPCTRL = reg; 00359 #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ 00360 00361 #if (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO) 00362 if (config->enableLpoClock) 00363 { 00364 base->STOPCTRL &= ~SMC_STOPCTRL_LPOPO_MASK; 00365 } 00366 else 00367 { 00368 base->STOPCTRL |= SMC_STOPCTRL_LPOPO_MASK; 00369 } 00370 #endif /* FSL_FEATURE_SMC_HAS_LPOPO */ 00371 00372 /* Set the SLEEPDEEP bit to enable deep sleep mode */ 00373 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; 00374 00375 /* read back to make sure the configuration valid before enter stop mode */ 00376 (void)base->PMCTRL; 00377 SMC_EnterStopRamFunc(); 00378 00379 /* check whether the power mode enter LLS mode succeed */ 00380 if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) 00381 { 00382 return kStatus_SMC_StopAbort ; 00383 } 00384 else 00385 { 00386 return kStatus_Success; 00387 } 00388 } 00389 #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ 00390 00391 #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) 00392 /*! 00393 * brief Configures the system to VLLS power mode. 00394 * 00395 * param base SMC peripheral base address. 00396 * param config The VLLS power mode configuration structure. 00397 * return SMC configuration error code. 00398 */ 00399 status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config) 00400 { 00401 uint8_t reg; 00402 00403 #if (defined(FSL_FEATURE_SMC_HAS_PORPO) && FSL_FEATURE_SMC_HAS_PORPO) 00404 #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) || \ 00405 (defined(FSL_FEATURE_SMC_USE_STOPCTRL_VLLSM) && FSL_FEATURE_SMC_USE_STOPCTRL_VLLSM) || \ 00406 (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) 00407 if (config->subMode == kSMC_StopSub0 ) 00408 #endif 00409 { 00410 /* configure whether the Por Detect work in Vlls0 mode */ 00411 if (config->enablePorDetectInVlls0 ) 00412 { 00413 #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) 00414 base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK; 00415 #else 00416 base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK; 00417 #endif 00418 } 00419 else 00420 { 00421 #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) 00422 base->VLLSCTRL |= SMC_VLLSCTRL_PORPO_MASK; 00423 #else 00424 base->STOPCTRL |= SMC_STOPCTRL_PORPO_MASK; 00425 #endif 00426 } 00427 } 00428 #endif /* FSL_FEATURE_SMC_HAS_PORPO */ 00429 00430 #if (defined(FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION) && FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION) 00431 else if (config->subMode == kSMC_StopSub2 ) 00432 { 00433 /* configure whether the Por Detect work in Vlls0 mode */ 00434 if (config->enableRam2InVlls2 ) 00435 { 00436 #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) 00437 base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK; 00438 #else 00439 base->STOPCTRL |= SMC_STOPCTRL_RAM2PO_MASK; 00440 #endif 00441 } 00442 else 00443 { 00444 #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) 00445 base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK; 00446 #else 00447 base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK; 00448 #endif 00449 } 00450 } 00451 else 00452 { 00453 } 00454 #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */ 00455 00456 /* configure to VLLS mode */ 00457 reg = base->PMCTRL; 00458 reg &= ~SMC_PMCTRL_STOPM_MASK; 00459 reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT); 00460 base->PMCTRL = reg; 00461 00462 /* configure the VLLS sub-mode */ 00463 #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) 00464 reg = base->VLLSCTRL; 00465 reg &= ~SMC_VLLSCTRL_VLLSM_MASK; 00466 reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT); 00467 base->VLLSCTRL = reg; 00468 #else 00469 #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) 00470 reg = base->STOPCTRL; 00471 reg &= ~SMC_STOPCTRL_LLSM_MASK; 00472 reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT); 00473 base->STOPCTRL = reg; 00474 #else 00475 reg = base->STOPCTRL; 00476 reg &= ~SMC_STOPCTRL_VLLSM_MASK; 00477 reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT); 00478 base->STOPCTRL = reg; 00479 #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */ 00480 #endif 00481 00482 #if (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO) 00483 if (config->enableLpoClock ) 00484 { 00485 base->STOPCTRL &= ~SMC_STOPCTRL_LPOPO_MASK; 00486 } 00487 else 00488 { 00489 base->STOPCTRL |= SMC_STOPCTRL_LPOPO_MASK; 00490 } 00491 #endif /* FSL_FEATURE_SMC_HAS_LPOPO */ 00492 00493 /* Set the SLEEPDEEP bit to enable deep sleep mode */ 00494 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; 00495 00496 /* read back to make sure the configuration valid before enter stop mode */ 00497 (void)base->PMCTRL; 00498 SMC_EnterStopRamFunc(); 00499 00500 /* check whether the power mode enter LLS mode succeed */ 00501 if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK) 00502 { 00503 return kStatus_SMC_StopAbort ; 00504 } 00505 else 00506 { 00507 return kStatus_Success; 00508 } 00509 } 00510 #endif /* FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE */
Generated on Tue Jul 12 2022 15:37:18 by
