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