system_n32l43x.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. /*****************************************************************************
  2. * Copyright (c) 2022, Nations Technologies Inc.
  3. *
  4. * All rights reserved.
  5. * ****************************************************************************
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. *
  10. * - Redistributions of source code must retain the above copyright notice,
  11. * this list of conditions and the disclaimer below.
  12. *
  13. * Nations' name may not be used to endorse or promote products derived from
  14. * this software without specific prior written permission.
  15. *
  16. * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  19. * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  21. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  22. * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  23. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  24. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  25. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. * ****************************************************************************/
  27. /**
  28. * @file system_n32l43x.c
  29. * @author Nations
  30. * @version v1.2.0
  31. *
  32. * @copyright Copyright (c) 2022, Nations Technologies Inc. All rights reserved.
  33. */
  34. #include "n32l43x.h"
  35. /* Uncomment the line corresponding to the desired System clock (SYSCLK)
  36. frequency (after reset the HSI is used as SYSCLK source)
  37. IMPORTANT NOTE:
  38. ==============
  39. 1. After each device reset the HSI is used as System clock source.
  40. 2. Please make sure that the selected System clock doesn't exceed your
  41. device's maximum frequency.
  42. 3. If none of the define below is enabled, the HSI is used as System clock
  43. source.
  44. 4. The System clock configuration functions provided within this file assume
  45. that:
  46. - For Low, Medium and High density Value line devices an external 8MHz
  47. crystal is used to drive the System clock.
  48. - For Low, Medium and High density devices an external 8MHz crystal is
  49. used to drive the System clock.
  50. - For Connectivity line devices an external 25MHz crystal is used to
  51. drive the System clock. If you are using different crystal you have to adapt
  52. those functions accordingly.
  53. */
  54. #define SYSCLK_USE_MSI 0
  55. #define SYSCLK_USE_HSI 1
  56. #define SYSCLK_USE_HSE 2
  57. #define SYSCLK_USE_HSI_PLL 3
  58. #define SYSCLK_USE_HSE_PLL 4
  59. #ifndef SYSCLK_FREQ
  60. #define SYSCLK_FREQ 108000000
  61. #endif
  62. /*
  63. * SYSCLK_SRC *
  64. ** SYSCLK_USE_MSI **
  65. ** SYSCLK_USE_HSI **
  66. ** SYSCLK_USE_HSE **
  67. ** SYSCLK_USE_HSI_PLL **
  68. ** SYSCLK_USE_HSE_PLL **
  69. */
  70. #ifndef SYSCLK_SRC
  71. #define SYSCLK_SRC SYSCLK_USE_HSE_PLL
  72. #endif
  73. #define PLL_DIV2_DISABLE 0x00000000
  74. #define PLL_DIV2_ENABLE 0x00000002
  75. #if SYSCLK_SRC == SYSCLK_USE_MSI
  76. #if (SYSCLK_FREQ == MSI_VALUE_L0)
  77. #define MSI_CLK 0
  78. #elif (SYSCLK_FREQ == MSI_VALUE_L1)
  79. #define MSI_CLK 1
  80. #elif (SYSCLK_FREQ == MSI_VALUE_L2)
  81. #define MSI_CLK 2
  82. #elif (SYSCLK_FREQ == MSI_VALUE_L3)
  83. #define MSI_CLK 3
  84. #elif (SYSCLK_FREQ == MSI_VALUE_L4)
  85. #define MSI_CLK 4
  86. #elif (SYSCLK_FREQ == MSI_VALUE_L5)
  87. #define MSI_CLK 5
  88. #elif (SYSCLK_FREQ == MSI_VALUE_L6)
  89. #define MSI_CLK 6
  90. #else
  91. #error SYSCL_FREQ must be set to MSI_VALUE_Lx(x=0~6)
  92. #endif
  93. #elif SYSCLK_SRC == SYSCLK_USE_HSI
  94. #if SYSCLK_FREQ != HSI_VALUE
  95. #error SYSCL_FREQ must be set to HSI_VALUE
  96. #endif
  97. #elif SYSCLK_SRC == SYSCLK_USE_HSE
  98. #ifndef HSE_VALUE
  99. #error HSE_VALUE must be defined!
  100. #endif
  101. #if SYSCLK_FREQ != HSE_VALUE
  102. #error SYSCL_FREQ must be set to HSE_VALUE
  103. #endif
  104. #elif SYSCLK_SRC == SYSCLK_USE_HSI_PLL
  105. #ifndef HSI_VALUE
  106. #error HSI_VALUE must be defined!
  107. #endif
  108. #if ((SYSCLK_FREQ % (HSI_VALUE / 2)) == 0) && (SYSCLK_FREQ / (HSI_VALUE / 2) >= 2) \
  109. && (SYSCLK_FREQ / (HSI_VALUE / 2) <= 32)
  110. #define PLLSRC_DIV 2
  111. #define PLL_DIV PLL_DIV2_DISABLE
  112. #define PLL_MUL (SYSCLK_FREQ / (HSI_VALUE / 2))
  113. #elif (SYSCLK_FREQ % HSI_VALUE == 0) && (SYSCLK_FREQ / HSI_VALUE >= 2) && (SYSCLK_FREQ / HSI_VALUE <= 32)
  114. #define PLLSRC_DIV 1
  115. #define PLL_DIV PLL_DIV2_DISABLE
  116. #define PLL_MUL (SYSCLK_FREQ / HSI_VALUE)
  117. #elif ((SYSCLK_FREQ % (HSI_VALUE / 4)) == 0) && (SYSCLK_FREQ / (HSI_VALUE / 4) >= 2) \
  118. && (SYSCLK_FREQ / (HSI_VALUE / 4) <= 32)
  119. #define PLLSRC_DIV 2
  120. #define PLL_DIV PLL_DIV2_ENABLE
  121. #define PLL_MUL (SYSCLK_FREQ / (HSI_VALUE / 4))
  122. #else
  123. #error Cannot make a PLL multiply factor to SYSCLK_FREQ.
  124. #endif
  125. #elif SYSCLK_SRC == SYSCLK_USE_HSE_PLL
  126. #ifndef HSE_VALUE
  127. #error HSE_VALUE must be defined!
  128. #endif
  129. #if ((SYSCLK_FREQ % (HSE_VALUE / 2)) == 0) && (SYSCLK_FREQ / (HSE_VALUE / 2) >= 2) \
  130. && (SYSCLK_FREQ / (HSE_VALUE / 2) <= 32)
  131. #define PLLSRC_DIV 2
  132. #define PLL_DIV PLL_DIV2_DISABLE
  133. #define PLL_MUL (SYSCLK_FREQ / (HSE_VALUE / 2))
  134. #elif (SYSCLK_FREQ % HSE_VALUE == 0) && (SYSCLK_FREQ / HSE_VALUE >= 2) && (SYSCLK_FREQ / HSE_VALUE <= 32)
  135. #define PLLSRC_DIV 1
  136. #define PLL_DIV PLL_DIV2_DISABLE
  137. #define PLL_MUL (SYSCLK_FREQ / HSE_VALUE)
  138. #elif ((SYSCLK_FREQ % (HSE_VALUE / 4)) == 0) && (SYSCLK_FREQ / (HSE_VALUE / 4) >= 2) \
  139. && (SYSCLK_FREQ / (HSE_VALUE / 4) <= 32)
  140. #define PLLSRC_DIV 2
  141. #define PLL_DIV PLL_DIV2_ENABLE
  142. #define PLL_MUL (SYSCLK_FREQ / (HSE_VALUE / 4))
  143. #else
  144. #error Cannot make a PLL multiply factor to SYSCLK_FREQ.
  145. #endif
  146. #else
  147. #error wrong value for SYSCLK_SRC
  148. #endif
  149. /* #define VECT_TAB_SRAM */
  150. #define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field. This value must be a multiple of 0x200. */
  151. /*******************************************************************************
  152. * Clock Definitions
  153. *******************************************************************************/
  154. uint32_t SystemCoreClock = SYSCLK_FREQ; /*!< System Clock Frequency (Core Clock) */
  155. const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
  156. const uint32_t MSIClockTable[7] = {MSI_VALUE_L0, MSI_VALUE_L1, MSI_VALUE_L2, MSI_VALUE_L3,
  157. MSI_VALUE_L4, MSI_VALUE_L5, MSI_VALUE_L6};
  158. static void SetSysClock(void);
  159. #ifdef DATA_IN_ExtSRAM
  160. static void SystemInit_ExtMemCtl(void);
  161. #endif /* DATA_IN_ExtSRAM */
  162. /**
  163. * @brief Setup the microcontroller system
  164. * Initialize the Embedded Flash Interface, the PLL and update the
  165. * SystemCoreClock variable.
  166. * @note This function should be used only after reset.
  167. */
  168. void SystemInit(void)
  169. {
  170. /* FPU settings
  171. * ------------------------------------------------------------*/
  172. #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
  173. SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10 and CP11 Full Access */
  174. #endif
  175. /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  176. /* Set MSIEN bit */
  177. RCC->CTRLSTS |= (uint32_t)0x00000004;
  178. /* Reset SW, HPRE, PPRE1, PPRE2 and MCO bits */
  179. RCC->CFG &= (uint32_t)0xF8FFC000;
  180. /* Reset HSEON, CLKSSEN and PLLEN bits */
  181. RCC->CTRL &= (uint32_t)0xFEF6FFFF;
  182. /* Reset HSEBYP bit */
  183. RCC->CTRL &= (uint32_t)0xFFFBFFFF;
  184. /* Reset PLLSRC, PLLXTPRE, PLLMUL, MCOPRES and USBPRES bits */
  185. RCC->CFG &= (uint32_t)0x0700FFFF;
  186. /* Reset CFG2 register */
  187. RCC->CFG2 = 0x00007000;
  188. /* Reset CFG3 register */
  189. RCC->CFG3 = 0x00003800;
  190. /* Reset RDCTRL register */
  191. RCC->RDCTRL = 0x00000000;
  192. /* Reset PLLHSIPRE register */
  193. RCC->PLLHSIPRE = 0x00000000;
  194. /* Disable all interrupts and clear pending bits */
  195. RCC->CLKINT = 0x04BF8000;
  196. /* Enable ex mode */
  197. RCC->APB1PCLKEN |= RCC_APB1PCLKEN_PWREN;
  198. RCC->APB1PCLKEN &= (uint32_t)(~RCC_APB1PCLKEN_PWREN);
  199. /* Enable ICACHE and Prefetch Buffer */
  200. FLASH->AC |= (uint32_t)(FLASH_AC_ICAHEN | FLASH_AC_PRFTBFEN);
  201. /* Checks whether the Low Voltage Mode status is SET or RESET */
  202. if ((FLASH->AC & FLASH_AC_LVMF) != RESET)
  203. {
  204. /* FLASH Low Voltage Mode Disable */
  205. FLASH->AC &= (uint32_t)(~FLASH_AC_LVMEN);
  206. }
  207. #ifdef DATA_IN_ExtSRAM
  208. SystemInit_ExtMemCtl();
  209. #endif /* DATA_IN_ExtSRAM */
  210. /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  211. /* Configure the Flash Latency cycles and enable prefetch buffer */
  212. SetSysClock();
  213. #ifdef VECT_TAB_SRAM
  214. SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
  215. #else
  216. SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
  217. #endif
  218. }
  219. /**
  220. * @brief Update SystemCoreClock variable according to Clock Register Values.
  221. * The SystemCoreClock variable contains the core clock (HCLK), it can
  222. * be used by the user application to setup the SysTick timer or
  223. * configure other parameters.
  224. *
  225. * @note Each time the core clock (HCLK) changes, this function must be called
  226. * to update SystemCoreClock variable value. Otherwise, any
  227. * configuration based on this variable will be incorrect.
  228. *
  229. * @note - The system frequency computed by this function is not the real
  230. * frequency in the chip. It is calculated based on the predefined
  231. * constant and the selected clock source:
  232. *
  233. * - If SYSCLK source is MSI, SystemCoreClock will contain the
  234. * MSI_VALUE(*)
  235. *
  236. * - If SYSCLK source is HSI, SystemCoreClock will contain the
  237. * HSI_VALUE(**)
  238. *
  239. * - If SYSCLK source is HSE, SystemCoreClock will contain the
  240. * HSE_VALUE(***)
  241. *
  242. * - If SYSCLK source is PLL, SystemCoreClock will contain the
  243. * HSE_VALUE(***) or HSI_VALUE(**) multiplied by the PLL factors.
  244. *
  245. * (*) MSI_VALUE is a constant defined in n32l43x.h file (default value
  246. * 4 MHz, 100KHz/200KHz/400KHz/800KHz/1MHz/2MHz/4MHz ) but the real
  247. * value may vary depending on the variations in voltage and temperature.
  248. *
  249. * (**) HSI_VALUE is a constant defined in n32l43x.h file (default value
  250. * 8 MHz) but the real value may vary depending on the variations
  251. * in voltage and temperature.
  252. *
  253. * (***) HSE_VALUE is a constant defined in n32l43x.h file (default value
  254. * 8 MHz or 25 MHz, depedning on the product used), user has to
  255. * ensure that HSE_VALUE is same as the real frequency of the crystal used.
  256. * Otherwise, this function may have wrong result.
  257. *
  258. * - The result of this function could be not correct when using
  259. * fractional value for HSE crystal.
  260. */
  261. void SystemCoreClockUpdate(void)
  262. {
  263. uint32_t tmp = 0, pllmull = 0, pllsource = 0, plldiv2 = 0;
  264. uint8_t msi_clk = 0;
  265. /* Get SYSCLK source
  266. * -------------------------------------------------------*/
  267. tmp = RCC->CFG & RCC_CFG_SCLKSTS;
  268. /* Get MSI clock
  269. * -------------------------------------------------------*/
  270. msi_clk = (uint8_t) ((RCC->CTRLSTS & RCC_CTRLSTS_MSIRANGE)>>4);
  271. switch (tmp)
  272. {
  273. case 0x00: /* MSI used as system clock */
  274. SystemCoreClock = MSIClockTable[msi_clk];
  275. break;
  276. case 0x04: /* HSI used as system clock */
  277. SystemCoreClock = HSI_VALUE;
  278. break;
  279. case 0x08: /* HSE used as system clock */
  280. SystemCoreClock = HSE_VALUE;
  281. break;
  282. case 0x0C: /* PLL used as system clock */
  283. /* Get PLL clock source and multiplication factor
  284. * ----------------------*/
  285. pllmull = RCC->CFG & RCC_CFG_PLLMULFCT;
  286. pllsource = RCC->CFG & RCC_CFG_PLLSRC;
  287. plldiv2 = RCC->PLLHSIPRE & RCC_PLLHSIPRE_PLLSRCDIV;
  288. if ((pllmull & RCC_CFG_PLLMULFCT_4) == 0)
  289. {
  290. pllmull = (pllmull >> 18) + 2; // PLLMUL[4]=0
  291. }
  292. else
  293. {
  294. pllmull = ((pllmull >> 18) - 496) + 1; // PLLMUL[4]=1
  295. }
  296. if (pllsource == 0x00)
  297. {
  298. /* HSI selected as PLL clock entry */
  299. if ((RCC->PLLHSIPRE & RCC_PLLHSIPRE_PLLSRCDIV) != (uint32_t)RESET)
  300. { /* HSI oscillator clock divided by 2 */
  301. SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
  302. }
  303. else
  304. {
  305. SystemCoreClock = HSI_VALUE * pllmull;
  306. }
  307. }
  308. else
  309. {
  310. /* HSE selected as PLL clock entry */
  311. if ((RCC->CFG & RCC_CFG_PLLHSEPRES) != (uint32_t)RESET)
  312. { /* HSE oscillator clock divided by 2 */
  313. SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
  314. }
  315. else
  316. {
  317. SystemCoreClock = HSE_VALUE * pllmull;
  318. }
  319. }
  320. if (plldiv2 == 0x02)
  321. {
  322. /* PLL source clock divided by 2 selected as PLL clock entry */
  323. SystemCoreClock >>= 1;
  324. }
  325. break;
  326. default:
  327. SystemCoreClock = MSIClockTable[msi_clk];
  328. break;
  329. }
  330. /* Compute HCLK clock frequency ----------------*/
  331. /* Get HCLK prescaler */
  332. tmp = AHBPrescTable[((RCC->CFG & RCC_CFG_AHBPRES) >> 4)];
  333. /* HCLK clock frequency */
  334. SystemCoreClock >>= tmp;
  335. }
  336. /**
  337. * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1
  338. * prescalers.
  339. */
  340. static void SetSysClock(void)
  341. {
  342. uint32_t rcc_cfg = 0;
  343. uint32_t rcc_pllhsipre = 0;
  344. uint32_t StartUpCounter = 0;
  345. #if (SYSCLK_SRC == SYSCLK_USE_MSI)
  346. uint8_t i=0;
  347. bool MSIStatus = 0;
  348. /* Config MSI */
  349. RCC->CTRLSTS &= 0xFFFFFF8F;
  350. /*Delay for while*/
  351. for(i=0;i<0x30;i++);
  352. RCC->CTRLSTS |= (((uint32_t)MSI_CLK) << 4);
  353. /*Delay for while*/
  354. for(i=0;i<0x30;i++);
  355. /* Enable MSI */
  356. RCC->CTRLSTS |= ((uint32_t)RCC_CTRLSTS_MSIEN);
  357. /* Wait till MSI is ready and if Time out is reached exit */
  358. do
  359. {
  360. MSIStatus = RCC->CTRLSTS & RCC_CTRLSTS_MSIRD;
  361. StartUpCounter++;
  362. } while ((MSIStatus == 0) && (StartUpCounter != MSI_STARTUP_TIMEOUT));
  363. MSIStatus = ((RCC->CTRLSTS & RCC_CTRLSTS_MSIRD) != RESET);
  364. if (!MSIStatus)
  365. {
  366. /* If MSI fails to start-up, the application will have wrong clock
  367. * configuration. User can add here some code to deal with this error */
  368. SystemCoreClock = MSI_VALUE_L6;
  369. return;
  370. }
  371. #elif ((SYSCLK_SRC == SYSCLK_USE_HSI) || (SYSCLK_SRC == SYSCLK_USE_HSI_PLL))
  372. bool HSIStatus = 0;
  373. /* Enable HSI */
  374. RCC->CTRL |= ((uint32_t)RCC_CTRL_HSIEN);
  375. /* Wait till HSI is ready and if Time out is reached exit */
  376. do
  377. {
  378. HSIStatus = RCC->CTRL & RCC_CTRL_HSIRDF;
  379. StartUpCounter++;
  380. } while ((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));
  381. HSIStatus = ((RCC->CTRL & RCC_CTRL_HSIRDF) != RESET);
  382. if (!HSIStatus)
  383. {
  384. /* If HSI fails to start-up, the application will have wrong clock
  385. * configuration. User can add here some code to deal with this error */
  386. SystemCoreClock = MSI_VALUE_L6;
  387. return;
  388. }
  389. #elif ((SYSCLK_SRC == SYSCLK_USE_HSE) || (SYSCLK_SRC == SYSCLK_USE_HSE_PLL))
  390. bool HSEStatus = 0;
  391. /* Enable HSE */
  392. RCC->CTRL |= ((uint32_t)RCC_CTRL_HSEEN);
  393. /* Wait till HSE is ready and if Time out is reached exit */
  394. do
  395. {
  396. HSEStatus = RCC->CTRL & RCC_CTRL_HSERDF;
  397. StartUpCounter++;
  398. } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
  399. HSEStatus = ((RCC->CTRL & RCC_CTRL_HSERDF) != RESET);
  400. if (!HSEStatus)
  401. {
  402. /* If HSE fails to start-up, the application will have wrong clock
  403. * configuration. User can add here some code to deal with this error */
  404. SystemCoreClock = MSI_VALUE_L6;
  405. return;
  406. }
  407. #endif
  408. /* If the system clock is greater than 64MHz, the voltage range of the main voltage regulator
  409. must be configured as 1.1V */
  410. if (SYSCLK_FREQ >= 64000000)
  411. {
  412. /* Enables PWR peripheral clock */
  413. RCC->APB1PCLKEN |= RCC_APB1_PERIPH_PWR;
  414. /* Check PWR->CTRL1.MRSEL configuration */
  415. if ((PWR->CTRL1 & ((uint32_t)PWR_CTRL1_MRSEL)) == ((uint32_t)PWR_CTRL1_MRSEL2))
  416. {
  417. /* Config 1.1V */
  418. PWR->CTRL1 |= PWR_CTRL1_MRSEL1;
  419. }
  420. }
  421. /* Flash wait state
  422. 0: HCLK <= 32M
  423. 1: HCLK <= 64M
  424. 2: HCLK <= 96M
  425. 3: HCLK <= 128M
  426. */
  427. FLASH->AC &= (uint32_t)((uint32_t)~FLASH_AC_LATENCY);
  428. FLASH->AC |= (uint32_t)((SYSCLK_FREQ - 1) / 32000000);
  429. /* HCLK = SYSCLK */
  430. RCC->CFG |= (uint32_t)RCC_CFG_AHBPRES_DIV1;
  431. /* PCLK2 max 54M */
  432. if (SYSCLK_FREQ > 54000000)
  433. {
  434. RCC->CFG |= (uint32_t)RCC_CFG_APB2PRES_DIV2;
  435. }
  436. else
  437. {
  438. RCC->CFG |= (uint32_t)RCC_CFG_APB2PRES_DIV1;
  439. }
  440. /* PCLK1 max 27M */
  441. if (SYSCLK_FREQ > 54000000)
  442. {
  443. RCC->CFG |= (uint32_t)RCC_CFG_APB1PRES_DIV4;
  444. }
  445. else if (SYSCLK_FREQ > 27000000)
  446. {
  447. RCC->CFG |= (uint32_t)RCC_CFG_APB1PRES_DIV2;
  448. }
  449. else
  450. {
  451. RCC->CFG |= (uint32_t)RCC_CFG_APB1PRES_DIV1;
  452. }
  453. #if SYSCLK_SRC == SYSCLK_USE_MSI
  454. /* Select MSI as system clock source */
  455. RCC->CFG &= (uint32_t)((uint32_t) ~(RCC_CFG_SCLKSW));
  456. RCC->CFG |= (uint32_t)RCC_CFG_SCLKSW_MSI;
  457. /* Wait till MSI is used as system clock source */
  458. while ((RCC->CFG & (uint32_t)RCC_CFG_SCLKSTS) != (uint32_t)0x00)
  459. {
  460. }
  461. #elif SYSCLK_SRC == SYSCLK_USE_HSI
  462. /* Select HSI as system clock source */
  463. RCC->CFG &= (uint32_t)((uint32_t) ~(RCC_CFG_SCLKSW));
  464. RCC->CFG |= (uint32_t)RCC_CFG_SCLKSW_HSI;
  465. /* Wait till HSI is used as system clock source */
  466. while ((RCC->CFG & (uint32_t)RCC_CFG_SCLKSTS) != (uint32_t)0x04)
  467. {
  468. }
  469. #elif SYSCLK_SRC == SYSCLK_USE_HSE
  470. /* Select HSE as system clock source */
  471. RCC->CFG &= (uint32_t)((uint32_t) ~(RCC_CFG_SCLKSW));
  472. RCC->CFG |= (uint32_t)RCC_CFG_SCLKSW_HSE;
  473. /* Wait till HSE is used as system clock source */
  474. while ((RCC->CFG & (uint32_t)RCC_CFG_SCLKSTS) != (uint32_t)0x08)
  475. {
  476. }
  477. #elif SYSCLK_SRC == SYSCLK_USE_HSI_PLL || SYSCLK_SRC == SYSCLK_USE_HSE_PLL
  478. /* clear bits */
  479. RCC->CFG &= (uint32_t)((uint32_t) ~(RCC_CFG_PLLSRC | RCC_CFG_PLLHSEPRES | RCC_CFG_PLLMULFCT));
  480. RCC->PLLHSIPRE &= (uint32_t)((uint32_t) ~(RCC_PLLHSIPRE_PLLHSIPRE | RCC_PLLHSIPRE_PLLSRCDIV));
  481. /* set PLL source */
  482. rcc_cfg = RCC->CFG;
  483. rcc_cfg |= (SYSCLK_SRC == SYSCLK_USE_HSI_PLL ? RCC_CFG_PLLSRC_HSI : RCC_CFG_PLLSRC_HSE);
  484. /* PLL DIV */
  485. rcc_pllhsipre = RCC->PLLHSIPRE;
  486. #if SYSCLK_SRC == SYSCLK_USE_HSI_PLL
  487. rcc_pllhsipre |= (PLLSRC_DIV == 1 ? RCC_PLLHSIPRE_PLLHSIPRE_HSI : RCC_PLLHSIPRE_PLLHSIPRE_HSI_DIV2);
  488. #elif SYSCLK_SRC == SYSCLK_USE_HSE_PLL
  489. rcc_cfg |= (PLLSRC_DIV == 1 ? RCC_CFG_PLLHSEPRES_HSE : RCC_CFG_PLLHSEPRES_HSE_DIV2);
  490. #endif
  491. /* set PLL DIV */
  492. rcc_pllhsipre |= (PLL_DIV == PLL_DIV2_DISABLE ? RCC_PLLHSIPRE_PLLSRCDIV_DISABLE : RCC_PLLHSIPRE_PLLSRCDIV_ENABLE);
  493. /* set PLL multiply factor */
  494. #if PLL_MUL <= 16
  495. rcc_cfg |= (PLL_MUL - 2) << 18;
  496. #else
  497. rcc_cfg |= ((PLL_MUL - 17) << 18) | (1 << 27);
  498. #endif
  499. RCC->CFG = rcc_cfg;
  500. RCC->PLLHSIPRE = rcc_pllhsipre;
  501. /* Enable PLL */
  502. RCC->CTRL |= RCC_CTRL_PLLEN;
  503. /* Wait till PLL is ready */
  504. while ((RCC->CTRL & RCC_CTRL_PLLRDF) == 0)
  505. {
  506. }
  507. /* Select PLL as system clock source */
  508. RCC->CFG &= (uint32_t)((uint32_t) ~(RCC_CFG_SCLKSW));
  509. RCC->CFG |= (uint32_t)RCC_CFG_SCLKSW_PLL;
  510. /* Wait till PLL is used as system clock source */
  511. while ((RCC->CFG & (uint32_t)RCC_CFG_SCLKSTS) != (uint32_t)0x0C)
  512. {
  513. }
  514. #endif
  515. }