1 /*!
2  * @file        system_apm32f0xx.c
3  *
4  * @brief       CMSIS Cortex-M0+ Device Peripheral Access Layer System Source File
5  *
6  * @version     V1.0.3
7  *
8  * @date        2022-09-20
9  *
10  * @attention
11  *
12  *  Copyright (C) 2020-2022 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 useful 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 "apm32f0xx.h"
28 
29 /** @addtogroup CMSIS
30   @{
31 */
32 
33 /** @addtogroup APM32F0xx_System
34   @{
35 */
36 
37 /** @defgroup System_Macros Macros
38   @{
39   */
40 
41 /* HSE is used as system clock source */
42 //#define SYSTEM_CLOCK_HSE    HSE_VALUE
43 
44 /* HSE (8MHz) used to clock the PLL, and the PLL is used as system clock source */
45 //#define SYSTEM_CLOCK_24MHz  (24000000)
46 //#define SYSTEM_CLOCK_36MHz  (36000000)
47 #define SYSTEM_CLOCK_48MHz  (48000000)
48 
49 //#define VECT_TAB_SRAM
50 /* Vector Table base offset field. This value must be a multiple of 0x200. */
51 #define VECT_TAB_OFFSET       0x00
52 
53 /**@} end of group System_Macros */
54 
55 /** @defgroup System_Enumerations Enumerations
56   @{
57   */
58 
59 /**@} end of group System_Enumerations */
60 
61 /** @defgroup System_Structures Structures
62   @{
63   */
64 
65 /**@} end of group System_Structures */
66 
67 /** @defgroup System_Variables Variables
68   @{
69   */
70 
71 #ifdef SYSTEM_CLOCK_HSE
72     uint32_t SystemCoreClock         = SYSTEM_CLOCK_HSE;
73 #elif defined SYSTEM_CLOCK_24MHz
74     uint32_t SystemCoreClock         = SYSTEM_CLOCK_24MHz;
75 #elif defined SYSTEM_CLOCK_36MHz
76     uint32_t SystemCoreClock         = SYSTEM_CLOCK_36MHz;
77 #elif defined SYSTEM_CLOCK_48MHz
78     uint32_t SystemCoreClock         = SYSTEM_CLOCK_48MHz;
79 #else
80     uint32_t SystemCoreClock         = HSI_VALUE;
81 #endif
82 
83 static void SystemClockConfig(void);
84 
85 #ifdef SYSTEM_CLOCK_HSE
86     static void SystemClockHSE(void);
87 #elif defined SYSTEM_CLOCK_24MHz
88     static void SystemClock24M(void);
89 #elif defined SYSTEM_CLOCK_36MHz
90     static void SystemClock36M(void);
91 #elif defined SYSTEM_CLOCK_48MHz
92     static void SystemClock48M(void);
93 
94 #endif
95 
96 /**@} end of group System_Variables */
97 
98 /** @defgroup System_Functions Functions
99   @{
100   */
101 
102 /*!
103  * @brief       Setup the microcontroller system
104  *
105  * @param       None
106  *
107  * @retval      None
108  *
109  * @note
110  */
SystemInit(void)111 void SystemInit(void)
112 {
113     /* Set HSIEN bit */
114     RCM->CTRL1_B.HSIEN = BIT_SET;
115     /* Reset SCLKSEL, AHBPSC, APB1PSC, APB2PSC, ADCPSC and COC bits */
116     RCM->CFG1 &= (uint32_t)0x08FFB80CU;
117     /* Reset HSEEN, CSSEN and PLLEN bits */
118     RCM->CTRL1 &= (uint32_t)0xFEF6FFFFU;
119     /* Reset HSEBCFG bit */
120     RCM->CTRL1_B.HSEBCFG = BIT_RESET;
121     /* Reset PLLSRCSEL, PLLHSEPSC, PLLMULCFG bits */
122     RCM->CFG1 &= (uint32_t)0xFFC0FFFFU;
123     /* Reset PREDIV[3:0] bits */
124     RCM->CFG1 &= (uint32_t)0xFFFFFFF0U;
125     /* Reset USARTSW[1:0], I2CSW, CECSW and ADCSW bits */
126     RCM->CFG3 &= (uint32_t)0xFFFFFEAC;
127     /* Reset  HSI14 bit */
128     RCM->CTRL2_B.HSI14EN = BIT_RESET;
129     /* Disable all interrupts */
130     RCM->INT = 0x00000000U;
131 
132     SystemClockConfig();
133 
134 #ifdef VECT_TAB_SRAM
135     SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;
136 #else
137     SCB->VTOR = FMC_BASE | VECT_TAB_OFFSET;
138 #endif
139 }
140 
141 /*!
142  * @brief       Update SystemCoreClock variable according to Clock Register Values
143  *              The SystemCoreClock variable contains the core clock (HCLK)
144  *
145  * @param       None
146  *
147  * @retval      None
148  *
149  * @note
150  */
SystemCoreClockUpdate(void)151 void SystemCoreClockUpdate(void)
152 {
153     uint32_t sysClock, pllMull, pllSource, Prescaler;
154     uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
155 
156     /* Get SYSCLK source */
157     sysClock = RCM->CFG1_B.SCLKSWSTS;
158 
159     switch (sysClock)
160     {
161         case 0:
162             SystemCoreClock = HSI_VALUE;
163             break;
164 
165         /* sys clock is HSE */
166         case 1:
167             SystemCoreClock = HSE_VALUE;
168             break;
169 
170         /* sys clock is PLL */
171         case 2:
172             pllMull = RCM->CFG1_B.PLLMULCFG + 2;
173             pllSource = RCM->CFG1_B.PLLSRCSEL;
174 
175             /* PLL entry clock source is HSE */
176             if (pllSource == 2)
177             {
178                 SystemCoreClock = HSE_VALUE * pllMull;
179 
180                 /* HSE clock divided by 2 */
181                 if (pllSource == RCM->CFG1_B.PLLHSEPSC)
182                 {
183                     SystemCoreClock >>= 1;
184                 }
185             }
186             /* PLL entry clock source is HSI/2 */
187             else
188             {
189                 SystemCoreClock = (HSI_VALUE >> 1) * pllMull;
190             }
191 
192             break;
193 
194         default:
195             SystemCoreClock  = HSI_VALUE;
196             break;
197     }
198 
199     Prescaler = AHBPrescTable[(RCM->CFG1_B.AHBPSC)];
200     SystemCoreClock >>= Prescaler;
201 }
202 /*!
203  * @brief       Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers
204  *
205  * @param       None
206  *
207  * @retval      None
208  *
209  * @note
210  */
SystemClockConfig(void)211 static void SystemClockConfig(void)
212 {
213 #ifdef SYSTEM_CLOCK_HSE
214     SystemClockHSE();
215 #elif defined SYSTEM_CLOCK_24MHz
216     SystemClock24M();
217 #elif defined SYSTEM_CLOCK_36MHz
218     SystemClock36M();
219 #elif defined SYSTEM_CLOCK_48MHz
220     SystemClock48M();
221 #endif
222 }
223 
224 #if defined SYSTEM_CLOCK_HSE
225 
226 /*!
227  * @brief       Selects HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers
228  *
229  * @param       None
230  *
231  * @retval      None
232  *
233  * @note
234  */
SystemClockHSE(void)235 static void SystemClockHSE(void)
236 {
237     uint32_t i;
238 
239     RCM->CTRL1_B.HSEEN = BIT_SET;
240 
241     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
242     {
243         if (RCM->CTRL1_B.HSERDYFLG)
244         {
245             break;
246         }
247     }
248 
249     if (RCM->CTRL1_B.HSERDYFLG)
250     {
251         /* Enable Prefetch Buffer */
252         FMC->CTRL1_B.PBEN = BIT_SET;
253         /* Flash 0 wait state */
254         FMC->CTRL1_B.WS = 0;
255 
256         /* HCLK = SYSCLK */
257         RCM->CFG1_B.AHBPSC = 0X00;
258 
259         /* PCLK = HCLK */
260         RCM->CFG1_B.APB1PSC = 0X00;
261 
262         /* Select HSE as system clock source */
263         RCM->CFG1_B.SCLKSEL = 1;
264 
265         /* Wait till HSE is used as system clock source */
266         while (RCM->CFG1_B.SCLKSWSTS != 0x01);
267     }
268 }
269 
270 #elif defined SYSTEM_CLOCK_24MHz
271 
272 /*!
273  * @brief       Sets System clock frequency to 24MHz and configure HCLK, PCLK2 and PCLK1 prescalers
274  *
275  * @param       None
276  *
277  * @retval      None
278  *
279  * @note
280  */
SystemClock24M(void)281 static void SystemClock24M(void)
282 {
283     uint32_t i;
284 
285     RCM->CTRL1_B.HSEEN = BIT_SET;
286 
287     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
288     {
289         if (RCM->CTRL1_B.HSERDYFLG)
290         {
291             break;
292         }
293     }
294 
295     if (RCM->CTRL1_B.HSERDYFLG)
296     {
297         /* Enable Prefetch Buffer */
298         FMC->CTRL1_B.PBEN = BIT_SET;
299         /* Flash 1 wait state */
300         FMC->CTRL1_B.WS = 1;
301 
302         /* HCLK = SYSCLK */
303         RCM->CFG1_B.AHBPSC = 0X00;
304 
305         /* PCLK = HCLK */
306         RCM->CFG1_B.APB1PSC = 0X00;
307 
308         /* PLL: (HSE / 2) * 6 */
309         RCM->CFG1_B.PLLSRCSEL = 2;
310         RCM->CFG1_B.PLLHSEPSC = 1;
311         RCM->CFG1_B.PLLMULCFG = 4;
312 
313         /* Enable PLL */
314         RCM->CTRL1_B.PLLEN = 1;
315 
316         /* Wait PLL Ready */
317         while (RCM->CTRL1_B.PLLRDYFLG == BIT_RESET);
318 
319         /* Select PLL as system clock source */
320         RCM->CFG1_B.SCLKSEL = 2;
321 
322         /* Wait till PLL is used as system clock source */
323         while (RCM->CFG1_B.SCLKSWSTS != 0x02);
324     }
325 }
326 
327 #elif defined SYSTEM_CLOCK_36MHz
328 
329 /*!
330  * @brief       Sets System clock frequency to 36MHz and configure HCLK, PCLK2 and PCLK1 prescalers
331  *
332  * @param       None
333  *
334  * @retval      None
335  *
336  * @note
337  */
SystemClock36M(void)338 static void SystemClock36M(void)
339 {
340     uint32_t i;
341 
342     RCM->CTRL1_B.HSEEN = BIT_SET;
343 
344     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
345     {
346         if (RCM->CTRL1_B.HSERDYFLG)
347         {
348             break;
349         }
350     }
351 
352     if (RCM->CTRL1_B.HSERDYFLG)
353     {
354         /* Enable Prefetch Buffer */
355         FMC->CTRL1_B.PBEN = BIT_SET;
356         /* Flash 1 wait state */
357         FMC->CTRL1_B.WS = 1;
358 
359         /* HCLK = SYSCLK */
360         RCM->CFG1_B.AHBPSC = 0X00;
361 
362         /* PCLK = HCLK */
363         RCM->CFG1_B.APB1PSC = 0X00;
364 
365         /* PLL: (HSE / 2) * 9 */
366         RCM->CFG1_B.PLLSRCSEL = 2;
367         RCM->CFG1_B.PLLHSEPSC = 1;
368         RCM->CFG1_B.PLLMULCFG = 7;
369 
370         /* Enable PLL */
371         RCM->CTRL1_B.PLLEN = 1;
372 
373         /* Wait PLL Ready */
374         while (RCM->CTRL1_B.PLLRDYFLG == BIT_RESET);
375 
376         /* Select PLL as system clock source */
377         RCM->CFG1_B.SCLKSEL = 2;
378 
379         /* Wait till PLL is used as system clock source */
380         while (RCM->CFG1_B.SCLKSWSTS != 0x02);
381     }
382 }
383 
384 #elif defined SYSTEM_CLOCK_48MHz
385 
386 /*!
387  * @brief       Sets System clock frequency to 46MHz and configure HCLK, PCLK2 and PCLK1 prescalers
388  *
389  * @param       None
390  *
391  * @retval      None
392  *
393  * @note
394  */
SystemClock48M(void)395 static void SystemClock48M(void)
396 {
397     uint32_t i;
398 
399     RCM->CTRL1_B.HSEEN = BIT_SET;
400 
401     for (i = 0; i < HSE_STARTUP_TIMEOUT; i++)
402     {
403         if (RCM->CTRL1_B.HSERDYFLG)
404         {
405             break;
406         }
407     }
408 
409     if (RCM->CTRL1_B.HSERDYFLG)
410     {
411         /* Enable Prefetch Buffer */
412         FMC->CTRL1_B.PBEN = BIT_SET;
413         /* Flash 1 wait state */
414         FMC->CTRL1_B.WS = 1;
415 
416         /* HCLK = SYSCLK */
417         RCM->CFG1_B.AHBPSC = 0X00;
418 
419         /* PCLK = HCLK */
420         RCM->CFG1_B.APB1PSC = 0X00;
421 
422         /* PLL: HSE * 6 */
423         RCM->CFG1_B.PLLSRCSEL = 2;
424         RCM->CFG1_B.PLLMULCFG = 4;
425 
426         /* Enable PLL */
427         RCM->CTRL1_B.PLLEN = 1;
428 
429         /* Wait PLL Ready */
430         while (RCM->CTRL1_B.PLLRDYFLG == BIT_RESET);
431 
432         /* Select PLL as system clock source */
433         RCM->CFG1_B.SCLKSEL = 2;
434 
435         /* Wait till PLL is used as system clock source */
436         while (RCM->CFG1_B.SCLKSWSTS != 0x02);
437     }
438 }
439 
440 #endif
441 
442 /**@} end of group System_Functions */
443 /**@} end of group APM32F0xx_System */
444 /**@} end of group CMSIS */
445