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.
stm32l4xx_ll_utils.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32l4xx_ll_utils.c 00004 * @author MCD Application Team 00005 * @version V1.5.1 00006 * @date 31-May-2016 00007 * @brief UTILS LL module driver. 00008 ****************************************************************************** 00009 * @attention 00010 * 00011 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00012 * 00013 * Redistribution and use in source and binary forms, with or without modification, 00014 * are permitted provided that the following conditions are met: 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 2. Redistributions in binary form must reproduce the above copyright notice, 00018 * this list of conditions and the following disclaimer in the documentation 00019 * and/or other materials provided with the distribution. 00020 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00021 * may be used to endorse or promote products derived from this software 00022 * without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00025 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00026 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00028 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00029 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00030 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00032 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 ****************************************************************************** 00036 */ 00037 /* Includes ------------------------------------------------------------------*/ 00038 #include "stm32l4xx_ll_utils.h" 00039 #include "stm32l4xx_ll_rcc.h" 00040 #include "stm32l4xx_ll_system.h" 00041 #include "stm32l4xx_ll_pwr.h" 00042 00043 /** @addtogroup STM32L4xx_LL_Driver 00044 * @{ 00045 */ 00046 00047 /** @addtogroup UTILS_LL 00048 * @{ 00049 */ 00050 00051 /* Private types -------------------------------------------------------------*/ 00052 /* Private variables ---------------------------------------------------------*/ 00053 /* Private constants ---------------------------------------------------------*/ 00054 /** @addtogroup UTILS_LL_Private_Constants 00055 * @{ 00056 */ 00057 #define UTILS_MAX_FREQUENCY_SCALE1 ((uint32_t)80000000) /*!< Maximum frequency for system clock at power scale1, in Hz */ 00058 #define UTILS_MAX_FREQUENCY_SCALE2 ((uint32_t)26000000) /*!< Maximum frequency for system clock at power scale2, in Hz */ 00059 00060 /* Defines used for PLL range */ 00061 #define UTILS_PLLVCO_INPUT_MIN ((uint32_t)4000000) /*!< Frequency min for PLLVCO input, in Hz */ 00062 #define UTILS_PLLVCO_INPUT_MAX ((uint32_t)16000000) /*!< Frequency max for PLLVCO input, in Hz */ 00063 #define UTILS_PLLVCO_OUTPUT_MIN ((uint32_t)64000000) /*!< Frequency min for PLLVCO output, in Hz */ 00064 #define UTILS_PLLVCO_OUTPUT_MAX ((uint32_t)344000000) /*!< Frequency max for PLLVCO output, in Hz */ 00065 00066 /* Defines used for HSE range */ 00067 #define UTILS_HSE_FREQUENCY_MIN ((uint32_t)4000000) /*!< Frequency min for HSE frequency, in Hz */ 00068 #define UTILS_HSE_FREQUENCY_MAX ((uint32_t)48000000) /*!< Frequency max for HSE frequency, in Hz */ 00069 00070 /* Defines used for FLASH latency according to HCLK Frequency */ 00071 #define UTILS_SCALE1_LATENCY1_FREQ ((uint32_t)16000000) /*!< HCLK frequency to set FLASH latency 1 in power scale 1 */ 00072 #define UTILS_SCALE1_LATENCY2_FREQ ((uint32_t)32000000) /*!< HCLK frequency to set FLASH latency 2 in power scale 1 */ 00073 #define UTILS_SCALE1_LATENCY3_FREQ ((uint32_t)48000000) /*!< HCLK frequency to set FLASH latency 3 in power scale 1 */ 00074 #define UTILS_SCALE1_LATENCY4_FREQ ((uint32_t)64000000) /*!< HCLK frequency to set FLASH latency 4 in power scale 1 */ 00075 #define UTILS_SCALE2_LATENCY1_FREQ ((uint32_t)6000000) /*!< HCLK frequency to set FLASH latency 1 in power scale 2 */ 00076 #define UTILS_SCALE2_LATENCY2_FREQ ((uint32_t)12000000) /*!< HCLK frequency to set FLASH latency 2 in power scale 2 */ 00077 #define UTILS_SCALE2_LATENCY3_FREQ ((uint32_t)18000000) /*!< HCLK frequency to set FLASH latency 3 in power scale 2 */ 00078 /** 00079 * @} 00080 */ 00081 00082 /* Private macros ------------------------------------------------------------*/ 00083 /** @addtogroup UTILS_LL_Private_Macros 00084 * @{ 00085 */ 00086 #define IS_LL_UTILS_SYSCLK_DIV(__VALUE__) (((__VALUE__) == LL_RCC_SYSCLK_DIV_1) \ 00087 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_2) \ 00088 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_4) \ 00089 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_8) \ 00090 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_16) \ 00091 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_64) \ 00092 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_128) \ 00093 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_256) \ 00094 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_512)) 00095 00096 #define IS_LL_UTILS_APB1_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB1_DIV_1) \ 00097 || ((__VALUE__) == LL_RCC_APB1_DIV_2) \ 00098 || ((__VALUE__) == LL_RCC_APB1_DIV_4) \ 00099 || ((__VALUE__) == LL_RCC_APB1_DIV_8) \ 00100 || ((__VALUE__) == LL_RCC_APB1_DIV_16)) 00101 00102 #define IS_LL_UTILS_APB2_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB2_DIV_1) \ 00103 || ((__VALUE__) == LL_RCC_APB2_DIV_2) \ 00104 || ((__VALUE__) == LL_RCC_APB2_DIV_4) \ 00105 || ((__VALUE__) == LL_RCC_APB2_DIV_8) \ 00106 || ((__VALUE__) == LL_RCC_APB2_DIV_16)) 00107 00108 #define IS_LL_UTILS_PLLM_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLLM_DIV_1) \ 00109 || ((__VALUE__) == LL_RCC_PLLM_DIV_2) \ 00110 || ((__VALUE__) == LL_RCC_PLLM_DIV_3) \ 00111 || ((__VALUE__) == LL_RCC_PLLM_DIV_4) \ 00112 || ((__VALUE__) == LL_RCC_PLLM_DIV_5) \ 00113 || ((__VALUE__) == LL_RCC_PLLM_DIV_6) \ 00114 || ((__VALUE__) == LL_RCC_PLLM_DIV_7) \ 00115 || ((__VALUE__) == LL_RCC_PLLM_DIV_8)) 00116 00117 #define IS_LL_UTILS_PLLN_VALUE(__VALUE__) ((8 <= (__VALUE__)) && ((__VALUE__) <= 86)) 00118 00119 #define IS_LL_UTILS_PLLR_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLLR_DIV_2) \ 00120 || ((__VALUE__) == LL_RCC_PLLR_DIV_4) \ 00121 || ((__VALUE__) == LL_RCC_PLLR_DIV_6) \ 00122 || ((__VALUE__) == LL_RCC_PLLR_DIV_8)) 00123 00124 #define IS_LL_UTILS_PLLVCO_INPUT(__VALUE__) ((UTILS_PLLVCO_INPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_INPUT_MAX)) 00125 00126 #define IS_LL_UTILS_PLLVCO_OUTPUT(__VALUE__) ((UTILS_PLLVCO_OUTPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_OUTPUT_MAX)) 00127 00128 #define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) ((LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE1) : \ 00129 ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE2)) 00130 00131 #define IS_LL_UTILS_HSE_BYPASS(__STATE__) (((__STATE__) == LL_UTILS_HSEBYPASS_ON) \ 00132 || ((__STATE__) == LL_UTILS_HSEBYPASS_OFF)) 00133 00134 #define IS_LL_UTILS_HSE_FREQUENCY(__FREQUENCY__) (((__FREQUENCY__) >= UTILS_HSE_FREQUENCY_MIN) && ((__FREQUENCY__) <= UTILS_HSE_FREQUENCY_MAX)) 00135 /** 00136 * @} 00137 */ 00138 /* Private function prototypes -----------------------------------------------*/ 00139 /** @defgroup UTILS_LL_Private_Functions UTILS Private functions 00140 * @{ 00141 */ 00142 static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, 00143 LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct); 00144 static ErrorStatus UTILS_SetFlashLatency(uint32_t HCLK_Frequency); 00145 static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct); 00146 static ErrorStatus UTILS_PLL_IsBusy(void); 00147 /** 00148 * @} 00149 */ 00150 00151 /* Exported functions --------------------------------------------------------*/ 00152 /** @addtogroup UTILS_LL_Exported_Functions 00153 * @{ 00154 */ 00155 00156 /** @addtogroup UTILS_LL_EF_DELAY 00157 * @{ 00158 */ 00159 00160 /** 00161 * @brief This function configures the Cortex-M SysTick source to have 1ms time base. 00162 * @note When a RTOS is used, it is recommended to avoid changing the Systick 00163 * configuration by calling this function, for a delay use rather osDelay RTOS service. 00164 * @param HCLKFrequency HCLK frequency in Hz 00165 * @note HCLK frequency can be calculated thanks to RCC helper macro or function @ref LL_RCC_GetSystemClocksFreq 00166 * @retval None 00167 */ 00168 void LL_Init1msTick(uint32_t HCLKFrequency) 00169 { 00170 /* Use frequency provided in argument */ 00171 LL_InitTick(HCLKFrequency, 1000); 00172 } 00173 00174 /** 00175 * @brief This function provides accurate delay (in milliseconds) based 00176 * on SysTick counter flag 00177 * @note When a RTOS is used, it is recommended to avoid using blocking delay 00178 * and use rather osDelay service. 00179 * @note To respect 1ms timebase, user should call @ref LL_Init1msTick function which 00180 * will configure Systick to 1ms 00181 * @param Delay specifies the delay time length, in milliseconds. 00182 * @retval None 00183 */ 00184 void LL_mDelay(uint32_t Delay) 00185 { 00186 __IO uint32_t tmp = SysTick->CTRL; /* Clear the COUNTFLAG first */ 00187 /* Add this code to indicate that local variable is not used */ 00188 ((void)tmp); 00189 00190 /* Add a period to guaranty minimum wait */ 00191 if (Delay < LL_MAX_DELAY) 00192 { 00193 Delay++; 00194 } 00195 00196 while (Delay) 00197 { 00198 if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0) 00199 { 00200 Delay--; 00201 } 00202 } 00203 } 00204 00205 /** 00206 * @} 00207 */ 00208 00209 /** @addtogroup UTILS_EF_SYSTEM 00210 * @brief System Configuration functions 00211 * 00212 @verbatim 00213 =============================================================================== 00214 ##### System Configuration functions ##### 00215 =============================================================================== 00216 [..] 00217 System, AHB and APB buses clocks configuration 00218 00219 (+) The maximum frequency of the SYSCLK, HCLK, PCLK1 and PCLK2 is 80000000 Hz. 00220 @endverbatim 00221 @internal 00222 Depending on the device voltage range, the maximum frequency should be 00223 adapted accordingly: 00224 00225 (++) Table 1. HCLK clock frequency. 00226 (++) +-------------------------------------------------------+ 00227 (++) | Latency | HCLK clock frequency (MHz) | 00228 (++) | |-------------------------------------| 00229 (++) | | voltage range 1 | voltage range 2 | 00230 (++) | | 1.2 V | 1.0 V | 00231 (++) |-----------------|------------------|------------------| 00232 (++) |0WS(1 CPU cycles)| 0 < HCLK <= 16 | 0 < HCLK <= 6 | 00233 (++) |-----------------|------------------|------------------| 00234 (++) |1WS(2 CPU cycles)| 16 < HCLK <= 32 | 6 < HCLK <= 12 | 00235 (++) |-----------------|------------------|------------------| 00236 (++) |2WS(3 CPU cycles)| 32 < HCLK <= 48 | 12 < HCLK <= 18 | 00237 (++) |-----------------|------------------|------------------| 00238 (++) |3WS(4 CPU cycles)| 48 < HCLK <= 64 | 18 < HCLK <= 26 | 00239 (++) |-----------------|------------------|------------------| 00240 (++) |4WS(5 CPU cycles)| 64 < HCLK <= 80 | 18 < HCLK <= 26 | 00241 (++) +-------------------------------------------------------+ 00242 @endinternal 00243 * @{ 00244 */ 00245 00246 /** 00247 * @brief This function sets directly SystemCoreClock CMSIS variable. 00248 * @note Variable can be calculated also through SystemCoreClockUpdate function. 00249 * @param HCLKFrequency HCLK frequency in Hz (can be calculated thanks to RCC helper macro) 00250 * @retval None 00251 */ 00252 void LL_SetSystemCoreClock(uint32_t HCLKFrequency) 00253 { 00254 /* HCLK clock frequency */ 00255 SystemCoreClock = HCLKFrequency; 00256 } 00257 00258 /** 00259 * @brief This function configures system clock with MSI as clock source of the PLL 00260 * @note The application needs to ensure that PLL, PLLSAI1 and/or PLLSAI2 are disabled. 00261 * @note Function is based on the following formula: 00262 * - PLL output frequency = (((MSI frequency / PLLM) * PLLN) / PLLR) 00263 * - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = MSI frequency / PLLM) 00264 * - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN) 00265 * - PLLR: ensure that max frequency at 80 MHz is reach (PLLVCO_output / PLLR) 00266 * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains 00267 * the configuration information for the PLL. 00268 * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains 00269 * the configuration information for the BUS prescalers. 00270 * @retval An ErrorStatus enumeration value: 00271 * - SUCCESS: Max frequency configuration done 00272 * - ERROR: Max frequency configuration not done 00273 */ 00274 ErrorStatus LL_PLL_ConfigSystemClock_MSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, 00275 LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct) 00276 { 00277 ErrorStatus status = SUCCESS; 00278 uint32_t pllfreq = 0, msi_range = 0; 00279 00280 /* Check if one of the PLL is enabled */ 00281 if (UTILS_PLL_IsBusy() == SUCCESS) 00282 { 00283 /* Get the current MSI range */ 00284 if (LL_RCC_MSI_IsEnabledRangeSelect()) 00285 { 00286 msi_range = LL_RCC_MSI_GetRange(); 00287 switch (msi_range) 00288 { 00289 case LL_RCC_MSIRANGE_0: /* MSI = 100 KHz */ 00290 case LL_RCC_MSIRANGE_1: /* MSI = 200 KHz */ 00291 case LL_RCC_MSIRANGE_2: /* MSI = 400 KHz */ 00292 case LL_RCC_MSIRANGE_3: /* MSI = 800 KHz */ 00293 case LL_RCC_MSIRANGE_4: /* MSI = 1 MHz */ 00294 case LL_RCC_MSIRANGE_5: /* MSI = 2 MHz */ 00295 /* PLLVCO input frequency can not in the range from 4 to 16 MHz*/ 00296 status = ERROR; 00297 break; 00298 00299 case LL_RCC_MSIRANGE_6: /* MSI = 4 MHz */ 00300 case LL_RCC_MSIRANGE_7: /* MSI = 8 MHz */ 00301 case LL_RCC_MSIRANGE_8: /* MSI = 16 MHz */ 00302 case LL_RCC_MSIRANGE_9: /* MSI = 24 MHz */ 00303 case LL_RCC_MSIRANGE_10: /* MSI = 32 MHz */ 00304 case LL_RCC_MSIRANGE_11: /* MSI = 48 MHz */ 00305 default: 00306 break; 00307 } 00308 } 00309 else 00310 { 00311 msi_range = LL_RCC_MSI_GetRangeAfterStandby(); 00312 switch (msi_range) 00313 { 00314 case LL_RCC_MSISRANGE_4: /* MSI = 1 MHz */ 00315 case LL_RCC_MSISRANGE_5: /* MSI = 2 MHz */ 00316 /* PLLVCO input frequency is not in the range from 4 to 16 MHz*/ 00317 status = ERROR; 00318 break; 00319 00320 case LL_RCC_MSISRANGE_7: /* MSI = 8 MHz */ 00321 case LL_RCC_MSISRANGE_6: /* MSI = 4 MHz */ 00322 default: 00323 break; 00324 } 00325 } 00326 00327 /* Main PLL configuration and activation */ 00328 if (status != ERROR) 00329 { 00330 /* Calculate the new PLL output frequency */ 00331 pllfreq = UTILS_GetPLLOutputFrequency(__LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), msi_range), 00332 UTILS_PLLInitStruct); 00333 00334 /* Enable MSI if not enabled */ 00335 if (LL_RCC_MSI_IsReady() != 1) 00336 { 00337 LL_RCC_MSI_Enable(); 00338 while ((LL_RCC_MSI_IsReady() != 1)) 00339 { 00340 /* Wait for MSI ready */ 00341 } 00342 } 00343 00344 /* Configure PLL */ 00345 LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, UTILS_PLLInitStruct->PLLM , UTILS_PLLInitStruct->PLLN , 00346 UTILS_PLLInitStruct->PLLR ); 00347 00348 /* Enable PLL and switch system clock to PLL */ 00349 status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct); 00350 } 00351 } 00352 else 00353 { 00354 /* Current PLL configuration cannot be modified */ 00355 status = ERROR; 00356 } 00357 00358 return status; 00359 } 00360 00361 /** 00362 * @brief This function configures system clock at maximum frequency with HSI as clock source of the PLL 00363 * @note The application need to ensure that PLL, PLLSAI1 and/or PLLSAI2 are disabled. 00364 * @note Function is based on the following formula: 00365 * - PLL output frequency = (((HSI frequency / PLLM) * PLLN) / PLLR) 00366 * - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = HSI frequency / PLLM) 00367 * - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN) 00368 * - PLLR: ensure that max frequency at 80 MHz is reach (PLLVCO_output / PLLR) 00369 * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains 00370 * the configuration information for the PLL. 00371 * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains 00372 * the configuration information for the BUS prescalers. 00373 * @retval An ErrorStatus enumeration value: 00374 * - SUCCESS: Max frequency configuration done 00375 * - ERROR: Max frequency configuration not done 00376 */ 00377 ErrorStatus LL_PLL_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, 00378 LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct) 00379 { 00380 ErrorStatus status = SUCCESS; 00381 uint32_t pllfreq = 0; 00382 00383 /* Check if one of the PLL is enabled */ 00384 if (UTILS_PLL_IsBusy() == SUCCESS) 00385 { 00386 /* Calculate the new PLL output frequency */ 00387 pllfreq = UTILS_GetPLLOutputFrequency(HSI_VALUE, UTILS_PLLInitStruct); 00388 00389 /* Enable HSI if not enabled */ 00390 if (LL_RCC_HSI_IsReady() != 1) 00391 { 00392 LL_RCC_HSI_Enable(); 00393 while (LL_RCC_HSI_IsReady() != 1) 00394 { 00395 /* Wait for HSI ready */ 00396 } 00397 } 00398 00399 /* Configure PLL */ 00400 LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, UTILS_PLLInitStruct->PLLM , UTILS_PLLInitStruct->PLLN , 00401 UTILS_PLLInitStruct->PLLR ); 00402 00403 /* Enable PLL and switch system clock to PLL */ 00404 status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct); 00405 } 00406 else 00407 { 00408 /* Current PLL configuration cannot be modified */ 00409 status = ERROR; 00410 } 00411 00412 return status; 00413 } 00414 00415 /** 00416 * @brief This function configures system clock with HSE as clock source of the PLL 00417 * @note The application need to ensure that PLL, PLLSAI1 and/or PLLSAI2 are disabled. 00418 * @note Function is based on the following formula: 00419 * - PLL output frequency = (((HSE frequency / PLLM) * PLLN) / PLLR) 00420 * - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = HSE frequency / PLLM) 00421 * - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN) 00422 * - PLLR: ensure that max frequency at 80 MHz is reach (PLLVCO_output / PLLR) 00423 * @param HSEFrequency Value between Min_Data = 4000000 and Max_Data = 48000000 00424 * @param HSEBypass This parameter can be one of the following values: 00425 * @arg @ref LL_UTILS_HSEBYPASS_ON 00426 * @arg @ref LL_UTILS_HSEBYPASS_OFF 00427 * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains 00428 * the configuration information for the PLL. 00429 * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains 00430 * the configuration information for the BUS prescalers. 00431 * @retval An ErrorStatus enumeration value: 00432 * - SUCCESS: Max frequency configuration done 00433 * - ERROR: Max frequency configuration not done 00434 */ 00435 ErrorStatus LL_PLL_ConfigSystemClock_HSE(uint32_t HSEFrequency, uint32_t HSEBypass, 00436 LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct) 00437 { 00438 ErrorStatus status = SUCCESS; 00439 uint32_t pllfreq = 0; 00440 00441 /* Check the parameters */ 00442 assert_param(IS_LL_UTILS_HSE_FREQUENCY(HSEFrequency)); 00443 assert_param(IS_LL_UTILS_HSE_BYPASS(HSEBypass)); 00444 00445 /* Check if one of the PLL is enabled */ 00446 if (UTILS_PLL_IsBusy() == SUCCESS) 00447 { 00448 /* Calculate the new PLL output frequency */ 00449 pllfreq = UTILS_GetPLLOutputFrequency(HSEFrequency, UTILS_PLLInitStruct); 00450 00451 /* Enable HSE if not enabled */ 00452 if (LL_RCC_HSE_IsReady() != 1) 00453 { 00454 /* Check if need to enable HSE bypass feature or not */ 00455 if (HSEBypass == LL_UTILS_HSEBYPASS_ON) 00456 { 00457 LL_RCC_HSE_EnableBypass(); 00458 } 00459 else 00460 { 00461 LL_RCC_HSE_DisableBypass(); 00462 } 00463 00464 /* Enable HSE */ 00465 LL_RCC_HSE_Enable(); 00466 while (LL_RCC_HSE_IsReady() != 1) 00467 { 00468 /* Wait for HSE ready */ 00469 } 00470 } 00471 00472 /* Configure PLL */ 00473 LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, UTILS_PLLInitStruct->PLLM , UTILS_PLLInitStruct->PLLN , 00474 UTILS_PLLInitStruct->PLLR ); 00475 00476 /* Enable PLL and switch system clock to PLL */ 00477 status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct); 00478 } 00479 else 00480 { 00481 /* Current PLL configuration cannot be modified */ 00482 status = ERROR; 00483 } 00484 00485 return status; 00486 } 00487 00488 /** 00489 * @} 00490 */ 00491 00492 /** 00493 * @} 00494 */ 00495 00496 /** @addtogroup UTILS_LL_Private_Functions 00497 * @{ 00498 */ 00499 /** 00500 * @brief Update number of Flash wait states in line with new frequency and current 00501 voltage range. 00502 * @param HCLK_Frequency HCLK frequency 00503 * @retval An ErrorStatus enumeration value: 00504 * - SUCCESS: Latency has been modified 00505 * - ERROR: Latency cannot be modified 00506 */ 00507 static ErrorStatus UTILS_SetFlashLatency(uint32_t HCLK_Frequency) 00508 { 00509 ErrorStatus status = SUCCESS; 00510 00511 uint32_t latency = LL_FLASH_LATENCY_0; /* default value 0WS */ 00512 00513 /* Frequency cannot be equal to 0 */ 00514 if (HCLK_Frequency == 0) 00515 { 00516 status = ERROR; 00517 } 00518 else 00519 { 00520 if (LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) 00521 { 00522 if (HCLK_Frequency > UTILS_SCALE1_LATENCY4_FREQ) 00523 { 00524 /* 64 < HCLK <= 80 => 4WS (5 CPU cycles) */ 00525 latency = LL_FLASH_LATENCY_4; 00526 } 00527 else if (HCLK_Frequency > UTILS_SCALE1_LATENCY3_FREQ) 00528 { 00529 /* 48 < HCLK <= 64 => 3WS (4 CPU cycles) */ 00530 latency = LL_FLASH_LATENCY_3; 00531 } 00532 else if (HCLK_Frequency > UTILS_SCALE1_LATENCY2_FREQ) 00533 { 00534 /* 32 < HCLK <= 48 => 2WS (3 CPU cycles) */ 00535 latency = LL_FLASH_LATENCY_2; 00536 } 00537 else 00538 { 00539 if (HCLK_Frequency > UTILS_SCALE1_LATENCY1_FREQ) 00540 { 00541 /* 16 < HCLK <= 32 => 1WS (2 CPU cycles) */ 00542 latency = LL_FLASH_LATENCY_1; 00543 } 00544 /* else HCLK_Frequency < 16MHz default LL_FLASH_LATENCY_0 0WS */ 00545 } 00546 } 00547 else 00548 { 00549 if (HCLK_Frequency > UTILS_SCALE2_LATENCY3_FREQ) 00550 { 00551 /* 18 < HCLK <= 26 => 3WS (4 CPU cycles) */ 00552 latency = LL_FLASH_LATENCY_3; 00553 } 00554 else if (HCLK_Frequency > UTILS_SCALE2_LATENCY2_FREQ) 00555 { 00556 /* 12 < HCLK <= 18 => 2WS (3 CPU cycles) */ 00557 latency = LL_FLASH_LATENCY_2; 00558 } 00559 else 00560 { 00561 if (HCLK_Frequency > UTILS_SCALE2_LATENCY1_FREQ) 00562 { 00563 /* 6 < HCLK <= 12 => 1WS (2 CPU cycles) */ 00564 latency = LL_FLASH_LATENCY_1; 00565 } 00566 /* else HCLK_Frequency < 6MHz default LL_FLASH_LATENCY_0 0WS */ 00567 } 00568 } 00569 00570 LL_FLASH_SetLatency(latency); 00571 00572 /* Check that the new number of wait states is taken into account to access the Flash 00573 memory by reading the FLASH_ACR register */ 00574 if (LL_FLASH_GetLatency() != latency) 00575 { 00576 status = ERROR; 00577 } 00578 } 00579 return status; 00580 } 00581 00582 /** 00583 * @brief Function to check that PLL can be modified 00584 * @param PLL_InputFrequency PLL input frequency (in Hz) 00585 * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains 00586 * the configuration information for the PLL. 00587 * @retval PLL output frequency (in Hz) 00588 */ 00589 static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct) 00590 { 00591 uint32_t pllfreq = 0; 00592 00593 /* Check the parameters */ 00594 assert_param(IS_LL_UTILS_PLLM_VALUE(UTILS_PLLInitStruct->PLLM )); 00595 assert_param(IS_LL_UTILS_PLLN_VALUE(UTILS_PLLInitStruct->PLLN )); 00596 assert_param(IS_LL_UTILS_PLLR_VALUE(UTILS_PLLInitStruct->PLLR )); 00597 00598 /* Check different PLL parameters according to RM */ 00599 /* - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz. */ 00600 pllfreq = PLL_InputFrequency / (((UTILS_PLLInitStruct->PLLM >> RCC_POSITION_PLLM) + 1)); 00601 assert_param(IS_LL_UTILS_PLLVCO_INPUT(pllfreq)); 00602 00603 /* - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz.*/ 00604 pllfreq = pllfreq * (UTILS_PLLInitStruct->PLLN & (RCC_PLLCFGR_PLLN >> RCC_POSITION_PLLN)); 00605 assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(pllfreq)); 00606 00607 /* - PLLR: ensure that max frequency at 80 MHz is reach */ 00608 pllfreq = pllfreq / (((UTILS_PLLInitStruct->PLLR >> RCC_POSITION_PLLR) + 1) * 2); 00609 assert_param(IS_LL_UTILS_PLL_FREQUENCY(pllfreq)); 00610 00611 return pllfreq; 00612 } 00613 00614 /** 00615 * @brief Function to check that PLL can be modified 00616 * @retval An ErrorStatus enumeration value: 00617 * - SUCCESS: PLL modification can be done 00618 * - ERROR: PLL is busy 00619 */ 00620 static ErrorStatus UTILS_PLL_IsBusy(void) 00621 { 00622 ErrorStatus status = SUCCESS; 00623 00624 /* Check if PLL is busy*/ 00625 if (LL_RCC_PLL_IsReady() != 0) 00626 { 00627 /* PLL configuration cannot be modified */ 00628 status = ERROR; 00629 } 00630 00631 /* Check if PLLSAI1 is busy*/ 00632 if (LL_RCC_PLLSAI1_IsReady() != 0) 00633 { 00634 /* PLLSAI1 configuration cannot be modified */ 00635 status = ERROR; 00636 } 00637 00638 #if defined(RCC_PLLSAI2_SUPPORT) 00639 /* Check if PLLSAI2 is busy*/ 00640 if (LL_RCC_PLLSAI2_IsReady() != 0) 00641 { 00642 /* PLLSAI2 configuration cannot be modified */ 00643 status = ERROR; 00644 } 00645 #endif /*RCC_PLLSAI2_SUPPORT*/ 00646 00647 00648 return status; 00649 } 00650 00651 /** 00652 * @brief Function to enable PLL and switch system clock to PLL 00653 * @param SYSCLK_Frequency SYSCLK frequency 00654 * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains 00655 * the configuration information for the BUS prescalers. 00656 * @retval An ErrorStatus enumeration value: 00657 * - SUCCESS: No problem to switch system to PLL 00658 * - ERROR: Problem to switch system to PLL 00659 */ 00660 static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct) 00661 { 00662 ErrorStatus status = SUCCESS; 00663 uint32_t hclk_frequency = 0; 00664 00665 assert_param(IS_LL_UTILS_SYSCLK_DIV(UTILS_ClkInitStruct->AHBCLKDivider )); 00666 assert_param(IS_LL_UTILS_APB1_DIV(UTILS_ClkInitStruct->APB1CLKDivider )); 00667 assert_param(IS_LL_UTILS_APB2_DIV(UTILS_ClkInitStruct->APB2CLKDivider )); 00668 00669 /* Calculate HCLK frequency */ 00670 hclk_frequency = __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, UTILS_ClkInitStruct->AHBCLKDivider ); 00671 00672 /* Increasing the number of wait states because of higher CPU frequency */ 00673 if (SystemCoreClock < hclk_frequency) 00674 { 00675 /* Set FLASH latency to highest latency */ 00676 status = UTILS_SetFlashLatency(hclk_frequency); 00677 } 00678 00679 /* Update system clock configuration */ 00680 if (status == SUCCESS) 00681 { 00682 /* Enable PLL */ 00683 LL_RCC_PLL_Enable(); 00684 LL_RCC_PLL_EnableDomain_SYS(); 00685 while (LL_RCC_PLL_IsReady() != 1) 00686 { 00687 /* Wait for PLL ready */ 00688 } 00689 00690 /* Sysclk activation on the main PLL */ 00691 LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider ); 00692 LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); 00693 while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) 00694 { 00695 /* Wait for system clock switch to PLL */ 00696 } 00697 00698 /* Set APB1 & APB2 prescaler*/ 00699 LL_RCC_SetAPB1Prescaler(UTILS_ClkInitStruct->APB1CLKDivider ); 00700 LL_RCC_SetAPB2Prescaler(UTILS_ClkInitStruct->APB2CLKDivider ); 00701 } 00702 00703 /* Decreasing the number of wait states because of lower CPU frequency */ 00704 if (SystemCoreClock > hclk_frequency) 00705 { 00706 /* Set FLASH latency to lowest latency */ 00707 status = UTILS_SetFlashLatency(hclk_frequency); 00708 } 00709 00710 /* Update SystemCoreClock variable */ 00711 if (status == SUCCESS) 00712 { 00713 LL_SetSystemCoreClock(hclk_frequency); 00714 } 00715 00716 return status; 00717 } 00718 00719 /** 00720 * @} 00721 */ 00722 00723 /** 00724 * @} 00725 */ 00726 00727 /** 00728 * @} 00729 */ 00730 00731 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 11:00:00 by
