1 /*!
2  * @file        system_apm32s10x.c
3  *
4  * @brief       CMSIS Cortex-M3 Device Peripheral Access Layer System Source File
5  *
6  * @version     V1.0.1
7  *
8  * @date        2022-12-31
9  *
10  * @attention
11  *
12  *  Copyright (C) 2022-2023 Geehy Semiconductor
13  *
14  *  You may not use this file except in compliance with the
15  *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
16  *
17  *  The program is only for reference, which is distributed in the hope
18  *  that it will be usefull and instructional for customers to develop
19  *  their software. Unless required by applicable law or agreed to in
20  *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
21  *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
23  *  and limitations under the License.
24  */
25 
26 /* Includes */
27 #include "apm32s10x.h"
28 
29 /** @addtogroup CMSIS
30   @{
31 */
32 
33 /** @addtogroup APM32S10x_System
34   * @brief APM32S10x system configuration
35   @{
36 */
37 
38 /** @defgroup System_Macros
39   @{
40 */
41 
42 /*****************************************************************
43  * If SYSCLK source is PLL,SystemCoreClock will contain the      *
44  * HSE_VALUE or HSI_VALUE multiplied/divided by the PLL factors. *
45 ******************************************************************/
46 
47 //#define SYSTEM_CLOCK_HSE    HSE_VALUE
48 //#define SYSTEM_CLOCK_24MHz  (24000000)
49 //#define SYSTEM_CLOCK_36MHz  (36000000)
50 //#define SYSTEM_CLOCK_48MHz  (48000000)
51 //#define SYSTEM_CLOCK_56MHz  (56000000)
52 #define SYSTEM_CLOCK_72MHz  (72000000)
53 //#define SYSTEM_CLOCK_96MHz  (96000000)
54 
55 /* #define VECT_TAB_SRAM */
56 #define VECT_TAB_OFFSET     0x00
57 
58 /**@} end of group System_Macros */
59 
60 /** @defgroup System_Variables
61   @{
62 */
63 
64 #ifdef SYSTEM_CLOCK_HSE
65     uint32_t SystemCoreClock         = SYSTEM_CLOCK_HSE;
66 #elif defined SYSTEM_CLOCK_24MHz
67     uint32_t SystemCoreClock         = SYSTEM_CLOCK_24MHz;
68 #elif defined SYSTEM_CLOCK_36MHz
69     uint32_t SystemCoreClock         = SYSTEM_CLOCK_36MHz;
70 #elif defined SYSTEM_CLOCK_48MHz
71     uint32_t SystemCoreClock         = SYSTEM_CLOCK_48MHz;
72 #elif defined SYSTEM_CLOCK_56MHz
73     uint32_t SystemCoreClock         = SYSTEM_CLOCK_56MHz;
74 #elif defined SYSTEM_CLOCK_72MHz
75     uint32_t SystemCoreClock         = SYSTEM_CLOCK_72MHz;
76 #else
77     uint32_t SystemCoreClock         = SYSTEM_CLOCK_96MHz;
78 #endif
79 
80 /**@} end of group System_Variables */
81 
82 /** @defgroup System_Functions
83   @{
84 */
85 
86 static void SystemClockConfig(void);
87 
88 #ifdef SYSTEM_CLOCK_HSE
89     static void SystemClockHSE(void);
90 #elif defined SYSTEM_CLOCK_24MHz
91     static void SystemClock24M(void);
92 #elif defined SYSTEM_CLOCK_36MHz
93     static void SystemClock36M(void);
94 #elif defined SYSTEM_CLOCK_48MHz
95     static void SystemClock48M(void);
96 #elif defined SYSTEM_CLOCK_56MHz
97     static void SystemClock56M(void);
98 #elif defined SYSTEM_CLOCK_72MHz
99     static void SystemClock72M(void);
100 #elif defined SYSTEM_CLOCK_96MHz
101     static void SystemClock96M(void);
102 #endif
103 
104 /*!
105  * @brief       Setup the microcontroller system
106  *
107  * @param       None
108  *
109  * @retval      None
110  *
111  */
SystemInit(void)112 void SystemInit(void)
113 {
114     /* Set HSIEN bit */
115     RCM->CTRL_B.HSIEN = BIT_SET;
116     /* Reset SCLKSEL, AHBPSC, APB1PSC, APB2PSC, ADCPSC and MCOSEL bits */
117     RCM->CFG &= (uint32_t)0xF8FF0000;
118     /* Reset HSEEN, CSSEN and PLLEN bits */
119     RCM->CTRL &= (uint32_t)0xFEF6FFFF;
120     /* Reset HSEBCFG bit */
121     RCM->CTRL_B.HSEBCFG = BIT_RESET;
122     /* Reset PLLSRCSEL, PLLHSEPSC, PLLMULCFG and USBDIV bits */
123     RCM->CFG &= (uint32_t)0xFF80FFFF;
124     /* Disable all interrupts and clear pending bits */
125     RCM->INT = 0x009F0000;
126 
127     SystemClockConfig();
128 
129 #ifdef VECT_TAB_SRAM
130     SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;
131 #else
132     SCB->VTOR = FMC_BASE | VECT_TAB_OFFSET;
133 #endif
134 }
135 
136 /*!
137  * @brief       Update SystemCoreClock variable according to Clock Register Values
138  *              The SystemCoreClock variable contains the core clock (HCLK)
139  *
140  * @param       None
141  *
142  * @retval      None
143  *
144  */
SystemCoreClockUpdate(void)145 void SystemCoreClockUpdate(void)
146 {
147     uint32_t sysClock, pllMull, pllSource, Prescaler;
148     uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
149 
150     sysClock = RCM->CFG_B.SCLKSELSTS;
151 
152     switch (sysClock)
153     {
154         /* sys clock is HSI */
155         case 0:
156             SystemCoreClock = HSI_VALUE;
157             break;
158 
159         /* sys clock is HSE */
160         case 1:
161             SystemCoreClock = HSE_VALUE;
162             break;
163 
164         /* sys clock is PLL */
165         case 2:
166             pllMull = RCM->CFG_B.PLLMULCFG + 2;
167             pllSource = RCM->CFG_B.PLLSRCSEL;
168 
169             /* PLL entry clock source is HSE */
170             if (pllSource == BIT_SET)
171             {
172                 SystemCoreClock = HSE_VALUE * pllMull;
173 
174                 /* HSE clock divided by 2 */
175                 if (pllSource == RCM->CFG_B.PLLHSEPSC)
176                 {
177                     SystemCoreClock >>= 1;
178                 }
179             }
180             /* PLL entry clock source is HSI/2 */
181             else
182             {
183                 SystemCoreClock = (HSI_VALUE >> 1) * pllMull;
184             }
185             break;
186 
187         default:
188             SystemCoreClock  = HSI_VALUE;
189             break;
190     }
191 
192     Prescaler = AHBPrescTable[RCM->CFG_B.AHBPSC];
193     SystemCoreClock >>= Prescaler;
194 }
195 
196 /*!
197  * @brief       Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers
198  *
199  * @param       None
200  *
201  * @retval      None
202  *
203  */
SystemClockConfig(void)204 static void SystemClockConfig(void)
205 {
206 #ifdef SYSTEM_CLOCK_HSE
207     SystemClockHSE();
208 #elif defined SYSTEM_CLOCK_24MHz
209     SystemClock24M();
210 #elif defined SYSTEM_CLOCK_36MHz
211     SystemClock36M();
212 #elif defined SYSTEM_CLOCK_48MHz
213     SystemClock48M();
214 #elif defined SYSTEM_CLOCK_56MHz
215     SystemClock56M();
216 #elif defined SYSTEM_CLOCK_72MHz
217     SystemClock72M();
218 #elif defined SYSTEM_CLOCK_96MHz
219     SystemClock96M();
220 #endif
221 }
222 
223 #if defined SYSTEM_CLOCK_HSE
224 /*!
225  * @brief       Select HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers
226  *
227  * @param       None
228  *
229  * @retval      None
230  *
231  */
SystemClockHSE(void)232 static void SystemClockHSE(void)
233 {
234     __IO uint32_t i;
235 
236     RCM->CTRL_B.HSEEN = BIT_SET;
237 
238     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
239     {
240         if (RCM->CTRL_B.HSERDYFLG)
241         {
242             break;
243         }
244     }
245 
246     if (RCM->CTRL_B.HSERDYFLG)
247     {
248         /* Enable Prefetch Buffer */
249         FMC->CTRL1_B.PBEN = BIT_SET;
250         /* Flash 0 wait state */
251         FMC->CTRL1_B.WS = 0;
252 
253         /* HCLK = SYSCLK */
254         RCM->CFG_B.AHBPSC = 0X00;
255         /* PCLK2 = HCLK */
256         RCM->CFG_B.APB2PSC = 0;
257         /* PCLK1 = HCLK */
258         RCM->CFG_B.APB1PSC = 0;
259 
260         /* Select HSE as system clock source */
261         RCM->CFG_B.SCLKSEL = 1;
262 
263         /* Wait till HSE is used as system clock source */
264         while (RCM->CFG_B.SCLKSELSTS != 0x01);
265     }
266 }
267 
268 
269 #elif defined SYSTEM_CLOCK_24MHz
270 /*!
271  * @brief       Set System clock frequency to 24MHz and configure HCLK, PCLK2 and PCLK1 prescalers
272  *
273  * @param       None
274  *
275  * @retval      None
276  *
277  */
SystemClock24M(void)278 static void SystemClock24M(void)
279 {
280     __IO uint32_t i;
281 
282     RCM->CTRL_B.HSEEN = BIT_SET;
283 
284     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
285     {
286         if (RCM->CTRL_B.HSERDYFLG)
287         {
288             break;
289         }
290     }
291 
292     if (RCM->CTRL_B.HSERDYFLG)
293     {
294         /* Enable Prefetch Buffer */
295         FMC->CTRL1_B.PBEN = BIT_SET;
296         /* Flash 0 wait state */
297         FMC->CTRL1_B.WS = 0;
298 
299         /* HCLK = SYSCLK */
300         RCM->CFG_B.AHBPSC = 0X00;
301         /* PCLK2 = HCLK */
302         RCM->CFG_B.APB2PSC = 0;
303         /* PCLK1 = HCLK */
304         RCM->CFG_B.APB1PSC = 0;
305 
306         /* PLL: (HSE / 2) * 6 */
307         RCM->CFG_B.PLLSRCSEL = 1;
308         RCM->CFG_B.PLLHSEPSC = 1;
309         RCM->CFG_B.PLLMULCFG = 4;
310 
311         /* Enable PLL */
312         RCM->CTRL_B.PLLEN = 1;
313         /* Wait PLL Ready */
314         while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET);
315 
316         /* Select PLL as system clock source */
317         RCM->CFG_B.SCLKSEL = 2;
318         /* Wait till PLL is used as system clock source */
319         while (RCM->CFG_B.SCLKSELSTS != 0x02);
320     }
321 }
322 
323 #elif defined SYSTEM_CLOCK_36MHz
324 /*!
325  * @brief       Set System clock frequency to 36MHz and configure HCLK, PCLK2 and PCLK1 prescalers
326  *
327  * @param       None
328  *
329  * @retval      None
330  *
331  */
SystemClock36M(void)332 static void SystemClock36M(void)
333 {
334     __IO uint32_t i;
335 
336     RCM->CTRL_B.HSEEN = BIT_SET;
337 
338     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
339     {
340         if (RCM->CTRL_B.HSERDYFLG)
341         {
342             break;
343         }
344     }
345 
346     if (RCM->CTRL_B.HSERDYFLG)
347     {
348         /* Enable Prefetch Buffer */
349         FMC->CTRL1_B.PBEN = BIT_SET;
350         /* Flash 1 wait state */
351         FMC->CTRL1_B.WS = 1;
352 
353         /* HCLK = SYSCLK */
354         RCM->CFG_B.AHBPSC = 0X00;
355         /* PCLK2 = HCLK */
356         RCM->CFG_B.APB2PSC = 0;
357         /* PCLK1 = HCLK */
358         RCM->CFG_B.APB1PSC = 0;
359 
360         /* PLL: (HSE / 2) * 9 */
361         RCM->CFG_B.PLLSRCSEL = 1;
362         RCM->CFG_B.PLLHSEPSC = 1;
363         RCM->CFG_B.PLLMULCFG = 7;
364 
365         /* Enable PLL */
366         RCM->CTRL_B.PLLEN = 1;
367         /* Wait PLL Ready */
368         while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET);
369 
370         /* Select PLL as system clock source */
371         RCM->CFG_B.SCLKSEL = 2;
372         /* Wait till PLL is used as system clock source */
373         while (RCM->CFG_B.SCLKSELSTS != 0x02);
374     }
375 }
376 
377 #elif defined SYSTEM_CLOCK_48MHz
378 /*!
379  * @brief       Set System clock frequency to 46MHz and configure HCLK, PCLK2 and PCLK1 prescalers
380  *
381  * @param       None
382  *
383  * @retval      None
384  *
385  */
SystemClock48M(void)386 static void SystemClock48M(void)
387 {
388     __IO uint32_t i;
389 
390     RCM->CTRL_B.HSEEN = BIT_SET;
391 
392     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
393     {
394         if (RCM->CTRL_B.HSERDYFLG)
395         {
396             break;
397         }
398     }
399 
400     if (RCM->CTRL_B.HSERDYFLG)
401     {
402         /* Enable Prefetch Buffer */
403         FMC->CTRL1_B.PBEN = BIT_SET;
404         /* Flash 1 wait state */
405         FMC->CTRL1_B.WS = 1;
406 
407         /* HCLK = SYSCLK */
408         RCM->CFG_B.AHBPSC = 0X00;
409         /* PCLK2 = HCLK */
410         RCM->CFG_B.APB2PSC = 0;
411         /* PCLK1 = HCLK / 2 */
412         RCM->CFG_B.APB1PSC = 4;
413 
414         /* PLL: HSE * 6 */
415         RCM->CFG_B.PLLSRCSEL = 1;
416         RCM->CFG_B.PLLMULCFG = 4;
417 
418         /* Enable PLL */
419         RCM->CTRL_B.PLLEN = 1;
420         /* Wait PLL Ready */
421         while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET);
422 
423         /* Select PLL as system clock source */
424         RCM->CFG_B.SCLKSEL = 2;
425         /* Wait till PLL is used as system clock source */
426         while (RCM->CFG_B.SCLKSELSTS != 0x02);
427     }
428 }
429 
430 #elif defined SYSTEM_CLOCK_56MHz
431 /*!
432  * @brief       Set System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers
433  *
434  * @param       None
435  *
436  * @retval      None
437  *
438  */
SystemClock56M(void)439 static void SystemClock56M(void)
440 {
441     __IO uint32_t i;
442 
443     RCM->CTRL_B.HSEEN = BIT_SET;
444 
445     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
446     {
447         if (RCM->CTRL_B.HSERDYFLG)
448         {
449             break;
450         }
451     }
452 
453     if (RCM->CTRL_B.HSERDYFLG)
454     {
455         /* Enable Prefetch Buffer */
456         FMC->CTRL1_B.PBEN = BIT_SET;
457         /* Flash 2 wait state */
458         FMC->CTRL1_B.WS = 2;
459 
460         /* HCLK = SYSCLK */
461         RCM->CFG_B.AHBPSC = 0X00;
462         /* PCLK2 = HCLK */
463         RCM->CFG_B.APB2PSC = 0;
464         /* PCLK1 = HCLK / 2 */
465         RCM->CFG_B.APB1PSC = 4;
466 
467         /* PLL: HSE * 7 */
468         RCM->CFG_B.PLLSRCSEL = 1;
469         RCM->CFG_B.PLLMULCFG = 5;
470 
471         /* Enable PLL */
472         RCM->CTRL_B.PLLEN = 1;
473         /* Wait PLL Ready */
474         while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET);
475 
476         /* Select PLL as system clock source */
477         RCM->CFG_B.SCLKSEL = 2;
478         /* Wait till PLL is used as system clock source */
479         while (RCM->CFG_B.SCLKSELSTS != 0x02);
480     }
481 }
482 
483 #elif defined SYSTEM_CLOCK_72MHz
484 /*!
485  * @brief       Set System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers
486  *
487  * @param       None
488  *
489  * @retval      None
490  *
491  */
SystemClock72M(void)492 static void SystemClock72M(void)
493 {
494     __IO uint32_t i;
495 
496     RCM->CTRL_B.HSEEN = BIT_SET;
497 
498     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
499     {
500         if (RCM->CTRL_B.HSERDYFLG)
501         {
502             break;
503         }
504     }
505 
506     if (RCM->CTRL_B.HSERDYFLG)
507     {
508         /* Enable Prefetch Buffer */
509         FMC->CTRL1_B.PBEN = BIT_SET;
510         /* Flash 2 wait state */
511         FMC->CTRL1_B.WS = 2;
512 
513         /* HCLK = SYSCLK */
514         RCM->CFG_B.AHBPSC = 0X00;
515         /* PCLK2 = HCLK */
516         RCM->CFG_B.APB2PSC = 0;
517         /* PCLK1 = HCLK / 2 */
518         RCM->CFG_B.APB1PSC = 4;
519 
520         /* PLL: HSE * 9 */
521         RCM->CFG_B.PLLSRCSEL = 1;
522         RCM->CFG_B.PLLMULCFG = 7;
523 
524         /* Enable PLL */
525         RCM->CTRL_B.PLLEN = 1;
526         /* Wait PLL Ready */
527         while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET);
528 
529         /* Select PLL as system clock source */
530         RCM->CFG_B.SCLKSEL = 2;
531         /* Wait till PLL is used as system clock source */
532         while (RCM->CFG_B.SCLKSELSTS != 0x02);
533     }
534 
535 }
536 
537 #elif defined SYSTEM_CLOCK_96MHz
538 /*!
539  * @brief       Set System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers
540  *
541  * @param       None
542  *
543  * @retval      None
544  *
545  */
SystemClock96M(void)546 static void SystemClock96M(void)
547 {
548     __IO uint32_t i;
549 
550     RCM->CTRL_B.HSEEN = BIT_SET;
551 
552     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
553     {
554         if (RCM->CTRL_B.HSERDYFLG)
555         {
556             break;
557         }
558     }
559 
560     if (RCM->CTRL_B.HSERDYFLG)
561     {
562         /* Enable Prefetch Buffer */
563         FMC->CTRL1_B.PBEN = BIT_SET;
564         /* Flash 3 wait state */
565         FMC->CTRL1_B.WS = 3;
566 
567         /* HCLK = SYSCLK */
568         RCM->CFG_B.AHBPSC = 0X00;
569         /* PCLK2 = HCLK */
570         RCM->CFG_B.APB2PSC = 0;
571         /* PCLK1 = HCLK / 2 */
572         RCM->CFG_B.APB1PSC = 4;
573 
574         /* PLL: HSE * 12 */
575         RCM->CFG_B.PLLSRCSEL = 1;
576         RCM->CFG_B.PLLMULCFG = 10;
577 
578         /* Enable PLL */
579         RCM->CTRL_B.PLLEN = 1;
580         /* Wait PLL Ready */
581         while (RCM->CTRL_B.PLLRDYFLG == BIT_RESET);
582 
583         /* Select PLL as system clock source */
584         RCM->CFG_B.SCLKSEL = 2;
585         /* Wait till PLL is used as system clock source */
586         while (RCM->CFG_B.SCLKSELSTS != 0x02);
587     }
588 }
589 #endif
590 
591 /**@} end of group System_Functions */
592 /**@} end of group APM32S10x_System */
593 /**@} end of group CMSIS */
594 
595