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