1 /*!
2     \file    gd32l23x_rcu.c
3     \brief   RCU driver
4 
5     \version 2021-08-04, V1.0.0, firmware for GD32L23x
6 */
7 
8 /*
9     Copyright (c) 2021, 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 "gd32l23x_rcu.h"
36 
37 /* define clock source */
38 #define SEL_IRC16M      0x00U
39 #define SEL_HXTAL       0x01U
40 #define SEL_PLL         0x02U
41 
42 /* define startup timeout count */
43 #define OSC_STARTUP_TIMEOUT         ((uint32_t)0x000FFFFFU)
44 #define LXTAL_STARTUP_TIMEOUT       ((uint32_t)0x03FFFFFFU)
45 
46 /*!
47     \brief      deinitialize the RCU
48     \param[in]  none
49     \param[out] none
50     \retval     none
51 */
rcu_deinit(void)52 void rcu_deinit(void)
53 {
54     /* enable IRC16M */
55     RCU_CTL |= RCU_CTL_IRC16MEN;
56     while(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)) {
57     }
58     RCU_CFG0 &= ~RCU_CFG0_SCS;
59     RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN | RCU_CTL_HXTALBPS);
60     /* reset RCU */
61     RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | \
62                   RCU_CFG0_ADCPSC | RCU_CFG0_CKOUTSEL | RCU_CFG0_CKOUTDIV | RCU_CFG0_PLLDV);
63     RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF  | RCU_CFG0_PLLDV);
64     RCU_CFG1 &= ~(RCU_CFG1_PREDV);
65     RCU_CFG2 &= ~(RCU_CFG2_USART0SEL | RCU_CFG2_ADCSEL);
66     RCU_CFG2 &= ~RCU_CFG2_ADCPSC2;
67 
68     RCU_INT = 0x00000000U;
69 }
70 
71 /*!
72     \brief      enable the peripherals clock
73     \param[in]  periph: RCU peripherals, refer to rcu_periph_enum
74                 only one parameter can be selected which is shown as below:
75       \arg        RCU_GPIOx (x=A,B,C,D,F): GPIO ports clock
76       \arg        RCU_DMA: DMA clock
77       \arg        RCU_CAU: CAU clock
78       \arg        RCU_TRNG: TRNG clock
79       \arg        RCU_CRC: CRC clock
80       \arg        RCU_CMP: CMP clock
81       \arg        RCU_SYSCFG: SYSCFG clock
82       \arg        RCU_ADC: ADC clock
83       \arg        RCU_TIMERx (x=1,2,5,6,8,11): TIMER clock
84       \arg        RCU_LPTIMER: LPTIMER clock
85       \arg        RCU_SPIx (x=0,1): SPI clock
86       \arg        RCU_USARTx (x=0,1): USART clock
87       \arg        RCU_UARTx (x=3,4): UART clock
88       \arg        RCU_LPUART: LPUART clock
89       \arg        RCU_WWDGT: WWDGT clock
90       \arg        RCU_I2Cx (x=0,1,2): I2C clock
91       \arg        RCU_PMU: PMU clock
92       \arg        RCU_RTC: RTC clock
93       \arg        RCU_DBGMCU: DBGMCU clock
94       \arg        RCU_CAU: CAU clock
95       \arg        RCU_DAC: DAC clock
96       \arg        RCU_CTC: CTC clock
97       \arg        RCU_BKP: BKP clock
98       \arg        RCU_USBD: USBD clock
99       \arg        RCU_SLCD: SLCD clock
100     \param[out] none
101     \retval     none
102 */
rcu_periph_clock_enable(rcu_periph_enum periph)103 void rcu_periph_clock_enable(rcu_periph_enum periph)
104 {
105     RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
106 }
107 
108 /*!
109     \brief      disable the peripherals clock
110     \param[in]  periph: RCU peripherals, refer to rcu_periph_enum
111                 only one parameter can be selected which is shown as below:
112       \arg        RCU_GPIOx (x=A,B,C,D,F): GPIO ports clock
113       \arg        RCU_DMA: DMA clock
114       \arg        RCU_CAU: CAU clock
115       \arg        RCU_TRNG: TRNG clock
116       \arg        RCU_CRC: CRC clock
117       \arg        RCU_CMP: CMP clock
118       \arg        RCU_SYSCFG: SYSCFG clock
119       \arg        RCU_ADC: ADC clock
120       \arg        RCU_TIMERx (x=1,2,5,6,8,11): TIMER clock
121       \arg        RCU_LPTIMER: LPTIMER clock
122       \arg        RCU_SPIx (x=0,1): SPI clock
123       \arg        RCU_USARTx (x=0,1): USART clock
124       \arg        RCU_UARTx (x=3,4): UART clock
125       \arg        RCU_LPUART: LPUART clock
126       \arg        RCU_WWDGT: WWDGT clock
127       \arg        RCU_I2Cx (x=0,1,2): I2C clock
128       \arg        RCU_PMU: PMU clock
129       \arg        RCU_RTC: RTC clock
130       \arg        RCU_DBGMCU: DBGMCU clock
131       \arg        RCU_CAU: CAU clock
132       \arg        RCU_DAC: DAC clock
133       \arg        RCU_CTC: CTC clock
134       \arg        RCU_BKP: BKP clock
135       \arg        RCU_USBD: USBD clock
136       \arg        RCU_SLCD: SLCD clock
137     \param[out] none
138     \retval     none
139 */
rcu_periph_clock_disable(rcu_periph_enum periph)140 void rcu_periph_clock_disable(rcu_periph_enum periph)
141 {
142     RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
143 }
144 
145 /*!
146     \brief      enable the peripherals clock when sleep mode
147     \param[in]  periph: RCU peripherals, refer to rcu_periph_sleep_enum
148                 only one parameter can be selected which is shown as below:
149       \arg        RCU_FMC_SLP: FMC clock
150       \arg        RCU_SRAM0_SLP: SRAM0 clock
151       \arg        RCU_SRAM1_SLP: SRAM1 clock
152     \param[out] none
153     \retval     none
154 */
rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)155 void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)
156 {
157     RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
158 }
159 
160 /*!
161     \brief      disable the peripherals clock when sleep mode
162     \param[in]  periph: RCU peripherals, refer to rcu_periph_sleep_enum
163                 only one parameter can be selected which is shown as below:
164       \arg        RCU_FMC_SLP: FMC clock
165       \arg        RCU_SRAM0_SLP: SRAM clock
166       \arg        RCU_SRAM1_SLP: SRAM clock
167     \param[out] none
168     \retval     none
169 */
rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)170 void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)
171 {
172     RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
173 }
174 /*!
175     \brief      reset the peripherals
176     \param[in]  periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
177                 only one parameter can be selected which is shown as below:
178       \arg        RCU_GPIOxRST (x=A,B,C,D,F): reset GPIO ports
179       \arg        RCU_CAU: reset CAU
180       \arg        RCU_CRC: reset CRC
181       \arg        RCU_TRNG: reset TRNG
182       \arg        RCU_CMPRST: reset CMP
183       \arg        RCU_SYSCFGRST: reset SYSCFG
184       \arg        RCU_ADCRST: reset ADC
185       \arg        RCU_TIMERxRST (x=1,2,5,6,8,11): reset TIMER
186       \arg        RCU_SPIxRST (x=0,1): reset SPI
187       \arg        RCU_USARTxRST (x=0,1): reset USART
188       \arg        RCU_LPTIMERRST: reset LPTIMER
189       \arg        RCU_SLCDRRST: reset SLCD
190       \arg        RCU_WWDGTRST: reset WWDGT
191       \arg        RCU_LPUARTRST: reset LPUART
192       \arg        RCU_UARTxRST (x=3,4): reset UART
193       \arg        RCU_I2CxRST (x=0,1,2): reset I2C
194       \arg        RCU_USBDRST: reset USBD
195       \arg        RCU_PMURST: reset PMU
196       \arg        RCU_DACRST : reset DAC
197       \arg        RCU_CTCRST : reset CTC
198     \param[out] none
199     \retval     none
200 */
rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)201 void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)
202 {
203     RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset));
204 }
205 
206 /*!
207     \brief      disable reset the peripheral
208     \param[in]  periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
209                 only one parameter can be selected which is shown as below:
210       \arg        RCU_GPIOxRST (x=A,B,C,D,F): reset GPIO ports
211       \arg        RCU_CAU: reset CAU
212       \arg        RCU_CRC: reset CRC
213       \arg        RCU_TRNG: reset TRNG
214       \arg        RCU_CMPRST: reset CMP
215       \arg        RCU_SYSCFGRST: reset SYSCFG
216       \arg        RCU_ADCRST: reset ADC
217       \arg        RCU_TIMERxRST (x=1,2,5,6,8,11): reset TIMER
218       \arg        RCU_SPIxRST (x=0,1): reset SPI
219       \arg        RCU_USARTxRST (x=0,1): reset USART
220       \arg        RCU_LPTIMERRST: reset LPTIMER
221       \arg        RCU_SLCDRRST: reset LPTIMER
222       \arg        RCU_WWDGTRST: reset WWDGT
223       \arg        RCU_LPUARTRST: reset LPUART
224       \arg        RCU_UARTxRST (x=3,4): reset UART
225       \arg        RCU_I2CxRST (x=0,1,2): reset I2C
226       \arg        RCU_USBDRST: reset USBD
227       \arg        RCU_PMURST: reset PMU
228       \arg        RCU_DACRST : reset DAC
229       \arg        RCU_CTCRST : reset CTC
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
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 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_IRC16M: select CK_IRC16M 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       \arg        RCU_CKSYSSRC_IRC48M: select CK_IRC48M as the CK_SYS source
268     \param[out] none
269     \retval     none
270 */
rcu_system_clock_source_config(uint32_t ck_sys)271 void rcu_system_clock_source_config(uint32_t ck_sys)
272 {
273     uint32_t cksys_source = 0U;
274     cksys_source = RCU_CFG0;
275     /* reset the SCS bits and set according to ck_sys */
276     cksys_source &= ~RCU_CFG0_SCS;
277     RCU_CFG0 = (ck_sys | cksys_source);
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_IRC16M: select CK_IRC16M as the CK_SYS source
286       \arg        RCU_SCSS_HXTAL: select CK_HXTAL as the CK_SYS source
287       \arg        RCU_SCSS_PLL: select CK_PLL as the CK_SYS source
288       \arg        RCU_SCSS_IRC48M: select CK_IRC48M as the CK_SYS source
289 */
rcu_system_clock_source_get(void)290 uint32_t rcu_system_clock_source_get(void)
291 {
292     return (RCU_CFG0 & RCU_CFG0_SCSS);
293 }
294 
295 /*!
296     \brief      configure the AHB clock prescaler selection
297     \param[in]  ck_ahb: AHB clock prescaler selection
298                 only one parameter can be selected which is shown as below:
299       \arg        RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512
300     \param[out] none
301     \retval     none
302 */
rcu_ahb_clock_config(uint32_t ck_ahb)303 void rcu_ahb_clock_config(uint32_t ck_ahb)
304 {
305     uint32_t ahbpsc = 0U;
306     ahbpsc = RCU_CFG0;
307     /* reset the AHBPSC bits and set according to ck_ahb */
308     ahbpsc &= ~RCU_CFG0_AHBPSC;
309     RCU_CFG0 = (ck_ahb | ahbpsc);
310 }
311 
312 /*!
313     \brief      configure the APB1 clock prescaler selection
314     \param[in]  ck_apb1: APB1 clock prescaler selection
315                 only one parameter can be selected which is shown as below:
316       \arg        RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1
317       \arg        RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1
318       \arg        RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1
319       \arg        RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1
320       \arg        RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1
321     \param[out] none
322     \retval     none
323 */
rcu_apb1_clock_config(uint32_t ck_apb1)324 void rcu_apb1_clock_config(uint32_t ck_apb1)
325 {
326     uint32_t apb1psc = 0U;
327     apb1psc = RCU_CFG0;
328     /* reset the APB1PSC and set according to ck_apb1 */
329     apb1psc &= ~RCU_CFG0_APB1PSC;
330     RCU_CFG0 = (ck_apb1 | apb1psc);
331 }
332 
333 /*!
334     \brief      configure the APB2 clock prescaler selection
335     \param[in]  ck_apb2: APB2 clock prescaler selection
336                 only one parameter can be selected which is shown as below:
337       \arg        RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2
338       \arg        RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2
339       \arg        RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2
340       \arg        RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2
341       \arg        RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2
342     \param[out] none
343     \retval     none
344 */
rcu_apb2_clock_config(uint32_t ck_apb2)345 void rcu_apb2_clock_config(uint32_t ck_apb2)
346 {
347     uint32_t apb2psc = 0U;
348     apb2psc = RCU_CFG0;
349     /* reset the APB2PSC and set according to ck_apb2 */
350     apb2psc &= ~RCU_CFG0_APB2PSC;
351     RCU_CFG0 = (ck_apb2 | apb2psc);
352 }
353 
354 /*!
355     \brief      configure the ADC clock prescaler selection
356     \param[in]  ck_adc: ADC clock prescaler selection, refer to rcu_adc_clock_enum
357                 only one parameter can be selected which is shown as below:
358       \arg        RCU_ADCCK_IRC16M: select CK_IRC16M as CK_ADC
359       \arg        RCU_ADCCK_APB2_DIV2: select CK_APB2/2 as CK_ADC
360       \arg        RCU_ADCCK_APB2_DIV4: select CK_APB2/4 as CK_ADC
361       \arg        RCU_ADCCK_APB2_DIV6: select CK_APB2/6 as CK_ADC
362       \arg        RCU_ADCCK_APB2_DIV8: select CK_APB2/8 as CK_ADC
363       \arg        RCU_ADCCK_APB2_DIV10: select CK_APB2/10 as CK_ADC
364       \arg        RCU_ADCCK_APB2_DIV12: select CK_APB2/12 as CK_ADC
365       \arg        RCU_ADCCK_APB2_DIV14: select CK_APB2/14 as CK_ADC
366       \arg        RCU_ADCCK_APB2_DIV16: select CK_APB2/16 as CK_ADC
367       \arg        RCU_ADCCK_AHB_DIV3: select CK_AHB/3 as CK_ADC
368       \arg        RCU_ADCCK_AHB_DIV5: select CK_AHB/5 as CK_ADC
369       \arg        RCU_ADCCK_AHB_DIV7: select CK_AHB/7 as CK_ADC
370       \arg        RCU_ADCCK_AHB_DIV9: select CK_AHB/9 as CK_ADC
371       \arg        RCU_ADCCK_AHB_DIV11: select CK_AHB/11 as CK_ADC
372       \arg        RCU_ADCCK_AHB_DIV13: select CK_AHB/13 as CK_ADC
373       \arg        RCU_ADCCK_AHB_DIV15: select CK_AHB/15 as CK_ADC
374     \param[out] none
375     \retval     none
376 */
rcu_adc_clock_config(uint32_t ck_adc)377 void rcu_adc_clock_config(uint32_t ck_adc)
378 {
379     /* reset the ADCPSC, ADCSEL bits */
380     RCU_CFG0 &= ~RCU_CFG0_ADCPSC;
381     RCU_CFG2 &= ~(RCU_CFG2_ADCSEL | RCU_CFG2_ADCPSC2);
382 
383     /* set the ADC clock according to ck_adc */
384     if(ck_adc <= 15U) {
385         RCU_CFG0 |= ((ck_adc & 0x3U) << 14U);
386         RCU_CFG2 |= (((ck_adc & 0xCU) >> 2U) << 30U);
387         RCU_CFG2 |= RCU_CFG2_ADCSEL;
388     }
389     if(ck_adc == 16U) {
390         RCU_CFG2 &= ~RCU_CFG2_ADCSEL;
391     }
392 }
393 
394 /*!
395     \brief      configure the CK_OUT clock source and divider
396     \param[in]  ckout_src: CK_OUT clock source selection
397                 only one parameter can be selected which is shown as below:
398       \arg        RCU_CKOUTSRC_NONE: no clock selected
399       \arg        RCU_CKOUTSRC_IRC48M: IRC48M selected
400       \arg        RCU_CKOUTSRC_IRC32K: IRC32K selected
401       \arg        RCU_CKOUTSRC_LXTAL: LXTAL selected
402       \arg        RCU_CKOUTSRC_CKSYS: CKSYS selected
403       \arg        RCU_CKOUTSRC_IRC16M: IRC16M selected
404       \arg        RCU_CKOUTSRC_HXTAL: HXTAL selected
405       \arg        RCU_CKOUTSRC_CKPLL_DIV1: CK_PLL selected
406       \arg        RCU_CKOUTSRC_CKPLL_DIV2: CK_PLL/2 selected
407     \param[in]  ckout_div: CK_OUT divider
408       \arg        RCU_CKOUT_DIVx(x=1,2,4,8,16,32,64,128): CK_OUT is divided by x
409     \param[out] none
410     \retval     none
411 */
rcu_ckout_config(uint32_t ckout_src,uint32_t ckout_div)412 void rcu_ckout_config(uint32_t ckout_src, uint32_t ckout_div)
413 {
414     uint32_t ckout = 0U;
415     ckout = RCU_CFG0;
416     /* reset the CKOUTSEL, CKOUTDIV and PLLDV bits and set according to ckout_src and ckout_div */
417     ckout &= ~(RCU_CFG0_CKOUTSEL | RCU_CFG0_CKOUTDIV | RCU_CFG0_PLLDV);
418     RCU_CFG0 = (ckout | ckout_src | ckout_div);
419 }
420 
421 /*!
422     \brief      configure the PLL clock source selection and PLL multiply factor
423     \param[in]  pll_src: PLL clock source selection
424                 only one parameter can be selected which is shown as below:
425       \arg        RCU_PLLSRC_IRC16M: select CK_IRC16M as PLL source clock
426       \arg        RCU_PLLSRC_HXTAL: select HXTAL as PLL source clock
427       \arg        RCU_PLLSRC_IRC48M: select CK_IRC48M as PLL source clock
428     \param[in]  pll_mul: PLL multiply factor
429                 only one parameter can be selected which is shown as below:
430       \arg        RCU_PLL_MULx(x=4..127): PLL source clock * x
431     \param[out] none
432     \retval     none
433 */
rcu_pll_config(uint32_t pll_src,uint32_t pll_mul)434 void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul)
435 {
436     RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF);
437     RCU_CFG0 |= (pll_src | pll_mul);
438 }
439 
440 /*!
441     \brief      configure the USARTx(x=0,1) clock source selection
442     \param[in]  usart_idx: IDX_USARTx(x=0,1)
443     \param[in]  ck_usart: USART clock source selection
444                 only one parameter can be selected which is shown as below:
445       \arg        RCU_USARTSRC_CKAPB: CK_USART select CK_APB1/CK_APB2
446       \arg        RCU_USARTSRC_CKSYS: CK_USART select CK_SYS
447       \arg        RCU_USARTSRC_LXTAL: CK_USART select CK_LXTAL
448       \arg        RCU_USARTSRC_IRC16MDIV: CK_USART select CK_IRC16MDIV
449     \param[out] none
450     \retval     none
451 */
rcu_usart_clock_config(usart_idx_enum usart_idx,uint32_t ck_usart)452 void rcu_usart_clock_config(usart_idx_enum usart_idx, uint32_t ck_usart)
453 {
454     switch(usart_idx) {
455     case IDX_USART0:
456         /* reset the USART0SEL bits and set according to ck_usart */
457         RCU_CFG2 &= ~RCU_CFG2_USART0SEL;
458         RCU_CFG2 |= ck_usart;
459         break;
460     case IDX_USART1:
461         /* reset the USART1SEL bits and set according to ck_usart */
462         RCU_CFG2 &= ~RCU_CFG2_USART1SEL;
463         RCU_CFG2 |= (uint32_t)ck_usart << 16U;
464         break;
465     default:
466         break;
467     }
468 }
469 
470 /*!
471     \brief      configure the I2Cx(x=0,1,2) clock source selection
472     \param[in]  i2c_idx: IDX_I2Cx(x=0,1,2)
473     \param[in]  ck_i2c: I2C clock source selection
474                 only one parameter can be selected which is shown as below:
475       \arg        RCU_I2CSRC_CKAPB1: CK_I2C select CK_APB1
476       \arg        RCU_I2CSRC_CKSYS: CK_I2C select CK_SYS
477       \arg        RCU_I2CSRC_IRC16MDIV: CK_I2C select IRC16MDIV
478     \param[out] none
479     \retval     none
480 */
rcu_i2c_clock_config(i2c_idx_enum i2c_idx,uint32_t ck_i2c)481 void rcu_i2c_clock_config(i2c_idx_enum i2c_idx, uint32_t ck_i2c)
482 {
483     switch(i2c_idx) {
484     case IDX_I2C0:
485         /* reset the I2C0SEL bits and set according to ck_i2c */
486         RCU_CFG2 &= ~RCU_CFG2_I2C0SEL;
487         RCU_CFG2 |= ck_i2c;
488         break;
489     case IDX_I2C1:
490         /* reset the I2C1SEL bits and set according to ck_i2c */
491         RCU_CFG2 &= ~RCU_CFG2_I2C1SEL;
492         RCU_CFG2 |= (uint32_t)ck_i2c << 2U;
493         break;
494     case IDX_I2C2:
495         /* reset the I2C2SEL bits and set according to ck_i2c */
496         RCU_CFG2 &= ~RCU_CFG2_I2C2SEL;
497         RCU_CFG2 |= (uint32_t)ck_i2c << 4U;
498         break;
499     default:
500         break;
501     }
502 }
503 /*!
504     \brief      configure the LPTIMER clock source selection
505     \param[in]  ck_lptimer: LPTIMER clock source selection
506                 only one parameter can be selected which is shown as below:
507       \arg        RCU_LPTIMERSRC_CKAPB1: CK_LPTIMER select CK_APB1
508       \arg        RCU_LPTIMERSRC_IRC32K: CK_LPTIMER select CK_IRC32K
509       \arg        RCU_LPTIMERSRC_LXTAL: CK_LPTIMER select CK_LXTAL
510       \arg        RCU_LPTIMERSRC_IRC16MDIV: CK_LPTIMER select CK_IRC16MDIV
511     \param[out] none
512     \retval     none
513 */
rcu_lptimer_clock_config(uint32_t ck_lptimer)514 void rcu_lptimer_clock_config(uint32_t ck_lptimer)
515 {
516     /* reset the LPTIMERSEL bits and set according to ck_lptimer */
517     RCU_CFG2 &= ~RCU_CFG2_LPTIMERSEL;
518     RCU_CFG2 |= ck_lptimer;
519 }
520 
521 /*!
522     \brief      configure the LPUART clock source selection
523     \param[in]  ck_lpusart: LPUART clock source selection
524                 only one parameter can be selected which is shown as below:
525       \arg        RCU_LPUARTSRC_CKAPB1: LPUART select CK_APB1
526       \arg        RCU_LPUARTSRC_CKSYS: LPUART select CK_SYS
527       \arg        RCU_LPUARTSRC_LXTAL: LPUART select CK_LXTAL
528       \arg        RCU_LPUARTSRC_IRC16MDIV: LPUART select CK_IRC16MDIV
529     \param[out] none
530     \retval     none
531 */
rcu_lpuart_clock_config(uint32_t ck_lpuart)532 void rcu_lpuart_clock_config(uint32_t ck_lpuart)
533 {
534     /* reset the LPUARTSEL bits and set according to ck_lpuart */
535     RCU_CFG2 &= ~RCU_CFG2_LPUARTSEL;
536     RCU_CFG2 |= ck_lpuart;
537 }
538 
539 /*!
540     \brief      configure the IRC16MDIV clock selection
541     \param[in]  ck_irc16mdiv: IRC16MDIV clock selection
542                 only one parameter can be selected which is shown as below:
543       \arg        RCU_IRC16MDIV_NONE: CK_IRC16MDIV select CK_IRC16M
544       \arg        RCU_IRC16MDIV_2: CK_IRC16MDIV select CK_IRC16M divided by 2
545       \arg        RCU_IRC16MDIV_4: CK_IRC16MDIV select CK_IRC16M divided by 4
546       \arg        RCU_IRC16MDIV_8: CK_IRC16MDIV select CK_IRC16M divided by 8
547       \arg        RCU_IRC16MDIV_16: CK_IRC16MDIV select CK_IRC16M divided by 16
548     \param[out] none
549     \retval     none
550 */
rcu_irc16mdiv_clock_config(uint32_t ck_irc16mdiv)551 void rcu_irc16mdiv_clock_config(uint32_t ck_irc16mdiv)
552 {
553     /* reset the LPUARTSEL bits and set according to ck_lpuart */
554     RCU_CFG2 &= ~RCU_CFG2_IRC16MDIVSEL;
555     RCU_CFG2 |= ck_irc16mdiv;
556 }
557 
558 /*!
559     \brief      configure the USBD clock source selection
560     \param[in]  ck_usart: USBD clock source selection
561                 only one parameter can be selected which is shown as below:
562       \arg        RCU_USBDSRC_IRC48M: USBD select CK_IRC48M
563       \arg        RCU_USBDSRC_PLL: USBD select CK_PLL
564     \param[out] none
565     \retval     none
566 */
rcu_usbd_clock_config(uint32_t ck_usbd)567 void rcu_usbd_clock_config(uint32_t ck_usbd)
568 {
569     /* reset the USBDSEL bits and set according to ck_usbd */
570     RCU_CFG2 &= ~RCU_CFG2_USBDSEL;
571     RCU_CFG2 |= ck_usbd;
572 }
573 
574 /*!
575     \brief      configure the RTC clock source selection
576     \param[in]  rtc_clock_source: RTC clock source selection
577                 only one parameter can be selected which is shown as below:
578       \arg        RCU_RTCSRC_NONE: no clock selected
579       \arg        RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock
580       \arg        RCU_RTCSRC_IRC32K: CK_IRC32K selected as RTC source clock
581       \arg        RCU_RTCSRC_HXTAL_DIV32: CK_HXTAL/32 selected as RTC source clock
582     \param[out] none
583     \retval     none
584 */
rcu_rtc_clock_config(uint32_t rtc_clock_source)585 void rcu_rtc_clock_config(uint32_t rtc_clock_source)
586 {
587     /* reset the RTCSRC bits and set according to rtc_clock_source */
588     RCU_BDCTL &= ~RCU_BDCTL_RTCSRC;
589     RCU_BDCTL |= rtc_clock_source;
590 }
591 
592 /*!
593     \brief      configure PLL source clocks pre-divider
594     \param[in]  pllsource_ck_prediv: PLL source clocks divider used as input of PLL
595                 only one parameter can be selected which is shown as below:
596       \arg        RCU_PLL_PREDVx(x=1..16): PLL source clocks divided x used as input of PLL
597     \param[out] none
598     \retval     none
599 */
rcu_pll_source_ck_prediv_config(uint32_t pllsource_ck_prediv)600 void rcu_pll_source_ck_prediv_config(uint32_t pllsource_ck_prediv)
601 {
602     uint32_t prediv = 0U;
603     prediv = RCU_CFG1;
604     /* reset the PREDV bits and set according to pllsource_ck_prediv */
605     prediv &= ~RCU_CFG1_PREDV;
606     RCU_CFG1 = (prediv | pllsource_ck_prediv);
607 }
608 
609 /*!
610     \brief      configure the LXTAL drive capability
611     \param[in]  lxtal_dricap: drive capability of LXTAL
612                 only one parameter can be selected which is shown as below:
613       \arg        RCU_LXTAL_LOWDRI: lower driving capability
614       \arg        RCU_LXTAL_MED_LOWDRI: medium low driving capability
615       \arg        RCU_LXTAL_MED_HIGHDRI: medium high driving capability
616       \arg        RCU_LXTAL_HIGHDRI: higher driving capability
617     \param[out] none
618     \retval     none
619 */
rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap)620 void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap)
621 {
622     /* reset the LXTALDRI bits and set according to lxtal_dricap */
623     RCU_BDCTL &= ~RCU_BDCTL_LXTALDRI;
624     RCU_BDCTL |= lxtal_dricap;
625 }
626 
627 /*!
628     \brief      configure the low power mode LDO voltage selection
629     \param[in]  lp_ldo_voltage: low power mode LDO voltage
630                 only one parameter can be selected which is shown as below:
631       \arg        RCU_LP_LDO_V_0_8: LP_LDO output voltage 0.8V
632       \arg        RCU_LP_LDO_V_0_9: LP_LDO output voltage 0.9V
633     \param[out] none
634     \retval     none
635 */
rcu_lp_ldo_config(uint32_t lp_ldo_voltage)636 void rcu_lp_ldo_config(uint32_t lp_ldo_voltage)
637 {
638     /* reset the RCU_LPB_LPBMODE bits and set according to lp_ldo_voltage */
639     RCU_LPLDO &= ~RCU_LPB_LPBMSEL;
640     RCU_LPLDO |= lp_ldo_voltage;
641 }
642 
643 /*!
644     \brief      configure low power bandgap mode selection
645     \param[in]  lp_bandgap_clock: low power bandgap clock
646                 only one parameter can be selected which is shown as below:
647       \arg        RCU_LPBM_32CLK: The length of holding phase is 3.2ms, 32 clock cycles
648       \arg        RCU_LPBM_64CLK: The length of holding phase is 6.4ms, 64 clock cycles
649       \arg        RCU_LPBM_128CLK: The length of holding phase is 12.8ms, 128 clock cycles
650       \arg        RCU_LPBM_256CLK: The length of holding phase is 25.6ms, 256 clock cycles
651       \arg        RCU_LPBM_512CLK: The length of holding phase is 51.2ms, 512 clock cycles
652       \arg        RCU_LPBM_1024CLK: The length of holding phase is 102.4ms, 1024 clock cycles
653       \arg        RCU_LPBM_2048CLK: The length of holding phase is 204.8ms, 2048 clock cycles
654     \param[out] none
655     \retval     none
656 */
rcu_lp_bandgap_config(uint32_t lp_bandgap_clock)657 void rcu_lp_bandgap_config(uint32_t lp_bandgap_clock)
658 {
659     /* reset the RCU_LPB_LPBMODE bits and set according to lp_ldo_voltage */
660     RCU_LPB &= ~RCU_LPB_LPBMSEL;
661     RCU_LPB |= lp_bandgap_clock;
662 }
663 
664 /*!
665     \brief      get the clock stabilization and periphral reset flags
666     \param[in]  flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum
667                 only one parameter can be selected which is shown as below:
668       \arg        RCU_FLAG_IRC32KSTB: IRC32K stabilization flag
669       \arg        RCU_FLAG_LXTALSTB: LXTAL stabilization flag
670       \arg        RCU_FLAG_IRC16MSTB: IRC16M stabilization flag
671       \arg        RCU_FLAG_HXTALSTB: HXTAL stabilization flag
672       \arg        RCU_FLAG_PLLSTB: PLL stabilization flag
673       \arg        RCU_FLAG_IRC48MSTB: IRC48M stabilization flag
674       \arg        RCU_FLAG_V12RST: V12 domain power reset flag
675       \arg        RCU_FLAG_EPRST: external pin reset flag
676       \arg        RCU_FLAG_PORRST: power reset flag
677       \arg        RCU_FLAG_SWRST: software reset flag
678       \arg        RCU_FLAG_FWDGTRST: free watchdog timer reset flag
679       \arg        RCU_FLAG_WWDGTRST: window watchdog timer reset flag
680       \arg        RCU_FLAG_LPRST: low-power reset flag
681     \param[out] none
682     \retval     FlagStatus: SET or RESET
683 */
rcu_flag_get(rcu_flag_enum flag)684 FlagStatus rcu_flag_get(rcu_flag_enum flag)
685 {
686     if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))) {
687         return SET;
688     } else {
689         return RESET;
690     }
691 }
692 
693 /*!
694     \brief      clear the reset flag
695     \param[in]  none
696     \param[out] none
697     \retval     none
698 */
rcu_all_reset_flag_clear(void)699 void rcu_all_reset_flag_clear(void)
700 {
701     RCU_RSTSCK |= RCU_RSTSCK_RSTFC;
702 }
703 
704 /*!
705     \brief      get the clock stabilization interrupt and ckm flags
706     \param[in]  int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum
707                 only one parameter can be selected which is shown as below:
708       \arg        RCU_INT_FLAG_IRC32KSTB: IRC32K stabilization interrupt flag
709       \arg        RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag
710       \arg        RCU_INT_FLAG_IRC16MSTB: IRC16M stabilization interrupt flag
711       \arg        RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag
712       \arg        RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag
713       \arg        RCU_INT_FLAG_IRC48MSTB: IRC48M stabilization interrupt flag
714       \arg        RCU_INT_FLAG_LXTALCKM: LXTAL clock stuck interrupt flag
715       \arg        RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag
716     \param[out] none
717     \retval     FlagStatus: SET or RESET
718 */
rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)719 FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)
720 {
721     if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))) {
722         return SET;
723     } else {
724         return RESET;
725     }
726 }
727 
728 /*!
729     \brief      clear the interrupt flags
730     \param[in]  int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum
731                 only one parameter can be selected which is shown as below:
732       \arg        RCU_INT_FLAG_IRC32KSTB_CLR: IRC32K stabilization interrupt flag clear
733       \arg        RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear
734       \arg        RCU_INT_FLAG_IRC16MSTB_CLR: IRC16M stabilization interrupt flag clear
735       \arg        RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear
736       \arg        RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear
737       \arg        RCU_INT_FLAG_IRC48MSTB_CLR: IRC48M stabilization interrupt flag clear
738       \arg        RCU_INT_FLAG_LXTALCKM_CLR: LXTAL clock stuck interrupt flag clear
739       \arg        RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear
740     \param[out] none
741     \retval     none
742 */
rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)743 void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)
744 {
745     RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear));
746 }
747 
748 /*!
749     \brief      enable the stabilization interrupt
750     \param[in]  stab_int: clock stabilization interrupt, refer to rcu_int_enum
751                 only one parameter can be selected which is shown as below:
752       \arg        RCU_INT_IRC32KSTB: IRC32K stabilization interrupt enable
753       \arg        RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
754       \arg        RCU_INT_IRC16MSTB: IRC16M stabilization interrupt enable
755       \arg        RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
756       \arg        RCU_INT_PLLSTB: PLL stabilization interrupt enable
757       \arg        RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable
758       \arg        RCU_INT_LXTALCKM: LXTAL clock stuck interrup enable
759     \param[out] none
760     \retval     none
761 */
rcu_interrupt_enable(rcu_int_enum stab_int)762 void rcu_interrupt_enable(rcu_int_enum stab_int)
763 {
764     RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int));
765 }
766 
767 /*!
768     \brief      disable the stabilization interrupt
769     \param[in]  stab_int: clock stabilization interrupt, refer to rcu_int_enum
770                 only one parameter can be selected which is shown as below:
771       \arg        RCU_INT_IRC32KSTB: IRC32K stabilization interrupt disable
772       \arg        RCU_INT_LXTALSTB: LXTAL stabilization interrupt disable
773       \arg        RCU_INT_IRC16MSTB: IRC16M stabilization interrupt disable
774       \arg        RCU_INT_HXTALSTB: HXTAL stabilization interrupt disable
775       \arg        RCU_INT_PLLSTB: PLL stabilization interrupt disable
776       \arg        RCU_INT_IRC48MSTB: IRC48M stabilization interrupt disable
777       \arg        RCU_INT_LXTALCKM: LXTAL clock stuck interrup disable
778     \param[out] none
779     \retval     none
780 */
rcu_interrupt_disable(rcu_int_enum stab_int)781 void rcu_interrupt_disable(rcu_int_enum stab_int)
782 {
783     RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int));
784 }
785 
786 /*!
787     \brief      wait until oscillator stabilization flags is SET
788     \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
789                 only one parameter can be selected which is shown as below:
790       \arg        RCU_HXTAL: HXTAL
791       \arg        RCU_LXTAL: LXTAL
792       \arg        RCU_IRC16M: IRC16M
793       \arg        RCU_IRC48M: IRC48M
794       \arg        RCU_IRC32K: IRC32K
795       \arg        RCU_PLL_CK: PLL
796     \param[out] none
797     \retval     ErrStatus: SUCCESS or ERROR
798 */
rcu_osci_stab_wait(rcu_osci_type_enum osci)799 ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci)
800 {
801     uint32_t stb_cnt = 0U;
802     ErrStatus reval = ERROR;
803     FlagStatus osci_stat = RESET;
804     switch(osci) {
805     case RCU_HXTAL:
806         /* wait until HXTAL is stabilization and osci_stat is not more than timeout */
807         while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)) {
808             osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB);
809             stb_cnt++;
810         }
811         /* check whether flag is set or not */
812         if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)) {
813             reval = SUCCESS;
814         }
815         break;
816 
817     /* wait LXTAL stable */
818     case RCU_LXTAL:
819         while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)) {
820             osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB);
821             stb_cnt++;
822         }
823         /* check whether flag is set or not */
824         if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)) {
825             reval = SUCCESS;
826         }
827         break;
828 
829     /* wait IRC16M stable */
830     case RCU_IRC16M:
831         while((RESET == osci_stat) && (IRC16M_STARTUP_TIMEOUT != stb_cnt)) {
832             osci_stat = rcu_flag_get(RCU_FLAG_IRC16MSTB);
833             stb_cnt++;
834         }
835         /* check whether flag is set or not */
836         if(RESET != rcu_flag_get(RCU_FLAG_IRC16MSTB)) {
837             reval = SUCCESS;
838         }
839         break;
840 
841     /* wait IRC48M stable */
842     case RCU_IRC48M:
843         while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) {
844             osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB);
845             stb_cnt++;
846         }
847         /* check whether flag is set or not */
848         if(RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)) {
849             reval = SUCCESS;
850         }
851         break;
852 
853     /* wait IRC32K stable */
854     case RCU_IRC32K:
855         while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) {
856             osci_stat = rcu_flag_get(RCU_FLAG_IRC32KSTB);
857             stb_cnt++;
858         }
859         /* check whether flag is set or not */
860         if(RESET != rcu_flag_get(RCU_FLAG_IRC32KSTB)) {
861             reval = SUCCESS;
862         }
863         break;
864 
865     /* wait PLL stable */
866     case RCU_PLL_CK:
867         while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) {
868             osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB);
869             stb_cnt++;
870         }
871         /* check whether flag is set or not */
872         if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)) {
873             reval = SUCCESS;
874         }
875         break;
876 
877     default:
878         break;
879     }
880     /* return value */
881     return reval;
882 }
883 
884 /*!
885     \brief      turn on the oscillator
886     \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
887                 only one parameter can be selected which is shown as below:
888       \arg        RCU_HXTAL: HXTAL
889       \arg        RCU_LXTAL: LXTAL
890       \arg        RCU_IRC16M: IRC16M
891       \arg        RCU_IRC48M: IRC48M
892       \arg        RCU_IRC32K: IRC32K
893       \arg        RCU_PLL_CK: PLL
894     \param[out] none
895     \retval     none
896 */
rcu_osci_on(rcu_osci_type_enum osci)897 void rcu_osci_on(rcu_osci_type_enum osci)
898 {
899     RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci));
900 }
901 
902 /*!
903     \brief      turn off the oscillator
904     \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
905                 only one parameter can be selected which is shown as below:
906       \arg        RCU_HXTAL: HXTAL
907       \arg        RCU_LXTAL: LXTAL
908       \arg        RCU_IRC16M: IRC16M
909       \arg        RCU_IRC48M: IRC48M
910       \arg        RCU_IRC32K: IRC32K
911       \arg        RCU_PLL_CK: PLL
912     \param[out] none
913     \retval     none
914 */
rcu_osci_off(rcu_osci_type_enum osci)915 void rcu_osci_off(rcu_osci_type_enum osci)
916 {
917     RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci));
918 }
919 
920 /*!
921     \brief      enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
922     \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
923                 only one parameter can be selected which is shown as below:
924       \arg        RCU_HXTAL: HXTAL
925       \arg        RCU_LXTAL: LXTAL
926     \param[out] none
927     \retval     none
928 */
rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)929 void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)
930 {
931     uint32_t reg;
932     switch(osci) {
933     case RCU_HXTAL:
934         /* HXTALEN must be reset before enable the oscillator bypass mode */
935         reg = RCU_CTL;
936         RCU_CTL &= ~RCU_CTL_HXTALEN;
937         RCU_CTL = (reg | RCU_CTL_HXTALBPS);
938         break;
939     case RCU_LXTAL:
940         /* LXTALEN must be reset before enable the oscillator bypass mode */
941         reg = RCU_BDCTL;
942         RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
943         RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS);
944         break;
945     case RCU_IRC16M:
946     case RCU_IRC48M:
947     case RCU_IRC32K:
948     case RCU_PLL_CK:
949         break;
950     default:
951         break;
952     }
953 }
954 
955 /*!
956     \brief      disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
957     \param[in]  osci: oscillator types, refer to rcu_osci_type_enum
958                 only one parameter can be selected which is shown as below:
959       \arg        RCU_HXTAL: HXTAL
960       \arg        RCU_LXTAL: LXTAL
961     \param[out] none
962     \retval     none
963 */
rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)964 void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)
965 {
966     uint32_t reg;
967     switch(osci) {
968     case RCU_HXTAL:
969         /* HXTALEN must be reset before disable the oscillator bypass mode */
970         reg = RCU_CTL;
971         RCU_CTL &= ~RCU_CTL_HXTALEN;
972         RCU_CTL = (reg & (~RCU_CTL_HXTALBPS));
973         break;
974     case RCU_LXTAL:
975         /* LXTALEN must be reset before disable the oscillator bypass mode */
976         reg = RCU_BDCTL;
977         RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
978         RCU_BDCTL = (reg & (~RCU_BDCTL_LXTALBPS));
979         break;
980     case RCU_IRC16M:
981     case RCU_IRC48M:
982     case RCU_IRC32K:
983     case RCU_PLL_CK:
984         break;
985     default:
986         break;
987     }
988 }
989 
990 /*!
991     \brief      enable the HXTAL clock monitor
992     \param[in]  none
993     \param[out] none
994     \retval     none
995 */
rcu_hxtal_clock_monitor_enable(void)996 void rcu_hxtal_clock_monitor_enable(void)
997 {
998     RCU_CTL |= RCU_CTL_CKMEN;
999 }
1000 
1001 /*!
1002     \brief      disable the HXTAL clock monitor
1003     \param[in]  none
1004     \param[out] none
1005     \retval     none
1006 */
rcu_hxtal_clock_monitor_disable(void)1007 void rcu_hxtal_clock_monitor_disable(void)
1008 {
1009     RCU_CTL &= ~RCU_CTL_CKMEN;
1010 }
1011 
1012 /*!
1013     \brief      enable the LXTAL clock monitor
1014     \param[in]  none
1015     \param[out] none
1016     \retval     none
1017 */
rcu_lxtal_clock_monitor_enable(void)1018 void rcu_lxtal_clock_monitor_enable(void)
1019 {
1020     RCU_CTL |= RCU_CTL_LXTALCKMEN;
1021 }
1022 
1023 /*!
1024     \brief      disable the LXTAL clock monitor
1025     \param[in]  none
1026     \param[out] none
1027     \retval     none
1028 */
rcu_lxtal_clock_monitor_disable(void)1029 void rcu_lxtal_clock_monitor_disable(void)
1030 {
1031     RCU_CTL &= ~RCU_CTL_LXTALCKMEN;
1032 }
1033 
1034 /*!
1035     \brief      set the IRC16M adjust value
1036     \param[in]  irc16m_adjval: IRC16M adjust value, must be between 0 and 0x1F
1037     \param[out] none
1038     \retval     none
1039 */
rcu_irc16m_adjust_value_set(uint8_t irc16m_adjval)1040 void rcu_irc16m_adjust_value_set(uint8_t irc16m_adjval)
1041 {
1042     uint32_t adjust = 0U;
1043     adjust = RCU_CTL;
1044     /* reset the IRC16MADJ bits and set according to irc16m_adjval */
1045     adjust &= ~RCU_CTL_IRC16MADJ;
1046     RCU_CTL = (adjust | (((uint32_t)irc16m_adjval) << 3));
1047 }
1048 
1049 
1050 /*!
1051     \brief      unlock the voltage key
1052     \param[in]  none
1053     \param[out] none
1054     \retval     none
1055 */
rcu_voltage_key_unlock(void)1056 void rcu_voltage_key_unlock(void)
1057 {
1058     /* reset the KEY bits and set 0x1A2B3C4D */
1059     RCU_VKEY &= ~RCU_VKEY_KEY;
1060     RCU_VKEY |= RCU_VKEY_UNLOCK;
1061 }
1062 
1063 /*!
1064     \brief      get the system clock, bus and peripheral clock frequency
1065     \param[in]  clock: the clock frequency which to get
1066                 only one parameter can be selected which is shown as below:
1067       \arg        CK_SYS: system clock frequency
1068       \arg        CK_AHB: AHB clock frequency
1069       \arg        CK_APB1: APB1 clock frequency
1070       \arg        CK_APB2: APB2 clock frequency
1071       \arg        CK_ADC: ADC clock frequency
1072       \arg        CK_USART0: USART0 clock frequency
1073       \arg        CK_USART1: USART1 clock frequency
1074       \arg        CK_LPTIMER: LPTIMER clock frequency
1075       \arg        CK_LPUART: LPUART clock frequency
1076     \param[out] none
1077     \retval     clock frequency of system, AHB, APB1, APB2, ADC or USRAT0/1, LPUART, LPTIMER
1078 */
rcu_clock_freq_get(rcu_clock_freq_enum clock)1079 uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock)
1080 {
1081     uint32_t sws = 0U, adcps = 0U, adcps2 = 0U, ck_freq = 0U;
1082     uint32_t cksys_freq = 0U, ahb_freq = 0U, apb1_freq = 0U, apb2_freq = 0U;
1083     uint32_t adc_freq = 0U, usart_freq = 0U, lptimer_freq = 0U;
1084     uint32_t pllmf = 0U, pllmf6 = 0U, pllsel = 0U, prediv = 0U, idx = 0U, clk_exp = 0U;
1085     /* exponent of AHB, APB1 and APB2 clock divider */
1086     const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
1087     const uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1088     const uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1089     const uint8_t IRC16M_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1090 
1091     sws = GET_BITS(RCU_CFG0, 2, 3);
1092     switch(sws) {
1093     /* IRC16M is selected as CK_SYS */
1094     case SEL_IRC16M:
1095         cksys_freq = IRC16M_VALUE;
1096         break;
1097     /* HXTAL is selected as CK_SYS */
1098     case SEL_HXTAL:
1099         cksys_freq = HXTAL_VALUE;
1100         break;
1101     /* PLL is selected as CK_SYS */
1102     case SEL_PLL:
1103         /* get the value of PLLMF[5:0] */
1104         pllmf  = GET_BITS(RCU_CFG0, 18, 23);
1105         pllmf6 = GET_BITS(RCU_CFG0, 27, 27);
1106         pllmf  = ((pllmf6 << 6) + pllmf);
1107         /* high 16 bits */
1108         if(14U <= pllmf) {
1109             pllmf += 1U;
1110         } else if(15U == pllmf) {
1111             pllmf = 16U;
1112         } else {
1113             pllmf += 2U;
1114         }
1115 
1116         /* PLL clock source selection, HXTAL or IRC16M_VALUE or IRC48M_VALUE */
1117         pllsel = GET_BITS(RCU_CFG0, 16, 17);
1118         if(0U == pllsel) {
1119             prediv = (GET_BITS(RCU_CFG1, 0, 3) + 1U);
1120             cksys_freq = (IRC16M_VALUE / prediv) * pllmf;
1121         } else if(1U == pllsel) {
1122             prediv = (GET_BITS(RCU_CFG1, 0, 3) + 1U);
1123             cksys_freq = (HXTAL_VALUE / prediv) * pllmf;
1124         } else {
1125             prediv = (GET_BITS(RCU_CFG1, 0, 3) + 1U);
1126             cksys_freq = (IRC48M_VALUE / prediv) * pllmf;
1127         }
1128         break;
1129     /* IRC16M is selected as CK_SYS */
1130     default:
1131         cksys_freq = IRC16M_VALUE;
1132         break;
1133     }
1134     /* calculate AHB clock frequency */
1135     idx = GET_BITS(RCU_CFG0, 4, 7);
1136     clk_exp = ahb_exp[idx];
1137     ahb_freq = cksys_freq >> clk_exp;
1138 
1139     /* calculate APB1 clock frequency */
1140     idx = GET_BITS(RCU_CFG0, 8, 10);
1141     clk_exp = apb1_exp[idx];
1142     apb1_freq = ahb_freq >> clk_exp;
1143 
1144     /* calculate APB2 clock frequency */
1145     idx = GET_BITS(RCU_CFG0, 11, 13);
1146     clk_exp = apb2_exp[idx];
1147     apb2_freq = ahb_freq >> clk_exp;
1148 
1149     /* return the clocks frequency */
1150     switch(clock) {
1151     case CK_SYS:
1152         ck_freq = cksys_freq;
1153         break;
1154     case CK_AHB:
1155         ck_freq = ahb_freq;
1156         break;
1157     case CK_APB1:
1158         ck_freq = apb1_freq;
1159         break;
1160     case CK_APB2:
1161         ck_freq = apb2_freq;
1162         break;
1163     case CK_ADC:
1164         /* calculate ADC clock frequency */
1165         if(RCU_ADCSRC_AHB_APB2DIV != (RCU_CFG2 & RCU_CFG2_ADCSEL)) {
1166             adc_freq = IRC48M_VALUE;
1167         } else {
1168             /* ADC clock select CK_APB2 divided by 2/4/6/8 or CK_AHB divided by 3/5/7/9 */
1169             adcps = GET_BITS(RCU_CFG0, 14, 15);
1170             adcps2 = GET_BITS(RCU_CFG2, 30, 31);
1171             switch(adcps) {
1172             case 0:
1173                 if(0U == adcps2) {
1174                     adc_freq = apb2_freq / 2U;
1175                 } else if(1U == adcps2) {
1176                     adc_freq = apb2_freq / 10U;
1177                 } else if(2U == adcps2) {
1178                     adc_freq = ahb_freq / 3U;
1179                 } else if(3U == adcps2) {
1180                     adc_freq = ahb_freq / 11U;
1181                 } else {
1182                 }
1183                 break;
1184             case 1:
1185                 if(0U == adcps2) {
1186                     adc_freq = apb2_freq / 4U;
1187                 } else if(1U == adcps2) {
1188                     adc_freq = apb2_freq / 12U;
1189                 } else if(2U == adcps2) {
1190                     adc_freq = ahb_freq / 5U;
1191                 } else if(3U == adcps2) {
1192                     adc_freq = ahb_freq / 13U;
1193                 } else {
1194                 }
1195                 break;
1196             case 2:
1197                 if(0U == adcps2) {
1198                     adc_freq = apb2_freq / 6U;
1199                 } else if(1U == adcps2) {
1200                     adc_freq = apb2_freq / 14U;
1201                 } else if(2U == adcps2) {
1202                     adc_freq = ahb_freq /  7U;
1203                 } else if(3U == adcps2) {
1204                     adc_freq = ahb_freq / 15U;
1205                 } else {
1206                 }
1207                 break;
1208             case 3:
1209                 if(0U == adcps2) {
1210                     adc_freq = apb2_freq / 8U;
1211                 } else if(1U == adcps2) {
1212                     adc_freq = apb2_freq / 16U;
1213                 } else if(2U == adcps2) {
1214                     adc_freq = ahb_freq /  9U;
1215                 } else if(3U == adcps2) {
1216                     adc_freq = ahb_freq / 17U;
1217                 } else {
1218                 }
1219                 break;
1220             default:
1221                 break;
1222             }
1223         }
1224         ck_freq = adc_freq;
1225         break;
1226     case CK_USART0:
1227         /* calculate USART0 clock frequency */
1228         if(RCU_USART0SRC_CKAPB2 == (RCU_CFG2 & RCU_CFG2_USART0SEL)) {
1229             usart_freq = apb2_freq;
1230         } else if(RCU_USART0SRC_CKSYS == (RCU_CFG2 & RCU_CFG2_USART0SEL)) {
1231             usart_freq = cksys_freq;
1232         } else if(RCU_USART0SRC_LXTAL == (RCU_CFG2 & RCU_CFG2_USART0SEL)) {
1233             usart_freq = LXTAL_VALUE;
1234         } else if(RCU_USART0SRC_IRC16MDIV == (RCU_CFG2 & RCU_CFG2_USART0SEL)) {
1235             /* calculate IRC16MDIV clock frequency */
1236             idx = GET_BITS(RCU_CFG2, 18, 20);
1237             clk_exp = IRC16M_exp[idx];
1238             usart_freq = IRC16M_VALUE >> clk_exp;
1239         } else {
1240         }
1241         ck_freq = usart_freq;
1242         break;
1243     case CK_USART1:
1244         /* calculate USART1 clock frequency */
1245         if(RCU_USART1SRC_CKAPB1 == (RCU_CFG2 & RCU_CFG2_USART1SEL)) {
1246             usart_freq = apb1_freq;
1247         } else if(RCU_USART1SRC_CKSYS == (RCU_CFG2 & RCU_CFG2_USART1SEL)) {
1248             usart_freq = cksys_freq;
1249         } else if(RCU_USART1SRC_LXTAL == (RCU_CFG2 & RCU_CFG2_USART1SEL)) {
1250             usart_freq = LXTAL_VALUE;
1251         } else if(RCU_USART1SRC_IRC16MDIV == (RCU_CFG2 & RCU_CFG2_USART1SEL)) {
1252             /* calculate IRC16MDIV clock frequency */
1253             idx = GET_BITS(RCU_CFG2, 18, 20);
1254             clk_exp = IRC16M_exp[idx];
1255             usart_freq = IRC16M_VALUE >> clk_exp;
1256         } else {
1257         }
1258         ck_freq = usart_freq;
1259         break;
1260     case CK_LPUART:
1261         /* calculate LPUART clock frequency */
1262         if(RCU_LPUARTSRC_CKAPB1 == (RCU_CFG2 & RCU_CFG2_LPUARTSEL)) {
1263             usart_freq = apb1_freq;
1264         } else if(RCU_LPUARTSRC_CKSYS == (RCU_CFG2 & RCU_CFG2_LPUARTSEL)) {
1265             usart_freq = cksys_freq;
1266         } else if(RCU_LPUARTSRC_LXTAL == (RCU_CFG2 & RCU_CFG2_LPUARTSEL)) {
1267             usart_freq = LXTAL_VALUE;
1268         } else if(RCU_LPUARTSRC_IRC16MDIV == (RCU_CFG2 & RCU_CFG2_LPUARTSEL)) {
1269             /* calculate IRC16MDIV clock frequency */
1270             idx = GET_BITS(RCU_CFG2, 18, 20);
1271             clk_exp = IRC16M_exp[idx];
1272             usart_freq = IRC16M_VALUE >> clk_exp;
1273         } else {
1274         }
1275         ck_freq = usart_freq;
1276         break;
1277     case CK_LPTIMER:
1278         /* calculate LPTIMER clock frequency */
1279         if(RCU_LPTIMERSRC_CKAPB1 == (RCU_CFG2 & RCU_CFG2_LPTIMERSEL)) {
1280             lptimer_freq = apb1_freq;
1281         } else if(RCU_LPTIMERSRC_IRC32K == (RCU_CFG2 & RCU_CFG2_LPTIMERSEL)) {
1282             lptimer_freq = IRC32K_VALUE;
1283         } else if(RCU_LPTIMERSRC_LXTAL == (RCU_CFG2 & RCU_CFG2_LPTIMERSEL)) {
1284             lptimer_freq = LXTAL_VALUE;
1285         } else if(RCU_LPTIMERSRC_IRC16MDIV == (RCU_CFG2 & RCU_CFG2_LPTIMERSEL)) {
1286             /* calculate IRC16MDIV clock frequency */
1287             idx = GET_BITS(RCU_CFG2, 18, 20);
1288             clk_exp = IRC16M_exp[idx];
1289             usart_freq = IRC16M_VALUE >> clk_exp;
1290         } else {
1291         }
1292         ck_freq = lptimer_freq;
1293         break;
1294     default:
1295         break;
1296     }
1297     return ck_freq;
1298 }
1299