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.
Fork of TUKS-COURSE-TIMER by
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 17:38:51 by
