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