py32f0xx_ll_utils.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /**
  2. ******************************************************************************
  3. * @file py32f0xx_ll_utils.c
  4. * @author MCU Application Team
  5. * @brief UTILS LL module driver.
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * <h2><center>&copy; Copyright (c) 2023 Puya Semiconductor Co.
  10. * All rights reserved.</center></h2>
  11. *
  12. * This software component is licensed by Puya under BSD 3-Clause license,
  13. * the "License"; You may not use this file except in compliance with the
  14. * License. You may obtain a copy of the License at:
  15. * opensource.org/licenses/BSD-3-Clause
  16. *
  17. ******************************************************************************
  18. * @attention
  19. *
  20. * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
  21. * All rights reserved.</center></h2>
  22. *
  23. * This software component is licensed by ST under BSD 3-Clause license,
  24. * the "License"; You may not use this file except in compliance with the
  25. * License. You may obtain a copy of the License at:
  26. * opensource.org/licenses/BSD-3-Clause
  27. *
  28. ******************************************************************************
  29. */
  30. /* Includes ------------------------------------------------------------------*/
  31. #include "py32f0xx_ll_utils.h"
  32. #include "py32f0xx_ll_rcc.h"
  33. #include "py32f0xx_ll_system.h"
  34. #ifdef USE_FULL_ASSERT
  35. #include "py32_assert.h"
  36. #else
  37. #define assert_param(expr) ((void)0U)
  38. #endif /* USE_FULL_ASSERT */
  39. /** @addtogroup PY32F0xx_LL_Driver
  40. * @{
  41. */
  42. /** @addtogroup UTILS_LL
  43. * @{
  44. */
  45. /* Private types -------------------------------------------------------------*/
  46. /* Private variables ---------------------------------------------------------*/
  47. /* Private constants ---------------------------------------------------------*/
  48. /** @addtogroup UTILS_LL_Private_Constants
  49. * @{
  50. */
  51. #if defined(RCC_PLL_SUPPORT)
  52. /* Defines used for HSE range */
  53. #define UTILS_HSE_FREQUENCY_MIN 4000000U /*!< Frequency min for HSE frequency, in Hz */
  54. #define UTILS_HSE_FREQUENCY_MAX 32000000U /*!< Frequency max for HSE frequency, in Hz */
  55. /* Defines used for PLL input range */
  56. #define LL_RCC_PLLINPUT_FREQ_MIN 16000000U /*!< Frequency min for PLL input frequency, in Hz */
  57. #define LL_RCC_PLLINPUT_FREQ_MAX 24000000U /*!< Frequency max for PLL input frequency, in Hz */
  58. #endif
  59. /* Defines used for FLASH latency according to HCLK Frequency */
  60. #define UTILS_SCALE1_LATENCY1_FREQ 24000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 1 */
  61. #define UTILS_SCALE1_LATENCY2_FREQ 48000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 1 */
  62. /**
  63. * @}
  64. */
  65. /* Private macros ------------------------------------------------------------*/
  66. /** @addtogroup UTILS_LL_Private_Macros
  67. * @{
  68. */
  69. #define IS_LL_UTILS_SYSCLK_DIV(__VALUE__) (((__VALUE__) == LL_RCC_SYSCLK_DIV_1) \
  70. || ((__VALUE__) == LL_RCC_SYSCLK_DIV_2) \
  71. || ((__VALUE__) == LL_RCC_SYSCLK_DIV_4) \
  72. || ((__VALUE__) == LL_RCC_SYSCLK_DIV_8) \
  73. || ((__VALUE__) == LL_RCC_SYSCLK_DIV_16) \
  74. || ((__VALUE__) == LL_RCC_SYSCLK_DIV_64) \
  75. || ((__VALUE__) == LL_RCC_SYSCLK_DIV_128) \
  76. || ((__VALUE__) == LL_RCC_SYSCLK_DIV_256) \
  77. || ((__VALUE__) == LL_RCC_SYSCLK_DIV_512))
  78. #define IS_LL_UTILS_APB1_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB1_DIV_1) \
  79. || ((__VALUE__) == LL_RCC_APB1_DIV_2) \
  80. || ((__VALUE__) == LL_RCC_APB1_DIV_4) \
  81. || ((__VALUE__) == LL_RCC_APB1_DIV_8) \
  82. || ((__VALUE__) == LL_RCC_APB1_DIV_16))
  83. #define IS_LL_UTILS_HSE_BYPASS(__STATE__) (((__STATE__) == LL_UTILS_HSEBYPASS_ON) \
  84. || ((__STATE__) == LL_UTILS_HSEBYPASS_OFF))
  85. #if defined(RCC_PLL_SUPPORT)
  86. #define IS_LL_UTILS_HSE_FREQUENCY(__FREQUENCY__) (((__FREQUENCY__) >= UTILS_HSE_FREQUENCY_MIN) && ((__FREQUENCY__) <= UTILS_HSE_FREQUENCY_MAX))
  87. #define IS_LL_UTILS_PLL_INPUT_FREQUENCY(__FREQUENCY__) (((__FREQUENCY__) >= LL_RCC_PLLINPUT_FREQ_MIN) && ((__FREQUENCY__) <= LL_RCC_PLLINPUT_FREQ_MAX))
  88. #endif
  89. /**
  90. * @}
  91. */
  92. #if defined(RCC_PLL_SUPPORT)
  93. /* Private function prototypes -----------------------------------------------*/
  94. /** @defgroup UTILS_LL_Private_Functions UTILS Private functions
  95. * @{
  96. */
  97. static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct);
  98. static ErrorStatus UTILS_PLL_IsBusy(void);
  99. /**
  100. * @}
  101. */
  102. #endif
  103. /* Exported functions --------------------------------------------------------*/
  104. /** @addtogroup UTILS_LL_Exported_Functions
  105. * @{
  106. */
  107. /** @addtogroup UTILS_LL_EF_DELAY
  108. * @{
  109. */
  110. /**
  111. * @brief This function configures the Cortex-M SysTick source to have 1ms time base.
  112. * @note When a RTOS is used, it is recommended to avoid changing the Systick
  113. * configuration by calling this function, for a delay use rather osDelay RTOS service.
  114. * @param HCLKFrequency HCLK frequency in Hz
  115. * @note HCLK frequency can be calculated thanks to RCC helper macro or function @ref LL_RCC_GetSystemClocksFreq
  116. * @retval None
  117. */
  118. void LL_Init1msTick(uint32_t HCLKFrequency)
  119. {
  120. /* Use frequency provided in argument */
  121. LL_InitTick(HCLKFrequency, 1000U);
  122. }
  123. /**
  124. * @brief This function provides accurate delay (in milliseconds) based
  125. * on SysTick counter flag
  126. * @note When a RTOS is used, it is recommended to avoid using blocking delay
  127. * and use rather osDelay service.
  128. * @note To respect 1ms timebase, user should call @ref LL_Init1msTick function which
  129. * will configure Systick to 1ms
  130. * @param Delay specifies the delay time length, in milliseconds.
  131. * @retval None
  132. */
  133. void LL_mDelay(uint32_t Delay)
  134. {
  135. __IO uint32_t tmp = SysTick->CTRL; /* Clear the COUNTFLAG first */
  136. uint32_t tmpDelay; /* MISRAC2012-Rule-17.8 */
  137. /* Add this code to indicate that local variable is not used */
  138. ((void)tmp);
  139. tmpDelay = Delay;
  140. /* Add a period to guaranty minimum wait */
  141. if (tmpDelay < LL_MAX_DELAY)
  142. {
  143. tmpDelay ++;
  144. }
  145. while (tmpDelay != 0U)
  146. {
  147. if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U)
  148. {
  149. tmpDelay --;
  150. }
  151. }
  152. }
  153. /**
  154. * @}
  155. */
  156. /** @addtogroup UTILS_EF_SYSTEM
  157. * @brief System Configuration functions
  158. *
  159. @verbatim
  160. ===============================================================================
  161. ##### System Configuration functions #####
  162. ===============================================================================
  163. [..]
  164. System, AHB and APB1 buses clocks configuration
  165. (+) The maximum frequency of the SYSCLK, HCLK, PCLK1 is 48000000 Hz.
  166. @endverbatim
  167. @internal
  168. Depending on the device voltage range, the maximum frequency should be
  169. adapted accordingly:
  170. (++) Table 1. HCLK clock frequency.
  171. (++) +-------------------------------------------------------+
  172. (++) | Latency | HCLK clock frequency (MHz) |
  173. (++) | |-------------------------------------|
  174. (++) | | voltage range 1 | voltage range 2 |
  175. (++) | | 1.08V - 1.32V | 0.9 V - 1.10V |
  176. (++) |-----------------|------------------|------------------|
  177. (++) |0WS(1 CPU cycles)| HCLK <= 24 | HCLK <= 8 |
  178. (++) |-----------------|------------------|------------------|
  179. (++) |1WS(2 CPU cycles)| HCLK <= 48 | HCLK <= 16 |
  180. (++) |-----------------|------------------|------------------|
  181. @endinternal
  182. * @{
  183. */
  184. /**
  185. * @brief This function sets directly SystemCoreClock CMSIS variable.
  186. * @note Variable can be calculated also through SystemCoreClockUpdate function.
  187. * @param HCLKFrequency HCLK frequency in Hz (can be calculated thanks to RCC helper macro)
  188. * @retval None
  189. */
  190. void LL_SetSystemCoreClock(uint32_t HCLKFrequency)
  191. {
  192. /* HCLK clock frequency */
  193. SystemCoreClock = HCLKFrequency;
  194. }
  195. #if defined(RCC_PLL_SUPPORT)
  196. /**
  197. * @brief This function configures system clock with HSI as clock source of the PLL
  198. * @note The application need to ensure that PLL is disabled.
  199. * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
  200. * the configuration information for the BUS prescalers.
  201. * @retval An ErrorStatus enumeration value:
  202. * - SUCCESS: configuration done
  203. * - ERROR: frequency configuration not done
  204. */
  205. ErrorStatus LL_PLL_ConfigSystemClock_HSI(LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
  206. {
  207. ErrorStatus status;
  208. uint32_t pllfreq;
  209. /* Check if one of the PLL is enabled */
  210. if (UTILS_PLL_IsBusy() == SUCCESS)
  211. {
  212. /* Check if the new PLL input frequency is correct */
  213. if (!IS_LL_UTILS_PLL_INPUT_FREQUENCY(LL_RCC_HSI_GetFreq()))
  214. {
  215. /* the new PLL input frequency is error */
  216. return ERROR;
  217. }
  218. /* Calculate the new PLL output frequency */
  219. pllfreq = 2 * LL_RCC_HSI_GetFreq();
  220. /* Enable HSI if not enabled */
  221. if (LL_RCC_HSI_IsReady() != 1U)
  222. {
  223. LL_RCC_HSI_Enable();
  224. while (LL_RCC_HSI_IsReady() != 1U)
  225. {
  226. /* Wait for HSI ready */
  227. }
  228. }
  229. /* Configure PLL */
  230. LL_RCC_PLL_SetMainSource(LL_RCC_PLLSOURCE_HSI);
  231. /* Enable PLL and switch system clock to PLL */
  232. status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct);
  233. }
  234. else
  235. {
  236. /* Current PLL configuration cannot be modified */
  237. status = ERROR;
  238. }
  239. return status;
  240. }
  241. /**
  242. * @brief This function configures system clock with HSE as clock source of the PLL
  243. * @note The application need to ensure that PLL is disabled.
  244. * @param HSEFrequency Value between Min_Data = 4000000 and Max_Data = 48000000
  245. * @param HSEBypass This parameter can be one of the following values:
  246. * @arg @ref LL_UTILS_HSEBYPASS_ON
  247. * @arg @ref LL_UTILS_HSEBYPASS_OFF
  248. * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
  249. * the configuration information for the BUS prescalers.
  250. * @retval An ErrorStatus enumeration value:
  251. * - SUCCESS: Max frequency configuration done
  252. * - ERROR: Max frequency configuration not done
  253. */
  254. ErrorStatus LL_PLL_ConfigSystemClock_HSE(uint32_t HSEFrequency, uint32_t HSEBypass, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
  255. {
  256. ErrorStatus status;
  257. uint32_t pllfreq;
  258. /* Check the parameters */
  259. assert_param(IS_LL_UTILS_HSE_FREQUENCY(HSEFrequency));
  260. assert_param(IS_LL_UTILS_HSE_BYPASS(HSEBypass));
  261. /* Check if one of the PLL is enabled */
  262. if (UTILS_PLL_IsBusy() == SUCCESS)
  263. {
  264. /* Check if the new PLL input frequency is correct */
  265. if (!IS_LL_UTILS_PLL_INPUT_FREQUENCY(HSEFrequency))
  266. {
  267. /* the new PLL input frequency is error */
  268. return ERROR;
  269. }
  270. /* Calculate the new PLL output frequency */
  271. pllfreq = HSEFrequency * 2;
  272. /* Enable HSE if not enabled */
  273. if (LL_RCC_HSE_IsReady() != 1U)
  274. {
  275. /* Set frequency range of the HSE */
  276. LL_RCC_HSE_SetFreqRegion(LL_RCC_HSE_16_32MHz);
  277. /* Check if need to enable HSE bypass feature or not */
  278. if (HSEBypass == LL_UTILS_HSEBYPASS_ON)
  279. {
  280. LL_RCC_HSE_EnableBypass();
  281. }
  282. else
  283. {
  284. LL_RCC_HSE_DisableBypass();
  285. }
  286. /* Enable HSE */
  287. LL_RCC_HSE_Enable();
  288. while (LL_RCC_HSE_IsReady() != 1U)
  289. {
  290. /* Wait for HSE ready */
  291. }
  292. }
  293. /* Configure PLL */
  294. LL_RCC_PLL_SetMainSource(LL_RCC_PLLSOURCE_HSE);
  295. /* Enable PLL and switch system clock to PLL */
  296. status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct);
  297. }
  298. else
  299. {
  300. /* Current PLL configuration cannot be modified */
  301. status = ERROR;
  302. }
  303. return status;
  304. }
  305. #endif
  306. /**
  307. * @brief Update number of Flash wait states in line with new frequency and current
  308. * voltage range.
  309. * @param HCLKFrequency HCLK frequency
  310. * @retval An ErrorStatus enumeration value:
  311. * - SUCCESS: Latency has been modified
  312. * - ERROR: Latency cannot be modified
  313. */
  314. ErrorStatus LL_SetFlashLatency(uint32_t HCLKFrequency)
  315. {
  316. uint32_t timeout;
  317. uint32_t getlatency;
  318. uint32_t latency;
  319. ErrorStatus status;
  320. /* Frequency cannot be equal to 0 or greater than max clock */
  321. if ((HCLKFrequency == 0U) || (HCLKFrequency > UTILS_SCALE1_LATENCY2_FREQ))
  322. {
  323. status = ERROR;
  324. return status;
  325. }
  326. else
  327. {
  328. if (HCLKFrequency > UTILS_SCALE1_LATENCY1_FREQ)
  329. {
  330. /* 24 < HCLK <= 48 => 1WS (2 CPU cycles) */
  331. latency = LL_FLASH_LATENCY_1;
  332. }
  333. else
  334. {
  335. /* else HCLKFrequency < 24MHz default LL_FLASH_LATENCY_0 0WS */
  336. latency = LL_FLASH_LATENCY_0;
  337. }
  338. }
  339. LL_FLASH_SetLatency(latency);
  340. /* Check that the new number of wait states is taken into account to access the Flash
  341. memory by reading the FLASH_ACR register */
  342. timeout = 2u;
  343. do
  344. {
  345. /* Wait for Flash latency to be updated */
  346. getlatency = LL_FLASH_GetLatency();
  347. timeout--;
  348. }
  349. while ((getlatency != latency) && (timeout > 0u));
  350. if (getlatency != latency)
  351. {
  352. status = ERROR;
  353. }
  354. else
  355. {
  356. status = SUCCESS;
  357. }
  358. return status;
  359. }
  360. /**
  361. * @}
  362. */
  363. /**
  364. * @}
  365. */
  366. #if defined(RCC_PLL_SUPPORT)
  367. /** @addtogroup UTILS_LL_Private_Functions
  368. * @{
  369. */
  370. /**
  371. * @brief Function to check that PLL can be modified
  372. * @retval An ErrorStatus enumeration value:
  373. * - SUCCESS: PLL modification can be done
  374. * - ERROR: PLL is busy
  375. */
  376. static ErrorStatus UTILS_PLL_IsBusy(void)
  377. {
  378. ErrorStatus status = SUCCESS;
  379. /* Check if PLL is busy*/
  380. if (LL_RCC_PLL_IsReady() != 0U)
  381. {
  382. /* PLL configuration cannot be modified */
  383. status = ERROR;
  384. }
  385. return status;
  386. }
  387. /**
  388. * @brief Function to enable PLL and switch system clock to PLL
  389. * @param SYSCLK_Frequency SYSCLK frequency
  390. * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
  391. * the configuration information for the BUS prescalers.
  392. * @retval An ErrorStatus enumeration value:
  393. * - SUCCESS: No problem to switch system to PLL
  394. * - ERROR: Problem to switch system to PLL
  395. */
  396. static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
  397. {
  398. ErrorStatus status = SUCCESS;
  399. uint32_t hclk_frequency;
  400. assert_param(IS_LL_UTILS_SYSCLK_DIV(UTILS_ClkInitStruct->AHBCLKDivider));
  401. assert_param(IS_LL_UTILS_APB1_DIV(UTILS_ClkInitStruct->APB1CLKDivider));
  402. /* Calculate HCLK frequency */
  403. hclk_frequency = __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, UTILS_ClkInitStruct->AHBCLKDivider);
  404. /* Increasing the number of wait states because of higher CPU frequency */
  405. if (SystemCoreClock < hclk_frequency)
  406. {
  407. /* Set FLASH latency to highest latency */
  408. status = LL_SetFlashLatency(hclk_frequency);
  409. }
  410. /* Update system clock configuration */
  411. if (status == SUCCESS)
  412. {
  413. /* Enable PLL */
  414. LL_RCC_PLL_Enable();
  415. while (LL_RCC_PLL_IsReady() != 1U)
  416. {
  417. /* Wait for PLL ready */
  418. }
  419. /* Sysclk activation on the main PLL */
  420. LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider);
  421. LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
  422. while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
  423. {
  424. /* Wait for system clock switch to PLL */
  425. }
  426. /* Set APB1 prescaler*/
  427. LL_RCC_SetAPB1Prescaler(UTILS_ClkInitStruct->APB1CLKDivider);
  428. }
  429. /* Decreasing the number of wait states because of lower CPU frequency */
  430. if (SystemCoreClock > hclk_frequency)
  431. {
  432. /* Set FLASH latency to lowest latency */
  433. status = LL_SetFlashLatency(hclk_frequency);
  434. }
  435. /* Update SystemCoreClock variable */
  436. if (status == SUCCESS)
  437. {
  438. LL_SetSystemCoreClock(hclk_frequency);
  439. }
  440. return status;
  441. }
  442. /**
  443. * @}
  444. */
  445. #endif
  446. /**
  447. * @}
  448. */
  449. /**
  450. * @}
  451. */
  452. /************************ (C) COPYRIGHT Puya *****END OF FILE****/