• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*!
2     \file    gd32vf103_rcu.c
3     \brief   RCU driver
4 
5     \version 2019-6-5, V1.0.0, firmware for GD32VF103
6 */
7 
8 /*
9     Copyright (c) 2019, GigaDevice Semiconductor Inc.
10 
11     Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13 
14     1. Redistributions of source code must retain the above copyright notice, this
15        list of conditions and the following disclaimer.
16     2. Redistributions in binary form must reproduce the above copyright notice,
17        this list of conditions and the following disclaimer in the documentation
18        and/or other materials provided with the distribution.
19     3. Neither the name of the copyright holder nor the names of its contributors
20        may be used to endorse or promote products derived from this software without
21        specific prior written permission.
22 
23     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 OF SUCH DAMAGE.
33 */
34 
35 #include "gd32vf103_rcu.h"
36 
37 
38 /*!
39     \brief      deinitialize the RCU
40     \param[in]  none
41     \param[out] none
42     \retval     none
43 */
rcu_deinit(void)44 void rcu_deinit(void)
45 {
46     /* enable IRC8M */
47     RCU_CTL |= RCU_CTL_IRC8MEN;
48     rcu_osci_stab_wait(RCU_IRC8M);
49 
50     /* reset CFG0 register */
51     RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |
52                   RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF |
53                   RCU_CFG0_USBFSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4);
54     /* reset CTL register */
55     RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN);
56     RCU_CTL &= ~RCU_CTL_HXTALBPS;
57     RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN);
58     /* reset INT and CFG1 register */
59     RCU_INT = 0x00ff0000U;
60     RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF |
61                   RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL);
62 }
63 
64 /*!
65     \brief      enable the peripherals clock
66     \param[in]  periph: RCU peripherals, refer to rcu_periph_enum
67                 only one parameter can be selected which is shown as below:
68       \arg        RCU_GPIOx (x=A,B,C,D,E): GPIO ports clock
69       \arg        RCU_AF : alternate function clock
70       \arg        RCU_CRC: CRC clock
71       \arg        RCU_DMAx (x=0,1): DMA clock
72       \arg        RCU_USBFS: USBFS clock
73       \arg        RCU_EXMC: EXMC clock
74       \arg        RCU_TIMERx (x=0,1,2,3,4,5,6): TIMER clock
75       \arg        RCU_WWDGT: WWDGT clock
76       \arg        RCU_SPIx (x=0,1,2): SPI clock
77       \arg        RCU_USARTx (x=0,1,2): USART clock
78       \arg        RCU_UARTx (x=3,4): UART clock
79       \arg        RCU_I2Cx (x=0,1): I2C clock
80       \arg        RCU_CANx (x=0,1): CAN clock
81       \arg        RCU_PMU: PMU clock
82       \arg        RCU_DAC: DAC clock
83       \arg        RCU_RTC: RTC clock
84       \arg        RCU_ADCx (x=0,1): ADC clock
85       \arg        RCU_BKPI: BKP interface clock
86     \param[out] none
87     \retval     none
88 */
rcu_periph_clock_enable(rcu_periph_enum periph)89 void rcu_periph_clock_enable(rcu_periph_enum periph)
90 {
91     RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
92 }
93 
94 /*!
95     \brief      disable the peripherals clock
96     \param[in]  periph: RCU peripherals, refer to rcu_periph_enum
97                 only one parameter can be selected which is shown as below:
98       \arg        RCU_GPIOx (x=A,B,C,D,E): GPIO ports clock
99       \arg        RCU_AF: alternate function clock
100       \arg        RCU_CRC: CRC clock
101       \arg        RCU_DMAx (x=0,1): DMA clock
102       \arg        RCU_USBFS: USBFS clock
103       \arg        RCU_EXMC: EXMC clock
104       \arg        RCU_TIMERx (x=0,1,2,3,4,5,6): TIMER clock
105       \arg        RCU_WWDGT: WWDGT clock
106       \arg        RCU_SPIx (x=0,1,2): SPI clock
107       \arg        RCU_USARTx (x=0,1,2): USART clock
108       \arg        RCU_UARTx (x=3,4): UART clock
109       \arg        RCU_I2Cx (x=0,1): I2C clock
110       \arg        RCU_CANx (x=0,1): CAN clock
111       \arg        RCU_PMU: PMU clock
112       \arg        RCU_DAC: DAC clock
113       \arg        RCU_RTC: RTC clock
114       \arg        RCU_ADCx (x=0,1): ADC clock
115       \arg        RCU_BKPI: BKP interface clock
116     \param[out] none
117     \retval     none
118 */
rcu_periph_clock_disable(rcu_periph_enum periph)119 void rcu_periph_clock_disable(rcu_periph_enum periph)
120 {
121     RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
122 }
123 
124 /*!
125     \brief      enable the peripherals clock when sleep mode
126     \param[in]  periph: RCU peripherals, refer to rcu_periph_sleep_enum
127                 only one parameter can be selected which is shown as below:
128       \arg        RCU_FMC_SLP: FMC clock
129       \arg        RCU_SRAM_SLP: SRAM clock
130     \param[out] none
131     \retval     none
132 */
rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)133 void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)
134 {
135     RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
136 }
137 
138 /*!
139     \brief      disable the peripherals clock when sleep mode
140     \param[in]  periph: RCU peripherals, refer to rcu_periph_sleep_enum
141                 only one parameter can be selected which is shown as below:
142       \arg        RCU_FMC_SLP: FMC clock
143       \arg        RCU_SRAM_SLP: SRAM clock
144     \param[out] none
145     \retval     none
146 */
rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)147 void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)
148 {
149     RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
150 }
151 
152 /*!
153     \brief      reset the peripherals
154     \param[in]  periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
155                 only one parameter can be selected which is shown as below:
156       \arg        RCU_GPIOxRST (x=A,B,C,D,E): reset GPIO ports
157       \arg        RCU_AFRST : reset alternate function clock
158       \arg        RCU_USBFSRST: reset USBFS
159       \arg        RCU_TIMERxRST (x=0,1,2,3,4,5,6): reset TIMER
160       \arg        RCU_WWDGTRST: reset WWDGT
161       \arg        RCU_SPIxRST (x=0,1,2): reset SPI
162       \arg        RCU_USARTxRST (x=0,1,2): reset USART
163       \arg        RCU_UARTxRST (x=3,4): reset UART
164       \arg        RCU_I2CxRST (x=0,1): reset I2C
165       \arg        RCU_CANxRST (x=0,1): reset CAN
166       \arg        RCU_PMURST: reset PMU
167       \arg        RCU_DACRST: reset DAC
168       \arg        RCU_ADCxRST (x=0,1): reset ADC
169       \arg        RCU_BKPIRST: reset BKPI
170     \param[out] none
171     \retval     none
172 */
rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)173 void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)
174 {
175     RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset));
176 }
177 
178 /*!
179     \brief      disable reset the peripheral
180     \param[in]  periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
181                 only one parameter can be selected which is shown as below:
182       \arg        RCU_GPIOxRST (x=A,B,C,D,E): reset GPIO ports
183       \arg        RCU_AFRST : reset alternate function clock
184       \arg        RCU_USBFSRST: reset USBFS
185       \arg        RCU_TIMERxRST (x=0,1,2,3,4,5,6): reset TIMER
186       \arg        RCU_WWDGTRST: reset WWDGT
187       \arg        RCU_SPIxRST (x=0,1,2): reset SPI
188       \arg        RCU_USARTxRST (x=0,1,2): reset USART
189       \arg        RCU_UARTxRST (x=3,4): reset UART
190       \arg        RCU_I2CxRST (x=0,1): reset I2C
191       \arg        RCU_CANxRST (x=0,1): reset CAN
192       \arg        RCU_PMURST: reset PMU
193       \arg        RCU_DACRST: reset DAC
194       \arg        RCU_ADCxRST (x=0,1): reset ADC
195       \arg        RCU_BKPIRST: reset BKPI
196     \param[out] none
197     \retval     none
198 */
rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset)199 void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset)
200 {
201     RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset));
202 }
203 
204 /*!
205     \brief      reset the BKP domain
206     \param[in]  none
207     \param[out] none
208     \retval     none
209 */
rcu_bkp_reset_enable(void)210 void rcu_bkp_reset_enable(void)
211 {
212     RCU_BDCTL |= RCU_BDCTL_BKPRST;
213 }
214 
215 /*!
216     \brief      disable the BKP domain reset
217     \param[in]  none
218     \param[out] none
219     \retval     none
220 */
rcu_bkp_reset_disable(void)221 void rcu_bkp_reset_disable(void)
222 {
223     RCU_BDCTL &= ~RCU_BDCTL_BKPRST;
224 }
225 
226 /*!
227     \brief      configure the system clock source
228     \param[in]  ck_sys: system clock source select
229                 only one parameter can be selected which is shown as below:
230       \arg        RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source
231       \arg        RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source
232       \arg        RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source
233     \param[out] none
234     \retval     none
235 */
rcu_system_clock_source_config(uint32_t ck_sys)236 void rcu_system_clock_source_config(uint32_t ck_sys)
237 {
238     uint32_t reg;
239 
240     reg = RCU_CFG0;
241     /* reset the SCS bits and set according to ck_sys */
242     reg &= ~RCU_CFG0_SCS;
243     RCU_CFG0 = (reg | ck_sys);
244 }
245 
246 /*!
247     \brief      get the system clock source
248     \param[in]  none
249     \param[out] none
250     \retval     which clock is selected as CK_SYS source
251       \arg        RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source
252       \arg        RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source
253       \arg        RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source
254 */
rcu_system_clock_source_get(void)255 uint32_t rcu_system_clock_source_get(void)
256 {
257     return (RCU_CFG0 & RCU_CFG0_SCSS);
258 }
259 
260 /*!
261     \brief      configure the AHB clock prescaler selection
262     \param[in]  ck_ahb: AHB clock prescaler selection
263                 only one parameter can be selected which is shown as below:
264       \arg        RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512
265     \param[out] none
266     \retval     none
267 */
rcu_ahb_clock_config(uint32_t ck_ahb)268 void rcu_ahb_clock_config(uint32_t ck_ahb)
269 {
270     uint32_t reg;
271 
272     reg = RCU_CFG0;
273 
274     /* reset the AHBPSC bits and set according to ck_ahb */
275     reg &= ~RCU_CFG0_AHBPSC;
276     RCU_CFG0 = (reg | ck_ahb);
277 }
278 
279 /*!
280     \brief      configure the APB1 clock prescaler selection
281     \param[in]  ck_apb1: APB1 clock prescaler selection
282                 only one parameter can be selected which is shown as below:
283       \arg        RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1
284       \arg        RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1
285       \arg        RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1
286       \arg        RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1
287       \arg        RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1
288     \param[out] none
289     \retval     none
290 */
rcu_apb1_clock_config(uint32_t ck_apb1)291 void rcu_apb1_clock_config(uint32_t ck_apb1)
292 {
293     uint32_t reg;
294 
295     reg = RCU_CFG0;
296 
297     /* reset the APB1PSC and set according to ck_apb1 */
298     reg &= ~RCU_CFG0_APB1PSC;
299     RCU_CFG0 = (reg | ck_apb1);
300 }
301 
302 /*!
303     \brief      configure the APB2 clock prescaler selection
304     \param[in]  ck_apb2: APB2 clock prescaler selection
305                 only one parameter can be selected which is shown as below:
306       \arg        RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2
307       \arg        RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2
308       \arg        RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2
309       \arg        RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2
310       \arg        RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2
311     \param[out] none
312     \retval     none
313 */
rcu_apb2_clock_config(uint32_t ck_apb2)314 void rcu_apb2_clock_config(uint32_t ck_apb2)
315 {
316     uint32_t reg;
317 
318     reg = RCU_CFG0;
319 
320     /* reset the APB2PSC and set according to ck_apb2 */
321     reg &= ~RCU_CFG0_APB2PSC;
322     RCU_CFG0 = (reg | ck_apb2);
323 }
324 
325 /*!
326     \brief      configure the CK_OUT0 clock source
327     \param[in]  ckout0_src: CK_OUT0 clock source selection
328                 only one parameter can be selected which is shown as below:
329       \arg        RCU_CKOUT0SRC_NONE: no clock selected
330       \arg        RCU_CKOUT0SRC_CKSYS: system clock selected
331       \arg        RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected
332       \arg        RCU_CKOUT0SRC_HXTAL: HXTAL selected
333       \arg        RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected
334       \arg        RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected
335       \arg        RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected
336       \arg        RCU_CKOUT0SRC_EXT1: EXT1 selected
337       \arg        RCU_CKOUT0SRC_CKPLL2: PLL2 selected
338     \param[out] none
339     \retval     none
340 */
rcu_ckout0_config(uint32_t ckout0_src)341 void rcu_ckout0_config(uint32_t ckout0_src)
342 {
343     uint32_t reg;
344 
345     reg = RCU_CFG0;
346 
347     /* reset the CKOUT0SRC, set according to ckout0_src */
348     reg &= ~RCU_CFG0_CKOUT0SEL;
349     RCU_CFG0 = (reg | ckout0_src);
350 }
351 
352 /*!
353     \brief      configure the main PLL clock
354     \param[in]  pll_src: PLL clock source selection
355                 only one parameter can be selected which is shown as below:
356       \arg        RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL
357       \arg        RCU_PLLSRC_HXTAL: HXTAL selected as source clock of PLL
358     \param[in]  pll_mul: PLL clock multiplication factor
359                 only one parameter can be selected which is shown as below:
360       \arg        RCU_PLL_MULx (x = 2..14, 6.5, 16..32)
361     \param[out] none
362     \retval     none
363 */
rcu_pll_config(uint32_t pll_src,uint32_t pll_mul)364 void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul)
365 {
366     uint32_t reg = 0U;
367 
368     reg = RCU_CFG0;
369 
370     /* PLL clock source and multiplication factor configuration */
371     reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
372     reg |= (pll_src | pll_mul);
373 
374     RCU_CFG0 = reg;
375 }
376 
377 /*!
378     \brief      configure the PREDV0 division factor and clock source
379     \param[in]  predv0_source: PREDV0 input clock source selection
380                 only one parameter can be selected which is shown as below:
381       \arg        RCU_PREDV0SRC_HXTAL: HXTAL selected as PREDV0 input source clock
382       \arg        RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock
383     \param[in]  predv0_div: PREDV0 division factor
384                 only one parameter can be selected which is shown as below:
385       \arg        RCU_PREDV0_DIVx, x = 1..16
386     \param[out] none
387     \retval     none
388 */
rcu_predv0_config(uint32_t predv0_source,uint32_t predv0_div)389 void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div)
390 {
391     uint32_t reg = 0U;
392 
393     reg = RCU_CFG1;
394     /* reset PREDV0SEL and PREDV0 bits */
395     reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0);
396     /* set the PREDV0SEL and PREDV0 division factor */
397     reg |= (predv0_source | predv0_div);
398 
399     RCU_CFG1 = reg;
400 }
401 
402 /*!
403     \brief      configure the PREDV1 division factor
404     \param[in]  predv1_div: PREDV1 division factor
405                 only one parameter can be selected which is shown as below:
406       \arg        RCU_PREDV1_DIVx, x = 1..16
407     \param[out] none
408     \retval     none
409 */
rcu_predv1_config(uint32_t predv1_div)410 void rcu_predv1_config(uint32_t predv1_div)
411 {
412     uint32_t reg = 0U;
413 
414     reg = RCU_CFG1;
415     /* reset the PREDV1 bits */
416     reg &= ~RCU_CFG1_PREDV1;
417     /* set the PREDV1 division factor */
418     reg |= predv1_div;
419 
420     RCU_CFG1 = reg;
421 }
422 
423 /*!
424     \brief      configure the PLL1 clock
425     \param[in]  pll_mul: PLL clock multiplication factor
426                 only one parameter can be selected which is shown as below:
427       \arg        RCU_PLL1_MULx (x = 8..16, 20)
428     \param[out] none
429     \retval     none
430 */
rcu_pll1_config(uint32_t pll_mul)431 void rcu_pll1_config(uint32_t pll_mul)
432 {
433     RCU_CFG1 &= ~RCU_CFG1_PLL1MF;
434     RCU_CFG1 |= pll_mul;
435 }
436 
437 /*!
438     \brief      configure the PLL2 clock
439     \param[in]  pll_mul: PLL clock multiplication factor
440                 only one parameter can be selected which is shown as below:
441       \arg        RCU_PLL2_MULx (x = 8..16, 20)
442     \param[out] none
443     \retval     none
444 */
rcu_pll2_config(uint32_t pll_mul)445 void rcu_pll2_config(uint32_t pll_mul)
446 {
447     RCU_CFG1 &= ~RCU_CFG1_PLL2MF;
448     RCU_CFG1 |= pll_mul;
449 }
450 
451 /*!
452     \brief      configure the ADC prescaler factor
453     \param[in]  adc_psc: ADC prescaler factor
454                 only one parameter can be selected which is shown as below:
455       \arg        RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2
456       \arg        RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4
457       \arg        RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6
458       \arg        RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8
459       \arg        RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12
460       \arg        RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16
461     \param[out] none
462     \retval     none
463 */
rcu_adc_clock_config(uint32_t adc_psc)464 void rcu_adc_clock_config(uint32_t adc_psc)
465 {
466     uint32_t reg0;
467 
468     /* reset the ADCPSC bits */
469     reg0 = RCU_CFG0;
470     reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC);
471 
472     /* set the ADC prescaler factor */
473     switch(adc_psc){
474         case RCU_CKADC_CKAPB2_DIV2:
475         case RCU_CKADC_CKAPB2_DIV4:
476         case RCU_CKADC_CKAPB2_DIV6:
477         case RCU_CKADC_CKAPB2_DIV8:
478             reg0 |= (adc_psc << 14);
479             break;
480 
481         case RCU_CKADC_CKAPB2_DIV12:
482         case RCU_CKADC_CKAPB2_DIV16:
483             adc_psc &= ~BIT(2);
484             reg0 |= (adc_psc << 14 | RCU_CFG0_ADCPSC_2);
485             break;
486 
487         default:
488             break;
489     }
490 
491     /* set the register */
492     RCU_CFG0 = reg0;
493 }
494 
495 /*!
496     \brief      configure the USBFS prescaler factor
497     \param[in]  usb_psc: USB prescaler factor
498                 only one parameter can be selected which is shown as below:
499       \arg        RCU_CKUSB_CKPLL_DIV1_5: USBFS prescaler select CK_PLL/1.5
500       \arg        RCU_CKUSB_CKPLL_DIV1: USBFS prescaler select CK_PLL/1
501       \arg        RCU_CKUSB_CKPLL_DIV2_5: USBFS prescaler select CK_PLL/2.5
502       \arg        RCU_CKUSB_CKPLL_DIV2: USBFS prescaler select CK_PLL/2
503     \param[out] none
504     \retval     none
505 */
rcu_usb_clock_config(uint32_t usb_psc)506 void rcu_usb_clock_config(uint32_t usb_psc)
507 {
508     uint32_t reg;
509 
510     reg = RCU_CFG0;
511 
512     /* configure the USBFS prescaler factor */
513     reg &= ~RCU_CFG0_USBFSPSC;
514     RCU_CFG0 = (reg | usb_psc);
515 }
516 
517 /*!
518     \brief      configure the RTC clock source selection
519     \param[in]  rtc_clock_source: RTC clock source selection
520                 only one parameter can be selected which is shown as below:
521       \arg        RCU_RTCSRC_NONE: no clock selected
522       \arg        RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock
523       \arg        RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock
524       \arg        RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock
525     \param[out] none
526     \retval     none
527 */
rcu_rtc_clock_config(uint32_t rtc_clock_source)528 void rcu_rtc_clock_config(uint32_t rtc_clock_source)
529 {
530     uint32_t reg;
531 
532     reg = RCU_BDCTL;
533     /* reset the RTCSRC bits and set according to rtc_clock_source */
534     reg &= ~RCU_BDCTL_RTCSRC;
535     RCU_BDCTL = (reg | rtc_clock_source);
536 }
537 
538 /*!
539     \brief      configure the I2S1 clock source selection
540     \param[in]  i2s_clock_source: I2S1 clock source selection
541                 only one parameter can be selected which is shown as below:
542       \arg        RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock
543       \arg        RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S1 source clock
544     \param[out] none
545     \retval     none
546 */
rcu_i2s1_clock_config(uint32_t i2s_clock_source)547 void rcu_i2s1_clock_config(uint32_t i2s_clock_source)
548 {
549     uint32_t reg;
550 
551     reg = RCU_CFG1;
552     /* reset the I2S1SEL bit and set according to i2s_clock_source */
553     reg &= ~RCU_CFG1_I2S1SEL;
554     RCU_CFG1 = (reg | i2s_clock_source);
555 }
556 
557 /*!
558     \brief      configure the I2S2 clock source selection
559     \param[in]  i2s_clock_source: I2S2 clock source selection
560                 only one parameter can be selected which is shown as below:
561       \arg        RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock
562       \arg        RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S2 source clock
563     \param[out] none
564     \retval     none
565 */
rcu_i2s2_clock_config(uint32_t i2s_clock_source)566 void rcu_i2s2_clock_config(uint32_t i2s_clock_source)
567 {
568     uint32_t reg;
569 
570     reg = RCU_CFG1;
571     /* reset the I2S2SEL bit and set according to i2s_clock_source */
572     reg &= ~RCU_CFG1_I2S2SEL;
573     RCU_CFG1 = (reg | i2s_clock_source);
574 }
575 
576 /*!
577     \brief      get the clock stabilization and periphral reset flags
578     \param[in]  flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum
579                 only one parameter can be selected which is shown as below:
580       \arg        RCU_FLAG_IRC8MSTB: IRC8M stabilization flag
581       \arg        RCU_FLAG_HXTALSTB: HXTAL stabilization flag
582       \arg        RCU_FLAG_PLLSTB: PLL stabilization flag
583       \arg        RCU_FLAG_PLL1STB: PLL1 stabilization flag
584       \arg        RCU_FLAG_PLL2STB: PLL2 stabilization flag
585       \arg        RCU_FLAG_LXTALSTB: LXTAL stabilization flag
586       \arg        RCU_FLAG_IRC40KSTB: IRC40K stabilization flag
587       \arg        RCU_FLAG_EPRST: external PIN reset flag
588       \arg        RCU_FLAG_PORRST: power reset flag
589       \arg        RCU_FLAG_SWRST: software reset flag
590       \arg        RCU_FLAG_FWDGTRST: free watchdog timer reset flag
591       \arg        RCU_FLAG_WWDGTRST: window watchdog timer reset flag
592       \arg        RCU_FLAG_LPRST: low-power reset flag
593     \param[out] none
594     \retval     FlagStatus: SET or RESET
595 */
rcu_flag_get(rcu_flag_enum flag)596 FlagStatus rcu_flag_get(rcu_flag_enum flag)
597 {
598     /* get the rcu flag */
599     if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){
600         return SET;
601     }else{
602         return RESET;
603     }
604 }
605 
606 /*!
607     \brief      clear all the reset flag
608     \param[in]  none
609     \param[out] none
610     \retval     none
611 */
rcu_all_reset_flag_clear(void)612 void rcu_all_reset_flag_clear(void)
613 {
614     RCU_RSTSCK |= RCU_RSTSCK_RSTFC;
615 }
616 
617 /*!
618     \brief      get the clock stabilization interrupt and ckm flags
619     \param[in]  int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum
620                 only one parameter can be selected which is shown as below:
621       \arg        RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag
622       \arg        RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag
623       \arg        RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag
624       \arg        RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag
625       \arg        RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag
626       \arg        RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag
627       \arg        RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag
628       \arg        RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag
629     \param[out] none
630     \retval     FlagStatus: SET or RESET
631 */
rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)632 FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)
633 {
634     /* get the rcu interrupt flag */
635     if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){
636         return SET;
637     }else{
638         return RESET;
639     }
640 }
641 
642 /*!
643     \brief      clear the interrupt flags
644     \param[in]  int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum
645                 only one parameter can be selected which is shown as below:
646       \arg        RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear
647       \arg        RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear
648       \arg        RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear
649       \arg        RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear
650       \arg        RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear
651       \arg        RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear
652       \arg        RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear
653       \arg        RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear
654     \param[out] none
655     \retval     none
656 */
rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)657 void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)
658 {
659     RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear));
660 }
661 
662 /*!
663     \brief      enable the stabilization interrupt
664     \param[in]  stab_int: clock stabilization interrupt, refer to rcu_int_enum
665                 Only one parameter can be selected which is shown as below:
666       \arg        RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable
667       \arg        RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
668       \arg        RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable
669       \arg        RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
670       \arg        RCU_INT_PLLSTB: PLL stabilization interrupt enable
671       \arg        RCU_INT_PLL1STB: PLL1 stabilization interrupt enable
672       \arg        RCU_INT_PLL2STB: PLL2 stabilization interrupt enable
673     \param[out] none
674     \retval     none
675 */
rcu_interrupt_enable(rcu_int_enum stab_int)676 void rcu_interrupt_enable(rcu_int_enum stab_int)
677 {
678     RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int));
679 }
680 
681 /*!
682     \brief      disable the stabilization interrupt
683     \param[in]  stab_int: clock stabilization interrupt, refer to rcu_int_enum
684                 only one parameter can be selected which is shown as below:
685       \arg        RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable
686       \arg        RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
687       \arg        RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable
688       \arg        RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
689       \arg        RCU_INT_PLLSTB: PLL stabilization interrupt enable
690       \arg        RCU_INT_PLL1STB: PLL1 stabilization interrupt enable
691       \arg        RCU_INT_PLL2STB: PLL2 stabilization interrupt enable
692     \param[out] none
693     \retval     none
694 */
rcu_interrupt_disable(rcu_int_enum stab_int)695 void rcu_interrupt_disable(rcu_int_enum stab_int)
696 {
697     RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int));
698 }
699 
700 /*!
701     \brief      wait for oscillator stabilization flags is SET or oscillator startup is timeout
702     \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
703                 only one parameter can be selected which is shown as below:
704       \arg        RCU_HXTAL: high speed crystal oscillator(HXTAL)
705       \arg        RCU_LXTAL: low speed crystal oscillator(LXTAL)
706       \arg        RCU_IRC8M: internal 8M RC oscillators(IRC8M)
707       \arg        RCU_IRC40K: internal 40K RC oscillator(IRC40K)
708       \arg        RCU_PLL_CK: phase locked loop(PLL)
709       \arg        RCU_PLL1_CK: phase locked loop 1
710       \arg        RCU_PLL2_CK: phase locked loop 2
711     \param[out] none
712     \retval     ErrStatus: SUCCESS or ERROR
713 */
rcu_osci_stab_wait(rcu_osci_type_enum osci)714 ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci)
715 {
716     uint32_t stb_cnt = 0U;
717     ErrStatus reval = ERROR;
718     FlagStatus osci_stat = RESET;
719 
720     switch(osci){
721     /* wait HXTAL stable */
722     case RCU_HXTAL:
723         while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){
724             osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB);
725             stb_cnt++;
726         }
727 
728         /* check whether flag is set or not */
729         if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){
730             reval = SUCCESS;
731         }
732         break;
733 
734     /* wait LXTAL stable */
735     case RCU_LXTAL:
736         while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){
737             osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB);
738             stb_cnt++;
739         }
740 
741         /* check whether flag is set or not */
742         if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){
743             reval = SUCCESS;
744         }
745         break;
746 
747     /* wait IRC8M stable */
748     case RCU_IRC8M:
749         while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){
750             osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB);
751             stb_cnt++;
752         }
753 
754         /* check whether flag is set or not */
755         if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){
756             reval = SUCCESS;
757         }
758         break;
759 
760     /* wait IRC40K stable */
761     case RCU_IRC40K:
762         while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
763             osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB);
764             stb_cnt++;
765         }
766 
767         /* check whether flag is set or not */
768         if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){
769             reval = SUCCESS;
770         }
771         break;
772 
773     /* wait PLL stable */
774     case RCU_PLL_CK:
775         while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
776             osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB);
777             stb_cnt++;
778         }
779 
780         /* check whether flag is set or not */
781         if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){
782             reval = SUCCESS;
783         }
784         break;
785     /* wait PLL1 stable */
786     case RCU_PLL1_CK:
787         while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
788             osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB);
789             stb_cnt++;
790         }
791 
792         /* check whether flag is set or not */
793         if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){
794             reval = SUCCESS;
795         }
796         break;
797     /* wait PLL2 stable */
798     case RCU_PLL2_CK:
799         while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
800             osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB);
801             stb_cnt++;
802         }
803 
804         /* check whether flag is set or not */
805         if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){
806             reval = SUCCESS;
807         }
808         break;
809 
810     default:
811         break;
812     }
813 
814     /* return value */
815     return reval;
816 }
817 
818 /*!
819     \brief      turn on the oscillator
820     \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
821                 only one parameter can be selected which is shown as below:
822       \arg        RCU_HXTAL: high speed crystal oscillator(HXTAL)
823       \arg        RCU_LXTAL: low speed crystal oscillator(LXTAL)
824       \arg        RCU_IRC8M: internal 8M RC oscillators(IRC8M)
825       \arg        RCU_IRC40K: internal 40K RC oscillator(IRC40K)
826       \arg        RCU_PLL_CK: phase locked loop(PLL)
827       \arg        RCU_PLL1_CK: phase locked loop 1
828       \arg        RCU_PLL2_CK: phase locked loop 2
829     \param[out] none
830     \retval     none
831 */
rcu_osci_on(rcu_osci_type_enum osci)832 void rcu_osci_on(rcu_osci_type_enum osci)
833 {
834     RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci));
835 }
836 
837 /*!
838     \brief      turn off the oscillator
839     \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
840                 only one parameter can be selected which is shown as below:
841       \arg        RCU_HXTAL: high speed crystal oscillator(HXTAL)
842       \arg        RCU_LXTAL: low speed crystal oscillator(LXTAL)
843       \arg        RCU_IRC8M: internal 8M RC oscillators(IRC8M)
844       \arg        RCU_IRC40K: internal 40K RC oscillator(IRC40K)
845       \arg        RCU_PLL_CK: phase locked loop(PLL)
846       \arg        RCU_PLL1_CK: phase locked loop 1
847       \arg        RCU_PLL2_CK: phase locked loop 2
848     \param[out] none
849     \retval     none
850 */
rcu_osci_off(rcu_osci_type_enum osci)851 void rcu_osci_off(rcu_osci_type_enum osci)
852 {
853     RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci));
854 }
855 
856 /*!
857     \brief      enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
858     \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
859                 only one parameter can be selected which is shown as below:
860       \arg        RCU_HXTAL: high speed crystal oscillator(HXTAL)
861       \arg        RCU_LXTAL: low speed crystal oscillator(LXTAL)
862     \param[out] none
863     \retval     none
864 */
rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)865 void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)
866 {
867     uint32_t reg;
868 
869     switch(osci){
870     /* enable HXTAL to bypass mode */
871     case RCU_HXTAL:
872         reg = RCU_CTL;
873         RCU_CTL &= ~RCU_CTL_HXTALEN;
874         RCU_CTL = (reg | RCU_CTL_HXTALBPS);
875         break;
876     /* enable LXTAL to bypass mode */
877     case RCU_LXTAL:
878         reg = RCU_BDCTL;
879         RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
880         RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS);
881         break;
882     case RCU_IRC8M:
883     case RCU_IRC40K:
884     case RCU_PLL_CK:
885     case RCU_PLL1_CK:
886     case RCU_PLL2_CK:
887         break;
888     default:
889         break;
890     }
891 }
892 
893 /*!
894     \brief      disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
895     \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
896                 only one parameter can be selected which is shown as below:
897       \arg        RCU_HXTAL: high speed crystal oscillator(HXTAL)
898       \arg        RCU_LXTAL: low speed crystal oscillator(LXTAL)
899     \param[out] none
900     \retval     none
901 */
rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)902 void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)
903 {
904     uint32_t reg;
905 
906     switch(osci){
907     /* disable HXTAL to bypass mode */
908     case RCU_HXTAL:
909         reg = RCU_CTL;
910         RCU_CTL &= ~RCU_CTL_HXTALEN;
911         RCU_CTL = (reg & ~RCU_CTL_HXTALBPS);
912         break;
913     /* disable LXTAL to bypass mode */
914     case RCU_LXTAL:
915         reg = RCU_BDCTL;
916         RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
917         RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS);
918         break;
919     case RCU_IRC8M:
920     case RCU_IRC40K:
921     case RCU_PLL_CK:
922     case RCU_PLL1_CK:
923     case RCU_PLL2_CK:
924         break;
925     default:
926         break;
927     }
928 }
929 
930 /*!
931     \brief      enable the HXTAL clock monitor
932     \param[in]  none
933     \param[out] none
934     \retval     none
935 */
936 
rcu_hxtal_clock_monitor_enable(void)937 void rcu_hxtal_clock_monitor_enable(void)
938 {
939     RCU_CTL |= RCU_CTL_CKMEN;
940 }
941 
942 /*!
943     \brief      disable the HXTAL clock monitor
944     \param[in]  none
945     \param[out] none
946     \retval     none
947 */
rcu_hxtal_clock_monitor_disable(void)948 void rcu_hxtal_clock_monitor_disable(void)
949 {
950     RCU_CTL &= ~RCU_CTL_CKMEN;
951 }
952 
953 /*!
954     \brief      set the IRC8M adjust value
955     \param[in]  irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F
956     \param[out] none
957     \retval     none
958 */
rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval)959 void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval)
960 {
961     uint32_t reg;
962 
963     reg = RCU_CTL;
964     /* reset the IRC8MADJ bits and set according to irc8m_adjval */
965     reg &= ~RCU_CTL_IRC8MADJ;
966     RCU_CTL = (reg | ((irc8m_adjval & 0x1FU) << 3));
967 }
968 
969 /*!
970     \brief      deep-sleep mode voltage select
971     \param[in]  dsvol: deep sleep mode voltage
972                 only one parameter can be selected which is shown as below:
973       \arg        RCU_DEEPSLEEP_V_1_2: the core voltage is 1.2V
974       \arg        RCU_DEEPSLEEP_V_1_1: the core voltage is 1.1V
975       \arg        RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V
976       \arg        RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V
977     \param[out] none
978     \retval     none
979 */
rcu_deepsleep_voltage_set(uint32_t dsvol)980 void rcu_deepsleep_voltage_set(uint32_t dsvol)
981 {
982     dsvol &= RCU_DSV_DSLPVS;
983     RCU_DSV = dsvol;
984 }
985 
986 /*!
987     \brief      get the system clock, bus and peripheral clock frequency
988     \param[in]  clock: the clock frequency which to get
989                 only one parameter can be selected which is shown as below:
990       \arg        CK_SYS: system clock frequency
991       \arg        CK_AHB: AHB clock frequency
992       \arg        CK_APB1: APB1 clock frequency
993       \arg        CK_APB2: APB2 clock frequency
994     \param[out] none
995     \retval     clock frequency of system, AHB, APB1, APB2
996 */
rcu_clock_freq_get(rcu_clock_freq_enum clock)997 uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock)
998 {
999     uint32_t sws, ck_freq = 0U;
1000     uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq;
1001     uint32_t pllsel, predv0sel, pllmf,ck_src, idx, clk_exp;
1002     uint32_t predv0, predv1, pll1mf;
1003 
1004     /* exponent of AHB, APB1 and APB2 clock divider */
1005     uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
1006     uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1007     uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1008 
1009     sws = GET_BITS(RCU_CFG0, 2, 3);
1010     switch(sws){
1011     /* IRC8M is selected as CK_SYS */
1012     case SEL_IRC8M:
1013         cksys_freq = IRC8M_VALUE;
1014         break;
1015     /* HXTAL is selected as CK_SYS */
1016     case SEL_HXTAL:
1017         cksys_freq = HXTAL_VALUE;
1018         break;
1019     /* PLL is selected as CK_SYS */
1020     case SEL_PLL:
1021         /* PLL clock source selection, HXTAL or IRC8M/2 */
1022         pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
1023 
1024         if(RCU_PLLSRC_HXTAL == pllsel) {
1025             /* PLL clock source is HXTAL */
1026             ck_src = HXTAL_VALUE;
1027 
1028             predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
1029             /* source clock use PLL1 */
1030             if(RCU_PREDV0SRC_CKPLL1 == predv0sel){
1031                 predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U;
1032                 pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U;
1033                 if(17U == pll1mf){
1034                     pll1mf = 20U;
1035                 }
1036                 ck_src = (ck_src / predv1) * pll1mf;
1037             }
1038             predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
1039             ck_src /= predv0;
1040         }else{
1041             /* PLL clock source is IRC8M/2 */
1042             ck_src = IRC8M_VALUE/2U;
1043         }
1044 
1045         /* PLL multiplication factor */
1046         pllmf = GET_BITS(RCU_CFG0, 18, 21);
1047         if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){
1048             pllmf |= 0x10U;
1049         }
1050         if(pllmf < 15U){
1051             pllmf += 2U;
1052         }else{
1053             pllmf += 1U;
1054         }
1055 
1056         cksys_freq = ck_src * pllmf;
1057 
1058         if(15U == pllmf){
1059             /* PLL source clock multiply by 6.5 */
1060             cksys_freq = ck_src * 6U + ck_src / 2U;
1061         }
1062 
1063         break;
1064     /* IRC8M is selected as CK_SYS */
1065     default:
1066         cksys_freq = IRC8M_VALUE;
1067         break;
1068     }
1069 
1070     /* calculate AHB clock frequency */
1071     idx = GET_BITS(RCU_CFG0, 4, 7);
1072     clk_exp = ahb_exp[idx];
1073     ahb_freq = cksys_freq >> clk_exp;
1074 
1075     /* calculate APB1 clock frequency */
1076     idx = GET_BITS(RCU_CFG0, 8, 10);
1077     clk_exp = apb1_exp[idx];
1078     apb1_freq = ahb_freq >> clk_exp;
1079 
1080     /* calculate APB2 clock frequency */
1081     idx = GET_BITS(RCU_CFG0, 11, 13);
1082     clk_exp = apb2_exp[idx];
1083     apb2_freq = ahb_freq >> clk_exp;
1084 
1085     /* return the clocks frequency */
1086     switch(clock){
1087     case CK_SYS:
1088         ck_freq = cksys_freq;
1089         break;
1090     case CK_AHB:
1091         ck_freq = ahb_freq;
1092         break;
1093     case CK_APB1:
1094         ck_freq = apb1_freq;
1095         break;
1096     case CK_APB2:
1097         ck_freq = apb2_freq;
1098         break;
1099     default:
1100         break;
1101     }
1102     return ck_freq;
1103 }
1104