1 /**
2   ******************************************************************************
3   * @file    system_hk32f0xx.c
4   * @version V1.0.1
5   * @date    2019-08-15
6   * @brief   CMSIS Cortex-M0 Device Peripheral Access Layer System Source File.
7   *          This file contains the system clock configuration for HK32F0xx devices,
8   *          and is generated by the clock configuration tool
9   *          HK32F0xx_Clock_Configuration_V1.0.1.xls
10   *
11   * 1.  This file provides two functions and one global variable to be called from
12   *     user application:
13   *      - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
14   *                      and Divider factors, AHB/APBx prescalers and Flash settings),
15   *                      depending on the configuration made in the clock xls tool.
16   *                      This function is called at startup just after reset and
17   *                      before branch to main program. This call is made inside
18   *                      the "startup_hk32f0xx.s" file.
19   *
20   *      - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
21   *                                  by the user application to setup the SysTick
22   *                                  timer or configure other parameters.
23   *
24   *      - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
25   *                                 be called whenever the core clock is changed
26   *                                 during program execution.
27   *
28   * 2. After each device reset the HSI (8 MHz Range) is used as system clock source.
29   *    Then SystemInit() function is called, in "startup_hk32f0xx.s" file, to
30   *    configure the system clock before to branch to main program.
31   *
32   * 3. If the system clock source selected by user fails to startup, the SystemInit()
33   *    function will do nothing and HSI still used as system clock source. User can
34   *    add some code to deal with this issue inside the SetSysClock() function.
35   *
36   * 4. The default value of HSE crystal is set to 8MHz, refer to "HSE_VALUE" define
37   *    in "hk32f0xx.h" file. When HSE is used as system clock source, directly or
38   *    through PLL, and you are using different crystal you have to adapt the HSE
39   *    value to your own configuration.
40   *
41   * 5. This file configures the system clock as follows:
42   *=============================================================================
43   *=============================================================================
44   *        System Clock source                    | PLL(HSE)
45   *-----------------------------------------------------------------------------
46   *        SYSCLK(Hz)                             | 48000000
47   *-----------------------------------------------------------------------------
48   *        HCLK(Hz)                               | 48000000
49   *-----------------------------------------------------------------------------
50   *        AHB Prescaler                          | 1
51   *-----------------------------------------------------------------------------
52   *        APB Prescaler                          | 1
53   *-----------------------------------------------------------------------------
54   *        HSE Frequency(Hz)                      | 8000000
55   *----------------------------------------------------------------------------
56   *        PLLMUL                                 | 6
57   *-----------------------------------------------------------------------------
58   *        PREDIV                                 | 1
59   *-----------------------------------------------------------------------------
60   *        Flash Latency(WS)                      | 1
61   *-----------------------------------------------------------------------------
62   *        Prefetch Buffer                        | ON
63   *-----------------------------------------------------------------------------
64   ******************************************************************************
65   */
66 
67 /** @addtogroup CMSIS
68   * @{
69   */
70 
71 /** @addtogroup HK32f0xx_system
72   * @{
73   */
74 
75 /** @addtogroup HK32F0xx_System_Private_Includes
76   * @{
77   */
78 
79 #include "hk32f0xx.h"
80 
81 /**
82   * @}
83   */
84 
85 /** @addtogroup HK32F0xx_System_Private_TypesDefinitions
86   * @{
87   */
88 
89 /**
90   * @}
91   */
92 
93 /** @addtogroup HK32F0xx_System_Private_Defines
94   * @{
95   */
96 /**
97   * @}
98   */
99 
100 /** @addtogroup HK32F0xx_System_Private_Macros
101   * @{
102   */
103 
104 /**
105   * @}
106   */
107 
108 /** @addtogroup HK32F0xx_System_Private_Variables
109   * @{
110   */
111 uint32_t SystemCoreClock    = 48000000;
112 __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
113 
114 /**
115   * @}
116   */
117 
118 /** @addtogroup HK32F0xx_System_Private_FunctionPrototypes
119   * @{
120   */
121 
122 static void SetSysClock(void);
123 
124 /**
125   * @}
126   */
127 
128 /** @addtogroup HK32F0xx_System_Private_Functions
129   * @{
130   */
131 
132 /**
133   * @brief  Setup the microcontroller system.
134   *         Initialize the Embedded Flash Interface, the PLL and update the
135   *         SystemCoreClock variable.
136   * @param  None
137   * @retval None
138   */
SystemInit(void)139 void SystemInit (void)
140 {
141   /* Set HSION bit */
142   RCC->CR |= (uint32_t)0x00000001;
143 
144   /* Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE and MCOSEL[2:0] bits */
145   RCC->CFGR &= (uint32_t)0xF8FFB80C;
146 
147   /* Reset HSEON, CSSON and PLLON bits */
148   RCC->CR &= (uint32_t)0xFEF6FFFF;
149 
150   /* Reset HSEBYP bit */
151   RCC->CR &= (uint32_t)0xFFFBFFFF;
152 
153   /* Reset PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */
154   RCC->CFGR &= (uint32_t)0xFFC0FFFF;
155 
156   /* Reset PREDIV1[3:0] bits */
157   RCC->CFGR2 &= (uint32_t)0xFFFFFFF0;
158 
159   /* Reset USARTSW[1:0], I2CSW, CECSW and ADCSW bits */
160   RCC->CFGR3 &= (uint32_t)0xFFFFFEAC;
161 
162   /* Reset HSI14 bit */
163   RCC->CR2 &= (uint32_t)0xFFFFFFFE;
164 
165   /* Disable all interrupts */
166   RCC->CIR = 0x00000000;
167 
168   /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
169   SetSysClock();
170 }
171 
172 /**
173   * @brief  Update SystemCoreClock according to Clock Register Values
174   *         The SystemCoreClock variable contains the core clock (HCLK), it can
175   *         be used by the user application to setup the SysTick timer or configure
176   *         other parameters.
177   *
178   * @note   Each time the core clock (HCLK) changes, this function must be called
179   *         to update SystemCoreClock variable value. Otherwise, any configuration
180   *         based on this variable will be incorrect.
181   *
182   * @note   - The system frequency computed by this function is not the real
183   *           frequency in the chip. It is calculated based on the predefined
184   *           constant and the selected clock source:
185   *
186   *           - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
187   *
188   *           - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
189   *
190   *           - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
191   *             or HSI_VALUE(*) multiplied/divided by the PLL factors.
192   *
193   *         (*) HSI_VALUE is a constant defined in HK32f0xx.h file (default value
194   *             8 MHz) but the real value may vary depending on the variations
195   *             in voltage and temperature.
196   *
197   *         (**) HSE_VALUE is a constant defined in HK32f0xx.h file (default value
198   *              8 MHz), user has to ensure that HSE_VALUE is same as the real
199   *              frequency of the crystal used. Otherwise, this function may
200   *              have wrong result.
201   *
202   *         - The result of this function could be not correct when using fractional
203   *           value for HSE crystal.
204   * @param  None
205   * @retval None
206   */
SystemCoreClockUpdate(void)207 void SystemCoreClockUpdate (void)
208 {
209   uint32_t tmp = 0, pllmull = 0, pllsource = 0, prediv1factor = 0;
210 
211   /* Get SYSCLK source -------------------------------------------------------*/
212   tmp = RCC->CFGR & RCC_CFGR_SWS;
213 
214   switch (tmp)
215   {
216     case 0x00:  /* HSI used as system clock */
217       SystemCoreClock = HSI_VALUE;
218       break;
219     case 0x04:  /* HSE used as system clock */
220       SystemCoreClock = HSE_VALUE;
221       break;
222     case 0x08:  /* PLL used as system clock */
223       /* Get PLL clock source and multiplication factor ----------------------*/
224       pllmull = RCC->CFGR & RCC_CFGR_PLLMUL;
225       pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
226       pllmull = ( pllmull >> 18) + 2;
227 
228       if (pllsource == 0x00)
229       {
230         /* HSI oscillator clock divided by 2 selected as PLL clock entry */
231         SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
232       }
233       else
234       {
235         prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV_1) + 1;
236         /* HSE oscillator clock selected as PREDIV1 clock entry */
237         SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull;
238       }
239       break;
240     default: /* HSI used as system clock */
241       SystemCoreClock = HSI_VALUE;
242       break;
243   }
244   /* Compute HCLK clock frequency ----------------*/
245   /* Get HCLK prescaler */
246   tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
247   /* HCLK clock frequency */
248   SystemCoreClock >>= tmp;
249 }
250 
251 /**
252   * @brief  Configures the System clock frequency, AHB/APBx prescalers and Flash
253   *         settings.
254   * @note   This function should be called only once the RCC clock configuration
255   *         is reset to the default reset state (done in SystemInit() function).
256   * @param  None
257   * @retval None
258   */
SetSysClock(void)259 static void SetSysClock(void)
260 {
261   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
262 
263 /******************************************************************************/
264 /*            PLL (clocked by HSE) used as System clock source                */
265 /******************************************************************************/
266 
267   /* SYSCLK, HCLK, PCLK configuration ----------------------------------------*/
268   *(uint32_t *)0x400210e0 |= 0x00060000;
269 
270   /* Enable HSE */
271   RCC->CR |= ((uint32_t)RCC_CR_HSEON);
272 
273   /* Wait till HSE is ready and if Time out is reached exit */
274   do
275   {
276     HSEStatus = RCC->CR & RCC_CR_HSERDY;
277     StartUpCounter++;
278   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
279 
280   if ((RCC->CR & RCC_CR_HSERDY) != RESET)
281   {
282     HSEStatus = (uint32_t)0x01;
283   }
284   else
285   {
286     HSEStatus = (uint32_t)0x00;
287   }
288 
289   if (HSEStatus == (uint32_t)0x01)
290   {
291     /* Enable Prefetch Buffer and set Flash Latency */
292     FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
293 
294     /* HCLK = SYSCLK */
295     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
296 
297     /* PCLK = HCLK */
298     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;
299 
300     /* PLL configuration */
301     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMUL));
302     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE_PREDIV | RCC_CFGR_PLLXTPRE_HSE_PREDIV_DIV1 | RCC_CFGR_PLLMUL6   );
303 
304     /* Enable PLL */
305     RCC->CR |= RCC_CR_PLLON;
306 
307     /* Wait till PLL is ready */
308     while((RCC->CR & RCC_CR_PLLRDY) == 0)
309     {
310     }
311 
312     /* Select PLL as system clock source */
313     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
314     RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
315 
316     /* Wait till PLL is used as system clock source */
317     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
318     {
319     }
320   }
321   else
322   { /* If HSE fails to start-up, the application will have wrong clock
323          configuration. User can add here some code to deal with this error */
324   }
325 }
326 
327 
328