1 /*!
2     \file    system_gd32vf103.c
3     \brief   RISC-V Device Peripheral Access Layer Source File for
4              GD32VF103 Device Series
5 
6     \version 2019-06-05, V1.0.0, firmware for GD32VF103
7     \version 2020-08-04, V1.1.0, firmware for GD32VF103
8     \version 2021-05-19, V1.1.1, firmware for GD32VF103
9 */
10 
11 /*
12     Copyright (c) 2020, GigaDevice Semiconductor Inc.
13 
14     Redistribution and use in source and binary forms, with or without modification,
15 are permitted provided that the following conditions are met:
16 
17     1. Redistributions of source code must retain the above copyright notice, this
18        list of conditions and the following disclaimer.
19     2. Redistributions in binary form must reproduce the above copyright notice,
20        this list of conditions and the following disclaimer in the documentation
21        and/or other materials provided with the distribution.
22     3. Neither the name of the copyright holder nor the names of its contributors
23        may be used to endorse or promote products derived from this software without
24        specific prior written permission.
25 
26     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 OF SUCH DAMAGE.
36 */
37 
38 /* This file refers the RISC-V standard, some adjustments are made according to GigaDevice chips */
39 
40 #include "gd32vf103.h"
41 
42 /* system frequency define */
43 #define __IRC8M           (IRC8M_VALUE)            /* internal 8 MHz RC oscillator frequency */
44 #define __HXTAL           (HXTAL_VALUE)            /* high speed crystal oscillator frequency */
45 #define __SYS_OSC_CLK     (__IRC8M)                /* main oscillator frequency */
46 
47 /* select a system clock by uncommenting the following line */
48 /* use IRC8M */
49 //#define __SYSTEM_CLOCK_48M_PLL_IRC8M            (uint32_t)(48000000)
50 //#define __SYSTEM_CLOCK_72M_PLL_IRC8M            (uint32_t)(72000000)
51 //#define __SYSTEM_CLOCK_108M_PLL_IRC8M           (uint32_t)(108000000)
52 
53 /********************************************************************/
54 //#define __SYSTEM_CLOCK_HXTAL                    (HXTAL_VALUE)
55 //#define __SYSTEM_CLOCK_24M_PLL_HXTAL            (uint32_t)(24000000)
56 /********************************************************************/
57 
58 //#define __SYSTEM_CLOCK_36M_PLL_HXTAL            (uint32_t)(36000000)
59 //#define __SYSTEM_CLOCK_48M_PLL_HXTAL            (uint32_t)(48000000)
60 //#define __SYSTEM_CLOCK_56M_PLL_HXTAL            (uint32_t)(56000000)
61 //#define __SYSTEM_CLOCK_72M_PLL_HXTAL            (uint32_t)(72000000)
62 //#define __SYSTEM_CLOCK_96M_PLL_HXTAL            (uint32_t)(96000000)
63 #define __SYSTEM_CLOCK_108M_PLL_HXTAL           (uint32_t)(108000000)
64 
65 #define SEL_IRC8M       0x00U
66 #define SEL_HXTAL       0x01U
67 #define SEL_PLL         0x02U
68 
69 /* set the system clock frequency and declare the system clock configuration function */
70 #ifdef __SYSTEM_CLOCK_48M_PLL_IRC8M
71 uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M;
72 static void system_clock_48m_irc8m(void);
73 #elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
74 uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M;
75 static void system_clock_72m_irc8m(void);
76 #elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
77 uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_IRC8M;
78 static void system_clock_108m_irc8m(void);
79 
80 #elif defined (__SYSTEM_CLOCK_HXTAL)
81 uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL;
82 static void system_clock_hxtal(void);
83 #elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL)
84 uint32_t SystemCoreClock = __SYSTEM_CLOCK_24M_PLL_HXTAL;
85 static void system_clock_24m_hxtal(void);
86 #elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL)
87 uint32_t SystemCoreClock = __SYSTEM_CLOCK_36M_PLL_HXTAL;
88 static void system_clock_36m_hxtal(void);
89 #elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
90 uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL;
91 static void system_clock_48m_hxtal(void);
92 #elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL)
93 uint32_t SystemCoreClock = __SYSTEM_CLOCK_56M_PLL_HXTAL;
94 static void system_clock_56m_hxtal(void);
95 #elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
96 uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL;
97 static void system_clock_72m_hxtal(void);
98 #elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL)
99 uint32_t SystemCoreClock = __SYSTEM_CLOCK_96M_PLL_HXTAL;
100 static void system_clock_96m_hxtal(void);
101 #elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
102 uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL;
103 static void system_clock_108m_hxtal(void);
104 #else
105 uint32_t SystemCoreClock = IRC8M_VALUE;
106 #endif /* __SYSTEM_CLOCK_48M_PLL_IRC8M */
107 
108 /* configure the system clock */
109 static void system_clock_config(void);
110 
111 /*!
112     \brief      configure the system clock
113     \param[in]  none
114     \param[out] none
115     \retval     none
116 */
system_clock_config(void)117 static void system_clock_config(void)
118 {
119 #ifdef __SYSTEM_CLOCK_HXTAL
120     system_clock_hxtal();
121 #elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL)
122     system_clock_24m_hxtal();
123 #elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL)
124     system_clock_36m_hxtal();
125 #elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
126     system_clock_48m_hxtal();
127 #elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL)
128     system_clock_56m_hxtal();
129 #elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
130     system_clock_72m_hxtal();
131 #elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL)
132     system_clock_96m_hxtal();
133 #elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
134     system_clock_108m_hxtal();
135 
136 #elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
137     system_clock_48m_irc8m();
138 #elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
139     system_clock_72m_irc8m();
140 #elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
141     system_clock_108m_irc8m();
142 #endif /* __SYSTEM_CLOCK_HXTAL */
143 }
144 
145 /*!
146     \brief      setup the microcontroller system, initialize the system
147     \param[in]  none
148     \param[out] none
149     \retval     none
150 */
SystemInit(void)151 void SystemInit(void)
152 {
153     /* reset the RCC clock configuration to the default reset state */
154     /* enable IRC8M */
155     RCU_CTL |= RCU_CTL_IRC8MEN;
156 
157     /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */
158     RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |
159                   RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL);
160 
161     /* reset HXTALEN, CKMEN, PLLEN bits */
162     RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN);
163 
164     /* Reset HXTALBPS bit */
165     RCU_CTL &= ~(RCU_CTL_HXTALBPS);
166 
167     /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */
168 
169     RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF |
170                   RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4);
171     RCU_CFG1 = 0x00000000U;
172 
173     /* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */
174     RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
175     /* disable all interrupts */
176     RCU_INT = 0x00FF0000U;
177 
178     /* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */
179     system_clock_config();
180 }
181 
182 /*!
183     \brief      update the SystemCoreClock with current core clock retrieved from cpu registers
184     \param[in]  none
185     \param[out] none
186     \retval     none
187 */
SystemCoreClockUpdate(void)188 void SystemCoreClockUpdate(void)
189 {
190     uint32_t scss = 0U;
191     uint32_t pllsel = 0U, predv0sel = 0U, pllmf = 0U, ck_src = 0U;
192     uint32_t predv0 = 0U, predv1 = 0U, pll1mf = 0U,idx = 0U,clk_exp = 0U;
193     /* exponent of AHB clock divider */
194     const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
195 
196     scss = GET_BITS(RCU_CFG0, 2, 3);
197 
198     switch (scss)
199     {
200         /* IRC8M is selected as CK_SYS */
201         case SEL_IRC8M:
202             SystemCoreClock = IRC8M_VALUE;
203             break;
204 
205         /* HXTAL is selected as CK_SYS */
206         case SEL_HXTAL:
207             SystemCoreClock = HXTAL_VALUE;
208             break;
209 
210         /* PLL is selected as CK_SYS */
211         case SEL_PLL:
212             /* PLL clock source selection, HXTAL or IRC8M/2 */
213             pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
214 
215 
216             if(RCU_PLLSRC_IRC8M_DIV2 == pllsel){
217                 /* PLL clock source is IRC8M/2 */
218                 ck_src = IRC8M_VALUE / 2U;
219             }else{
220                 /* PLL clock source is HXTAL */
221                 ck_src = HXTAL_VALUE;
222 
223                 predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
224 
225                 /* source clock use PLL1 */
226                 if(RCU_PREDV0SRC_CKPLL1 == predv0sel){
227                     predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U;
228                     pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U;
229                     if(17U == pll1mf){
230                         pll1mf = 20U;
231                     }
232                     ck_src = (ck_src / predv1) * pll1mf;
233                 }
234                 predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
235                 ck_src /= predv0;
236             }
237 
238             /* PLL multiplication factor */
239             pllmf = GET_BITS(RCU_CFG0, 18, 21);
240 
241             if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){
242                 pllmf |= 0x10U;
243             }
244 
245             if(pllmf >= 15U){
246                 pllmf += 1U;
247             }else{
248                 pllmf += 2U;
249             }
250 
251             SystemCoreClock = ck_src * pllmf;
252 
253             if(15U == pllmf){
254                 /* PLL source clock multiply by 6.5 */
255                 SystemCoreClock = ck_src * 6U + ck_src / 2U;
256             }
257 
258             break;
259 
260         /* IRC8M is selected as CK_SYS */
261         default:
262             SystemCoreClock = IRC8M_VALUE;
263             break;
264     }
265     /* calculate AHB clock frequency */
266     idx = GET_BITS(RCU_CFG0, 4, 7);
267     clk_exp = ahb_exp[idx];
268     SystemCoreClock >>= clk_exp;
269 }
270 
271 #ifdef __SYSTEM_CLOCK_HXTAL
272 /*!
273     \brief      configure the system clock to HXTAL
274     \param[in]  none
275     \param[out] none
276     \retval     none
277 */
system_clock_hxtal(void)278 static void system_clock_hxtal(void)
279 {
280     uint32_t timeout = 0U;
281     uint32_t stab_flag = 0U;
282 
283     /* enable HXTAL */
284     RCU_CTL |= RCU_CTL_HXTALEN;
285 
286     /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
287     do{
288         timeout++;
289         stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
290     }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
291 
292     /* if fail */
293     if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
294         while(1){
295         }
296     }
297 
298     /* AHB = SYSCLK */
299     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
300     /* APB2 = AHB/1 */
301     RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
302     /* APB1 = AHB/2 */
303     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
304 
305     /* select HXTAL as system clock */
306     RCU_CFG0 &= ~RCU_CFG0_SCS;
307     RCU_CFG0 |= RCU_CKSYSSRC_HXTAL;
308 
309     /* wait until HXTAL is selected as system clock */
310     while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){
311     }
312 }
313 
314 #elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL)
315 /*!
316     \brief      configure the system clock to 24M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
317     \param[in]  none
318     \param[out] none
319     \retval     none
320 */
system_clock_24m_hxtal(void)321 static void system_clock_24m_hxtal(void)
322 {
323     uint32_t timeout = 0U;
324     uint32_t stab_flag = 0U;
325 
326     /* enable HXTAL */
327     RCU_CTL |= RCU_CTL_HXTALEN;
328 
329     /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
330     do{
331         timeout++;
332         stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
333     }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
334 
335     /* if fail */
336     if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
337         while(1){
338         }
339     }
340 
341     /* HXTAL is stable */
342     /* AHB = SYSCLK */
343     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
344     /* APB2 = AHB/1 */
345     RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
346     /* APB1 = AHB/2 */
347     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
348 
349     /* CK_PLL = (CK_PREDIV0) * 6 = 24 MHz */
350     RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
351     RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6);
352 
353     if(HXTAL_VALUE==25000000){
354         /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
355         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
356         RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
357 
358         /* enable PLL1 */
359         RCU_CTL |= RCU_CTL_PLL1EN;
360         /* wait till PLL1 is ready */
361         while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
362         }
363 
364     }else if(HXTAL_VALUE==8000000){
365         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0);
366         RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 );
367     }
368 
369     /* enable PLL */
370     RCU_CTL |= RCU_CTL_PLLEN;
371 
372     /* wait until PLL is stable */
373     while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
374     }
375 
376     /* select PLL as system clock */
377     RCU_CFG0 &= ~RCU_CFG0_SCS;
378     RCU_CFG0 |= RCU_CKSYSSRC_PLL;
379 
380     /* wait until PLL is selected as system clock */
381     while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
382     }
383 }
384 
385 #elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL)
386 /*!
387     \brief      configure the system clock to 36M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
388     \param[in]  none
389     \param[out] none
390     \retval     none
391 */
system_clock_36m_hxtal(void)392 static void system_clock_36m_hxtal(void)
393 {
394     uint32_t timeout = 0U;
395     uint32_t stab_flag = 0U;
396 
397     /* enable HXTAL */
398     RCU_CTL |= RCU_CTL_HXTALEN;
399 
400     /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
401     do{
402         timeout++;
403         stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
404     }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
405 
406     /* if fail */
407     if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
408         while(1){
409         }
410     }
411 
412     /* HXTAL is stable */
413     /* AHB = SYSCLK */
414     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
415     /* APB2 = AHB/1 */
416     RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
417     /* APB1 = AHB/2 */
418     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
419 
420     /* CK_PLL = (CK_PREDIV0) * 9 = 36 MHz */
421     RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
422     RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9);
423 
424     if(HXTAL_VALUE==25000000){
425         /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
426         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
427         RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
428 
429         /* enable PLL1 */
430         RCU_CTL |= RCU_CTL_PLL1EN;
431         /* wait till PLL1 is ready */
432         while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
433         }
434 
435     }else if(HXTAL_VALUE==8000000){
436         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0);
437         RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 );
438     }
439 
440     /* enable PLL */
441     RCU_CTL |= RCU_CTL_PLLEN;
442 
443     /* wait until PLL is stable */
444     while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
445     }
446 
447     /* select PLL as system clock */
448     RCU_CFG0 &= ~RCU_CFG0_SCS;
449     RCU_CFG0 |= RCU_CKSYSSRC_PLL;
450 
451     /* wait until PLL is selected as system clock */
452     while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
453     }
454 }
455 
456 #elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
457 /*!
458     \brief      configure the system clock to 48M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
459     \param[in]  none
460     \param[out] none
461     \retval     none
462 */
system_clock_48m_hxtal(void)463 static void system_clock_48m_hxtal(void)
464 {
465     uint32_t timeout = 0U;
466     uint32_t stab_flag = 0U;
467 
468     /* enable HXTAL */
469     RCU_CTL |= RCU_CTL_HXTALEN;
470 
471     /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
472     do{
473         timeout++;
474         stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
475     }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
476 
477     /* if fail */
478     if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
479         while(1){
480         }
481     }
482 
483     /* HXTAL is stable */
484     /* AHB = SYSCLK */
485     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
486     /* APB2 = AHB/1 */
487     RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
488     /* APB1 = AHB/2 */
489     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
490 
491     /* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */
492     RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
493     RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL12);
494 
495     if(HXTAL_VALUE==25000000){
496 
497         /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
498         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
499         RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
500 
501         /* enable PLL1 */
502         RCU_CTL |= RCU_CTL_PLL1EN;
503         /* wait till PLL1 is ready */
504         while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
505         }
506 
507     }else if(HXTAL_VALUE==8000000){
508         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0);
509         RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 );
510     }
511 
512 
513 
514     /* enable PLL */
515     RCU_CTL |= RCU_CTL_PLLEN;
516 
517     /* wait until PLL is stable */
518     while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
519     }
520 
521     /* select PLL as system clock */
522     RCU_CFG0 &= ~RCU_CFG0_SCS;
523     RCU_CFG0 |= RCU_CKSYSSRC_PLL;
524 
525     /* wait until PLL is selected as system clock */
526     while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
527     }
528 }
529 
530 #elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL)
531 /*!
532     \brief      configure the system clock to 56M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
533     \param[in]  none
534     \param[out] none
535     \retval     none
536 */
system_clock_56m_hxtal(void)537 static void system_clock_56m_hxtal(void)
538 {
539     uint32_t timeout = 0U;
540     uint32_t stab_flag = 0U;
541 
542     /* enable HXTAL */
543     RCU_CTL |= RCU_CTL_HXTALEN;
544 
545     /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
546     do{
547         timeout++;
548         stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
549     }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
550 
551     /* if fail */
552     if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
553         while(1){
554         }
555     }
556 
557     /* HXTAL is stable */
558     /* AHB = SYSCLK */
559     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
560     /* APB2 = AHB/1 */
561     RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
562     /* APB1 = AHB/2 */
563     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
564 
565     /* CK_PLL = (CK_PREDIV0) * 14 = 56 MHz */
566     RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
567     RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL14);
568 
569     if(HXTAL_VALUE==25000000){
570 
571         /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
572         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
573         RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
574 
575         /* enable PLL1 */
576         RCU_CTL |= RCU_CTL_PLL1EN;
577         /* wait till PLL1 is ready */
578         while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
579         }
580 
581     }else if(HXTAL_VALUE==8000000){
582         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0);
583         RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 );
584     }
585 
586     /* enable PLL */
587     RCU_CTL |= RCU_CTL_PLLEN;
588 
589     /* wait until PLL is stable */
590     while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
591     }
592 
593     /* select PLL as system clock */
594     RCU_CFG0 &= ~RCU_CFG0_SCS;
595     RCU_CFG0 |= RCU_CKSYSSRC_PLL;
596 
597     /* wait until PLL is selected as system clock */
598     while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
599     }
600 }
601 
602 #elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
603 /*!
604     \brief      configure the system clock to 72M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
605     \param[in]  none
606     \param[out] none
607     \retval     none
608 */
system_clock_72m_hxtal(void)609 static void system_clock_72m_hxtal(void)
610 {
611     uint32_t timeout = 0U;
612     uint32_t stab_flag = 0U;
613 
614     /* enable HXTAL */
615     RCU_CTL |= RCU_CTL_HXTALEN;
616 
617     /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
618     do{
619         timeout++;
620         stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
621     }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
622 
623     /* if fail */
624     if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
625         while(1){
626         }
627     }
628 
629     /* HXTAL is stable */
630     /* AHB = SYSCLK */
631     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
632     /* APB2 = AHB/1 */
633     RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
634     /* APB1 = AHB/2 */
635     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
636 
637     /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */
638     RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
639     RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL18);
640 
641 
642     if(HXTAL_VALUE==25000000){
643 
644         /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
645         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
646         RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
647 
648         /* enable PLL1 */
649         RCU_CTL |= RCU_CTL_PLL1EN;
650         /* wait till PLL1 is ready */
651         while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
652         }
653 
654     }else if(HXTAL_VALUE==8000000){
655         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0);
656         RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 );
657     }
658 
659     /* enable PLL */
660     RCU_CTL |= RCU_CTL_PLLEN;
661 
662     /* wait until PLL is stable */
663     while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
664     }
665 
666     /* select PLL as system clock */
667     RCU_CFG0 &= ~RCU_CFG0_SCS;
668     RCU_CFG0 |= RCU_CKSYSSRC_PLL;
669 
670     /* wait until PLL is selected as system clock */
671     while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
672     }
673 }
674 
675 #elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL)
676 /*!
677     \brief      configure the system clock to 96M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
678     \param[in]  none
679     \param[out] none
680     \retval     none
681 */
system_clock_96m_hxtal(void)682 static void system_clock_96m_hxtal(void)
683 {
684     uint32_t timeout = 0U;
685     uint32_t stab_flag = 0U;
686 
687     /* enable HXTAL */
688     RCU_CTL |= RCU_CTL_HXTALEN;
689 
690     /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
691     do{
692         timeout++;
693         stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
694     }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
695 
696     /* if fail */
697     if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
698         while(1){
699         }
700     }
701 
702     /* HXTAL is stable */
703     /* AHB = SYSCLK */
704     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
705     /* APB2 = AHB/1 */
706     RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
707     /* APB1 = AHB/2 */
708     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
709 
710     if(HXTAL_VALUE==25000000){
711 
712         /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */
713         RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
714         RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24);
715 
716         /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
717         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
718         RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10);
719         /* enable PLL1 */
720         RCU_CTL |= RCU_CTL_PLL1EN;
721         /* wait till PLL1 is ready */
722         while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
723         }
724 
725     }else if(HXTAL_VALUE==8000000){
726         /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */
727         RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
728         RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24);
729 
730         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0);
731         RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 );
732     }
733 
734     /* enable PLL */
735     RCU_CTL |= RCU_CTL_PLLEN;
736 
737     /* wait until PLL is stable */
738     while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
739     }
740 
741     /* select PLL as system clock */
742     RCU_CFG0 &= ~RCU_CFG0_SCS;
743     RCU_CFG0 |= RCU_CKSYSSRC_PLL;
744 
745     /* wait until PLL is selected as system clock */
746     while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
747     }
748 }
749 
750 #elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
751 /*!
752     \brief      configure the system clock to 108M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source
753     \param[in]  none
754     \param[out] none
755     \retval     none
756 */
757 
system_clock_108m_hxtal(void)758 static void system_clock_108m_hxtal(void)
759 {
760     uint32_t timeout   = 0U;
761     uint32_t stab_flag = 0U;
762 
763     /* enable HXTAL */
764     RCU_CTL |= RCU_CTL_HXTALEN;
765 
766     /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
767     do{
768         timeout++;
769         stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
770     }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
771 
772     /* if fail */
773     if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
774         while(1){
775         }
776     }
777 
778     /* HXTAL is stable */
779     /* AHB = SYSCLK */
780     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
781     /* APB2 = AHB/1 */
782     RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
783     /* APB1 = AHB/2 */
784     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
785 
786     /* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */
787     RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
788     RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL27);
789 
790     if(HXTAL_VALUE==25000000){
791         /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
792         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0);
793         RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PREDV1_DIV5 | RCU_PLL1_MUL8 | RCU_PREDV0_DIV10);
794 
795         /* enable PLL1 */
796         RCU_CTL |= RCU_CTL_PLL1EN;
797         /* wait till PLL1 is ready */
798         while(0U == (RCU_CTL & RCU_CTL_PLL1STB)){
799         }
800 
801         /* enable PLL1 */
802         RCU_CTL |= RCU_CTL_PLL2EN;
803         /* wait till PLL1 is ready */
804         while(0U == (RCU_CTL & RCU_CTL_PLL2STB)){
805         }
806     }else if(HXTAL_VALUE==8000000){
807         RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0);
808         RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 | RCU_PREDV1_DIV2 | RCU_PLL1_MUL20 | RCU_PLL2_MUL20);
809 
810         /* enable PLL1 */
811         RCU_CTL |= RCU_CTL_PLL1EN;
812         /* wait till PLL1 is ready */
813         while(0U == (RCU_CTL & RCU_CTL_PLL1STB)){
814         }
815 
816         /* enable PLL2 */
817         RCU_CTL |= RCU_CTL_PLL2EN;
818         /* wait till PLL1 is ready */
819         while(0U == (RCU_CTL & RCU_CTL_PLL2STB)){
820         }
821 
822     }
823     /* enable PLL */
824     RCU_CTL |= RCU_CTL_PLLEN;
825 
826     /* wait until PLL is stable */
827     while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
828     }
829 
830     /* select PLL as system clock */
831     RCU_CFG0 &= ~RCU_CFG0_SCS;
832     RCU_CFG0 |= RCU_CKSYSSRC_PLL;
833 
834     /* wait until PLL is selected as system clock */
835     while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
836     }
837 }
838 
839 #elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
840 /*!
841     \brief      configure the system clock to 48M by PLL which selects IRC8M as its clock source
842     \param[in]  none
843     \param[out] none
844     \retval     none
845 */
system_clock_48m_irc8m(void)846 static void system_clock_48m_irc8m(void)
847 {
848     uint32_t timeout = 0U;
849     uint32_t stab_flag = 0U;
850 
851     /* enable IRC8M */
852     RCU_CTL |= RCU_CTL_IRC8MEN;
853 
854     /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
855     do{
856         timeout++;
857         stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
858     }
859     while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
860 
861     /* if fail */
862     if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
863       while(1){
864       }
865     }
866 
867     /* IRC8M is stable */
868     /* AHB = SYSCLK */
869     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
870     /* APB2 = AHB/1 */
871     RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
872     /* APB1 = AHB/2 */
873     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
874 
875     /* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */
876     RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
877     RCU_CFG0 |= RCU_PLL_MUL12;
878 
879     /* enable PLL */
880     RCU_CTL |= RCU_CTL_PLLEN;
881 
882     /* wait until PLL is stable */
883     while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
884     }
885 
886     /* select PLL as system clock */
887     RCU_CFG0 &= ~RCU_CFG0_SCS;
888     RCU_CFG0 |= RCU_CKSYSSRC_PLL;
889 
890     /* wait until PLL is selected as system clock */
891     while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
892     }
893 }
894 
895 #elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
896 /*!
897     \brief      configure the system clock to 72M by PLL which selects IRC8M as its clock source
898     \param[in]  none
899     \param[out] none
900     \retval     none
901 */
system_clock_72m_irc8m(void)902 static void system_clock_72m_irc8m(void)
903 {
904     uint32_t timeout = 0U;
905     uint32_t stab_flag = 0U;
906 
907     /* enable IRC8M */
908     RCU_CTL |= RCU_CTL_IRC8MEN;
909 
910     /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
911     do{
912         timeout++;
913         stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
914     }
915     while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
916 
917     /* if fail */
918     if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
919       while(1){
920       }
921     }
922 
923     /* IRC8M is stable */
924     /* AHB = SYSCLK */
925     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
926     /* APB2 = AHB/1 */
927     RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
928     /* APB1 = AHB/2 */
929     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
930 
931     /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */
932     RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
933     RCU_CFG0 |= RCU_PLL_MUL18;
934 
935     /* enable PLL */
936     RCU_CTL |= RCU_CTL_PLLEN;
937 
938     /* wait until PLL is stable */
939     while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
940     }
941 
942     /* select PLL as system clock */
943     RCU_CFG0 &= ~RCU_CFG0_SCS;
944     RCU_CFG0 |= RCU_CKSYSSRC_PLL;
945 
946     /* wait until PLL is selected as system clock */
947     while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
948     }
949 }
950 
951 #elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
952 /*!
953     \brief      configure the system clock to 108M by PLL which selects IRC8M as its clock source
954     \param[in]  none
955     \param[out] none
956     \retval     none
957 */
system_clock_108m_irc8m(void)958 static void system_clock_108m_irc8m(void)
959 {
960     uint32_t timeout = 0U;
961     uint32_t stab_flag = 0U;
962 
963     /* enable IRC8M */
964     RCU_CTL |= RCU_CTL_IRC8MEN;
965 
966     /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
967     do{
968         timeout++;
969         stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
970     }
971     while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
972 
973     /* if fail */
974     if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
975       while(1){
976       }
977     }
978 
979     /* IRC8M is stable */
980     /* AHB = SYSCLK */
981     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
982     /* APB2 = AHB/1 */
983     RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
984     /* APB1 = AHB/2 */
985     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
986 
987     /* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */
988     RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
989     RCU_CFG0 |= RCU_PLL_MUL27;
990 
991     /* enable PLL */
992     RCU_CTL |= RCU_CTL_PLLEN;
993 
994     /* wait until PLL is stable */
995     while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
996     }
997 
998     /* select PLL as system clock */
999     RCU_CFG0 &= ~RCU_CFG0_SCS;
1000     RCU_CFG0 |= RCU_CKSYSSRC_PLL;
1001 
1002     /* wait until PLL is selected as system clock */
1003     while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
1004     }
1005 }
1006 
1007 #endif
1008