1 /*!
2 \file system_gd32a50x.c
3 \brief CMSIS Cortex-M33 Device Peripheral Access Layer Source File for
4 GD32A50X Device Series
5 */
6
7 /* Copyright (c) 2012 ARM LIMITED
8
9 All rights reserved.
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are met:
12 - Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14 - Redistributions in binary form must reproduce the above copyright
15 notice, this list of conditions and the following disclaimer in the
16 documentation and/or other materials provided with the distribution.
17 - Neither the name of ARM nor the names of its contributors may be used
18 to endorse or promote products derived from this software without
19 specific prior written permission.
20 *
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE.
32 ---------------------------------------------------------------------------*/
33
34 /* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
35
36 #include "gd32a50x.h"
37
38 #define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */
39 #define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */
40
41 #define VECT_TAB_OFFSET (uint32_t)0x00 /* vector table base offset */
42
43 /* select a system clock by uncommenting the following line */
44 /* use IRC8M */
45 //#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M)
46 //#define __SYSTEM_CLOCK_24M_PLL_IRC8M (uint32_t)(24000000)
47 //#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000)
48 //#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000)
49 //#define __SYSTEM_CLOCK_100M_PLL_IRC8M (uint32_t)(100000000)
50
51 /* use HXTAL(CK_HXTAL = 8M)*/
52 //#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL)
53 //#define __SYSTEM_CLOCK_24M_PLL_HXTAL (uint32_t)(24000000)
54 //#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000)
55 //#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000)
56 #define __SYSTEM_CLOCK_100M_PLL_HXTAL (uint32_t)(100000000)
57
58
59 /* set the system clock frequency and declare the system clock configuration function */
60 #ifdef __SYSTEM_CLOCK_IRC8M
61 uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC8M;
62 static void system_clock_8m_irc8m(void);
63 #elif defined (__SYSTEM_CLOCK_24M_PLL_IRC8M)
64 uint32_t SystemCoreClock = __SYSTEM_CLOCK_24M_PLL_IRC8M;
65 static void system_clock_24m_pll_irc8m(void);
66 #elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
67 uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M;
68 static void system_clock_48m_pll_irc8m(void);
69 #elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
70 uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M;
71 static void system_clock_72m_pll_irc8m(void);
72 #elif defined (__SYSTEM_CLOCK_100M_PLL_IRC8M)
73 uint32_t SystemCoreClock = __SYSTEM_CLOCK_100M_PLL_IRC8M;
74 static void system_clock_100m_pll_irc8m(void);
75
76 #elif defined (__SYSTEM_CLOCK_HXTAL)
77 uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL;
78 static void system_clock_hxtal(void);
79 #elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL)
80 uint32_t SystemCoreClock = __SYSTEM_CLOCK_24M_PLL_HXTAL;
81 static void system_clock_24m_pll_hxtal(void);
82 #elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
83 uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL;
84 static void system_clock_48m_pll_hxtal(void);
85 #elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
86 uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL;
87 static void system_clock_72m_pll_hxtal(void);
88 #elif defined (__SYSTEM_CLOCK_100M_PLL_HXTAL)
89 uint32_t SystemCoreClock = __SYSTEM_CLOCK_100M_PLL_HXTAL;
90 static void system_clock_100m_pll_hxtal(void);
91 #endif /* __SYSTEM_CLOCK_IRC8M */
92
93 /* configure the system clock */
94 static void system_clock_config(void);
95
96 /*!
97 \brief setup the micro-controller system, initialize the system
98 \param[in] none
99 \param[out] none
100 \retval none
101 */
SystemInit(void)102 void SystemInit(void)
103 {
104 /* FPU settings */
105 #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
106 SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10 and CP11 Full Access */
107 #endif
108 /* reset the RCU clock configuration to the default reset state */
109 /* set IRC8MEN bit */
110 RCU_CTL |= RCU_CTL_IRC8MEN;
111
112 RCU_CFG0 &= ~RCU_CFG0_SCS;
113 /* reset HXTALSCAL, LCKMEN, PLLMEN, PLLEN, CKMEN and HXTALEN bits */
114 RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN | RCU_CTL_HXTALSCAL | RCU_CTL_LCKMEN | RCU_CTL_PLLMEN);
115 /* disable all interrupts */
116 RCU_INT = 0x00FF0000U;
117
118 /* Reset CFG0 and CFG1 registers */
119 RCU_CFG0 = 0x00020000U;
120 RCU_CFG1 = 0x00000000U;
121
122 /* reset HXTALBPS bit */
123 RCU_CTL &= ~(RCU_CTL_HXTALBPS);
124
125 /* configure the system clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */
126 system_clock_config();
127
128 /* LXTALBPS configuration */
129 if(0U == (RCU_APB1EN & RCU_APB1EN_PMUEN)) {
130 /* check whether PMU clock is enabled */
131 RCU_APB1EN |= RCU_APB1EN_PMUEN;
132 if(0U == (PMU_CTL & PMU_CTL_BKPWEN)) {
133 /* BKPWEN bit is not been set */
134 PMU_CTL |= PMU_CTL_BKPWEN;
135 /* LXTALBPS bit must be configured to 1 */
136 RCU_BDCTL |= RCU_BDCTL_LXTALBPS;
137 /* clear the BKPWEN bit */
138 PMU_CTL &= ~PMU_CTL_BKPWEN;
139 } else {
140 /* LXTALBPS bit must be configured to 1 */
141 RCU_BDCTL |= RCU_BDCTL_LXTALBPS;
142 }
143
144 /* disable the PMU clock */
145 RCU_APB1EN &= ~RCU_APB1EN_PMUEN;
146 } else {
147 /* the PMU clock is already enabled */
148 if(0U == (PMU_CTL & PMU_CTL_BKPWEN)) {
149 /* BKPWEN bit is not been set */
150 PMU_CTL |= PMU_CTL_BKPWEN;
151 /* LXTALBPS bit must be configured to 1 */
152 RCU_BDCTL |= RCU_BDCTL_LXTALBPS;
153 /* clear the BKPWEN bit */
154 PMU_CTL &= ~PMU_CTL_BKPWEN;
155 } else {
156 /* LXTALBPS bit must be configured to 1 */
157 RCU_BDCTL |= RCU_BDCTL_LXTALBPS;
158 }
159 }
160 }
161
162 /*!
163 \brief configure the system clock
164 \param[in] none
165 \param[out] none
166 \retval none
167 */
system_clock_config(void)168 static void system_clock_config(void)
169 {
170 #ifdef __SYSTEM_CLOCK_IRC8M
171 system_clock_8m_irc8m();
172 #elif defined (__SYSTEM_CLOCK_24M_PLL_IRC8M)
173 system_clock_24m_pll_irc8m();
174 #elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
175 system_clock_48m_pll_irc8m();
176 #elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
177 system_clock_72m_pll_irc8m();
178 #elif defined (__SYSTEM_CLOCK_100M_PLL_IRC8M)
179 system_clock_100m_pll_irc8m();
180
181 #elif defined (__SYSTEM_CLOCK_HXTAL)
182 system_clock_hxtal();
183 #elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL)
184 system_clock_24m_pll_hxtal();
185 #elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
186 system_clock_48m_pll_hxtal();
187 #elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
188 system_clock_72m_pll_hxtal();
189 #elif defined (__SYSTEM_CLOCK_100M_PLL_HXTAL)
190 system_clock_100m_pll_hxtal();
191 #endif /* __SYSTEM_CLOCK_IRC8M */
192 }
193
194 #ifdef __SYSTEM_CLOCK_IRC8M
195 /*!
196 \brief configure the system clock to 8M by IRC8M
197 \param[in] none
198 \param[out] none
199 \retval none
200 */
system_clock_8m_irc8m(void)201 static void system_clock_8m_irc8m(void)
202 {
203 uint32_t timeout = 0U;
204 uint32_t stab_flag = 0U;
205
206 /* enable IRC8M */
207 RCU_CTL |= RCU_CTL_IRC8MEN;
208
209 /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
210 do {
211 timeout++;
212 stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
213 } while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
214
215 /* if fail */
216 if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) {
217 while(1) {
218 }
219 }
220
221 FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(0);
222
223 RCU_APB1EN |= RCU_APB1EN_PMUEN;
224
225 /* AHB = SYSCLK */
226 RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
227 /* APB2 = AHB/1 */
228 RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
229 /* APB1 = AHB/1 */
230 RCU_CFG0 |= RCU_APB1_CKAHB_DIV1;
231
232 /* select IRC8M as system clock */
233 RCU_CFG0 &= ~RCU_CFG0_SCS;
234 RCU_CFG0 |= RCU_CKSYSSRC_IRC8M;
235
236 /* wait until IRC8M is selected as system clock */
237 while((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_IRC8M) {
238 }
239 }
240 /*!
241 \brief configure the system clock to 24M by PLL which selects IRC8M as its clock source
242 \param[in] none
243 \param[out] none
244 \retval none
245 */
246 #elif defined (__SYSTEM_CLOCK_24M_PLL_IRC8M)
system_clock_24m_pll_irc8m(void)247 static void system_clock_24m_pll_irc8m(void)
248 {
249 uint32_t timeout = 0U;
250 uint32_t stab_flag = 0U;
251
252 /* enable IRC8M */
253 RCU_CTL |= RCU_CTL_IRC8MEN;
254
255 /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
256 do {
257 timeout++;
258 stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
259 } while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
260
261 /* if fail */
262 if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) {
263 while(1) {
264 }
265 }
266
267 FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(0);
268
269 /* LDO output voltage high mode */
270 RCU_APB1EN |= RCU_APB1EN_PMUEN;
271
272 /* IRC8M is stable */
273 /* AHB = SYSCLK */
274 RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
275 /* APB2 = AHB/1 */
276 RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
277 /* APB1 = AHB/2 */
278 RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
279
280 /* CK_PLL = (CK_IRC8M/2) * 6 = 24 MHz */
281 RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
282 RCU_CFG0 |= RCU_PLL_MUL6;
283
284 /* enable PLL */
285 RCU_CTL |= RCU_CTL_PLLEN;
286
287 /* wait until PLL is stable */
288 while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) {
289 }
290
291 /* select PLL as system clock */
292 RCU_CFG0 &= ~RCU_CFG0_SCS;
293 RCU_CFG0 |= RCU_CKSYSSRC_PLL;
294
295 /* wait until PLL is selected as system clock */
296 while((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_PLL) {
297 }
298 }
299
300
301 #elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
302 /*!
303 \brief configure the system clock to 48M by PLL which selects IRC8M as its clock source
304 \param[in] none
305 \param[out] none
306 \retval none
307 */
system_clock_48m_pll_irc8m(void)308 static void system_clock_48m_pll_irc8m(void)
309 {
310 uint32_t timeout = 0U;
311 uint32_t stab_flag = 0U;
312
313 /* enable IRC8M */
314 RCU_CTL |= RCU_CTL_IRC8MEN;
315
316 /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
317 do {
318 timeout++;
319 stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
320 } while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
321
322 /* if fail */
323 if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) {
324 while(1) {
325 }
326 }
327
328 FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(1);
329
330 /* LDO output voltage high mode */
331 RCU_APB1EN |= RCU_APB1EN_PMUEN;
332
333 /* IRC8M is stable */
334 /* AHB = SYSCLK */
335 RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
336 /* APB2 = AHB/1 */
337 RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
338 /* APB1 = AHB/2 */
339 RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
340
341 /* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */
342 RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
343 RCU_CFG0 |= RCU_PLL_MUL12;
344
345 /* enable PLL */
346 RCU_CTL |= RCU_CTL_PLLEN;
347
348 /* wait until PLL is stable */
349 while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) {
350 }
351
352 /* select PLL as system clock */
353 RCU_CFG0 &= ~RCU_CFG0_SCS;
354 RCU_CFG0 |= RCU_CKSYSSRC_PLL;
355
356 /* wait until PLL is selected as system clock */
357 while((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_PLL) {
358 }
359 }
360
361 #elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
362 /*!
363 \brief configure the system clock to 72M by PLL which selects IRC8M as its clock source
364 \param[in] none
365 \param[out] none
366 \retval none
367 */
system_clock_72m_pll_irc8m(void)368 static void system_clock_72m_pll_irc8m(void)
369 {
370 uint32_t timeout = 0U;
371 uint32_t stab_flag = 0U;
372
373 /* enable IRC8M */
374 RCU_CTL |= RCU_CTL_IRC8MEN;
375
376 /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
377 do {
378 timeout++;
379 stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
380 } while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
381
382 /* if fail */
383 if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) {
384 while(1) {
385 }
386 }
387
388 FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(2);
389
390 /* LDO output voltage high mode */
391 RCU_APB1EN |= RCU_APB1EN_PMUEN;
392
393 /* IRC8M is stable */
394 /* AHB = SYSCLK */
395 RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
396 /* APB2 = AHB/1 */
397 RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
398 /* APB1 = AHB/2 */
399 RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
400
401 /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */
402 RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
403 RCU_CFG0 |= RCU_PLL_MUL18;
404
405 /* enable PLL */
406 RCU_CTL |= RCU_CTL_PLLEN;
407
408 /* wait until PLL is stable */
409 while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) {
410 }
411
412 /* select PLL as system clock */
413 RCU_CFG0 &= ~RCU_CFG0_SCS;
414 RCU_CFG0 |= RCU_CKSYSSRC_PLL;
415
416 /* wait until PLL is selected as system clock */
417 while((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_PLL) {
418 }
419 }
420
421 #elif defined (__SYSTEM_CLOCK_100M_PLL_IRC8M)
422 /*!
423 \brief configure the system clock to 100M by PLL which selects IRC8M as its clock source
424 \param[in] none
425 \param[out] none
426 \retval none
427 */
system_clock_100m_pll_irc8m(void)428 static void system_clock_100m_pll_irc8m(void)
429 {
430 uint32_t timeout = 0U;
431 uint32_t stab_flag = 0U;
432
433 /* enable IRC8M */
434 RCU_CTL |= RCU_CTL_IRC8MEN;
435
436 /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
437 do {
438 timeout++;
439 stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
440 } while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
441
442 /* if fail */
443 if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) {
444 while(1) {
445 }
446 }
447
448 FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(3);
449
450 /* LDO output voltage high mode */
451 RCU_APB1EN |= RCU_APB1EN_PMUEN;
452
453 /* IRC8M is stable */
454 /* AHB = SYSCLK */
455 RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
456 /* APB2 = AHB/1 */
457 RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
458 /* APB1 = AHB/2 */
459 RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
460
461 /* CK_PLL = (CK_IRC8M/2) * 25 = 100 MHz */
462 RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
463 RCU_CFG0 |= RCU_PLL_MUL25;
464
465 /* enable PLL */
466 RCU_CTL |= RCU_CTL_PLLEN;
467
468 /* wait until PLL is stable */
469 while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) {
470 }
471
472 /* select PLL as system clock */
473 RCU_CFG0 &= ~RCU_CFG0_SCS;
474 RCU_CFG0 |= RCU_CKSYSSRC_PLL;
475
476 /* wait until PLL is selected as system clock */
477 while((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_PLL) {
478 }
479 }
480
481 #elif defined (__SYSTEM_CLOCK_HXTAL)
482 /*!
483 \brief configure the system clock to HXTAL
484 \param[in] none
485 \param[out] none
486 \retval none
487 */
system_clock_hxtal(void)488 static void system_clock_hxtal(void)
489 {
490 uint32_t timeout = 0U;
491 uint32_t stab_flag = 0U;
492
493 /* enable HXTAL */
494 RCU_CTL |= RCU_CTL_HXTALEN;
495
496 /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
497 do {
498 timeout++;
499 stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
500 } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
501
502 /* if fail */
503 if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) {
504 while(1) {
505 }
506 }
507
508 FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(0);
509
510 RCU_APB1EN |= RCU_APB1EN_PMUEN;
511
512 /* AHB = SYSCLK */
513 RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
514 /* APB2 = AHB/1 */
515 RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
516 /* APB1 = AHB/1 */
517 RCU_CFG0 |= RCU_APB1_CKAHB_DIV1;
518
519 /* select HXTAL as system clock */
520 RCU_CFG0 &= ~RCU_CFG0_SCS;
521 RCU_CFG0 |= RCU_CKSYSSRC_HXTAL;
522
523 /* wait until HXTAL is selected as system clock */
524 while((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_HXTAL) {
525 }
526 }
527
528 #elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL)
529 /*!
530 \brief configure the system clock to 24M by PLL which selects HXTAL as its clock source
531 \param[in] none
532 \param[out] none
533 \retval none
534 */
system_clock_24m_pll_hxtal(void)535 static void system_clock_24m_pll_hxtal(void)
536 {
537 uint32_t timeout = 0U;
538 uint32_t stab_flag = 0U;
539
540 /* enable HXTAL */
541 RCU_CTL |= RCU_CTL_HXTALEN;
542
543 /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
544 do {
545 timeout++;
546 stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
547 } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
548
549 /* if fail */
550 if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) {
551 while(1) {
552 }
553 }
554
555 FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(0);
556
557 RCU_APB1EN |= RCU_APB1EN_PMUEN;
558
559 /* HXTAL is stable */
560 /* AHB = SYSCLK */
561 RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
562 /* APB2 = AHB/1 */
563 RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
564 /* APB1 = AHB/2 */
565 RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
566
567 /* CK_PLL = (HXTAL / 2) * 6 = 24 MHz */
568 RCU_CFG1 |= RCU_PREDV_DIV2;
569 RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
570 RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6);
571
572 /* enable PLL */
573 RCU_CTL |= RCU_CTL_PLLEN;
574
575 /* wait until PLL is stable */
576 while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) {
577 }
578
579 /* select PLL as system clock */
580 RCU_CFG0 &= ~RCU_CFG0_SCS;
581 RCU_CFG0 |= RCU_CKSYSSRC_PLL;
582
583 /* wait until PLL is selected as system clock */
584 while((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_PLL) {
585 }
586 }
587
588 #elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
589 /*!
590 \brief configure the system clock to 48M by PLL which selects HXTAL as its clock source
591 \param[in] none
592 \param[out] none
593 \retval none
594 */
system_clock_48m_pll_hxtal(void)595 static void system_clock_48m_pll_hxtal(void)
596 {
597 uint32_t timeout = 0U;
598 uint32_t stab_flag = 0U;
599
600 /* enable HXTAL */
601 RCU_CTL |= RCU_CTL_HXTALEN;
602
603 /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
604 do {
605 timeout++;
606 stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
607 } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
608
609 /* if fail */
610 if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) {
611 while(1) {
612 }
613 }
614
615 FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(1);
616
617 RCU_APB1EN |= RCU_APB1EN_PMUEN;
618
619 /* HXTAL is stable */
620 /* AHB = SYSCLK */
621 RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
622 /* APB2 = AHB/1 */
623 RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
624 /* APB1 = AHB/2 */
625 RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
626
627 /* CK_PLL = (HXTAL / 2) * 12 = 48 MHz */
628 RCU_CFG1 |= RCU_PREDV_DIV2;
629 RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
630 RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL12);
631
632 /* enable PLL */
633 RCU_CTL |= RCU_CTL_PLLEN;
634
635 /* wait until PLL is stable */
636 while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) {
637 }
638
639 /* select PLL as system clock */
640 RCU_CFG0 &= ~RCU_CFG0_SCS;
641 RCU_CFG0 |= RCU_CKSYSSRC_PLL;
642
643 /* wait until PLL is selected as system clock */
644 while((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_PLL) {
645 }
646 }
647
648 #elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
649 /*!
650 \brief configure the system clock to 72M by PLL which selects HXTAL as its clock source
651 \param[in] none
652 \param[out] none
653 \retval none
654 */
system_clock_72m_pll_hxtal(void)655 static void system_clock_72m_pll_hxtal(void)
656 {
657 uint32_t timeout = 0U;
658 uint32_t stab_flag = 0U;
659
660 /* enable HXTAL */
661 RCU_CTL |= RCU_CTL_HXTALEN;
662
663 /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
664 do {
665 timeout++;
666 stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
667 } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
668
669 /* if fail */
670 if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) {
671 while(1) {
672 }
673 }
674
675 FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(2);
676
677 RCU_APB1EN |= RCU_APB1EN_PMUEN;
678
679 /* HXTAL is stable */
680 /* AHB = SYSCLK */
681 RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
682 /* APB2 = AHB/1 */
683 RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
684 /* APB1 = AHB/2 */
685 RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
686
687 /* CK_PLL = (HXTAL / 2) * 18 = 72 MHz */
688 RCU_CFG1 |= RCU_PREDV_DIV2;
689 RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
690 RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL18);
691
692 /* enable PLL */
693 RCU_CTL |= RCU_CTL_PLLEN;
694
695 /* wait until PLL is stable */
696 while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) {
697 }
698
699 /* select PLL as system clock */
700 RCU_CFG0 &= ~RCU_CFG0_SCS;
701 RCU_CFG0 |= RCU_CKSYSSRC_PLL;
702
703 /* wait until PLL is selected as system clock */
704 while((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_PLL) {
705 }
706 }
707
708 #elif defined (__SYSTEM_CLOCK_100M_PLL_HXTAL)
709 /*!
710 \brief configure the system clock to 100M by PLL which selects HXTAL as its clock source
711 \param[in] none
712 \param[out] none
713 \retval none
714 */
system_clock_100m_pll_hxtal(void)715 static void system_clock_100m_pll_hxtal(void)
716 {
717 uint32_t timeout = 0U;
718 uint32_t stab_flag = 0U;
719
720 /* enable HXTAL */
721 RCU_CTL |= RCU_CTL_HXTALEN;
722
723 /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
724 do {
725 timeout++;
726 stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
727 } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
728
729 /* if fail */
730 if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) {
731 while(1) {
732 }
733 }
734
735 FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | WS_WSCNT(3);
736
737 RCU_APB1EN |= RCU_APB1EN_PMUEN;
738
739 /* HXTAL is stable */
740 /* AHB = SYSCLK */
741 RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
742 /* APB2 = AHB/1 */
743 RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
744 /* APB1 = AHB/2 */
745 RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
746
747 /* CK_PLL = (HXTAL / 2) * 25 = 100 MHz */
748 RCU_CFG1 |= RCU_PREDV_DIV2;
749 RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
750 RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL25);
751
752 /* enable PLL */
753 RCU_CTL |= RCU_CTL_PLLEN;
754
755 /* wait until PLL is stable */
756 while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) {
757 }
758
759 /* select PLL as system clock */
760 RCU_CFG0 &= ~RCU_CFG0_SCS;
761 RCU_CFG0 |= RCU_CKSYSSRC_PLL;
762
763 /* wait until PLL is selected as system clock */
764 while((RCU_CFG0 & RCU_CFG0_SCSS) != RCU_SCSS_PLL) {
765 }
766 }
767 #endif /* __SYSTEM_CLOCK_IRC8M */
768
769 /*!
770 \brief update the SystemCoreClock with current core clock retrieved from CPU registers
771 \param[in] none
772 \param[out] none
773 \retval none
774 */
SystemCoreClockUpdate(void)775 void SystemCoreClockUpdate(void)
776 {
777 uint32_t sws;
778 uint32_t pllsel, pllmf, ck_src, idx, clk_exp;
779 uint32_t predv0;
780
781 /* exponent of AHB, APB1 and APB2 clock divider */
782 uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
783
784 sws = RCU_CFG0 & RCU_CFG0_SCSS;
785 switch(sws) {
786 /* IRC8M is selected as CK_SYS */
787 case RCU_SCSS_IRC8M:
788 SystemCoreClock = IRC8M_VALUE;
789 break;
790 /* HXTAL is selected as CK_SYS */
791 case RCU_SCSS_HXTAL:
792 SystemCoreClock = HXTAL_VALUE;
793 break;
794 /* PLL is selected as CK_SYS */
795 case RCU_SCSS_PLL:
796 /* PLL clock source selection, HXTAL or IRC8M/2 */
797 pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
798
799 if(RCU_PLLSRC_HXTAL == pllsel) {
800 /* PLL clock source is HXTAL */
801 ck_src = HXTAL_VALUE;
802 predv0 = (RCU_CFG1 & RCU_CFG1_PREDV) + 1U;
803 ck_src /= predv0;
804 } else {
805 /* PLL clock source is IRC8M/2 */
806 ck_src = IRC8M_VALUE / 2U;
807 }
808
809 /* PLL multiplication factor */
810 pllmf = GET_BITS(RCU_CFG0, 18, 21);
811 pllmf += ((RCU_CFG0 & RCU_CFG0_PLLMF_4) ? 15U : 0U);
812 pllmf += ((RCU_CFG0_PLLMF == (RCU_CFG0 & RCU_CFG0_PLLMF)) ? 1U : 2U);
813
814 SystemCoreClock = ck_src * pllmf;
815
816 break;
817 /* IRC8M is selected as CK_SYS */
818 default:
819 SystemCoreClock = IRC8M_VALUE;
820 break;
821 }
822
823 /* calculate AHB clock frequency */
824 idx = GET_BITS(RCU_CFG0, 4, 7);
825 clk_exp = ahb_exp[idx];
826 SystemCoreClock >>= clk_exp;
827 }
828