1 /*!
2  * @file        apm32s10x_rcm.c
3  *
4  * @brief       This file provides all the RCM firmware functions
5  *
6  * @version     V1.0.1
7  *
8  * @date        2022-12-31
9  *
10  * @attention
11  *
12  *  Copyright (C) 2022-2023 Geehy Semiconductor
13  *
14  *  You may not use this file except in compliance with the
15  *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
16  *
17  *  The program is only for reference, which is distributed in the hope
18  *  that it will be usefull and instructional for customers to develop
19  *  their software. Unless required by applicable law or agreed to in
20  *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
21  *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
23  *  and limitations under the License.
24  */
25 
26 /* Includes */
27 #include "apm32s10x_rcm.h"
28 
29 /** @addtogroup APM32S10x_StdPeriphDriver
30   @{
31 */
32 
33 /** @addtogroup RCM_Driver RCM Driver
34   @{
35 */
36 
37 /** @defgroup RCM_Functions Functions
38   @{
39 */
40 
41 /*!
42  * @brief     Reset the clock configuration to the default state
43  *
44  * @param     None
45  *
46  * @retval    None
47  */
RCM_Reset(void)48 void RCM_Reset(void)
49 {
50     /* Open HSI clock */
51     RCM->CTRL_B.HSIEN = BIT_SET;
52     /* Config HSI to system clock and Reset AHBPSC, APB1PSC, APB2PSC, ADCPSC and MCOSEL bits */
53     RCM->CFG &= (uint32_t)0xF8FF0000;
54     /* Reset HSEEN, CSSEN and PLLEN bits */
55     RCM->CTRL &= (uint32_t)0xFEF6FFFF;
56     /* Reset HSEBCFG bit */
57     RCM->CTRL_B.HSEBCFG = BIT_RESET;
58     /* Reset PLLSRCSEL, PLLHSEPSC, PLLMULCFG and USBDIV bits */
59     RCM->CFG &= (uint32_t)0xFF00FFFF;
60     /* Disable all interrupts and clear pending bits */
61     RCM->INT = 0x009F0000;
62 }
63 
64 /*!
65  * @brief     Configure the HSE oscillator
66  *
67  * @param     state: state of the HSE
68  *              This parameter can be one of the following values:
69  *              @arg RCM_HSE_CLOSE:  Turn off the HSE oscillator
70  *              @arg RCM_HSE_OPEN:   Turn on the HSE oscillator
71  *              @arg RCM_HSE_BYPASS: HSE oscillator bypassed with external clock
72  *
73  * @retval    None
74  *
75  * @note      When HSE is not used directly or through the PLL as system clock, it can be stopped.
76  */
RCM_ConfigHSE(RCM_HSE_T state)77 void RCM_ConfigHSE(RCM_HSE_T state)
78 {
79     /* Reset HSEEN bit */
80     RCM->CTRL_B.HSEEN = BIT_RESET;
81 
82     /* Reset HSEBCFG bit */
83     RCM->CTRL_B.HSEBCFG = BIT_RESET;
84 
85     if (state == RCM_HSE_OPEN)
86     {
87         RCM->CTRL_B.HSEEN = BIT_SET;
88     }
89     else if (state == RCM_HSE_BYPASS)
90     {
91         RCM->CTRL_B.HSEBCFG = BIT_SET;
92         RCM->CTRL_B.HSEEN = BIT_SET;
93     }
94 }
95 
96 /*!
97  * @brief     Wait for HSE to be ready
98  *
99  * @param     None
100  *
101  * @retval    SUCCESS: HSE oscillator is ready
102  *            ERROR  : HSE oscillator is not ready
103  */
RCM_WaitHSEReady(void)104 uint8_t RCM_WaitHSEReady(void)
105 {
106     __IO uint32_t cnt;
107 
108     for (cnt = 0; cnt < HSE_STARTUP_TIMEOUT; cnt++)
109     {
110         if (RCM->CTRL_B.HSERDYFLG == BIT_SET)
111         {
112             return SUCCESS;
113         }
114     }
115 
116     return ERROR;
117 }
118 
119 /*!
120  * @brief     Configure HSI trimming value
121  *
122  * @param     HSITrim: HSI trimming value
123  *              This parameter must be a number between 0 and 0x1F.
124  *
125  * @retval    None
126  */
RCM_ConfigHSITrim(uint8_t HSITrim)127 void RCM_ConfigHSITrim(uint8_t HSITrim)
128 {
129     RCM->CTRL_B.HSITRIM = HSITrim;
130 }
131 
132 /*!
133  * @brief     Enable the HSI
134  *
135  * @param     None
136  *
137  * @retval    None
138  */
RCM_EnableHSI(void)139 void RCM_EnableHSI(void)
140 {
141     RCM->CTRL_B.HSIEN = BIT_SET;
142 }
143 
144 /*!
145  * @brief     Disable the HSI
146  *
147  * @param     None
148  *
149  * @retval    None
150  *
151  * @note      When HSI is not used directly or through the PLL as system clock, it can be stopped.
152  */
153 
RCM_DisableHSI(void)154 void RCM_DisableHSI(void)
155 {
156     RCM->CTRL_B.HSIEN = BIT_RESET;
157 }
158 
159 /*!
160  * @brief     Configure the External Low Speed oscillator (LSE)
161  *
162  * @param     state : Specify the new state of the LSE
163  *              This parameter can be one of the following values:
164  *              @arg RCM_LSE_CLOSE  : Close the LSE
165  *              @arg RCM_LSE_OPEN   : Open the LSE
166  *              @arg RCM_LSE_BYPASS : LSE bypass
167  *
168  * @retval    None
169  */
RCM_ConfigLSE(RCM_LSE_T state)170 void RCM_ConfigLSE(RCM_LSE_T state)
171 {
172     RCM->BDCTRL_B.LSEEN = BIT_RESET;
173     RCM->BDCTRL_B.LSEBCFG = BIT_RESET;
174 
175     if (state == RCM_LSE_OPEN)
176     {
177         RCM->BDCTRL_B.LSEEN = BIT_SET;
178     }
179     else if (state == RCM_LSE_BYPASS)
180     {
181         RCM->BDCTRL_B.LSEBCFG = BIT_SET;
182         RCM->BDCTRL_B.LSEEN = BIT_SET;
183     }
184 }
185 
186 /*!
187  * @brief     Enable the Internal Low Speed oscillator (LSI)
188  *
189  * @param     None
190  *
191  * @retval    None
192  */
RCM_EnableLSI(void)193 void RCM_EnableLSI(void)
194 {
195     RCM->CSTS_B.LSIEN = BIT_SET;
196 }
197 
198 /*!
199  * @brief     Disable the Internal Low Speed oscillator (LSI)
200  *
201  * @param     None
202  *
203  * @retval    None
204  */
RCM_DisableLSI(void)205 void RCM_DisableLSI(void)
206 {
207     RCM->CSTS_B.LSIEN = BIT_RESET;
208 }
209 
210 /*!
211  * @brief     Configure the PLL clock source and multiplication factor
212  *
213  * @param     pllSelect : PLL entry clock source select
214  *              This parameter can be one of the following values:
215  *              @arg RCM_PLLSEL_HSI_DIV_2: HSI clock divided by 2 selected as PLL clock source
216  *              @arg RCM_PLLSEL_HSE:       HSE clock selected as PLL clock source
217  *              @arg RCM_PLLSEL_HSE_DIV2:  HSE clock divided by 2 selected as PLL clock source
218  *
219  * @param     pllMf : PLL multiplication factor
220  *              This parameter can be RCM_PLLMF_x where x can be a value from 2 to 16.
221  *
222  * @retval    None
223  *
224  * @note      PLL should be disabled while use this function.
225  */
RCM_ConfigPLL(RCM_PLLSEL_T pllSelect,RCM_PLLMF_T pllMf)226 void RCM_ConfigPLL(RCM_PLLSEL_T pllSelect, RCM_PLLMF_T pllMf)
227 {
228     RCM->CFG_B.PLLMULCFG = pllMf;
229     RCM->CFG_B.PLLSRCSEL = pllSelect & 0x01;
230     RCM->CFG_B.PLLHSEPSC = (pllSelect >> 1) & 0x01;
231 }
232 
233 /*!
234  * @brief      Enable the PLL
235  *
236  * @param      None
237  *
238  * @retval     None
239  */
RCM_EnablePLL(void)240 void RCM_EnablePLL(void)
241 {
242     RCM->CTRL_B.PLLEN = BIT_SET;
243 }
244 
245 /*!
246 * @brief      Disable the PLL
247 *
248 * @param      None
249 *
250 * @retval     None
251 *
252 * @note       When PLL is not used as system clock, it can be stopped.
253 */
RCM_DisablePLL(void)254 void RCM_DisablePLL(void)
255 {
256     RCM->CTRL_B.PLLEN = BIT_RESET;
257 }
258 
259 /*!
260  * @brief     Enable the Clock Security System
261  *
262  * @param     None
263  *
264  * @retval    None
265  */
RCM_EnableCSS(void)266 void RCM_EnableCSS(void)
267 {
268     RCM->CTRL_B.CSSEN = BIT_SET;
269 }
270 
271 /*!
272  * @brief     Disable the Clock Security System
273  *
274  * @param     None
275  *
276  * @retval    None
277  */
RCM_DisableCSS(void)278 void RCM_DisableCSS(void)
279 {
280     RCM->CTRL_B.CSSEN = BIT_RESET;
281 }
282 
283 /*!
284  * @brief     Select the MCO pin clock ouput source
285  *
286  * @param     mcoClock: specify the clock source to output
287  *              This parameter can be one of the following values:
288  *              @arg RCM_MCOCLK_NO_CLOCK     : No clock selected.
289  *              @arg RCM_MCOCLK_SYSCLK       : System clock selected.
290  *              @arg RCM_MCOCLK_HSI          : HSI oscillator clock selected.
291  *              @arg RCM_MCOCLK_HSE          : HSE oscillator clock selected.
292  *              @arg RCM_MCOCLK_PLLCLK_DIV_2 : PLL clock divided by 2 selected.
293  *
294  * @retval    None
295  */
RCM_ConfigMCO(RCM_MCOCLK_T mcoClock)296 void RCM_ConfigMCO(RCM_MCOCLK_T mcoClock)
297 {
298     RCM->CFG_B.MCOSEL = mcoClock;
299 }
300 
301 /*!
302  * @brief    Configure the system clock source
303  *
304  * @param    sysClkSelect: specify the clock source used as system clock
305  *             This parameter can be one of the following values:
306  *             @arg RCM_SYSCLK_SEL_HSI: HSI is selected as system clock source
307  *             @arg RCM_SYSCLK_SEL_HSE: HSE is selected as system clock source
308  *             @arg RCM_SYSCLK_SEL_PLL: PLL is selected as system clock source
309  *
310  * @retva    None
311  */
RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_T sysClkSelect)312 void RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_T sysClkSelect)
313 {
314     RCM->CFG_B.SCLKSEL = sysClkSelect;
315 }
316 
317 /*!
318  * @brief     Return the clock source which is used as system clock
319  *
320  * @param     None
321  *
322  * @retval    The clock source used as system clock
323  */
RCM_ReadSYSCLKSource(void)324 RCM_SYSCLK_SEL_T RCM_ReadSYSCLKSource(void)
325 {
326     return (RCM_SYSCLK_SEL_T)RCM->CFG_B.SCLKSELSTS;
327 }
328 
329 /*!
330  * @brief     Configure the AHB clock prescaler.
331  *
332  * @param     AHBDiv : Specify the AHB clock prescaler from the system clock.
333  *              This parameter can be one of the following values:
334  *              @arg RCM_AHB_DIV_1   : HCLK = SYSCLK
335  *              @arg RCM_AHB_DIV_2   : HCLK = SYSCLK / 2
336  *              @arg RCM_AHB_DIV_4   : HCLK = SYSCLK / 4
337  *              @arg RCM_AHB_DIV_8   : HCLK = SYSCLK / 8
338  *              @arg RCM_AHB_DIV_16  : HCLK = SYSCLK / 16
339  *              @arg RCM_AHB_DIV_64  : HCLK = SYSCLK / 64
340  *              @arg RCM_AHB_DIV_128 : HCLK = SYSCLK / 128
341  *              @arg RCM_AHB_DIV_256 : HCLK = SYSCLK / 256
342  *              @arg RCM_AHB_DIV_512 : HCLK = SYSCLK / 512
343  *
344  * @retval    None
345  */
RCM_ConfigAHB(RCM_AHB_DIV_T AHBDiv)346 void RCM_ConfigAHB(RCM_AHB_DIV_T AHBDiv)
347 {
348     RCM->CFG_B.AHBPSC = AHBDiv;
349 }
350 
351 /*!
352  * @brief     Configure the APB1 clock prescaler.
353  *
354  * @param     APB1Div: Specify the APB1 clock prescaler from the AHB clock.
355  *              This parameter can be one of the following values:
356  *              @arg RCM_APB_DIV_1  : PCLK1 = HCLK
357  *              @arg RCM_APB_DIV_2  : PCLK1 = HCLK / 2
358  *              @arg RCM_APB_DIV_4  : PCLK1 = HCLK / 4
359  *              @arg RCM_APB_DIV_8  : PCLK1 = HCLK / 8
360  *              @arg RCM_APB_DIV_16 : PCLK1 = HCLK / 16
361  *
362  * @retval    None
363  */
RCM_ConfigAPB1(RCM_APB_DIV_T APB1Div)364 void RCM_ConfigAPB1(RCM_APB_DIV_T APB1Div)
365 {
366     RCM->CFG_B.APB1PSC = APB1Div;
367 }
368 
369 /*!
370  * @brief     Configure the APB2 clock prescaler
371  *
372  * @param     APB2Div: Specify the APB2 clock prescaler from the AHB clock.
373  *              This parameter can be one of the following values:
374  *              @arg RCM_APB_DIV_1  : PCLK2 = HCLK
375  *              @arg RCM_APB_DIV_2  : PCLK2 = HCLK / 2
376  *              @arg RCM_APB_DIV_4  : PCLK2 = HCLK / 4
377  *              @arg RCM_APB_DIV_8  : PCLK2 = HCLK / 8
378  *              @arg RCM_APB_DIV_16 : PCLK2 = HCLK / 16
379  *
380  * @retval    None
381  */
RCM_ConfigAPB2(RCM_APB_DIV_T APB2Div)382 void RCM_ConfigAPB2(RCM_APB_DIV_T APB2Div)
383 {
384     RCM->CFG_B.APB2PSC = APB2Div;
385 }
386 
387 /*!
388  * @brief     Configure the USB clock prescaler
389  *
390  * @param     USBDiv: Specify the USB clock prescaler from the PLL clock.
391  *              This parameter can be one of the following values:
392  *              @arg RCM_USB_DIV_1_5 : USBCLK = PLL clock /1.5
393  *              @arg RCM_USB_DIV_1   : USBCLK = PLL clock
394  *              @arg RCM_USB_DIV_2   : USBCLK = PLL clock / 2
395  *
396  * @retval    None
397  */
RCM_ConfigUSBCLK(RCM_USB_DIV_T USBDiv)398 void RCM_ConfigUSBCLK(RCM_USB_DIV_T USBDiv)
399 {
400     RCM->CFG_B.USBDPSC = USBDiv;
401 }
402 
403 /*!
404  * @brief     Configure the FPU clock prescaler
405  *
406  * @param     FPUDiv: Specify the FPU clock prescaler from the AHB clock.
407  *              This parameter can be one of the following values:
408  *              @arg RCM_FPU_DIV_1 : FPUCLK = HCLK
409  *              @arg RCM_FPU_DIV_2 : FPUCLK = HCLK /2
410  *
411  * @retval    None
412  */
RCM_ConfigFPUCLK(RCM_FPU_DIV_T FPUDiv)413 void RCM_ConfigFPUCLK(RCM_FPU_DIV_T FPUDiv)
414 {
415     RCM->CFG_B.FPUPSC = FPUDiv;
416 }
417 
418 /*!
419  * @brief     Configure the ADC clock prescaler
420  *
421  * @param     ADCDiv : Specify the ADC clock prescaler from the APB2 clock.
422  *              This parameter can be one of the following values:
423  *              @arg RCM_PCLK2_DIV_2: ADCCLK = PCLK2 / 2
424  *              @arg RCM_PCLK2_DIV_4: ADCCLK = PCLK2 / 4
425  *              @arg RCM_PCLK2_DIV_6: ADCCLK = PCLK2 / 6
426  *              @arg RCM_PCLK2_DIV_8: ADCCLK = PCLK2 / 8
427  *
428  * @retval    None
429  */
RCM_ConfigADCCLK(RCM_PCLK2_DIV_T ADCDiv)430 void RCM_ConfigADCCLK(RCM_PCLK2_DIV_T ADCDiv)
431 {
432     RCM->CFG_B.ADCPSC = ADCDiv;
433 }
434 
435 /*!
436  * @brief     Configure the RTC clock source
437  *
438  * @param     rtcClkSelect : specify the RTC clock source.
439  *              This parameter can be one of the following values:
440  *              @arg RCM_RTCCLK_LSE        : RTCCLK = LSE clock
441  *              @arg RCM_RTCCLK_LSI        : RTCCLK = LSI clock
442  *              @arg RCM_RTCCLK_HSE_DIV_128: RTCCLK = HSE clock / 128
443  *
444  * @retval    None
445  *
446  * @note      Once the RTC clock is configed it can't be changed unless reset the Backup domain.
447  */
RCM_ConfigRTCCLK(RCM_RTCCLK_T rtcClkSelect)448 void RCM_ConfigRTCCLK(RCM_RTCCLK_T rtcClkSelect)
449 {
450     RCM->BDCTRL_B.RTCSRCSEL = rtcClkSelect;
451 }
452 
453 /*!
454  * @brief     Enable the RTC clock
455  *
456  * @param     None
457  *
458  * @retval    None
459  */
RCM_EnableRTCCLK(void)460 void RCM_EnableRTCCLK(void)
461 {
462     RCM->BDCTRL_B.RTCCLKEN = BIT_SET;
463 }
464 
465 /*!
466  * @brief     Disable the RTC clock
467  *
468  * @param     None
469  *
470  * @retval    None
471  */
RCM_DisableRTCCLK(void)472 void RCM_DisableRTCCLK(void)
473 {
474     RCM->BDCTRL_B.RTCCLKEN = BIT_RESET;
475 }
476 
477 /*!
478  * @brief     Reads the frequency of SYSCLK
479  *
480  * @param     None
481  *
482  * @retval    Return the frequency of SYSCLK
483  */
RCM_ReadSYSCLKFreq(void)484 uint32_t RCM_ReadSYSCLKFreq(void)
485 {
486     uint32_t sysClock, pllMull, pllSource;
487 
488     /* get sys clock */
489     sysClock = RCM->CFG_B.SCLKSEL;
490 
491     switch (sysClock)
492     {
493         /* sys clock is HSI */
494         case RCM_SYSCLK_SEL_HSI:
495             sysClock = HSI_VALUE;
496             break;
497 
498         /* sys clock is HSE */
499         case RCM_SYSCLK_SEL_HSE:
500             sysClock = HSE_VALUE;
501             break;
502 
503         /* sys clock is PLL */
504         case RCM_SYSCLK_SEL_PLL:
505             pllMull = RCM->CFG_B.PLLMULCFG + 2;
506             pllSource = RCM->CFG_B.PLLSRCSEL;
507 
508             /* PLL entry clock source is HSE */
509             if (pllSource == BIT_SET)
510             {
511                 sysClock = HSE_VALUE * pllMull;
512 
513                 /* HSE clock divided by 2 */
514                 if (pllSource == RCM->CFG_B.PLLHSEPSC)
515                 {
516                     sysClock >>= 1;
517                 }
518             }
519             /* PLL entry clock source is HSI/2 */
520             else
521             {
522                 sysClock = (HSI_VALUE >> 1) * pllMull;
523             }
524 
525             break;
526 
527         default:
528             sysClock  = HSI_VALUE;
529             break;
530     }
531 
532     return sysClock;
533 }
534 
535 /*!
536  * @brief     Read the frequency of HCLK(AHB)
537  *
538  * @param     None
539  *
540  * @retval    Return the frequency of HCLK
541  */
RCM_ReadHCLKFreq(void)542 uint32_t RCM_ReadHCLKFreq(void)
543 {
544     uint32_t divider;
545     uint32_t sysClk, hclk;
546     uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
547 
548     sysClk = RCM_ReadSYSCLKFreq();
549     divider = AHBPrescTable[RCM->CFG_B.AHBPSC];
550     hclk = sysClk >> divider;
551 
552     return hclk;
553 }
554 
555 /*!
556  * @brief     Read the frequency of PCLK1 And PCLK2
557  *
558  * @param     PCLK1 : Return the frequency of PCLK1
559  *
560  * @param     PCLK1 : Return the frequency of PCLK2
561  *
562  * @retval    None
563  */
RCM_ReadPCLKFreq(uint32_t * PCLK1,uint32_t * PCLK2)564 void RCM_ReadPCLKFreq(uint32_t* PCLK1, uint32_t* PCLK2)
565 {
566     uint32_t hclk, divider;
567     uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
568 
569     hclk = RCM_ReadHCLKFreq();
570 
571     if (PCLK1)
572     {
573         divider = APBPrescTable[RCM->CFG_B.APB1PSC];
574         *PCLK1 = hclk >> divider;
575     }
576 
577     if (PCLK2)
578     {
579         divider = APBPrescTable[RCM->CFG_B.APB2PSC];
580         *PCLK2 = hclk >> divider;
581     }
582 }
583 
584 /*!
585  * @brief     Read the frequency of ADCCLK
586  *
587  * @param     None
588  *
589  * @retval    Return the frequency of ADCCLK
590  */
RCM_ReadADCCLKFreq(void)591 uint32_t RCM_ReadADCCLKFreq(void)
592 {
593     uint32_t adcClk, pclk2, divider;
594     uint8_t ADCPrescTable[4] = {2, 4, 6, 8};
595 
596     RCM_ReadPCLKFreq(NULL, &pclk2);
597 
598     /** Get ADC CLK */
599     divider = ADCPrescTable[RCM->CFG_B.ADCPSC];
600     adcClk = pclk2 / divider;
601 
602     return adcClk;
603 }
604 
605 /*!
606  * @brief    Enables AHB peripheral clock.
607  *
608  * @param    AHBPeriph : Enable the specified clock of AHB peripheral.
609  *             This parameter can be any combination of the following values:
610  *             @arg RCM_AHB_PERIPH_DMA1 : Enable DMA1 clock
611  *             @arg RCM_AHB_PERIPH_SRAM : Enable SRAM clock
612  *             @arg RCM_AHB_PERIPH_FPU  : Enable FPU clock
613  *             @arg RCM_AHB_PERIPH_FMC  : Enable FMC clock
614  *             @arg RCM_AHB_PERIPH_QSPI : Enable QSPI clock
615  *             @arg RCM_AHB_PERIPH_CRC  : Enable CRC clock
616  *
617  * @retval   None
618  */
RCM_EnableAHBPeriphClock(uint32_t AHBPeriph)619 void RCM_EnableAHBPeriphClock(uint32_t AHBPeriph)
620 {
621     RCM->AHBCLKEN |= AHBPeriph;
622 }
623 
624 /*!
625  * @brief    Disable AHB peripheral clock.
626  *
627  * @param    AHBPeriph : Disable the specified clock of AHB peripheral.
628  *             This parameter can be any combination of the following values:
629  *             @arg RCM_AHB_PERIPH_DMA1 : Disable DMA1 clock
630  *             @arg RCM_AHB_PERIPH_SRAM : Disable SRAM clock
631  *             @arg RCM_AHB_PERIPH_FPU  : Disable FPU clock
632  *             @arg RCM_AHB_PERIPH_FMC  : Disable FMC clock
633  *             @arg RCM_AHB_PERIPH_QSPI : Disable QSPI clock
634  *             @arg RCM_AHB_PERIPH_CRC  : Disable CRC clock
635  *
636  * @retval   None
637  */
RCM_DisableAHBPeriphClock(uint32_t AHBPeriph)638 void RCM_DisableAHBPeriphClock(uint32_t AHBPeriph)
639 {
640     RCM->AHBCLKEN &= (uint32_t)~AHBPeriph;
641 }
642 
643 /*!
644  * @brief    Enable the High Speed APB (APB2) peripheral clock
645  *
646  * @param    APB2Periph : Enable the specified clock of the APB2 peripheral.
647  *             This parameter can be any combination of the following values:
648  *             @arg RCM_APB2_PERIPH_AFIO   : Enable AFIO clock
649  *             @arg RCM_APB2_PERIPH_GPIOA  : Enable GPIOA clock
650  *             @arg RCM_APB2_PERIPH_GPIOB  : Enable GPIOB clock
651  *             @arg RCM_APB2_PERIPH_GPIOC  : Enable GPIOC clock
652  *             @arg RCM_APB2_PERIPH_GPIOD  : Enable GPIOD clock
653  *             @arg RCM_APB2_PERIPH_GPIOE  : Enable GPIOE clock
654  *             @arg RCM_APB2_PERIPH_ADC1   : Enable ADC1 clock
655  *             @arg RCM_APB2_PERIPH_ADC2   : Enable ADC2 clock
656  *             @arg RCM_APB2_PERIPH_TMR1   : Enable TMR1 clock
657  *             @arg RCM_APB2_PERIPH_SPI1   : Enable SPI1 clock
658  *             @arg RCM_APB2_PERIPH_USART1 : Enable USART1 clock
659  *
660  * @retval   None
661  */
RCM_EnableAPB2PeriphClock(uint32_t APB2Periph)662 void RCM_EnableAPB2PeriphClock(uint32_t APB2Periph)
663 {
664     RCM->APB2CLKEN |= APB2Periph;
665 }
666 
667 /*!
668  * @brief    Disable the High Speed APB (APB2) peripheral clock
669  *
670  * @param    APB2Periph : Disable the specified clock of the APB2 peripheral.
671  *             This parameter can be any combination of the following values:
672  *             @arg RCM_APB2_PERIPH_AFIO   : Disable AFIO clock
673  *             @arg RCM_APB2_PERIPH_GPIOA  : Disable GPIOA clock
674  *             @arg RCM_APB2_PERIPH_GPIOB  : Disable GPIOB clock
675  *             @arg RCM_APB2_PERIPH_GPIOC  : Disable GPIOC clock
676  *             @arg RCM_APB2_PERIPH_GPIOD  : Disable GPIOD clock
677  *             @arg RCM_APB2_PERIPH_GPIOE  : Disable GPIOE clock
678  *             @arg RCM_APB2_PERIPH_ADC1   : Disable ADC1 clock
679  *             @arg RCM_APB2_PERIPH_ADC2   : Disable ADC2 clock
680  *             @arg RCM_APB2_PERIPH_TMR1   : Disable TMR1 clock
681  *             @arg RCM_APB2_PERIPH_SPI1   : Disable SPI1 clock
682  *             @arg RCM_APB2_PERIPH_USART1 : Disable USART1 clock
683  *
684  * @retval   None
685  */
RCM_DisableAPB2PeriphClock(uint32_t APB2Periph)686 void RCM_DisableAPB2PeriphClock(uint32_t APB2Periph)
687 {
688     RCM->APB2CLKEN &= (uint32_t)~APB2Periph;
689 }
690 
691 /*!
692  * @brief    Enable the Low Speed APB (APB1) peripheral clock
693  *
694  * @param    APB1Periph : Enable the specified clock of the APB1 peripheral.
695  *             This parameter can be any combination of the following values:
696  *             @arg RCM_APB1_PERIPH_TMR2   : Enable TMR2 clock
697  *             @arg RCM_APB1_PERIPH_TMR3   : Enable TMR3 clock
698  *             @arg RCM_APB1_PERIPH_TMR4   : Enable TMR4 clock
699  *             @arg RCM_APB1_PERIPH_WWDT   : Enable WWDT clock
700  *             @arg RCM_APB1_PERIPH_SPI2   : Enable SPI2 clock
701  *             @arg RCM_APB1_PERIPH_USART2 : Enable USART2 clock
702  *             @arg RCM_APB1_PERIPH_USART3 : Enable USART3 clock
703  *             @arg RCM_APB1_PERIPH_I2C1   : Enable I2C1 clock
704  *             @arg RCM_APB1_PERIPH_I2C2   : Enable I2C2 clock
705  *             @arg RCM_APB1_PERIPH_USB    : Enable USB clock
706  *             @arg RCM_APB1_PERIPH_CAN1   : Enable CAN1 clock
707  *             @arg RCM_APB1_PERIPH_CAN2   : Enable CAN2 clock
708  *             @arg RCM_APB1_PERIPH_BAKR   : Enable BAKR clock
709  *             @arg RCM_APB1_PERIPH_PMU    : Enable PMU clock
710  *
711  * @retval   None
712  */
RCM_EnableAPB1PeriphClock(uint32_t APB1Periph)713 void RCM_EnableAPB1PeriphClock(uint32_t APB1Periph)
714 {
715     RCM->APB1CLKEN |= APB1Periph;
716 }
717 
718 /*!
719  * @brief    Disable the Low Speed APB (APB1) peripheral clock
720  *
721  * @param    APB1Periph : Disable the specified clock of the APB1 peripheral.
722  *             This parameter can be any combination of the following values:
723  *             @arg RCM_APB1_PERIPH_TMR2   : Disable TMR2 clock
724  *             @arg RCM_APB1_PERIPH_TMR3   : Disable TMR3 clock
725  *             @arg RCM_APB1_PERIPH_TMR4   : Disable TMR4 clock
726  *             @arg RCM_APB1_PERIPH_WWDT   : Disable WWDT clock
727  *             @arg RCM_APB1_PERIPH_SPI2   : Disable SPI2 clock
728  *             @arg RCM_APB1_PERIPH_USART2 : Disable USART2 clock
729  *             @arg RCM_APB1_PERIPH_USART3 : Disable USART3 clock
730  *             @arg RCM_APB1_PERIPH_I2C1   : Disable I2C1 clock
731  *             @arg RCM_APB1_PERIPH_I2C2   : Disable I2C2 clock
732  *             @arg RCM_APB1_PERIPH_USB    : Disable USB clock
733  *             @arg RCM_APB1_PERIPH_CAN1   : Disable CAN1 clock
734  *             @arg RCM_APB1_PERIPH_CAN2   : Disable CAN2 clock
735  *             @arg RCM_APB1_PERIPH_BAKR   : Disable BAKR clock
736  *             @arg RCM_APB1_PERIPH_PMU    : Disable PMU clock
737  *
738  * @retval   None
739  */
RCM_DisableAPB1PeriphClock(uint32_t APB1Periph)740 void RCM_DisableAPB1PeriphClock(uint32_t APB1Periph)
741 {
742     RCM->APB1CLKEN &= (uint32_t)~APB1Periph;
743 }
744 
745 /*!
746  * @brief    Enable High Speed APB (APB2) peripheral reset
747  *
748  * @param    APB2Periph : Enable the specified APB2 peripheral reset.
749  *             This parameter can be any combination of the following values:
750  *             @arg RCM_APB2_PERIPH_AFIO   : Enable AFIO reset
751  *             @arg RCM_APB2_PERIPH_GPIOA  : Enable GPIOA reset
752  *             @arg RCM_APB2_PERIPH_GPIOB  : Enable GPIOB reset
753  *             @arg RCM_APB2_PERIPH_GPIOC  : Enable GPIOC reset
754  *             @arg RCM_APB2_PERIPH_GPIOD  : Enable GPIOD reset
755  *             @arg RCM_APB2_PERIPH_GPIOE  : Enable GPIOE reset
756  *             @arg RCM_APB2_PERIPH_ADC1   : Enable ADC1 reset
757  *             @arg RCM_APB2_PERIPH_ADC2   : Enable ADC2 reset
758  *             @arg RCM_APB2_PERIPH_TMR1   : Enable TMR1 reset
759  *             @arg RCM_APB2_PERIPH_SPI1   : Enable SPI1 reset
760  *             @arg RCM_APB2_PERIPH_USART1 : Enable USART1 reset
761  *
762  * @retval   None
763  */
RCM_EnableAPB2PeriphReset(uint32_t APB2Periph)764 void RCM_EnableAPB2PeriphReset(uint32_t APB2Periph)
765 {
766     RCM->APB2RST |= APB2Periph;
767 }
768 
769 /*!
770  * @brief    Disable High Speed APB (APB2) peripheral reset
771  *
772  * @param    APB2Periph : Disable the specified APB2 peripheral reset.
773  *             This parameter can be any combination of the following values:
774  *             @arg RCM_APB2_PERIPH_AFIO   : Disable AFIO reset
775  *             @arg RCM_APB2_PERIPH_GPIOA  : Disable GPIOA reset
776  *             @arg RCM_APB2_PERIPH_GPIOB  : Disable GPIOB reset
777  *             @arg RCM_APB2_PERIPH_GPIOC  : Disable GPIOC reset
778  *             @arg RCM_APB2_PERIPH_GPIOD  : Disable GPIOD reset
779  *             @arg RCM_APB2_PERIPH_GPIOE  : Disable GPIOE reset
780  *             @arg RCM_APB2_PERIPH_ADC1   : Disable ADC1 reset
781  *             @arg RCM_APB2_PERIPH_ADC2   : Disable ADC2 reset
782  *             @arg RCM_APB2_PERIPH_TMR1   : Disable TMR1 reset
783  *             @arg RCM_APB2_PERIPH_SPI1   : Disable SPI1 reset
784  *             @arg RCM_APB2_PERIPH_USART1 : Disable USART1 reset
785  *
786  * @retval   None
787  */
RCM_DisableAPB2PeriphReset(uint32_t APB2Periph)788 void RCM_DisableAPB2PeriphReset(uint32_t APB2Periph)
789 {
790     RCM->APB2RST &= (uint32_t)~APB2Periph;
791 }
792 
793 /*!
794  * @brief    Enable Low Speed APB (APB1) peripheral reset
795  *
796  * @param    APB1Periph : Enable the specified APB1 peripheral reset.
797  *             This parameter can be any combination of the following values:
798  *             @arg RCM_APB1_PERIPH_TMR2   : Enable TMR2 reset
799  *             @arg RCM_APB1_PERIPH_TMR3   : Enable TMR3 reset
800  *             @arg RCM_APB1_PERIPH_TMR4   : Enable TMR4 reset
801  *             @arg RCM_APB1_PERIPH_WWDT   : Enable WWDT reset
802  *             @arg RCM_APB1_PERIPH_SPI2   : Enable SPI2 reset
803  *             @arg RCM_APB1_PERIPH_USART2 : Enable USART2 reset
804  *             @arg RCM_APB1_PERIPH_USART3 : Enable USART3 reset
805  *             @arg RCM_APB1_PERIPH_I2C1   : Enable I2C1 reset
806  *             @arg RCM_APB1_PERIPH_I2C2   : Enable I2C2 reset
807  *             @arg RCM_APB1_PERIPH_USB    : Enable USB reset
808  *             @arg RCM_APB1_PERIPH_CAN1   : Enable CAN1 reset
809  *             @arg RCM_APB1_PERIPH_CAN2   : Enable CAN2 reset
810  *             @arg RCM_APB1_PERIPH_BAKR   : Enable BAKR reset
811  *             @arg RCM_APB1_PERIPH_PMU    : Enable PMU reset
812  *
813  * @retval   None
814  */
RCM_EnableAPB1PeriphReset(uint32_t APB1Periph)815 void RCM_EnableAPB1PeriphReset(uint32_t APB1Periph)
816 {
817     RCM->APB1RST |= APB1Periph;
818 }
819 
820 /*!
821  * @brief    Disable Low Speed APB (APB1) peripheral reset
822  *
823  * @param    APB1Periph : Disable the specified APB1 peripheral reset.
824  *             This parameter can be any combination of the following values:
825  *             @arg RCM_APB1_PERIPH_TMR2   : Disable TMR2 reset
826  *             @arg RCM_APB1_PERIPH_TMR3   : Disable TMR3 reset
827  *             @arg RCM_APB1_PERIPH_TMR4   : Disable TMR4 reset
828  *             @arg RCM_APB1_PERIPH_WWDT   : Disable WWDT reset
829  *             @arg RCM_APB1_PERIPH_SPI2   : Disable SPI2 reset
830  *             @arg RCM_APB1_PERIPH_USART2 : Disable USART2 reset
831  *             @arg RCM_APB1_PERIPH_USART3 : Disable USART3 reset
832  *             @arg RCM_APB1_PERIPH_I2C1   : Disable I2C1 reset
833  *             @arg RCM_APB1_PERIPH_I2C2   : Disable I2C2 reset
834  *             @arg RCM_APB1_PERIPH_USB    : Disable USB reset
835  *             @arg RCM_APB1_PERIPH_CAN1   : Disable CAN1 reset
836  *             @arg RCM_APB1_PERIPH_CAN2   : Disable CAN2 reset
837  *             @arg RCM_APB1_PERIPH_BAKR   : Disable BAKR reset
838  *             @arg RCM_APB1_PERIPH_PMU    : Disable PMU reset
839  *
840  * @retval   None
841  */
RCM_DisableAPB1PeriphReset(uint32_t APB1Periph)842 void RCM_DisableAPB1PeriphReset(uint32_t APB1Periph)
843 {
844     RCM->APB1RST &= (uint32_t)~APB1Periph;
845 }
846 
847 /*!
848  * @brief     Enable the Backup domain reset
849  *
850  * @param     None
851  *
852  * @retval    None
853  *
854  */
RCM_EnableBackupReset(void)855 void RCM_EnableBackupReset(void)
856 {
857     RCM->BDCTRL_B.BDRST = BIT_SET;
858 }
859 
860 /*!
861  * @brief     Disable the Backup domain reset
862  *
863  * @param     None
864  *
865  * @retval    None
866  */
RCM_DisableBackupReset(void)867 void RCM_DisableBackupReset(void)
868 {
869     RCM->BDCTRL_B.BDRST = BIT_RESET;
870 }
871 
872 /*!
873  * @brief     Enable RCM interrupts
874  *
875  * @param     interrupt : Enable the specified RCM interrupt sources.
876  *              This parameter can be any combination of the following values:
877  *              @arg RCM_INT_LSIRDY : LSI ready interrupt
878  *              @arg RCM_INT_LSERDY : LSE ready interrupt
879  *              @arg RCM_INT_HSIRDY : HSI ready interrupt
880  *              @arg RCM_INT_HSERDY : HSE ready interrupt
881  *              @arg RCM_INT_PLLRDY : PLL ready interrupt
882  *
883  * @retval    None
884  */
RCM_EnableInterrupt(uint32_t interrupt)885 void RCM_EnableInterrupt(uint32_t interrupt)
886 {
887     uint32_t temp;
888 
889     temp = interrupt << 8;
890 
891     RCM->INT |= temp;
892 }
893 
894 /*!
895  * @brief     Disable RCM interrupts
896  *
897  * @param     interrupt : Disable the specified RCM interrupt sources.
898  *              This parameter can be any combination of the following values:
899  *              @arg RCM_INT_LSIRDY : LSI ready interrupt
900  *              @arg RCM_INT_LSERDY : LSE ready interrupt
901  *              @arg RCM_INT_HSIRDY : HSI ready interrupt
902  *              @arg RCM_INT_HSERDY : HSE ready interrupt
903  *              @arg RCM_INT_PLLRDY : PLL ready interrupt
904  *
905  * @retval    None
906  */
RCM_DisableInterrupt(uint32_t interrupt)907 void RCM_DisableInterrupt(uint32_t interrupt)
908 {
909     uint32_t temp;
910 
911     temp = interrupt << 8;
912 
913     RCM->INT &= (uint32_t)~temp;
914 }
915 
916 /*!
917  * @brief     Read the specified RCM flag status
918  *
919  * @param     flag : Return the specified flag status.
920  *              This parameter can be one of the following values:
921  *              @arg RCM_FLAG_HSIRDY  : HSI ready flag
922  *              @arg RCM_FLAG_HSERDY  : HSE ready flag
923  *              @arg RCM_FLAG_PLLRDY  : PLL ready flag
924  *              @arg RCM_FLAG_LSERDY  : LSE ready flag
925  *              @arg RCM_FLAG_LSIRDY  : LSI ready flag
926  *              @arg RCM_FLAG_PINRST  : NRST PIN Reset Occur Flag
927  *              @arg RCM_FLAG_PORRST  : POR/PDR Reset Occur Flag
928  *              @arg RCM_FLAG_SWRST   : Software Reset Occur Flag
929  *              @arg RCM_FLAG_IWDTRST : Independent Watchdog Reset Occur Flag
930  *              @arg RCM_FLAG_WWDTRST : Window Watchdog Reset Occur Flag
931  *              @arg RCM_FLAG_LPRRST  : Low Power Reset Occur Flag
932  *
933  * @retval    The new state of flag (SET or RESET)
934  */
RCM_ReadStatusFlag(RCM_FLAG_T flag)935 uint8_t RCM_ReadStatusFlag(RCM_FLAG_T flag)
936 {
937     uint32_t reg, bit;
938 
939     bit = (uint32_t)(1 << (flag & 0xff));
940 
941     reg = (flag >> 8) & 0xff;
942 
943     switch (reg)
944     {
945         case 0:
946             reg = RCM->CTRL;
947             break;
948 
949         case 1:
950             reg = RCM->BDCTRL;
951             break;
952 
953         case 2:
954             reg = RCM->CSTS;
955             break;
956 
957         default:
958             break;
959     }
960 
961     if (reg & bit)
962     {
963         return SET;
964     }
965 
966     return RESET;
967 }
968 
969 /*!
970  * @brief     Clear all the RCM reset flags
971  *
972  * @param     None
973  *
974  * @retval    None
975  *
976  * @note      The reset flags are:
977  *            RCM_FLAG_PINRST,  RCM_FLAG_PWRST,   RCM_FLAG_SWRST,
978  *            RCM_FLAG_IWDTRST, RCM_FLAG_WWDTRST, RCM_FLAG_LPRRST
979  */
RCM_ClearStatusFlag(void)980 void RCM_ClearStatusFlag(void)
981 {
982     RCM->CSTS_B.RSTFLGCLR = BIT_SET;
983 }
984 
985 /*!
986  * @brief     Read the specified RCM interrupt Flag
987  *
988  * @param     flag : Read the specified RCM interrupt flag.
989  *              This parameter can be one of the following values:
990  *              @arg RCM_INT_LSIRDY : LSI ready interrupt flag
991  *              @arg RCM_INT_LSERDY : LSE ready interrupt flag
992  *              @arg RCM_INT_HSIRDY : HSI ready interrupt flag
993  *              @arg RCM_INT_HSERDY : HSE ready interrupt flag
994  *              @arg RCM_INT_PLLRDY : PLL ready interrupt flag
995  *              @arg RCM_INT_CSS    : Clock Security System interrupt flag
996  *
997  * @retval    The new state of intFlag (SET or RESET)
998  */
RCM_ReadIntFlag(RCM_INT_T flag)999 uint8_t RCM_ReadIntFlag(RCM_INT_T flag)
1000 {
1001     return (RCM->INT& flag) ? SET : RESET;
1002 }
1003 
1004 /*!
1005  * @brief     Clear the interrupt flag
1006  *
1007  * @param     flag : Clear the specified interrupt flag.
1008  *              @arg RCM_INT_LSIRDY : Clear LSI ready interrupt flag
1009  *              @arg RCM_INT_LSERDY : Clear LSE ready interrupt flag
1010  *              @arg RCM_INT_HSIRDY : Clear HSI ready interrupt flag
1011  *              @arg RCM_INT_HSERDY : Clear HSE ready interrupt flag
1012  *              @arg RCM_INT_PLLRDY : Clear PLL ready interrupt flag
1013  *              @arg RCM_INT_CSS    : Clear Clock Security System interrupt flag
1014  *
1015  * @retval    None
1016  */
RCM_ClearIntFlag(uint32_t flag)1017 void RCM_ClearIntFlag(uint32_t flag)
1018 {
1019     uint32_t temp;
1020 
1021     temp = flag << 16;
1022     RCM->INT |= temp;
1023 }
1024 
1025 /**@} end of group RCM_Functions */
1026 /**@} end of group RCM_Driver */
1027 /**@} end of group APM32S10x_StdPeriphDriver */
1028