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