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