1 /**
2   *********************************************************************************
3   *
4   * @file    ald_cmu.c
5   * @brief   CMU module driver.
6   *
7   * @version V1.0
8   * @date    13 Feb. 2023
9   * @author  AE Team
10   * @note
11   *          Change Logs:
12   *          Date            Author          Notes
13   *          13 Feb. 2023    Lisq            The first version
14   *
15   * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
16   *
17   * SPDX-License-Identifier: Apache-2.0
18   *
19   * Licensed under the Apache License, Version 2.0 (the License); you may
20   * not use this file except in compliance with the License.
21   * You may obtain a copy of the License at
22   *
23   * www.apache.org/licenses/LICENSE-2.0
24   *
25   * Unless required by applicable law or agreed to in writing, software
26   * distributed under the License is distributed on an AS IS BASIS, WITHOUT
27   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28   * See the License for the specific language governing permissions and
29   * limitations under the License.
30   **********************************************************************************
31   ==============================================================================
32                         ##### How to use this driver #####
33   ==============================================================================
34     [..]
35      *** System clock configure ***
36      =================================
37      [..]
38        (+) If you don't change system clock, you can using ald_cmu_clock_config_default() API.
39            It will select HRC as system clock. The system clock is 48MHz.
40        (+) If you want to change system clock, you can using ald_cmu_clock_config() API.
41            You can select one of the following as system clock:
42              @ref CMU_CLOCK_HRC   4MHz or 48MHz
43              @ref CMU_CLOCK_LRC   32000Hz
44              @ref CMU_CLOCK_PLL   48MHz, 64MHz or 72MHz
45              @ref CMU_CLOCK_HOSC  32000Hz, 4MHz, 8MHz, 12MHz, 16MHz, 20MHz, 24MHz
46        (+) If you select CMU_CLOCK_PLL as system clock, it must config the PLL
47            using ald_cmu_pll_config() API.
48        (+) If you get current clock, you can using ald_cmu_get_clock() API.
49   ******************************************************************************
50   */
51 
52 #include "ald_conf.h"
53 
54 /** @addtogroup ES32VF2264_ALD
55   * @{
56   */
57 
58 /** @defgroup CMU CMU
59   * @brief CMU module driver
60   * @{
61   */
62 
63 /**
64   * @defgroup CMU_Private_Variables CMU Private Variables
65   * @{
66   */
67 uint32_t __system_clock  = 48000000U;
68 /**
69   * @}
70   */
71 
72 /** @defgroup CMU_Private_Functions CMU Private Functions
73   * @{
74   */
75 
76 /**
77   * @brief  Update the current system clock. This function
78   *         will be invoked, when system clock has changed.
79   * @param  clock: The new clock.
80   * @retval None
81   */
82 
cmu_clock_update(uint32_t clock)83 static void cmu_clock_update(uint32_t clock)
84 {
85     __system_clock = clock;
86 
87     if (clock > 1000000)
88         ald_tick_init(TICK_INT_PRIORITY);
89 
90     return;
91 }
92 
93 /**
94   * @brief  CMU module interrupt handler
95   * @retval None
96   */
ald_cmu_irq_handler(void)97 void ald_cmu_irq_handler(void)
98 {
99     /* HOSC stop */
100     if (READ_BIT(CMU->HOSMCR, CMU_HOSMCR_STPIF_MSK) && READ_BIT(CMU->HOSMCR, CMU_HOSMCR_STPIE_MSK))
101     {
102         SYSCFG_UNLOCK();
103         SET_BIT(CMU->HOSMCR, CMU_HOSMCR_STPIF_MSK);
104         SYSCFG_LOCK();
105 
106         if ((READ_BIT(CMU->HOSMCR, CMU_HOSMCR_FLAG_MSK))
107                 && ((READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) == 3)
108                 || ((READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) == 5))))
109             cmu_clock_update(4000000);  /* HRC4M */
110 
111         ald_cmu_irq_cbk(ALD_CMU_HOSC_STOP);
112     }
113 
114     /* HOSC start */
115     if (READ_BIT(CMU->HOSMCR, CMU_HOSMCR_STRIF_MSK) && READ_BIT(CMU->HOSMCR, CMU_HOSMCR_STRIE_MSK))
116     {
117         SYSCFG_UNLOCK();
118         SET_BIT(CMU->HOSMCR, CMU_HOSMCR_STRIF_MSK);
119         SYSCFG_LOCK();
120 
121         if (!(READ_BIT(CMU->HOSMCR, CMU_HOSMCR_FLAG_MSK))
122                 && ((READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) == 3)))
123         {
124             if(READ_BITS(CMU->HOSCCFG, CMU_HOSCCFG_FREQ_MSK, CMU_HOSCCFG_FREQ_POSS) > 0x5)
125                 cmu_clock_update(4000000);  /* HOSC4M */
126             else
127                 cmu_clock_update((READ_BITS(CMU->HOSCCFG, CMU_HOSCCFG_FREQ_MSK, CMU_HOSCCFG_FREQ_POSS) + 1) * 4000000);
128         }
129 
130         ald_cmu_irq_cbk(ALD_CMU_HOSC_START);
131     }
132 
133     /* PLL unlock */
134     if (READ_BIT(CMU->PULMCR, CMU_PULMCR_ULKIF_MSK) && READ_BIT(CMU->PULMCR, CMU_PULMCR_ULKIE_MSK))
135     {
136         SYSCFG_UNLOCK();
137         SET_BIT(CMU->PULMCR, CMU_PULMCR_ULKIF_MSK);
138         SYSCFG_LOCK();
139 
140         if (READ_BIT(CMU->PULMCR, CMU_PULMCR_CLKS_MSK)
141                 && ((READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) == 3)
142                 || ((READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) == 5))))
143             cmu_clock_update(4000000);  /* HRC4M */
144 
145         ald_cmu_irq_cbk(ALD_CMU_PLL_UNLOCK);
146     }
147 
148     return;
149 }
150 /**
151   * @}
152   */
153 
154 /** @defgroup CMU_Public_Functions CMU Public Functions
155   * @{
156   */
157 
158 /** @defgroup CMU_Public_Functions_Group1 System clock configuration
159   * @brief    System clock configuration functions
160   *
161   ==============================================================================
162               ##### System clock Configuration functions #####
163   ==============================================================================
164     [..]  This section provides functions allowing to:
165       (+) Configure system clock using default parameters.
166       (+) Configure system clock using specified parameters.
167       (+) Configure PLL using specified parameters.
168       (+) Get system clock.
169   * @{
170   */
171 
172 /**
173   * @brief  Configure system clock using default.
174   *         Select CMU_CLOCK_HRC(48MHz) as system clock and
175   *         enable CMU_CLOCK_LRC(32000Hz).
176   * @retval The status of ALD.
177   */
ald_cmu_clock_config_default(void)178 ald_status_t ald_cmu_clock_config_default(void)
179 {
180     uint32_t cnt = 4000, tmp;
181 
182     ald_flash_wait_config(2);
183 
184     SYSCFG_UNLOCK();
185 
186     WRITE_REG(CMU->CFGR, 0x0);
187 
188     tmp = READ_REG(CMU->CLKENR);
189     /* Enable HRC48M */
190     SET_BIT(tmp, CMU_CLKENR_HRC48MEN_MSK);
191     WRITE_REG(CMU->CLKENR, tmp);
192 
193     for (cnt = 4000; cnt; --cnt);
194 
195     cnt = 4000;
196     while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_HRC48MACT_MSK))) && (--cnt));
197 
198     cnt = 4000;
199     while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_HRC48MRDY_MSK))) && (--cnt));
200 
201     /* Select HRC48M */
202     MODIFY_REG(CMU->CSR, CMU_CSR_SYS_CMD_MSK, ALD_CMU_CLOCK_HRC48M << CMU_CSR_SYS_CMD_POSS);
203 
204     cnt = 4000;
205     while (READ_BIT(CMU->CSR, CMU_CSR_SYS_RDYN_MSK) && (--cnt));
206 
207     if (READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) != ALD_CMU_CLOCK_HRC48M)
208     {
209         SYSCFG_LOCK();
210         return ALD_ERROR;
211     }
212 
213     cmu_clock_update(48000000);
214 
215     SYSCFG_LOCK();
216 
217     return ALD_OK;
218 }
219 
220 /**
221   * @brief  Configure system clock using specified parameters
222   * @param  clk: The parameter can be one of the following:
223   *           @arg @ref CMU_CLOCK_HRC  4MHz or 48MHz
224   *           @arg @ref CMU_CLOCK_LRC  32kHz
225   *           @arg @ref CMU_CLOCK_PLL  48MHz, 64MHz, 72MHz
226   *           @arg @ref CMU_CLOCK_HOSC 4MHz, 8MHz, 12MHz, 16MHz, 20MHz, 24MHz
227   * @param  clock: The clock which will be set. the value depends
228   *         on the parameter of clk.
229   * @retval The status of ALD.
230   */
ald_cmu_clock_config(ald_cmu_clock_t clk,uint32_t clock)231 ald_status_t ald_cmu_clock_config(ald_cmu_clock_t clk, uint32_t clock)
232 {
233     uint32_t cnt = 8000;
234 
235     ald_flash_wait_config(2);
236 
237     assert_param(IS_CMU_CLOCK(clk));
238     SYSCFG_UNLOCK();
239 
240     switch (clk) {
241     case ALD_CMU_CLOCK_HRC48M:
242         assert_param(clock == 48000000);
243 
244         SET_BIT(CMU->CLKENR, CMU_CLKENR_HRC48MEN_MSK);
245 
246         for (cnt = 4000; cnt; --cnt);
247         cnt = 4000;
248         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_HRC48MACT_MSK))) && (--cnt));
249         cnt = 4000;
250         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_HRC48MRDY_MSK))) && (--cnt));
251 
252         MODIFY_REG(CMU->CSR, CMU_CSR_SYS_CMD_MSK, ALD_CMU_CLOCK_HRC48M << CMU_CSR_SYS_CMD_POSS);
253 
254         cnt = 4000;
255         while (READ_BIT(CMU->CSR, CMU_CSR_SYS_RDYN_MSK) && (--cnt));
256 
257         if (READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) != ALD_CMU_CLOCK_HRC48M)
258         {
259             SYSCFG_LOCK();
260             return ALD_ERROR;
261         }
262 
263         cmu_clock_update(clock);
264 
265         break;
266 
267     case ALD_CMU_CLOCK_LRC:
268 
269         assert_param(clock == 32000);
270 
271         cnt = 4000;
272         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_LRCRDY_MSK))) && (--cnt));
273 
274         MODIFY_REG(CMU->CSR, CMU_CSR_SYS_CMD_MSK, ALD_CMU_CLOCK_LRC << CMU_CSR_SYS_CMD_POSS);
275 
276         cnt = 4000;
277         while (READ_BIT(CMU->CSR, CMU_CSR_SYS_RDYN_MSK) && (--cnt));
278 
279         if (READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) != ALD_CMU_CLOCK_LRC)
280         {
281             SYSCFG_LOCK();
282             return ALD_ERROR;
283         }
284 
285         cmu_clock_update(clock);
286 
287         break;
288 
289     case ALD_CMU_CLOCK_HOSC:
290         assert_param(clock == 4000000 || clock == 8000000 || clock == 12000000 ||
291                      clock == 16000000 || clock == 20000000 || clock == 24000000);
292 
293         if(clock > 12000000)
294             SET_BIT(CMU->CLKENR, CMU_CLKENR_HOSCFLYBPS_MSK);  /* HOSC > 12MHz, enable HOSC Bypass Filter */
295 
296         SET_BIT(CMU->CLKENR, CMU_CLKENR_HOSCEN_MSK);
297 
298         MODIFY_REG(CMU->HOSCCFG, CMU_HOSCCFG_FREQ_MSK, clock / 4000000 - 1);
299 
300         for (cnt = 8000; cnt; --cnt);
301 
302         cnt = 4000;
303 
304         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_HOSCACT_MSK))) && (--cnt));
305 
306         cnt = 4000;
307 
308         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_HOSCRDY_MSK))) && (--cnt));
309 
310         MODIFY_REG(CMU->CSR, CMU_CSR_SYS_CMD_MSK, ALD_CMU_CLOCK_HOSC << CMU_CSR_SYS_CMD_POSS);
311 
312         cnt = 4000;
313         while (READ_BIT(CMU->CSR, CMU_CSR_SYS_RDYN_MSK) && (--cnt));
314 
315         if (READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) != ALD_CMU_CLOCK_HOSC)
316         {
317             SYSCFG_LOCK();
318             return ALD_ERROR;
319         }
320 
321         cmu_clock_update(clock);
322         break;
323 
324     case ALD_CMU_CLOCK_PLL:
325         assert_param(clock == 72000000 || clock == 64000000 || clock == 48000000);
326 
327         SET_BIT(CMU->CLKENR, CMU_CLKENR_PLLEN_MSK);
328 
329         for (cnt = 4000; cnt; --cnt);
330 
331         cnt = 4000;
332 
333         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_PLLACT_MSK))) && (--cnt));
334 
335         cnt = 4000;
336 
337         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_PLLRDY_MSK))) && (--cnt));
338 
339         MODIFY_REG(CMU->CSR, CMU_CSR_SYS_CMD_MSK, ALD_CMU_CLOCK_PLL << CMU_CSR_SYS_CMD_POSS);
340 
341         cnt = 4000;
342         while (READ_BIT(CMU->CSR, CMU_CSR_SYS_RDYN_MSK) && (--cnt));
343 
344         if (READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) != ALD_CMU_CLOCK_PLL)
345         {
346             SYSCFG_LOCK();
347             return ALD_ERROR;
348         }
349 
350         cmu_clock_update(clock);
351 
352         break;
353 
354     case ALD_CMU_CLOCK_HRC4M:
355         assert_param(clock == 4000000);
356 
357         SET_BIT(CMU->CLKENR, CMU_CLKENR_HRC4MEN_MSK);
358 
359         for (cnt = 4000; cnt; --cnt);
360 
361         cnt = 4000;
362 
363         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_HRC4MACT_MSK))) && (--cnt));
364 
365         cnt = 4000;
366 
367         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_HRC4MRDY_MSK))) && (--cnt));
368 
369         MODIFY_REG(CMU->CSR, CMU_CSR_SYS_CMD_MSK, ALD_CMU_CLOCK_HRC4M << CMU_CSR_SYS_CMD_POSS);
370 
371         cnt = 4000;
372         while (READ_BIT(CMU->CSR, CMU_CSR_SYS_RDYN_MSK) && (--cnt));
373 
374         if (READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) != ALD_CMU_CLOCK_HRC4M)
375         {
376             SYSCFG_LOCK();
377             return ALD_ERROR;
378         }
379 
380         cmu_clock_update(clock);
381 
382         break;
383 
384     default:
385         break;
386     }
387 
388     SYSCFG_LOCK();
389     return ALD_OK;
390 }
391 
392 /**
393   * @brief  Configure PLL using specified parameters.
394   * @param  input: The input clock type.
395   * @param  output: The output clock which can be 48MHz/64MHz/72MHz.
396   * @retval None
397   */
ald_cmu_pll_config(ald_cmu_pll_input_t input,ald_cmu_pll_output_t output)398 void ald_cmu_pll_config(ald_cmu_pll_input_t input, ald_cmu_pll_output_t output)
399 {
400     uint32_t cnt = 4000;
401 
402     assert_param(IS_CMU_PLL_INPUT(input));
403     assert_param(IS_CMU_PLL_OUTPUT(output));
404 
405     SYSCFG_UNLOCK();
406 
407     if(READ_BITS(CMU->CSR, CMU_CSR_SYS_STU_MSK, CMU_CSR_SYS_STU_POSS) == ALD_CMU_CLOCK_PLL)
408     {
409         SET_BIT(CMU->CLKENR, CMU_CLKENR_HRC48MEN_MSK);
410 
411         for (cnt = 4000; cnt; --cnt);
412 
413         cnt = 4000;
414         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_HRC48MACT_MSK))) && (--cnt));
415 
416         cnt = 4000;
417         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_HRC48MRDY_MSK))) && (--cnt));
418 
419         MODIFY_REG(CMU->CSR, CMU_CSR_SYS_CMD_MSK, ALD_CMU_CLOCK_HRC48M << CMU_CSR_SYS_CMD_POSS);
420 
421         cnt = 4000;
422         while (READ_BIT(CMU->CSR, CMU_CSR_SYS_RDYN_MSK) && (--cnt));
423     }
424 
425     if (input == ALD_CMU_PLL_INPUT_HRC4M)
426     {
427         SET_BIT(CMU->CLKENR, CMU_CLKENR_HRC4MEN_MSK);
428     }
429     else
430     {
431         SET_BIT(CMU->CLKENR, CMU_CLKENR_HOSCEN_MSK);
432 
433         if(input == ALD_CMU_PLL_INPUT_HOSC4M)
434         {
435             MODIFY_REG(CMU->HOSCCFG, CMU_HOSCCFG_FREQ_MSK, 0);
436         }
437         else if(input == ALD_CMU_PLL_INPUT_HOSC8M)
438         {
439             MODIFY_REG(CMU->HOSCCFG, CMU_HOSCCFG_FREQ_MSK, 1);
440         }
441         else if(input == ALD_CMU_PLL_INPUT_HOSC16M)
442         {
443             /* HOSC > 12MHz, enable HOSC Bypass Filter */
444             SET_BIT(CMU->CLKENR, CMU_CLKENR_HOSCFLYBPS_MSK);
445             MODIFY_REG(CMU->HOSCCFG, CMU_HOSCCFG_FREQ_MSK, 3);
446         }
447 
448         cnt = 20000;
449         while ((!(READ_BIT(CMU->CLKSR, CMU_CLKSR_HOSCRDY_MSK))) && (--cnt));
450     }
451 
452     CLEAR_BIT(CMU->CLKENR, CMU_CLKENR_PLLEN_MSK);
453 
454     MODIFY_REG(CMU->PLLCFG, CMU_PLLCFG_REFS_MSK, input << CMU_PLLCFG_REFS_POSS);
455     MODIFY_REG(CMU->PLLCFG, CMU_PLLCFG_CLKOS_MSK, output << CMU_PLLCFG_CLKOS_POSS);
456 
457     SET_BIT(CMU->PULMCR, CMU_PULMCR_EN_MSK);
458     MODIFY_REG(CMU->PULMCR, CMU_PULMCR_MODE_MSK, 0x2 << CMU_PULMCR_MODE_POSS);
459 
460     SYSCFG_LOCK();
461     return;
462 }
463 
464 /**
465   * @brief  Gets current system clock.
466   * @retval The value of system clock.
467   */
ald_cmu_get_clock(void)468 uint32_t ald_cmu_get_clock(void)
469 {
470     return __system_clock;
471 }
472 
473 /**
474   * @}
475   */
476 
477 /**
478   * @brief  Configure the bus division.
479   * @param  bus: The type of bus:
480   *          @arg CMU_SYS
481   *          @arg CMU_PCLK
482   * @param  div: The value of divider.
483   * @retval None
484   */
ald_cmu_div_config(ald_cmu_bus_t bus,ald_cmu_div_t div)485 void ald_cmu_div_config(ald_cmu_bus_t bus, ald_cmu_div_t div)
486 {
487     assert_param(IS_CMU_BUS(bus));
488     assert_param(IS_CMU_DIV(div));
489 
490     SYSCFG_UNLOCK();
491 
492     switch (bus)
493     {
494         case ALD_CMU_SYS:
495             MODIFY_REG(CMU->CFGR, CMU_CFGR_SYSDIV_MSK, div << CMU_CFGR_SYSDIV_POSS);
496             ald_tick_init(TICK_INT_PRIORITY);
497             break;
498 
499         case ALD_CMU_PCLK:
500             MODIFY_REG(CMU->CFGR, CMU_CFGR_PCLKDIV_MSK, div << CMU_CFGR_PCLKDIV_POSS);
501             break;
502 
503         default:
504             break;
505     }
506 
507     SYSCFG_LOCK();
508     return;
509 }
510 
511 /**
512   * @brief  Get SYS clock.
513   * @retval The value of SYS clock.
514   */
ald_cmu_get_sys_clock(void)515 uint32_t ald_cmu_get_sys_clock(void)
516 {
517     uint32_t sys_div = READ_BITS(CMU->CFGR, CMU_CFGR_SYSDIV_MSK, CMU_CFGR_SYSDIV_POSS);
518 
519     return __system_clock >> sys_div;
520 }
521 
522 /**
523   * @brief  Get APB clock.
524   * @retval The value of APB clock.
525   */
ald_cmu_get_pclk_clock(void)526 uint32_t ald_cmu_get_pclk_clock(void)
527 {
528     uint32_t sys_div  = READ_BITS(CMU->CFGR, CMU_CFGR_SYSDIV_MSK, CMU_CFGR_SYSDIV_POSS);
529     uint32_t apb_div = READ_BITS(CMU->CFGR, CMU_CFGR_PCLKDIV_MSK, CMU_CFGR_PCLKDIV_POSS);
530 
531     return (__system_clock >> sys_div) >> apb_div;
532 }
533 
534 /**
535   * @}
536   */
537 
538 /** @defgroup CMU_Public_Functions_Group3 Clock safe configure
539   * @brief    Clock safe configure functions
540   *
541   * @verbatim
542   ==============================================================================
543               ##### Clock safe configure functions #####
544   ==============================================================================
545     [..]  This section provides functions allowing to:
546       (+) Enable/Disable outer high crystal safe mode.
547       (+) Enable/Disable outer low crystal safe mode.
548       (+) Enable/Disable PLL safe mode.
549       (+) Interrupt callback function.
550 
551     @endverbatim
552   * @{
553   */
554 
555 /**
556   * @brief  Enable/Disable outer high crystal safe mode.
557   * @param  clock: the value of outer crystal frequency.
558   * @param  status: The new status.
559   * @retval None
560   */
ald_cmu_hosc_safe_config(ald_cmu_hosc_range_t clock,type_func_t status)561 void ald_cmu_hosc_safe_config(ald_cmu_hosc_range_t clock, type_func_t status)
562 {
563     assert_param(IS_CMU_HOSC_RANGE(clock));
564     assert_param(IS_FUNC_STATE(status));
565 
566     SYSCFG_UNLOCK();
567 
568     if (status)
569     {
570         SET_BIT(CMU->HOSMCR, CMU_HOSMCR_STPIF_MSK);
571         MODIFY_REG(CMU->HOSMCR, CMU_HOSMCR_FRQS_MSK, clock << CMU_HOSMCR_FRQS_POSS);
572         SET_BIT(CMU->HOSMCR, CMU_HOSMCR_EN_MSK);
573         SET_BIT(CMU->HOSMCR, CMU_HOSMCR_STPIE_MSK);
574 
575         ald_mcu_irq_config(CMU_IRQn, 3, ENABLE);
576     }
577     else
578     {
579         CLEAR_BIT(CMU->HOSMCR, CMU_HOSMCR_EN_MSK);
580         CLEAR_BIT(CMU->HOSMCR, CMU_HOSMCR_STPIE_MSK);
581 
582         if (READ_BIT(CMU->PULMCR, CMU_PULMCR_EN_MSK) == 0)
583             ald_mcu_irq_config(CMU_IRQn, 3, DISABLE);
584     }
585 
586     SYSCFG_LOCK();
587     return;
588 }
589 
590 /**
591   * @brief  Enable/Disable PLL1 safe mode.
592   * @param  status: The new status.
593   * @retval None
594   */
ald_cmu_pll_safe_config(type_func_t status)595 void ald_cmu_pll_safe_config(type_func_t status)
596 {
597     assert_param(IS_FUNC_STATE(status));
598     SYSCFG_UNLOCK();
599 
600     if (status)
601     {
602         SET_BIT(CMU->PULMCR, CMU_PULMCR_ULKIF_MSK);
603         MODIFY_REG(CMU->PULMCR, CMU_PULMCR_MODE_MSK, 2 << CMU_PULMCR_MODE_POSS);
604         SET_BIT(CMU->PULMCR, CMU_PULMCR_EN_MSK);
605         SET_BIT(CMU->PULMCR, CMU_PULMCR_ULKIE_MSK);
606 
607         ald_mcu_irq_config(CMU_IRQn, 3, ENABLE);
608     }
609     else
610     {
611         CLEAR_BIT(CMU->PULMCR, CMU_PULMCR_EN_MSK);
612         CLEAR_BIT(CMU->PULMCR, CMU_PULMCR_ULKIE_MSK);
613 
614         if (READ_BIT(CMU->HOSMCR, CMU_HOSMCR_EN_MSK) == 0)
615             ald_mcu_irq_config(CMU_IRQn, 3, DISABLE);
616     }
617 
618     SYSCFG_LOCK();
619     return;
620 }
621 
622 /**
623   * @brief  Get current clock source.
624   * @retval Status:
625   *              - 0: Current clock is PLL
626   *              - 1: Current clock is HRC
627   */
ald_cmu_pulmcr_current_clock_source_get(void)628 uint32_t ald_cmu_pulmcr_current_clock_source_get(void)
629 {
630     return READ_BITS(CMU->PULMCR, CMU_PULMCR_CLKS_MSK, CMU_PULMCR_CLKS_POS);
631 }
632 
633 /**
634   * @brief  Get clock state.
635   * @param  sr: The state type, see @ref cmu_clock_state_t.
636   * @retval SET/RESET
637   */
ald_cmu_get_clock_state(ald_cmu_clock_state_t sr)638 flag_status_t ald_cmu_get_clock_state(ald_cmu_clock_state_t sr)
639 {
640     assert_param(IS_CMU_CLOCK_STATE(sr));
641 
642     if (READ_BIT(CMU->CLKSR, sr))
643         return SET;
644 
645     return RESET;
646 }
647 
648 /**
649   * @brief  Interrupt callback function.
650   * @note   This function is declared as __weak to be overwritten in case of other
651   *         implementations in user file.
652   * @retval None
653   */
ald_cmu_irq_cbk(ald_cmu_security_t se)654 __weak void ald_cmu_irq_cbk(ald_cmu_security_t se)
655 {
656     return;
657 }
658 /**
659   * @}
660   */
661 
662 /** @defgroup CMU_Public_Functions_Group4 Clock output configure
663   * @brief    Clock output configure functions
664   *
665   * @verbatim
666   ==============================================================================
667               ##### Clock output configure functions #####
668   ==============================================================================
669     [..]  This section provides functions allowing to:
670       (+) Configure the high-speed clock output.
671       (+) Configure the low-speed clock output.
672 
673     @endverbatim
674   * @{
675   */
676 
677 /**
678   * @brief  Configure the high-speed clock output.
679   * @param  sel: Select the source:
680   *           @arg CMU_OUTPUT_HIGH_SEL_HOSC
681   *           @arg CMU_OUTPUT_HIGH_SEL_HOSM
682   *           @arg CMU_OUTPUT_HIGH_SEL_HRC4M
683   *           @arg CMU_OUTPUT_HIGH_SEL_LRC
684   *           @arg CMU_OUTPUT_HIGH_SEL_SYSCLK
685   *           @arg CMU_OUTPUT_HIGH_SEL_HOSC32K
686   *           @arg CMU_OUTPUT_HIGH_SEL_HRC48M
687   *           @arg CMU_OUTPUT_HIGH_SEL_PLL
688   * @param  div: The value of divider:
689   *           @arg CMU_OUTPUT_DIV_1
690   *           @arg CMU_OUTPUT_DIV_2
691   *           @arg CMU_OUTPUT_DIV_4
692   *           @arg CMU_OUTPUT_DIV_8
693   *           @arg CMU_OUTPUT_DIV_16
694   *           @arg CMU_OUTPUT_DIV_32
695   *           @arg CMU_OUTPUT_DIV_64
696   *           @arg CMU_OUTPUT_DIV_128
697   * @param  status: The new status.
698   * @retval None
699   */
ald_cmu_output_high_clock_config(ald_cmu_output_high_sel_t sel,ald_cmu_output_high_div_t div,type_func_t status)700 void ald_cmu_output_high_clock_config(ald_cmu_output_high_sel_t sel,
701         ald_cmu_output_high_div_t div, type_func_t status)
702 {
703     assert_param(IS_CMU_OUTPUT_HIGH_SEL(sel));
704     assert_param(IS_CMU_OUTPUT_HIGH_DIV(div));
705     assert_param(IS_FUNC_STATE(status));
706 
707     SYSCFG_UNLOCK();
708 
709     if (status)
710     {
711         MODIFY_REG(CMU->CLKOCR, CMU_CLKOCR_HSCOS_MSK, sel << CMU_CLKOCR_HSCOS_POSS);
712         MODIFY_REG(CMU->CLKOCR, CMU_CLKOCR_HSCODIV_MSK, div << CMU_CLKOCR_HSCODIV_POSS);
713         SET_BIT(CMU->CLKOCR, CMU_CLKOCR_HSCOEN_MSK);
714     }
715     else
716     {
717         CLEAR_BIT(CMU->CLKOCR, CMU_CLKOCR_HSCOEN_MSK);
718     }
719 
720     SYSCFG_LOCK();
721     return;
722 }
723 
724 /**
725   * @brief  Configure the low-speed clock output.
726   * @param  sel: Select the source:
727   *           @arg CMU_OUTPUT_LOW_SEL_LRC
728   *           @arg CMU_OUTPUT_LOW_SEL_BUZZ
729   * @param  status: The new status.
730   * @retval None
731   */
ald_cmu_output_low_clock_config(ald_cmu_output_low_sel_t sel,type_func_t status)732 void ald_cmu_output_low_clock_config(ald_cmu_output_low_sel_t sel, type_func_t status)
733 {
734     assert_param(IS_CMU_OUTPUT_LOW_SEL(sel));
735     assert_param(IS_FUNC_STATE(status));
736 
737     SYSCFG_UNLOCK();
738 
739     if (status)
740     {
741         MODIFY_REG(CMU->CLKOCR, CMU_CLKOCR_LSCOS_MSK, sel << CMU_CLKOCR_LSCOS_POSS);
742         SET_BIT(CMU->CLKOCR, CMU_CLKOCR_LSCOEN_MSK);
743     }
744     else
745     {
746         CLEAR_BIT(CMU->CLKOCR, CMU_CLKOCR_LSCOEN_MSK);
747     }
748 
749     SYSCFG_LOCK();
750     return;
751 }
752 /**
753   * @}
754   */
755 
756 /** @defgroup CMU_Public_Functions_Group5 Peripheral Clock configure
757   * @brief    Peripheral clock configure functions
758   *
759   * @verbatim
760   ==============================================================================
761               ##### Peripheral clock configure functions #####
762   ==============================================================================
763     [..]  This section provides functions allowing to:
764       (+) Configure buzz clock.
765       (+) Enable/Disable peripheral clock.
766 
767     @endverbatim
768   * @{
769   */
770 
771 /**
772   * @brief  Configure buzz clock.
773   *         freq = sysclk / (2^(div + 1) * (dat + 1))
774   * @param  div: The value of divider.
775   * @param  dat: The value of coefficient.
776   * @param  status: The new status.
777   * @retval None
778   */
ald_cmu_buzz_config(ald_cmu_buzz_div_t div,uint16_t dat,type_func_t status)779 void ald_cmu_buzz_config(ald_cmu_buzz_div_t div, uint16_t dat, type_func_t status)
780 {
781     assert_param(IS_CMU_BUZZ_DIV(div));
782     assert_param(IS_FUNC_STATE(status));
783 
784     SYSCFG_UNLOCK();
785 
786     if (status)
787     {
788         MODIFY_REG(CMU->BUZZCR, CMU_BUZZCR_DIV_MSK, div << CMU_BUZZCR_DIV_POSS);
789         MODIFY_REG(CMU->BUZZCR, CMU_BUZZCR_DAT_MSK, dat << CMU_BUZZCR_DAT_POSS);
790         SET_BIT(CMU->BUZZCR, CMU_BUZZCR_EN_MSK);
791     }
792     else
793     {
794         CLEAR_BIT(CMU->BUZZCR, CMU_BUZZCR_EN_MSK);
795     }
796 
797     SYSCFG_LOCK();
798     return;
799 }
800 
801 /**
802   * @brief  Enable/Disable peripheral clock.
803   * @param  perh: The type of peripheral, you can see @ref cmu_perh_t
804   * @param  status: The new status.
805   * @retval None
806   */
ald_cmu_perh_clock_config(ald_cmu_perh_t perh,type_func_t status)807 void ald_cmu_perh_clock_config(ald_cmu_perh_t perh, type_func_t status)
808 {
809     uint32_t idx, pos;
810 
811     assert_param(IS_CMU_PERH(perh));
812     assert_param(IS_FUNC_STATE(status));
813 
814     SYSCFG_UNLOCK();
815 
816     if (perh == ALD_CMU_PERH_ALL) {
817         if (status) {
818             WRITE_REG(CMU->AHBENR, ~0);
819             WRITE_REG(CMU->APBENR, ~0);
820         }
821         else {
822             WRITE_REG(CMU->AHBENR, 0);
823             WRITE_REG(CMU->APBENR, 0);
824         }
825 
826         SYSCFG_LOCK();
827         return;
828     }
829 
830     idx = ((uint32_t)perh >> 27) & 0x1;
831     pos = perh & ~(0x1 << 27);
832 
833     if (status) {
834         switch (idx) {
835         case 0:
836             SET_BIT(CMU->AHBENR, pos);
837             break;
838 
839         case 1:
840             SET_BIT(CMU->APBENR, pos);
841             break;
842 
843         default:
844             break;
845         }
846     }
847     else {
848         switch (idx) {
849         case 0:
850             CLEAR_BIT(CMU->AHBENR, pos);
851             break;
852 
853         case 1:
854             CLEAR_BIT(CMU->APBENR, pos);
855             break;
856 
857         default:
858             break;
859         }
860     }
861 
862     SYSCFG_LOCK();
863     return;
864 }
865 
866 /**
867  * @}
868  */
869 /**
870  * @}
871  */
872 
873 /**
874  * @}
875  */
876 
877 /**
878  * @}
879  */
880