1 /**
2 ******************************************************************************
3 * @file stm32c0xx_hal_rcc_ex.c
4 * @author MCD Application Team
5 * @brief Extended RCC HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities RCC extended peripheral:
8 * + Extended Peripheral Control functions
9 * + Extended Clock management functions
10 *
11 ******************************************************************************
12 * @attention
13 *
14 * Copyright (c) 2022 STMicroelectronics.
15 * All rights reserved.
16 *
17 * This software is licensed under terms that can be found in the LICENSE file
18 * in the root directory of this software component.
19 * If no LICENSE file comes with this software, it is provided AS-IS.
20 *
21 ******************************************************************************
22 */
23
24 /* Includes ------------------------------------------------------------------*/
25 #include "stm32c0xx_hal.h"
26
27 /** @addtogroup STM32C0xx_HAL_Driver
28 * @{
29 */
30
31 /** @defgroup RCCEx RCCEx
32 * @brief RCC Extended HAL module driver
33 * @{
34 */
35
36 #ifdef HAL_RCC_MODULE_ENABLED
37
38 /* Private typedef -----------------------------------------------------------*/
39 /* Private defines -----------------------------------------------------------*/
40 /** @defgroup RCCEx_Private_Constants RCCEx Private Constants
41 * @{
42 */
43 #define LSCO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
44 #define LSCO_GPIO_PORT GPIOA
45 #define LSCO_PIN GPIO_PIN_2
46 /**
47 * @}
48 */
49
50 /* Private macros ------------------------------------------------------------*/
51 /* Private variables ---------------------------------------------------------*/
52 /* Private function prototypes -----------------------------------------------*/
53 /* Exported functions --------------------------------------------------------*/
54
55 /** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
56 * @{
57 */
58
59 /** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
60 * @brief Extended Peripheral Control functions
61 *
62 @verbatim
63 ===============================================================================
64 ##### Extended Peripheral Control functions #####
65 ===============================================================================
66 [..]
67 This subsection provides a set of functions allowing to control the RCC Clocks
68 frequencies.
69 [..]
70 (@) Important note: Care must be taken when @ref HAL_RCCEx_PeriphCLKConfig() is used to
71 select the RTC clock source; as consequence RTC registers and RCC_CSR1 register are
72 set to their reset values.
73
74 @endverbatim
75 * @{
76 */
77 /**
78 * @brief Initialize the RCC extended peripherals clocks according to the specified
79 * parameters in the @ref RCC_PeriphCLKInitTypeDef.
80 * @param PeriphClkInit pointer to a @ref RCC_PeriphCLKInitTypeDef structure that
81 * contains a field PeriphClockSelection which can be a combination of the following values:
82 * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
83 * @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock
84 * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock
85 * @arg @ref RCC_PERIPHCLK_I2S1 I2S1 peripheral clock
86 * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock
87 * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (*)
88 * @note Care must be taken when @ref HAL_RCCEx_PeriphCLKConfig() is used to select
89 * the RTC clock source: in this case the access to RTC domain is enabled.
90 * @note (*) not available on all devices
91 *
92 * @retval HAL status
93 */
HAL_RCCEx_PeriphCLKConfig(const RCC_PeriphCLKInitTypeDef * PeriphClkInit)94 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(const RCC_PeriphCLKInitTypeDef *PeriphClkInit)
95 {
96 uint32_t tmpregister;
97 uint32_t tickstart;
98 HAL_StatusTypeDef ret = HAL_OK; /* Intermediate status */
99 HAL_StatusTypeDef status = HAL_OK; /* Final status */
100
101 /* Check the parameters */
102 assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
103
104 /*-------------------------- RTC clock source configuration ----------------------*/
105 if ((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
106 {
107 FlagStatus pwrclkchanged = RESET;
108
109 /* Check for RTC Parameters used to output RTCCLK */
110 assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
111
112 /* Enable Power Clock */
113 if (__HAL_RCC_PWR_IS_CLK_DISABLED())
114 {
115 __HAL_RCC_PWR_CLK_ENABLE();
116 pwrclkchanged = SET;
117 }
118
119
120 /* Reset the RTC domain only if the RTC Clock source selection is modified from default */
121 tmpregister = READ_BIT(RCC->CSR1, RCC_CSR1_RTCSEL);
122
123 /* Reset the RTC domain only if the RTC Clock source selection is modified */
124 if ((tmpregister != RCC_RTCCLKSOURCE_NONE) && (tmpregister != PeriphClkInit->RTCClockSelection))
125 {
126 /* Store the content of CSR1 register before the reset of RTC Domain */
127 tmpregister = READ_BIT(RCC->CSR1, ~(RCC_CSR1_RTCSEL));
128 /* RTC Clock selection can be changed only if the RTC Domain is reset */
129 __HAL_RCC_BACKUPRESET_FORCE();
130 __HAL_RCC_BACKUPRESET_RELEASE();
131 /* Restore the Content of CSR1 register */
132 RCC->CSR1 = tmpregister;
133 }
134
135 /* Wait for LSE reactivation if LSE was enable prior to RTC Domain reset */
136 if (HAL_IS_BIT_SET(tmpregister, RCC_CSR1_LSEON))
137 {
138 /* Get Start Tick*/
139 tickstart = HAL_GetTick();
140
141 /* Wait till LSE is ready */
142 while (READ_BIT(RCC->CSR1, RCC_CSR1_LSERDY) == 0U)
143 {
144 if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
145 {
146 ret = HAL_TIMEOUT;
147 break;
148 }
149 }
150 }
151
152 if (ret == HAL_OK)
153 {
154 /* Apply new RTC clock source selection */
155 __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
156 }
157 else
158 {
159 /* set overall return value */
160 status = ret;
161 }
162
163 /* Restore clock configuration if changed */
164 if (pwrclkchanged == SET)
165 {
166 __HAL_RCC_PWR_CLK_DISABLE();
167 }
168 }
169
170 /*-------------------------- USART1 clock source configuration -------------------*/
171 if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1)
172 {
173 /* Check the parameters */
174 assert_param(IS_RCC_USART1CLKSOURCE(PeriphClkInit->Usart1ClockSelection));
175
176 /* Configure the USART1 clock source */
177 __HAL_RCC_USART1_CONFIG(PeriphClkInit->Usart1ClockSelection);
178 }
179
180 /*-------------------------- I2C1 clock source configuration ---------------------*/
181 if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1)
182 {
183 /* Check the parameters */
184 assert_param(IS_RCC_I2C1CLKSOURCE(PeriphClkInit->I2c1ClockSelection));
185
186 /* Configure the I2C1 clock source */
187 __HAL_RCC_I2C1_CONFIG(PeriphClkInit->I2c1ClockSelection);
188 }
189
190 /*-------------------------- ADC clock source configuration ----------------------*/
191 if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC)
192 {
193 /* Check the parameters */
194 assert_param(IS_RCC_ADCCLKSOURCE(PeriphClkInit->AdcClockSelection));
195
196 /* Configure the ADC interface clock source */
197 __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection);
198
199 }
200 #if defined (USB_DRD_FS)
201 /*-------------------------- USB clock source configuration ----------------*/
202 if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB)
203 {
204 /* Check the parameters */
205 assert_param(IS_RCC_USBCLKSOURCE(PeriphClkInit->UsbClockSelection));
206
207 /* Configure the USB clock source */
208 __HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection);
209
210 }
211 #endif /* USB_DRD_FS */
212 /*-------------------------- I2S1 clock source configuration ---------------------*/
213 if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S1) == RCC_PERIPHCLK_I2S1)
214 {
215 /* Check the parameters */
216 assert_param(IS_RCC_I2S1CLKSOURCE(PeriphClkInit->I2s1ClockSelection));
217
218 /* Configure the I2S1 clock source */
219 __HAL_RCC_I2S1_CONFIG(PeriphClkInit->I2s1ClockSelection);
220 }
221 /*------------------------------------ HSI Kernel clock source configuration --------------------------------------*/
222 if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_HSIKER) == RCC_PERIPHCLK_HSIKER)
223 {
224 /* Check the parameters */
225 assert_param(IS_RCC_HSIKERDIV(PeriphClkInit->HSIKerClockDivider));
226
227 /* Configure the HSI Kernel clock source Divider */
228 __HAL_RCC_HSIKER_CONFIG(PeriphClkInit->HSIKerClockDivider);
229 }
230 return status;
231 }
232
233 /**
234 * @brief Get the RCC_ClkInitStruct according to the internal RCC configuration registers.
235 * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
236 * returns the configuration information for the Extended Peripherals
237 * clocks: I2C1, I2S1, USART1, RTC, ADC,
238 * @retval None
239 */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)240 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
241 {
242 /* Set all possible values for the extended clock type parameter------------*/
243 PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2S1 | \
244 RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_HSIKER ;
245
246 #if defined(USB_DRD_FS)
247 PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_USB;
248 #endif /* USB_DRD_FS */
249 /* Get the USART1 clock source ---------------------------------------------*/
250 PeriphClkInit->Usart1ClockSelection = __HAL_RCC_GET_USART1_SOURCE();
251
252 /* Get the I2C1 clock source -----------------------------------------------*/
253 PeriphClkInit->I2c1ClockSelection = __HAL_RCC_GET_I2C1_SOURCE();
254
255 /* Get the RTC clock source ------------------------------------------------*/
256 PeriphClkInit->RTCClockSelection = __HAL_RCC_GET_RTC_SOURCE();
257
258 /* Get the ADC clock source -----------------------------------------------*/
259 PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE();
260
261 #if defined (USB_DRD_FS)
262 /* Get the USB clock source -------------------------------------------------*/
263 PeriphClkInit->UsbClockSelection = __HAL_RCC_GET_USB_SOURCE();
264 #endif /* USB_DRD_FS */
265
266 /* Get the I2S1 clock source -----------------------------------------------*/
267 PeriphClkInit->I2s1ClockSelection = __HAL_RCC_GET_I2S1_SOURCE();
268
269 /* Get the HSI Kernel clock divider -----------------------------------------------*/
270 PeriphClkInit->HSIKerClockDivider = __HAL_RCC_GET_HSIKER_DIVIDER();
271 }
272
273 /**
274 * @brief Return the peripheral clock frequency for peripherals
275 * @note Return 0 if peripheral clock identifier not managed by this API
276 * @param PeriphClk Peripheral clock identifier
277 * This parameter can be one of the following values:
278 * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
279 * @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock
280 * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock
281 * @arg @ref RCC_PERIPHCLK_I2S1 I2S1 peripheral clock
282 * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock
283 * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (*)
284 * @note (*) not available on all devices
285 * @retval Frequency in Hz
286 */
HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)287 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
288 {
289 uint32_t frequency = 0U;
290 uint32_t srcclk;
291
292 /* Check the parameters */
293 assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
294
295 if (PeriphClk == RCC_PERIPHCLK_RTC)
296 {
297 /* Get the current RTC source */
298 srcclk = __HAL_RCC_GET_RTC_SOURCE();
299
300 /* Check if LSE is ready and if RTC clock selection is LSE */
301 if ((HAL_IS_BIT_SET(RCC->CSR1, RCC_CSR1_LSERDY)) && (srcclk == RCC_RTCCLKSOURCE_LSE))
302 {
303 frequency = LSE_VALUE;
304 }
305 /* Check if LSI is ready and if RTC clock selection is LSI */
306 else if ((HAL_IS_BIT_SET(RCC->CSR2, RCC_CSR2_LSIRDY)) && (srcclk == RCC_RTCCLKSOURCE_LSI))
307 {
308 frequency = LSI_VALUE;
309 }
310 /* Check if HSE is ready and if RTC clock selection is HSI_DIV32*/
311 else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) && (srcclk == RCC_RTCCLKSOURCE_HSE_DIV32))
312 {
313 frequency = HSE_VALUE / 32U;
314 }
315 /* Clock not enabled for RTC*/
316 else
317 {
318 /* Nothing to do as frequency already initialized to 0U */
319 }
320 }
321 else
322 {
323 /* Other external peripheral clock source than RTC */
324
325 switch (PeriphClk)
326 {
327
328 case RCC_PERIPHCLK_USART1:
329 /* Get the current USART1 source */
330 srcclk = __HAL_RCC_GET_USART1_SOURCE();
331
332 if (srcclk == RCC_USART1CLKSOURCE_PCLK1) /* PCLK1 */
333 {
334 frequency = HAL_RCC_GetPCLK1Freq();
335 }
336 else if (srcclk == RCC_USART1CLKSOURCE_SYSCLK) /* SYSCLK */
337 {
338 frequency = HAL_RCC_GetSysClockFreq();
339 }
340 else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (srcclk == RCC_USART1CLKSOURCE_HSIKER))
341 {
342 frequency = (HSI_VALUE / ((__HAL_RCC_GET_HSIKER_DIVIDER() >> RCC_CR_HSIKERDIV_Pos) + 1U));
343 }
344 else if ((HAL_IS_BIT_SET(RCC->CSR1, RCC_CSR1_LSERDY)) && (srcclk == RCC_USART1CLKSOURCE_LSE))
345 {
346 frequency = LSE_VALUE;
347 }
348 /* Clock not enabled for USART1 */
349 else
350 {
351 /* Nothing to do as frequency already initialized to 0U */
352 }
353 break;
354
355 case RCC_PERIPHCLK_ADC:
356
357 srcclk = __HAL_RCC_GET_ADC_SOURCE();
358
359 if (srcclk == RCC_ADCCLKSOURCE_SYSCLK)
360 {
361 frequency = HAL_RCC_GetSysClockFreq();
362 }
363 else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (srcclk == RCC_ADCCLKSOURCE_HSIKER))
364 {
365 frequency = (HSI_VALUE / ((__HAL_RCC_GET_HSIKER_DIVIDER() >> RCC_CR_HSIKERDIV_Pos) + 1U));
366 }
367 /* Clock not enabled for ADC */
368 else
369 {
370 /* Nothing to do as frequency already initialized to 0U */
371 }
372 break;
373
374 case RCC_PERIPHCLK_I2C1:
375 /* Get the current I2C1 source */
376 srcclk = __HAL_RCC_GET_I2C1_SOURCE();
377
378 if (srcclk == RCC_I2C1CLKSOURCE_PCLK1)
379 {
380 frequency = HAL_RCC_GetPCLK1Freq();
381 }
382 else if (srcclk == RCC_I2C1CLKSOURCE_SYSCLK)
383 {
384 frequency = HAL_RCC_GetSysClockFreq();
385 }
386 else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (srcclk == RCC_I2C1CLKSOURCE_HSIKER))
387 {
388 frequency = (HSI_VALUE / ((__HAL_RCC_GET_HSIKER_DIVIDER() >> RCC_CR_HSIKERDIV_Pos) + 1U));
389 }
390 /* Clock not enabled for I2C1 */
391 else
392 {
393 /* Nothing to do as frequency already initialized to 0U */
394 }
395 break;
396
397 case RCC_PERIPHCLK_I2S1:
398 /* Get the current I2S1 source */
399 srcclk = __HAL_RCC_GET_I2S1_SOURCE();
400
401 if (srcclk == RCC_I2S1CLKSOURCE_SYSCLK)
402 {
403 frequency = HAL_RCC_GetSysClockFreq();
404 }
405 else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (srcclk == RCC_I2S1CLKSOURCE_HSIKER))
406 {
407 frequency = (HSI_VALUE / ((__HAL_RCC_GET_HSIKER_DIVIDER() >> RCC_CR_HSIKERDIV_Pos) + 1U));
408 }
409 else if (srcclk == RCC_I2S1CLKSOURCE_EXT)
410 {
411 /* External clock used.*/
412 frequency = EXTERNAL_I2S1_CLOCK_VALUE;
413 }
414 /* Clock not enabled for I2S1 */
415 else
416 {
417 /* Nothing to do as frequency already initialized to 0U */
418 }
419 break;
420 #if defined (USB_DRD_FS)
421 case RCC_PERIPHCLK_USB:
422 /* Get the current USB source */
423 srcclk = __HAL_RCC_GET_USB_SOURCE();
424 if (srcclk == RCC_USBCLKSOURCE_HSI48)
425 {
426 frequency = HSI48_VALUE;
427 }
428 else if (srcclk == RCC_USBCLKSOURCE_HSE)
429 {
430 frequency = HSE_VALUE;
431 }
432 /* Clock not enabled for USB */
433 else
434 {
435 /* Nothing to do as frequency already initialized to 0U */
436 }
437 #endif /* USB_DRD_FS */
438 default:
439 break;
440 }
441 }
442
443 return (frequency);
444 }
445
446 /**
447 * @}
448 */
449
450 /** @defgroup RCCEx_Exported_Functions_Group2 Extended Clock management functions
451 * @brief Extended Clock management functions
452 *
453 @verbatim
454 ===============================================================================
455 ##### Extended clock management functions #####
456 ===============================================================================
457 [..]
458 This subsection provides a set of functions allowing to control the
459 activation or deactivation of LSE CSS, Low speed clock output and
460 clock after wake-up from STOP mode.
461 @endverbatim
462 * @{
463 */
464
465 /**
466 * @brief Select the Low Speed clock source to output on LSCO pin (PA2).
467 * @param LSCOSource specifies the Low Speed clock source to output.
468 * This parameter can be one of the following values:
469 * @arg @ref RCC_LSCOSOURCE_LSI LSI clock selected as LSCO source
470 * @arg @ref RCC_LSCOSOURCE_LSE LSE clock selected as LSCO source
471 * @retval None
472 */
HAL_RCCEx_EnableLSCO(uint32_t LSCOSource)473 void HAL_RCCEx_EnableLSCO(uint32_t LSCOSource)
474 {
475 GPIO_InitTypeDef GPIO_InitStruct;
476
477 /* Check the parameters */
478 assert_param(IS_RCC_LSCOSOURCE(LSCOSource));
479
480 /* LSCO Pin Clock Enable */
481 LSCO_CLK_ENABLE();
482
483 /* configure the LSCO pin in analog mode */
484 GPIO_InitStruct.Pin = LSCO_PIN;
485 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
486 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
487 GPIO_InitStruct.Pull = GPIO_NOPULL;
488 HAL_GPIO_Init(LSCO_GPIO_PORT, &GPIO_InitStruct);
489
490 MODIFY_REG(RCC->CSR1, RCC_CSR1_LSCOSEL | RCC_CSR1_LSCOEN, LSCOSource | RCC_CSR1_LSCOEN);
491
492 }
493
494 /**
495 * @brief Disable the Low Speed clock output.
496 * @retval None
497 */
HAL_RCCEx_DisableLSCO(void)498 void HAL_RCCEx_DisableLSCO(void)
499 {
500
501 CLEAR_BIT(RCC->CSR1, RCC_CSR1_LSCOEN);
502
503 }
504
505 /**
506 * @}
507 */
508
509 #if defined(CRS)
510
511 /** @defgroup RCCEx_Exported_Functions_Group3 Extended Clock Recovery System Control functions
512 * @brief Extended Clock Recovery System Control functions
513 *
514 @verbatim
515 ===============================================================================
516 ##### Extended Clock Recovery System Control functions #####
517 ===============================================================================
518 [..]
519 For devices with Clock Recovery System feature (CRS), RCC Extension HAL driver can be used as follows:
520
521 (#) In System clock config, HSI48 needs to be enabled
522
523 (#) Enable CRS clock in IP MSP init which will use CRS functions
524
525 (#) Call CRS functions as follows:
526 (##) Prepare synchronization configuration necessary for HSI48 calibration
527 (+++) Default values can be set for frequency Error Measurement (reload and error limit)
528 and also HSI48 oscillator smooth trimming.
529 (+++) Macro __HAL_RCC_CRS_RELOADVALUE_CALCULATE can be also used to calculate
530 directly reload value with target and synchronization frequencies values
531 (##) Call function HAL_RCCEx_CRSConfig which
532 (+++) Resets CRS registers to their default values.
533 (+++) Configures CRS registers with synchronization configuration
534 (+++) Enables automatic calibration and frequency error counter feature
535 Note: When using USB LPM (Link Power Management) and the device is in Sleep mode, the
536 periodic USB SOF will not be generated by the host. No SYNC signal will therefore be
537 provided to the CRS to calibrate the HSI48 on the run. To guarantee the required clock
538 precision after waking up from Sleep mode, the LSE or reference clock on the GPIOs
539 should be used as SYNC signal.
540
541 (##) A polling function is provided to wait for complete synchronization
542 (+++) Call function HAL_RCCEx_CRSWaitSynchronization()
543 (+++) According to CRS status, user can decide to adjust again the calibration or continue
544 application if synchronization is OK
545
546 (#) User can retrieve information related to synchronization in calling function
547 HAL_RCCEx_CRSGetSynchronizationInfo()
548
549 (#) Regarding synchronization status and synchronization information, user can try a new calibration
550 in changing synchronization configuration and call again HAL_RCCEx_CRSConfig.
551 Note: When the SYNC event is detected during the downcounting phase (before reaching the zero value),
552 it means that the actual frequency is lower than the target (and so, that the TRIM value should be
553 incremented), while when it is detected during the upcounting phase it means that the actual frequency
554 is higher (and that the TRIM value should be decremented).
555
556 (#) In interrupt mode, user can resort to the available macros (__HAL_RCC_CRS_XXX_IT). Interrupts will go
557 through CRS Handler (CRS_IRQn/CRS_IRQHandler)
558 (++) Call function HAL_RCCEx_CRSConfig()
559 (++) Enable CRS_IRQn (thanks to NVIC functions)
560 (++) Enable CRS interrupt (__HAL_RCC_CRS_ENABLE_IT)
561 (++) Implement CRS status management in the following user callbacks called from
562 HAL_RCCEx_CRS_IRQHandler():
563 (+++) HAL_RCCEx_CRS_SyncOkCallback()
564 (+++) HAL_RCCEx_CRS_SyncWarnCallback()
565 (+++) HAL_RCCEx_CRS_ExpectedSyncCallback()
566 (+++) HAL_RCCEx_CRS_ErrorCallback()
567
568 (#) To force a SYNC EVENT, user can use the function HAL_RCCEx_CRSSoftwareSynchronizationGenerate().
569 This function can be called before calling HAL_RCCEx_CRSConfig (for instance in Systick handler)
570
571 @endverbatim
572 * @{
573 */
574
575 /**
576 * @brief Start automatic synchronization for polling mode
577 * @param pInit Pointer on RCC_CRSInitTypeDef structure
578 * @retval None
579 */
HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef * pInit)580 void HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef *pInit)
581 {
582 uint32_t value; /* no init needed */
583
584 /* Check the parameters */
585 assert_param(IS_RCC_CRS_SYNC_DIV(pInit->Prescaler));
586 assert_param(IS_RCC_CRS_SYNC_SOURCE(pInit->Source));
587 assert_param(IS_RCC_CRS_SYNC_POLARITY(pInit->Polarity));
588 assert_param(IS_RCC_CRS_RELOADVALUE(pInit->ReloadValue));
589 assert_param(IS_RCC_CRS_ERRORLIMIT(pInit->ErrorLimitValue));
590 assert_param(IS_RCC_CRS_HSI48CALIBRATION(pInit->HSI48CalibrationValue));
591
592 /* CONFIGURATION */
593
594 /* Before configuration, reset CRS registers to their default values*/
595 __HAL_RCC_CRS_FORCE_RESET();
596 __HAL_RCC_CRS_RELEASE_RESET();
597
598 /* Set the SYNCDIV[2:0] bits according to Prescaler value */
599 /* Set the SYNCSRC[1:0] bits according to Source value */
600 /* Set the SYNCSPOL bit according to Polarity value */
601 value = (pInit->Prescaler | pInit->Source | pInit->Polarity);
602 /* Set the RELOAD[15:0] bits according to ReloadValue value */
603 value |= pInit->ReloadValue;
604 /* Set the FELIM[7:0] bits according to ErrorLimitValue value */
605 value |= (pInit->ErrorLimitValue << CRS_CFGR_FELIM_Pos);
606 WRITE_REG(CRS->CFGR, value);
607
608 /* Adjust HSI48 oscillator smooth trimming */
609 /* Set the TRIM[6:0] bits according to RCC_CRS_HSI48CalibrationValue value */
610 MODIFY_REG(CRS->CR, CRS_CR_TRIM, (pInit->HSI48CalibrationValue << CRS_CR_TRIM_Pos));
611
612 /* START AUTOMATIC SYNCHRONIZATION*/
613
614 /* Enable Automatic trimming & Frequency error counter */
615 SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN | CRS_CR_CEN);
616 }
617
618 /**
619 * @brief Generate the software synchronization event
620 * @retval None
621 */
HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void)622 void HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void)
623 {
624 SET_BIT(CRS->CR, CRS_CR_SWSYNC);
625 }
626
627 /**
628 * @brief Return synchronization info
629 * @param pSynchroInfo Pointer on RCC_CRSSynchroInfoTypeDef structure
630 * @retval None
631 */
HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef * pSynchroInfo)632 void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo)
633 {
634 /* Check the parameter */
635 assert_param(pSynchroInfo != (void *)NULL);
636
637 /* Get the reload value */
638 pSynchroInfo->ReloadValue = (READ_BIT(CRS->CFGR, CRS_CFGR_RELOAD));
639
640 /* Get HSI48 oscillator smooth trimming */
641 pSynchroInfo->HSI48CalibrationValue = (READ_BIT(CRS->CR, CRS_CR_TRIM) >> CRS_CR_TRIM_Pos);
642
643 /* Get Frequency error capture */
644 pSynchroInfo->FreqErrorCapture = (READ_BIT(CRS->ISR, CRS_ISR_FECAP) >> CRS_ISR_FECAP_Pos);
645
646 /* Get Frequency error direction */
647 pSynchroInfo->FreqErrorDirection = (READ_BIT(CRS->ISR, CRS_ISR_FEDIR));
648 }
649
650 /**
651 * @brief Wait for CRS Synchronization status.
652 * @param Timeout Duration of the timeout
653 * @note Timeout is based on the maximum time to receive a SYNC event based on synchronization
654 * frequency.
655 * @note If Timeout set to HAL_MAX_DELAY, HAL_TIMEOUT will be never returned.
656 * @retval Combination of Synchronization status
657 * This parameter can be a combination of the following values:
658 * @arg @ref RCC_CRS_TIMEOUT
659 * @arg @ref RCC_CRS_SYNCOK
660 * @arg @ref RCC_CRS_SYNCWARN
661 * @arg @ref RCC_CRS_SYNCERR
662 * @arg @ref RCC_CRS_SYNCMISS
663 * @arg @ref RCC_CRS_TRIMOVF
664 */
HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout)665 uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout)
666 {
667 uint32_t crsstatus = RCC_CRS_NONE;
668 uint32_t tickstart;
669
670 /* Get timeout */
671 tickstart = HAL_GetTick();
672
673 /* Wait for CRS flag or timeout detection */
674 do
675 {
676 if (Timeout != HAL_MAX_DELAY)
677 {
678 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
679 {
680 crsstatus = RCC_CRS_TIMEOUT;
681 }
682 }
683 /* Check CRS SYNCOK flag */
684 if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCOK))
685 {
686 /* CRS SYNC event OK */
687 crsstatus |= RCC_CRS_SYNCOK;
688
689 /* Clear CRS SYNC event OK bit */
690 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCOK);
691 }
692
693 /* Check CRS SYNCWARN flag */
694 if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCWARN))
695 {
696 /* CRS SYNC warning */
697 crsstatus |= RCC_CRS_SYNCWARN;
698
699 /* Clear CRS SYNCWARN bit */
700 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCWARN);
701 }
702
703 /* Check CRS TRIM overflow flag */
704 if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_TRIMOVF))
705 {
706 /* CRS SYNC Error */
707 crsstatus |= RCC_CRS_TRIMOVF;
708
709 /* Clear CRS Error bit */
710 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_TRIMOVF);
711 }
712
713 /* Check CRS Error flag */
714 if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCERR))
715 {
716 /* CRS SYNC Error */
717 crsstatus |= RCC_CRS_SYNCERR;
718
719 /* Clear CRS Error bit */
720 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCERR);
721 }
722
723 /* Check CRS SYNC Missed flag */
724 if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCMISS))
725 {
726 /* CRS SYNC Missed */
727 crsstatus |= RCC_CRS_SYNCMISS;
728
729 /* Clear CRS SYNC Missed bit */
730 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCMISS);
731 }
732
733 /* Check CRS Expected SYNC flag */
734 if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_ESYNC))
735 {
736 /* frequency error counter reached a zero value */
737 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_ESYNC);
738 }
739 } while (RCC_CRS_NONE == crsstatus);
740
741 return crsstatus;
742 }
743
744 /**
745 * @brief Handle the Clock Recovery System interrupt request.
746 * @retval None
747 */
HAL_RCCEx_CRS_IRQHandler(void)748 void HAL_RCCEx_CRS_IRQHandler(void)
749 {
750 uint32_t crserror = RCC_CRS_NONE;
751 /* Get current IT flags and IT sources values */
752 uint32_t itflags = READ_REG(CRS->ISR);
753 uint32_t itsources = READ_REG(CRS->CR);
754
755 /* Check CRS SYNCOK flag */
756 if (((itflags & RCC_CRS_FLAG_SYNCOK) != 0U) && ((itsources & RCC_CRS_IT_SYNCOK) != 0U))
757 {
758 /* Clear CRS SYNC event OK flag */
759 WRITE_REG(CRS->ICR, CRS_ICR_SYNCOKC);
760
761 /* user callback */
762 HAL_RCCEx_CRS_SyncOkCallback();
763 }
764 /* Check CRS SYNCWARN flag */
765 else if (((itflags & RCC_CRS_FLAG_SYNCWARN) != 0U) && ((itsources & RCC_CRS_IT_SYNCWARN) != 0U))
766 {
767 /* Clear CRS SYNCWARN flag */
768 WRITE_REG(CRS->ICR, CRS_ICR_SYNCWARNC);
769
770 /* user callback */
771 HAL_RCCEx_CRS_SyncWarnCallback();
772 }
773 /* Check CRS Expected SYNC flag */
774 else if (((itflags & RCC_CRS_FLAG_ESYNC) != 0U) && ((itsources & RCC_CRS_IT_ESYNC) != 0U))
775 {
776 /* frequency error counter reached a zero value */
777 WRITE_REG(CRS->ICR, CRS_ICR_ESYNCC);
778
779 /* user callback */
780 HAL_RCCEx_CRS_ExpectedSyncCallback();
781 }
782 /* Check CRS Error flags */
783 else
784 {
785 if (((itflags & RCC_CRS_FLAG_ERR) != 0U) && ((itsources & RCC_CRS_IT_ERR) != 0U))
786 {
787 if ((itflags & RCC_CRS_FLAG_SYNCERR) != 0U)
788 {
789 crserror |= RCC_CRS_SYNCERR;
790 }
791 if ((itflags & RCC_CRS_FLAG_SYNCMISS) != 0U)
792 {
793 crserror |= RCC_CRS_SYNCMISS;
794 }
795 if ((itflags & RCC_CRS_FLAG_TRIMOVF) != 0U)
796 {
797 crserror |= RCC_CRS_TRIMOVF;
798 }
799
800 /* Clear CRS Error flags */
801 WRITE_REG(CRS->ICR, CRS_ICR_ERRC);
802
803 /* user error callback */
804 HAL_RCCEx_CRS_ErrorCallback(crserror);
805 }
806 }
807 }
808
809 /**
810 * @brief RCCEx Clock Recovery System SYNCOK interrupt callback.
811 * @retval none
812 */
HAL_RCCEx_CRS_SyncOkCallback(void)813 __weak void HAL_RCCEx_CRS_SyncOkCallback(void)
814 {
815 /* NOTE : This function should not be modified, when the callback is needed,
816 the @ref HAL_RCCEx_CRS_SyncOkCallback should be implemented in the user file
817 */
818 }
819
820 /**
821 * @brief RCCEx Clock Recovery System SYNCWARN interrupt callback.
822 * @retval none
823 */
HAL_RCCEx_CRS_SyncWarnCallback(void)824 __weak void HAL_RCCEx_CRS_SyncWarnCallback(void)
825 {
826 /* NOTE : This function should not be modified, when the callback is needed,
827 the @ref HAL_RCCEx_CRS_SyncWarnCallback should be implemented in the user file
828 */
829 }
830
831 /**
832 * @brief RCCEx Clock Recovery System Expected SYNC interrupt callback.
833 * @retval none
834 */
HAL_RCCEx_CRS_ExpectedSyncCallback(void)835 __weak void HAL_RCCEx_CRS_ExpectedSyncCallback(void)
836 {
837 /* NOTE : This function should not be modified, when the callback is needed,
838 the @ref HAL_RCCEx_CRS_ExpectedSyncCallback should be implemented in the user file
839 */
840 }
841
842 /**
843 * @brief RCCEx Clock Recovery System Error interrupt callback.
844 * @param Error Combination of Error status.
845 * This parameter can be a combination of the following values:
846 * @arg @ref RCC_CRS_SYNCERR
847 * @arg @ref RCC_CRS_SYNCMISS
848 * @arg @ref RCC_CRS_TRIMOVF
849 * @retval none
850 */
HAL_RCCEx_CRS_ErrorCallback(uint32_t Error)851 __weak void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error)
852 {
853 /* Prevent unused argument(s) compilation warning */
854 UNUSED(Error);
855
856 /* NOTE : This function should not be modified, when the callback is needed,
857 the @ref HAL_RCCEx_CRS_ErrorCallback should be implemented in the user file
858 */
859 }
860
861 /**
862 * @}
863 */
864
865 #endif /* CRS */
866 /**
867 * @}
868 */
869
870 /**
871 * @}
872 */
873
874 #endif /* HAL_RCC_MODULE_ENABLED */
875 /**
876 * @}
877 */
878
879 /**
880 * @}
881 */
882