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