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