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