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 * @note Care must be taken when @ref HAL_RCCEx_PeriphCLKConfig() is used to select
88 * the RTC clock source: in this case the access to RTC domain is enabled.
89 *
90 * @retval HAL status
91 */
HAL_RCCEx_PeriphCLKConfig(const RCC_PeriphCLKInitTypeDef * PeriphClkInit)92 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(const RCC_PeriphCLKInitTypeDef *PeriphClkInit)
93 {
94 uint32_t tmpregister;
95 uint32_t tickstart;
96 HAL_StatusTypeDef ret = HAL_OK; /* Intermediate status */
97 HAL_StatusTypeDef status = HAL_OK; /* Final status */
98
99 /* Check the parameters */
100 assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
101
102 /*-------------------------- RTC clock source configuration ----------------------*/
103 if ((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
104 {
105 FlagStatus pwrclkchanged = RESET;
106
107 /* Check for RTC Parameters used to output RTCCLK */
108 assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
109
110 /* Enable Power Clock */
111 if (__HAL_RCC_PWR_IS_CLK_DISABLED())
112 {
113 __HAL_RCC_PWR_CLK_ENABLE();
114 pwrclkchanged = SET;
115 }
116
117
118 /* Reset the RTC domain only if the RTC Clock source selection is modified from default */
119 tmpregister = READ_BIT(RCC->CSR1, RCC_CSR1_RTCSEL);
120
121 /* Reset the RTC domain only if the RTC Clock source selection is modified */
122 if ((tmpregister != RCC_RTCCLKSOURCE_NONE) && (tmpregister != PeriphClkInit->RTCClockSelection))
123 {
124 /* Store the content of CSR1 register before the reset of RTC Domain */
125 tmpregister = READ_BIT(RCC->CSR1, ~(RCC_CSR1_RTCSEL));
126 /* RTC Clock selection can be changed only if the RTC Domain is reset */
127 __HAL_RCC_BACKUPRESET_FORCE();
128 __HAL_RCC_BACKUPRESET_RELEASE();
129 /* Restore the Content of CSR1 register */
130 RCC->CSR1 = tmpregister;
131 }
132
133 /* Wait for LSE reactivation if LSE was enable prior to RTC Domain reset */
134 if (HAL_IS_BIT_SET(tmpregister, RCC_CSR1_LSEON))
135 {
136 /* Get Start Tick*/
137 tickstart = HAL_GetTick();
138
139 /* Wait till LSE is ready */
140 while (READ_BIT(RCC->CSR1, RCC_CSR1_LSERDY) == 0U)
141 {
142 if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
143 {
144 ret = HAL_TIMEOUT;
145 break;
146 }
147 }
148 }
149
150 if (ret == HAL_OK)
151 {
152 /* Apply new RTC clock source selection */
153 __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
154 }
155 else
156 {
157 /* set overall return value */
158 status = ret;
159 }
160
161 /* Restore clock configuration if changed */
162 if (pwrclkchanged == SET)
163 {
164 __HAL_RCC_PWR_CLK_DISABLE();
165 }
166 }
167
168 /*-------------------------- USART1 clock source configuration -------------------*/
169 if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1)
170 {
171 /* Check the parameters */
172 assert_param(IS_RCC_USART1CLKSOURCE(PeriphClkInit->Usart1ClockSelection));
173
174 /* Configure the USART1 clock source */
175 __HAL_RCC_USART1_CONFIG(PeriphClkInit->Usart1ClockSelection);
176 }
177
178 /*-------------------------- I2C1 clock source configuration ---------------------*/
179 if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1)
180 {
181 /* Check the parameters */
182 assert_param(IS_RCC_I2C1CLKSOURCE(PeriphClkInit->I2c1ClockSelection));
183
184 /* Configure the I2C1 clock source */
185 __HAL_RCC_I2C1_CONFIG(PeriphClkInit->I2c1ClockSelection);
186 }
187
188 /*-------------------------- ADC clock source configuration ----------------------*/
189 if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC)
190 {
191 /* Check the parameters */
192 assert_param(IS_RCC_ADCCLKSOURCE(PeriphClkInit->AdcClockSelection));
193
194 /* Configure the ADC interface clock source */
195 __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection);
196
197 }
198
199 /*-------------------------- I2S1 clock source configuration ---------------------*/
200 if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S1) == RCC_PERIPHCLK_I2S1)
201 {
202 /* Check the parameters */
203 assert_param(IS_RCC_I2S1CLKSOURCE(PeriphClkInit->I2s1ClockSelection));
204
205 /* Configure the I2S1 clock source */
206 __HAL_RCC_I2S1_CONFIG(PeriphClkInit->I2s1ClockSelection);
207 }
208 /*------------------------------------ HSI Kernel clock source configuration --------------------------------------*/
209 if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_HSIKER) == RCC_PERIPHCLK_HSIKER)
210 {
211 /* Check the parameters */
212 assert_param(IS_RCC_HSIKERDIV(PeriphClkInit->HSIKerClockDivider));
213
214 /* Configure the HSI Kernel clock source Divider */
215 __HAL_RCC_HSIKER_CONFIG(PeriphClkInit->HSIKerClockDivider);
216 }
217 return status;
218 }
219
220 /**
221 * @brief Get the RCC_ClkInitStruct according to the internal RCC configuration registers.
222 * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
223 * returns the configuration information for the Extended Peripherals
224 * clocks: I2C1, I2S1, USART1, RTC, ADC,
225 * @retval None
226 */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)227 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
228 {
229 /* Set all possible values for the extended clock type parameter------------*/
230 PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2S1 | \
231 RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_HSIKER ;
232
233
234 /* Get the USART1 clock source ---------------------------------------------*/
235 PeriphClkInit->Usart1ClockSelection = __HAL_RCC_GET_USART1_SOURCE();
236
237 /* Get the I2C1 clock source -----------------------------------------------*/
238 PeriphClkInit->I2c1ClockSelection = __HAL_RCC_GET_I2C1_SOURCE();
239
240 /* Get the RTC clock source ------------------------------------------------*/
241 PeriphClkInit->RTCClockSelection = __HAL_RCC_GET_RTC_SOURCE();
242
243 /* Get the ADC clock source -----------------------------------------------*/
244 PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE();
245
246 /* Get the I2S1 clock source -----------------------------------------------*/
247 PeriphClkInit->I2s1ClockSelection = __HAL_RCC_GET_I2S1_SOURCE();
248
249 /* Get the HSI Kernel clock divider -----------------------------------------------*/
250 PeriphClkInit->HSIKerClockDivider = __HAL_RCC_GET_HSIKER_DIVIDER();
251 }
252
253 /**
254 * @brief Return the peripheral clock frequency for peripherals
255 * @note Return 0 if peripheral clock identifier not managed by this API
256 * @param PeriphClk Peripheral clock identifier
257 * This parameter can be one of the following values:
258 * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
259 * @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock
260 * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock
261 * @arg @ref RCC_PERIPHCLK_I2S1 I2S1 peripheral clock
262 * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock
263 * @retval Frequency in Hz
264 */
HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)265 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
266 {
267 uint32_t frequency = 0U;
268 uint32_t srcclk;
269
270 /* Check the parameters */
271 assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
272
273 if (PeriphClk == RCC_PERIPHCLK_RTC)
274 {
275 /* Get the current RTC source */
276 srcclk = __HAL_RCC_GET_RTC_SOURCE();
277
278 /* Check if LSE is ready and if RTC clock selection is LSE */
279 if ((HAL_IS_BIT_SET(RCC->CSR1, RCC_CSR1_LSERDY)) && (srcclk == RCC_RTCCLKSOURCE_LSE))
280 {
281 frequency = LSE_VALUE;
282 }
283 /* Check if LSI is ready and if RTC clock selection is LSI */
284 else if ((HAL_IS_BIT_SET(RCC->CSR2, RCC_CSR2_LSIRDY)) && (srcclk == RCC_RTCCLKSOURCE_LSI))
285 {
286 frequency = LSI_VALUE;
287 }
288 /* Check if HSE is ready and if RTC clock selection is HSI_DIV32*/
289 else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) && (srcclk == RCC_RTCCLKSOURCE_HSE_DIV32))
290 {
291 frequency = HSE_VALUE / 32U;
292 }
293 /* Clock not enabled for RTC*/
294 else
295 {
296 /* Nothing to do as frequency already initialized to 0U */
297 }
298 }
299 else
300 {
301 /* Other external peripheral clock source than RTC */
302
303 switch (PeriphClk)
304 {
305
306 case RCC_PERIPHCLK_USART1:
307 /* Get the current USART1 source */
308 srcclk = __HAL_RCC_GET_USART1_SOURCE();
309
310 if (srcclk == RCC_USART1CLKSOURCE_PCLK1) /* PCLK1 */
311 {
312 frequency = HAL_RCC_GetPCLK1Freq();
313 }
314 else if (srcclk == RCC_USART1CLKSOURCE_SYSCLK) /* SYSCLK */
315 {
316 frequency = HAL_RCC_GetSysClockFreq();
317 }
318 else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (srcclk == RCC_USART1CLKSOURCE_HSIKER))
319 {
320 frequency = (HSI_VALUE / ((__HAL_RCC_GET_HSIKER_DIVIDER() >> RCC_CR_HSIKERDIV_Pos) + 1U));
321 }
322 else if ((HAL_IS_BIT_SET(RCC->CSR1, RCC_CSR1_LSERDY)) && (srcclk == RCC_USART1CLKSOURCE_LSE))
323 {
324 frequency = LSE_VALUE;
325 }
326 /* Clock not enabled for USART1 */
327 else
328 {
329 /* Nothing to do as frequency already initialized to 0U */
330 }
331 break;
332
333 case RCC_PERIPHCLK_ADC:
334
335 srcclk = __HAL_RCC_GET_ADC_SOURCE();
336
337 if (srcclk == RCC_ADCCLKSOURCE_SYSCLK)
338 {
339 frequency = HAL_RCC_GetSysClockFreq();
340 }
341 else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (srcclk == RCC_ADCCLKSOURCE_HSIKER))
342 {
343 frequency = (HSI_VALUE / ((__HAL_RCC_GET_HSIKER_DIVIDER() >> RCC_CR_HSIKERDIV_Pos) + 1U));
344 }
345 /* Clock not enabled for ADC */
346 else
347 {
348 /* Nothing to do as frequency already initialized to 0U */
349 }
350 break;
351
352 case RCC_PERIPHCLK_I2C1:
353 /* Get the current I2C1 source */
354 srcclk = __HAL_RCC_GET_I2C1_SOURCE();
355
356 if (srcclk == RCC_I2C1CLKSOURCE_PCLK1)
357 {
358 frequency = HAL_RCC_GetPCLK1Freq();
359 }
360 else if (srcclk == RCC_I2C1CLKSOURCE_SYSCLK)
361 {
362 frequency = HAL_RCC_GetSysClockFreq();
363 }
364 else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (srcclk == RCC_I2C1CLKSOURCE_HSIKER))
365 {
366 frequency = (HSI_VALUE / ((__HAL_RCC_GET_HSIKER_DIVIDER() >> RCC_CR_HSIKERDIV_Pos) + 1U));
367 }
368 /* Clock not enabled for I2C1 */
369 else
370 {
371 /* Nothing to do as frequency already initialized to 0U */
372 }
373 break;
374
375 case RCC_PERIPHCLK_I2S1:
376 /* Get the current I2S1 source */
377 srcclk = __HAL_RCC_GET_I2S1_SOURCE();
378
379 if (srcclk == RCC_I2S1CLKSOURCE_SYSCLK)
380 {
381 frequency = HAL_RCC_GetSysClockFreq();
382 }
383 else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (srcclk == RCC_I2S1CLKSOURCE_HSIKER))
384 {
385 frequency = (HSI_VALUE / ((__HAL_RCC_GET_HSIKER_DIVIDER() >> RCC_CR_HSIKERDIV_Pos) + 1U));
386 }
387 else if (srcclk == RCC_I2S1CLKSOURCE_EXT)
388 {
389 /* External clock used.*/
390 frequency = EXTERNAL_I2S1_CLOCK_VALUE;
391 }
392 /* Clock not enabled for I2S1 */
393 else
394 {
395 /* Nothing to do as frequency already initialized to 0U */
396 }
397 break;
398
399 default:
400 break;
401 }
402 }
403
404 return (frequency);
405 }
406
407 /**
408 * @}
409 */
410
411 /** @defgroup RCCEx_Exported_Functions_Group2 Extended Clock management functions
412 * @brief Extended Clock management functions
413 *
414 @verbatim
415 ===============================================================================
416 ##### Extended clock management functions #####
417 ===============================================================================
418 [..]
419 This subsection provides a set of functions allowing to control the
420 activation or deactivation of LSE CSS, Low speed clock output and
421 clock after wake-up from STOP mode.
422 @endverbatim
423 * @{
424 */
425
426 /**
427 * @brief Select the Low Speed clock source to output on LSCO pin (PA2).
428 * @param LSCOSource specifies the Low Speed clock source to output.
429 * This parameter can be one of the following values:
430 * @arg @ref RCC_LSCOSOURCE_LSI LSI clock selected as LSCO source
431 * @arg @ref RCC_LSCOSOURCE_LSE LSE clock selected as LSCO source
432 * @retval None
433 */
HAL_RCCEx_EnableLSCO(uint32_t LSCOSource)434 void HAL_RCCEx_EnableLSCO(uint32_t LSCOSource)
435 {
436 GPIO_InitTypeDef GPIO_InitStruct;
437
438 /* Check the parameters */
439 assert_param(IS_RCC_LSCOSOURCE(LSCOSource));
440
441 /* LSCO Pin Clock Enable */
442 LSCO_CLK_ENABLE();
443
444 /* configure the LSCO pin in analog mode */
445 GPIO_InitStruct.Pin = LSCO_PIN;
446 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
447 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
448 GPIO_InitStruct.Pull = GPIO_NOPULL;
449 HAL_GPIO_Init(LSCO_GPIO_PORT, &GPIO_InitStruct);
450
451 MODIFY_REG(RCC->CSR1, RCC_CSR1_LSCOSEL | RCC_CSR1_LSCOEN, LSCOSource | RCC_CSR1_LSCOEN);
452
453 }
454
455 /**
456 * @brief Disable the Low Speed clock output.
457 * @retval None
458 */
HAL_RCCEx_DisableLSCO(void)459 void HAL_RCCEx_DisableLSCO(void)
460 {
461
462 CLEAR_BIT(RCC->CSR1, RCC_CSR1_LSCOEN);
463
464 }
465
466 /**
467 * @}
468 */
469
470
471 /**
472 * @}
473 */
474
475 /**
476 * @}
477 */
478
479 #endif /* HAL_RCC_MODULE_ENABLED */
480 /**
481 * @}
482 */
483
484 /**
485 * @}
486 */
487