1 /********************************** (C) COPYRIGHT *******************************
2 * File Name : system_ch32v10x.c
3 * Author : WCH
4 * Version : V1.0.0
5 * Date : 2020/04/30
6 * Description : CH32V10x Device Peripheral Access Layer System Source File.
7 * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
8 * SPDX-License-Identifier: Apache-2.0
9 *********************************************************************************/
10 #include "ch32v10x.h"
11
12 /*
13 * Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
14 * reset the HSI is used as SYSCLK source).
15 * If none of the define below is enabled, the HSI is used as System clock source.
16 */
17 /* #define SYSCLK_FREQ_HSE HSE_VALUE */
18 /* #define SYSCLK_FREQ_24MHz 24000000 */
19 /* #define SYSCLK_FREQ_48MHz 48000000 */
20 /* #define SYSCLK_FREQ_56MHz 56000000 */
21 #define SYSCLK_FREQ_72MHz 72000000
22
23 /* Clock Definitions */
24 #ifdef SYSCLK_FREQ_HSE
25 uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
26 #elif defined SYSCLK_FREQ_24MHz
27 uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /* System Clock Frequency (Core Clock) */
28 #elif defined SYSCLK_FREQ_48MHz
29 uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /* System Clock Frequency (Core Clock) */
30 #elif defined SYSCLK_FREQ_56MHz
31 uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /* System Clock Frequency (Core Clock) */
32 #elif defined SYSCLK_FREQ_72MHz
33 uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /* System Clock Frequency (Core Clock) */
34 #else /* HSI Selected as System Clock source */
35 uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */
36 #endif
37
38 __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
39
40 /* ch32v10x_system_private_function_proto_types */
41 static void SetSysClock(void);
42
43 #ifdef SYSCLK_FREQ_HSE
44 static void SetSysClockToHSE(void);
45 #elif defined SYSCLK_FREQ_24MHz
46 static void SetSysClockTo24(void);
47 #elif defined SYSCLK_FREQ_48MHz
48 static void SetSysClockTo48(void);
49 #elif defined SYSCLK_FREQ_56MHz
50 static void SetSysClockTo56(void);
51 #elif defined SYSCLK_FREQ_72MHz
52 static void SetSysClockTo72(void);
53 #endif
54
55 /*********************************************************************
56 * @fn SystemInit
57 *
58 * @brief Setup the microcontroller system Initialize the Embedded Flash Interface,
59 * the PLL and update the SystemCoreClock variable.
60 *
61 * @return none
62 */
SystemInit(void)63 void SystemInit(void)
64 {
65 RCC->CTLR |= (uint32_t)0x00000001;
66 RCC->CFGR0 &= (uint32_t)0xF8FF0000;
67 RCC->CTLR &= (uint32_t)0xFEF6FFFF;
68 RCC->CTLR &= (uint32_t)0xFFFBFFFF;
69 RCC->CFGR0 &= (uint32_t)0xFF80FFFF;
70 RCC->INTR = 0x009F0000;
71 SetSysClock();
72 }
73
74 /*********************************************************************
75 * @fn SystemCoreClockUpdate
76 *
77 * @brief Update SystemCoreClock variable according to Clock Register Values.
78 *
79 * @return none
80 */
SystemCoreClockUpdate(void)81 void SystemCoreClockUpdate(void)
82 {
83 uint32_t tmp = 0, pllmull = 0, pllsource = 0;
84
85 tmp = RCC->CFGR0 & RCC_SWS;
86
87 switch(tmp)
88 {
89 case 0x00:
90 SystemCoreClock = HSI_VALUE;
91 break;
92 case 0x04:
93 SystemCoreClock = HSE_VALUE;
94 break;
95 case 0x08:
96 pllmull = RCC->CFGR0 & RCC_PLLMULL;
97 pllsource = RCC->CFGR0 & RCC_PLLSRC;
98 pllmull = (pllmull >> 18) + 2;
99 if(pllsource == 0x00)
100 {
101 SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
102 }
103 else
104 {
105 if((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET)
106 {
107 SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
108 }
109 else
110 {
111 SystemCoreClock = HSE_VALUE * pllmull;
112 }
113 }
114 break;
115 default:
116 SystemCoreClock = HSI_VALUE;
117 break;
118 }
119
120 tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)];
121 SystemCoreClock >>= tmp;
122 }
123
124 /*********************************************************************
125 * @fn SetSysClock
126 *
127 * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
128 *
129 * @return none
130 */
SetSysClock(void)131 static void SetSysClock(void)
132 {
133 #ifdef SYSCLK_FREQ_HSE
134 SetSysClockToHSE();
135 #elif defined SYSCLK_FREQ_24MHz
136 SetSysClockTo24();
137 #elif defined SYSCLK_FREQ_48MHz
138 SetSysClockTo48();
139 #elif defined SYSCLK_FREQ_56MHz
140 SetSysClockTo56();
141 #elif defined SYSCLK_FREQ_72MHz
142 SetSysClockTo72();
143 #endif
144
145 /* If none of the define above is enabled, the HSI is used as System clock
146 * source (default after reset)
147 */
148 }
149
150 #ifdef SYSCLK_FREQ_HSE
151
152 /*********************************************************************
153 * @fn SetSysClockToHSE
154 *
155 * @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers.
156 *
157 * @return none
158 */
SetSysClockToHSE(void)159 static void SetSysClockToHSE(void)
160 {
161 __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
162
163 RCC->CTLR |= ((uint32_t)RCC_HSEON);
164
165 /* Wait till HSE is ready and if Time out is reached exit */
166 do
167 {
168 HSEStatus = RCC->CTLR & RCC_HSERDY;
169 StartUpCounter++;
170 } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
171
172 if((RCC->CTLR & RCC_HSERDY) != RESET)
173 {
174 HSEStatus = (uint32_t)0x01;
175 }
176 else
177 {
178 HSEStatus = (uint32_t)0x00;
179 }
180
181 if(HSEStatus == (uint32_t)0x01)
182 {
183 FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
184 /* Flash 0 wait state */
185 FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
186 FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_0;
187
188 /* HCLK = SYSCLK */
189 RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
190 /* PCLK2 = HCLK */
191 RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
192 /* PCLK1 = HCLK */
193 RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
194
195 /* Select HSE as system clock source */
196 RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
197 RCC->CFGR0 |= (uint32_t)RCC_SW_HSE;
198
199 /* Wait till HSE is used as system clock source */
200 while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04)
201 {
202 }
203 }
204 else
205 {
206 /* If HSE fails to start-up, the application will have wrong clock
207 * configuration. User can add here some code to deal with this error
208 */
209 }
210 }
211
212 #elif defined SYSCLK_FREQ_24MHz
213
214 /*********************************************************************
215 * @fn SetSysClockTo24
216 *
217 * @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
218 *
219 * @return none
220 */
SetSysClockTo24(void)221 static void SetSysClockTo24(void)
222 {
223 __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
224
225 RCC->CTLR |= ((uint32_t)RCC_HSEON);
226
227 /* Wait till HSE is ready and if Time out is reached exit */
228 do
229 {
230 HSEStatus = RCC->CTLR & RCC_HSERDY;
231 StartUpCounter++;
232 } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
233
234 if((RCC->CTLR & RCC_HSERDY) != RESET)
235 {
236 HSEStatus = (uint32_t)0x01;
237 }
238 else
239 {
240 HSEStatus = (uint32_t)0x00;
241 }
242 if(HSEStatus == (uint32_t)0x01)
243 {
244 /* Enable Prefetch Buffer */
245 FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
246
247 /* Flash 0 wait state */
248 FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
249 FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_0;
250
251 /* HCLK = SYSCLK */
252 RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
253 /* PCLK2 = HCLK */
254 RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
255 /* PCLK1 = HCLK */
256 RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
257
258 RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
259 RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL3);
260 /* Enable PLL */
261 RCC->CTLR |= RCC_PLLON;
262
263 /* Wait till PLL is ready */
264 while((RCC->CTLR & RCC_PLLRDY) == 0)
265 {
266 }
267 /* Select PLL as system clock source */
268 RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
269 RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
270 /* Wait till PLL is used as system clock source */
271 while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
272 {
273 }
274 }
275 else
276 {
277 /* If HSE fails to start-up, the application will have wrong clock
278 * configuration. User can add here some code to deal with this error
279 */
280 }
281 }
282
283 #elif defined SYSCLK_FREQ_48MHz
284
285 /*********************************************************************
286 * @fn SetSysClockTo48
287 *
288 * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
289 *
290 * @return none
291 */
SetSysClockTo48(void)292 static void SetSysClockTo48(void)
293 {
294 __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
295
296 RCC->CTLR |= ((uint32_t)RCC_HSEON);
297 /* Wait till HSE is ready and if Time out is reached exit */
298 do
299 {
300 HSEStatus = RCC->CTLR & RCC_HSERDY;
301 StartUpCounter++;
302 } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
303
304 if((RCC->CTLR & RCC_HSERDY) != RESET)
305 {
306 HSEStatus = (uint32_t)0x01;
307 }
308 else
309 {
310 HSEStatus = (uint32_t)0x00;
311 }
312
313 if(HSEStatus == (uint32_t)0x01)
314 {
315 /* Enable Prefetch Buffer */
316 FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
317
318 /* Flash 1 wait state */
319 FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
320 FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
321
322 /* HCLK = SYSCLK */
323 RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
324 /* PCLK2 = HCLK */
325 RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
326 /* PCLK1 = HCLK */
327 RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
328
329 /* PLL configuration: PLLCLK = HSE * 6 = 48 MHz */
330 RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
331 RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL6);
332
333 /* Enable PLL */
334 RCC->CTLR |= RCC_PLLON;
335 /* Wait till PLL is ready */
336 while((RCC->CTLR & RCC_PLLRDY) == 0)
337 {
338 }
339 /* Select PLL as system clock source */
340 RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
341 RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
342 /* Wait till PLL is used as system clock source */
343 while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
344 {
345 }
346 }
347 else
348 {
349 /*
350 * If HSE fails to start-up, the application will have wrong clock
351 * configuration. User can add here some code to deal with this error
352 */
353 }
354 }
355
356 #elif defined SYSCLK_FREQ_56MHz
357
358 /*********************************************************************
359 * @fn SetSysClockTo56
360 *
361 * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
362 *
363 * @return none
364 */
SetSysClockTo56(void)365 static void SetSysClockTo56(void)
366 {
367 __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
368
369 RCC->CTLR |= ((uint32_t)RCC_HSEON);
370
371 /* Wait till HSE is ready and if Time out is reached exit */
372 do
373 {
374 HSEStatus = RCC->CTLR & RCC_HSERDY;
375 StartUpCounter++;
376 } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
377
378 if((RCC->CTLR & RCC_HSERDY) != RESET)
379 {
380 HSEStatus = (uint32_t)0x01;
381 }
382 else
383 {
384 HSEStatus = (uint32_t)0x00;
385 }
386
387 if(HSEStatus == (uint32_t)0x01)
388 {
389 /* Enable Prefetch Buffer */
390 FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
391
392 /* Flash 2 wait state */
393 FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
394 FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2;
395
396 /* HCLK = SYSCLK */
397 RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
398 /* PCLK2 = HCLK */
399 RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
400 /* PCLK1 = HCLK */
401 RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
402
403 /* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */
404 RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
405 RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL7);
406 /* Enable PLL */
407 RCC->CTLR |= RCC_PLLON;
408 /* Wait till PLL is ready */
409 while((RCC->CTLR & RCC_PLLRDY) == 0)
410 {
411 }
412
413 /* Select PLL as system clock source */
414 RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
415 RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
416 /* Wait till PLL is used as system clock source */
417 while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
418 {
419 }
420 }
421 else
422 {
423 /*
424 * If HSE fails to start-up, the application will have wrong clock
425 * configuration. User can add here some code to deal with this error
426 */
427 }
428 }
429
430 #elif defined SYSCLK_FREQ_72MHz
431
432 /*********************************************************************
433 * @fn SetSysClockTo72
434 *
435 * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
436 *
437 * @return none
438 */
SetSysClockTo72(void)439 static void SetSysClockTo72(void)
440 {
441 __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
442
443 RCC->CTLR |= ((uint32_t)RCC_HSEON);
444
445 /* Wait till HSE is ready and if Time out is reached exit */
446 do
447 {
448 HSEStatus = RCC->CTLR & RCC_HSERDY;
449 StartUpCounter++;
450 } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
451
452 if((RCC->CTLR & RCC_HSERDY) != RESET)
453 {
454 HSEStatus = (uint32_t)0x01;
455 }
456 else
457 {
458 HSEStatus = (uint32_t)0x00;
459 }
460
461 if(HSEStatus == (uint32_t)0x01)
462 {
463 /* Enable Prefetch Buffer */
464 FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
465
466 /* Flash 2 wait state */
467 FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
468 FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2;
469
470 /* HCLK = SYSCLK */
471 RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
472 /* PCLK2 = HCLK */
473 RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
474 /* PCLK1 = HCLK */
475 RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
476
477 /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
478 RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
479 RCC_PLLMULL));
480 RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL9);
481 /* Enable PLL */
482 RCC->CTLR |= RCC_PLLON;
483 /* Wait till PLL is ready */
484 while((RCC->CTLR & RCC_PLLRDY) == 0)
485 {
486 }
487 /* Select PLL as system clock source */
488 RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
489 RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
490 /* Wait till PLL is used as system clock source */
491 while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
492 {
493 }
494 }
495 else
496 {
497 /*
498 * If HSE fails to start-up, the application will have wrong clock
499 * configuration. User can add here some code to deal with this error
500 */
501 }
502 }
503 #endif
504