1 /**
2 ******************************************************************************
3 * @file stm32wb0x_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 of the RCC extended peripheral:
8 * + Extended Peripheral Control functions
9 * + Extended Clock management functions
10 *
11 ******************************************************************************
12 * @attention
13 *
14 * Copyright (c) 2024 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 "stm32wb0x_hal.h"
26
27 /** @addtogroup STM32WB0x_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
44 #if defined(STM32WB06) || defined(STM32WB07)
45 #define __LSCO1_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
46 #define LSCO1_GPIO_PORT GPIOA
47 #define LSCO1_PIN GPIO_PIN_4
48 #define LSCO1_GPIO_AF GPIO_AF0_LCO
49 #endif
50
51 #define __LSCO2_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
52 #define LSCO2_GPIO_PORT GPIOA
53 #define LSCO2_PIN GPIO_PIN_10
54 #if defined(STM32WB06) || defined(STM32WB07)
55 #define LSCO2_GPIO_AF GPIO_AF0_LCO
56 #endif
57
58 #define __LSCO3_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
59 #define LSCO3_GPIO_PORT GPIOB
60 #define LSCO3_PIN GPIO_PIN_12
61 #define LSCO3_GPIO_AF GPIO_AF1_LCO
62
63 /**
64 * @}
65 */
66
67 /* Private macros ------------------------------------------------------------*/
68 /* Private variables ---------------------------------------------------------*/
69 /* Private function prototypes -----------------------------------------------*/
70 /* Exported functions --------------------------------------------------------*/
71
72 /** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
73 * @{
74 */
75
76 /** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
77 * @brief Extended Peripheral Control functions
78 *
79 @verbatim
80 ===============================================================================
81 ##### Extended Peripheral Control functions #####
82 ===============================================================================
83 [..]
84 This subsection provides a set of functions allowing to control the RCC Clocks
85 frequencies.
86
87 @endverbatim
88 * @{
89 */
90
91 /**
92 * @brief Initialize the RCC extended peripherals clocks according to the specified
93 * parameters in the @ref RCC_PeriphCLKInitTypeDef.
94 * @param PeriphClkInit pointer to a @ref RCC_PeriphCLKInitTypeDef structure that
95 * contains a field PeriphClockSelection which can be a combination of the following values:
96 *
97 * @arg @ref RCC_PERIPHCLK_RF RF peripheral clock
98 * @arg @ref RCC_PERIPHCLK_SMPS SMPS peripheral clock
99 * @arg @ref RCC_PERIPHCLK_SPI2_I2S SPI2 I2S peripheral clock (*)
100 * @arg @ref RCC_PERIPHCLK_SPI3_I2S SPI3 I2S peripheral clock (*)
101 * @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock (*)
102 * @arg @ref RCC_PERIPHCLK_RTC_WDG_BLEWKUP RTC, WDG and BLEWKUP peripheral clock
103 * @note (*) Peripherals are not available on all devices
104 *
105 * @retval HAL status
106 */
HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)107 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
108 {
109 /* Check the parameters */
110 assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
111
112 /*-------------------------- RF_BLE clock source configuration ---------------------*/
113 if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RF) == RCC_PERIPHCLK_RF))
114 {
115 assert_param(IS_RCC_RF_BLE_CLOCK_SOURCE(PeriphClkInit->RFClockSelection));
116 __HAL_RCC_RF_CLK_SET_CONFIG(PeriphClkInit->RFClockSelection);
117 }
118
119 /*-------------------------- SMPS clock configuration -------------------------------*/
120 if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SMPS) == RCC_PERIPHCLK_SMPS))
121 {
122 assert_param(IS_RCC_SMPS_CLOCK_PRESC(PeriphClkInit->SmpsDivSelection));
123 __HAL_RCC_SMPS_DIV_CONFIG(PeriphClkInit->SmpsDivSelection);
124 }
125
126 #if defined(SPI2)
127 /*-------------------------- SPI2_I2S clock source configuration ---------------------*/
128 if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPI2_I2S) == RCC_PERIPHCLK_SPI2_I2S))
129 {
130 assert_param(IS_RCC_SPI2I2S_CLOCK_SOURCE(PeriphClkInit->SPI2I2SClockSelection));
131 __HAL_RCC_SPI2I2S_CLK_CONFIG(PeriphClkInit->SPI2I2SClockSelection);
132 }
133 #endif
134 #if defined(SPI3)
135 /*-------------------------- SPI3_I2S clock source configuration ---------------------*/
136 if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPI3_I2S) == RCC_PERIPHCLK_SPI3_I2S))
137 {
138 assert_param(IS_RCC_SPI3I2S_CLOCK_SOURCE(PeriphClkInit->SPI3I2SClockSelection));
139 __HAL_RCC_SPI3I2S_CLK_CONFIG(PeriphClkInit->SPI3I2SClockSelection);
140 }
141 #endif
142
143 #if defined(RCC_CFGR_LPUCLKSEL)
144 /*-------------------------- LPUART1 clock source configuration ---------------------*/
145 if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1))
146 {
147 assert_param(IS_RCC_LPUART1_CLOCK_SOURCE(PeriphClkInit->LPUART1ClockSelection));
148 __HAL_RCC_LPUART1_CLK_CONFIG(PeriphClkInit->LPUART1ClockSelection);
149 }
150 #endif /* RCC_CFGR_LPUCLKSEL */
151
152 /*-------------------------- RTC WDG BLEWKUP clock source configuration ---------------------*/
153 if ((((PeriphClkInit->RTCWDGBLEWKUPClockSelection) & RCC_PERIPHCLK_RTC_WDG_BLEWKUP) == RCC_PERIPHCLK_RTC_WDG_BLEWKUP))
154 {
155 assert_param(IS_RCC_RTC_WDG_BLEWKUP_CLOCK_SOURCE(PeriphClkInit->RTCWDGBLEWKUPClockSelection));
156 __HAL_RCC_RTC_WDG_BLEWKUP_CLK_CONFIG(PeriphClkInit->RTCWDGBLEWKUPClockSelection);
157 }
158
159 return HAL_OK;
160 }
161
162
163 /**
164 * @brief Get the RCC_ClkInitStruct according to the internal RCC configuration registers.
165 * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
166 * returns the configuration information for the Extended Peripherals
167 * clocks(RF, SMPS, SPI2I2S, SPI3I2S).
168 * @retval None
169 */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)170 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
171 {
172 /* Set all possible values for the extended clock type parameter------------*/
173 PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLOCK_ALL;
174
175 /* Get the SPI clock config --------------------------------------------------*/
176 #if defined(SPI2)
177 /* Get the SPI2 I2S clock config -------------------------------------------*/
178 PeriphClkInit->SPI2I2SClockSelection = __HAL_RCC_GET_SPI2I2S_CLK_CONFIG();
179 #endif
180
181 #if defined(SPI3)
182 /* Get the SPI3 I2S clock source -------------------------------------------*/
183 PeriphClkInit->SPI3I2SClockSelection = __HAL_RCC_GET_SPI3I2S_CLK_CONFIG();
184 #endif
185 /* Get the RF clock config -------------------------------------------------*/
186 PeriphClkInit->RFClockSelection = __HAL_RCC_RF_CLK_GET_CONFIG();
187
188 #if defined(RCC_CFGR_LPUCLKSEL)
189 PeriphClkInit->LPUART1ClockSelection = __HAL_RCC_GET_LPUART1_CLK_CONFIG();
190 #endif /* RCC_CFGR_LPUCLKSEL */
191
192 /* Get the SMPS clock divider ------------------------------------------------*/
193 PeriphClkInit->SmpsDivSelection = __HAL_RCC_GET_SMPS_DIV();
194
195 /* Get RTC, WDG and BLEWKUP clock */
196 PeriphClkInit->RTCWDGBLEWKUPClockSelection = __HAL_RCC_GET_RTC_WDG_BLEWKUP_CLK_CONFIG();
197 }
198
199 /**
200 * @brief Return the peripheral clock frequency for peripherals with clock source
201 * @note Return 0 if peripheral clock identifier not managed by this API
202 * @param PeriphClk Peripheral clock identifier
203 * This parameter can be one of the following values:
204 * @arg @ref RCC_PERIPHCLK_RF RF peripheral clock
205 * @arg @ref RCC_PERIPHCLK_SMPS SMPS peripheral clock
206 * @arg @ref RCC_PERIPHCLK_SPI2_I2S SPI2 I2S peripheral clock (*)
207 * @arg @ref RCC_PERIPHCLK_SPI3_I2S SPI3 I2S peripheral clock (*)
208 * @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock (*)
209 * @arg @ref RCC_PERIPHCLK_RTC_WDG_BLEWKUP RTC, WDG and BLEWKUP peripheral clock
210 * @retval Frequency in Hz
211 * @note (*) Peripherals are not available on all devices
212 */
HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)213 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
214 {
215 uint32_t frequency, spiFreqValue;
216
217 /* Check the parameters */
218 assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
219
220 /* No if clausule is covered */
221 frequency = 0;
222
223 switch (PeriphClk)
224 {
225 case RCC_PERIPHCLK_RF :
226 switch (__HAL_RCC_RF_CLK_GET_CONFIG())
227 {
228 case RCC_RF_CLK_32M:
229 frequency = HSE_VALUE;
230 break;
231 case RCC_RF_CLK_16M:
232 frequency = HSE_VALUE / 2;
233 break;
234 }
235
236 break;
237
238 case RCC_PERIPHCLK_SMPS :
239 switch (__HAL_RCC_GET_SMPS_DIV())
240 {
241 case RCC_SMPSCLK_DIV2:
242 frequency = HSE_VALUE / 4;
243 break;
244 case RCC_SMPSCLK_DIV4:
245 frequency = HSE_VALUE / 8;
246 break;
247 }
248 break;
249
250 #if defined(SPI2)
251 case RCC_PERIPHCLK_SPI2_I2S :
252 if (__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_DIRECT_HSE)
253 {
254 if (__HAL_RCC_GET_HSE_READYFLAG() == 0)
255 {
256 return 0;
257 }
258 }
259 else
260 {
261 if (__HAL_RCC_RC64MPLL_READYFLAG() == 0)
262 {
263 return 0;
264 }
265 }
266 if (__HAL_RCC_GET_SPI2I2S_CLK_CONFIG() == RCC_SPI2I2S_CLKSOURCE_16M)
267 {
268 frequency = HSE_VALUE / 2;
269 }
270 else
271 {
272 frequency = HSE_VALUE;
273 }
274 break;
275 #endif
276
277 case RCC_PERIPHCLK_SPI3_I2S :
278 if (__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_DIRECT_HSE)
279 {
280 if (__HAL_RCC_GET_HSE_READYFLAG() == 0)
281 {
282 return 0;
283 }
284 }
285 else
286 {
287 if (__HAL_RCC_RC64MPLL_READYFLAG() == 0)
288 {
289 return 0;
290 }
291 }
292 spiFreqValue = __HAL_RCC_GET_SPI3I2S_CLK_CONFIG();
293 if (spiFreqValue == RCC_SPI3I2S_CLKSOURCE_16M)
294 {
295 frequency = HSE_VALUE / 2;
296 }
297
298 if (spiFreqValue == RCC_SPI3I2S_CLKSOURCE_32M)
299 {
300 frequency = HSE_VALUE;
301 }
302 #if defined(RCC_SPI3I2S_CLKSOURCE_64M)
303 if (spiFreqValue == RCC_SPI3I2S_CLKSOURCE_64M)
304 {
305 frequency = HSE_VALUE * 2;
306 }
307 #endif
308 break;
309
310 #if defined(RCC_CFGR_LPUCLKSEL)
311 case RCC_PERIPHCLK_LPUART1 :
312 switch (__HAL_RCC_GET_LPUART1_CLK_CONFIG())
313 {
314 case RCC_LPUART1_CLKSOURCE_LSE:
315 frequency = LSE_VALUE;
316 break;
317 case RCC_LPUART1_CLKSOURCE_16M:
318 default:
319 frequency = HSE_VALUE / 2;
320 break;
321 }
322 break;
323 #endif /* RCC_CFGR_LPUCLKSEL */
324
325 case RCC_PERIPHCLK_RTC_WDG_BLEWKUP :
326 switch (LL_RCC_LSCO_GetSource())
327 {
328 case LL_RCC_LSCO_CLKSOURCE_LSE :
329 frequency = LSE_VALUE;
330 break;
331 case LL_RCC_LSCO_CLKSOURCE_LSI :
332 frequency = LSI_VALUE;
333 break;
334 case LL_RCC_LSCO_CLKSOURCE_HSI64M_DIV2048:
335 frequency = HSE_VALUE >> 10;
336 break;
337 default :
338 break;
339 }
340 break;
341 default :
342 break;
343 }
344
345 return (frequency);
346 }
347
348 /**
349 * @}
350 */
351
352 /** @defgroup RCCEx_Exported_Functions_Group2 Extended Clock management functions
353 * @brief Extended Clock management functions
354 *
355 @verbatim
356 ===============================================================================
357 ##### Extended clock management functions #####
358 ===============================================================================
359 [..]
360 This subsection provides a set of functions allowing to control the
361 activation or deactivation Low speed clock output.
362 @endverbatim
363 * @{
364 */
365
366 /**
367 * @brief Select the clock source to output on LSCO1 pin(PA4) or LSC02 pin (PA10) or LSCO3 pin (PB12).
368 * @note PA4, PA10 or PB12 should be configured in alternate function mode.
369 * @param RCC_LSCOx specifies the output direction for the clock source.
370 * @arg @ref RCC_LSCO1 Clock source to output on LSCO1 pin(PA4)
371 * @arg @ref RCC_LSCO2 Clock source to output on LSCO2 pin(PA10)
372 * @arg @ref RCC_LSCO3 Clock source to output on LSCO3 pin(PB12)
373 * @param RCC_LSCOSource specifies the clock source to output.
374 * This parameter can be one of the following values:
375 * @arg @ref RCC_LSCOSOURCE_LSI LSI clock selected as LSCO source
376 * @arg @ref RCC_LSCOSOURCE_LSE LSE clock selected as LSCO source
377 * @retval None
378 * @note LSCO should be disable with @ref HAL_RCCEx_DisableLSCO
379 */
HAL_RCCEx_EnableLSCO(uint32_t RCC_LSCOx,uint32_t RCC_LSCOSource)380 void HAL_RCCEx_EnableLSCO(uint32_t RCC_LSCOx, uint32_t RCC_LSCOSource)
381 {
382 GPIO_InitTypeDef GPIO_InitStruct;
383
384 /* Check the parameters */
385 assert_param(IS_RCC_LSCO(RCC_LSCOx));
386 assert_param(IS_RCC_LSCOSOURCE(RCC_LSCOSource));
387
388 /* Common GPIO init parameters */
389 if (RCC_LSCOSource == RCC_LSCOSOURCE_NOCLOCK)
390 {
391 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
392 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
393 }
394 else
395 {
396 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
397 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
398 }
399 GPIO_InitStruct.Pull = GPIO_NOPULL;
400
401 #if defined(LSCO1_PIN)
402 if (RCC_LSCOx == RCC_LSCO1)
403 {
404 /* LSCO1 Clock Enable */
405 __LSCO1_CLK_ENABLE();
406 /* Configure the LSCO1 pin in alternate function mode */
407 GPIO_InitStruct.Pin = LSCO1_PIN;
408 GPIO_InitStruct.Alternate = LSCO1_GPIO_AF;
409 HAL_GPIO_Init(LSCO1_GPIO_PORT, &GPIO_InitStruct);
410 }
411 #endif
412
413 if (RCC_LSCOx == RCC_LSCO2)
414 {
415 /* LSCO2 Clock Enable */
416 __LSCO2_CLK_ENABLE();
417 /* Configure the LSCO2 pin in alternate function mode */
418 GPIO_InitStruct.Pin = LSCO2_PIN;
419 #if defined(STM32WB06) || defined(STM32WB07)
420 GPIO_InitStruct.Alternate = LSCO2_GPIO_AF;
421 #endif
422 HAL_GPIO_Init(LSCO2_GPIO_PORT, &GPIO_InitStruct);
423 }
424
425 if (RCC_LSCOx == RCC_LSCO3)
426 {
427 /* LSCO3 Clock Enable */
428 __LSCO3_CLK_ENABLE();
429 /* Configure the LSCO3 pin in alternate function mode */
430 GPIO_InitStruct.Pin = LSCO3_PIN;
431 GPIO_InitStruct.Alternate = LSCO3_GPIO_AF;
432 HAL_GPIO_Init(LSCO3_GPIO_PORT, &GPIO_InitStruct);
433 }
434
435 /* Configure the clock source to output */
436 LL_RCC_ConfigLSCO(RCC_LSCOSource);
437 }
438
439
440 /**
441 * @brief Enable the Low Speed clock source to output on LSCO pin during STANDBY with retention.
442 * It is applicable only for LSCO2
443 * @param LSCOSource specifies the Low Speed clock source to output.
444 * This parameter can be one of the following values:
445 * @arg @ref RCC_LSCOSOURCE_NOCLOCK Internal LPMU slow clock source selected as LSCO source
446 * @arg @ref RCC_LSCOSOURCE_LSI LSI clock selected as LSCO source
447 * @arg @ref RCC_LSCOSOURCE_LSE LSE clock selected as LSCO source
448 * @retval None
449 */
HAL_RCCEx_EnableLSCOinDEEPSTOP(uint32_t LSCOSource)450 void HAL_RCCEx_EnableLSCOinDEEPSTOP(uint32_t LSCOSource)
451 {
452 GPIO_InitTypeDef GPIO_InitStruct;
453
454 /* Check the parameters */
455 assert_param(IS_RCC_LSCOSOURCE(LSCOSource));
456
457 /* LSCO Pin Clock Enable */
458 __LSCO2_CLK_ENABLE();
459
460 /* Configure the LSCO pin in alternate function mode */
461 GPIO_InitStruct.Pin = LSCO2_PIN;
462 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
463 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
464 GPIO_InitStruct.Pull = GPIO_NOPULL;
465 #if defined(STM32WB06) || defined(STM32WB07)
466 GPIO_InitStruct.Alternate = LSCO2_GPIO_AF;
467 #endif
468 HAL_GPIO_Init(LSCO2_GPIO_PORT, &GPIO_InitStruct);
469
470 /* Enable the LSCO2 pin during STANDBY with retention */
471 #if defined(RCC_CFGR_LCOEN)
472 LL_RCC_LSCOinDeepStop_Enable();
473 #endif
474 /* Configure the clock source to output */
475 LL_RCC_ConfigLSCO(LSCOSource);
476 }
477
478 /**
479 * @brief Disable the Low Speed clock output.
480 * @retval None
481 */
HAL_RCCEx_DisableLSCO(void)482 void HAL_RCCEx_DisableLSCO(void)
483 {
484 #if defined(RCC_CFGR_LCOEN)
485 LL_RCC_LSCOinDeepStop_Disable();
486 #endif
487 LL_RCC_ConfigLSCO(LL_RCC_LSCOSOURCE_NOCLOCK);
488
489 }
490
491
492 /**
493 * @}
494 */
495
496
497 /**
498 * @}
499 */
500
501 #endif /* HAL_RCC_MODULE_ENABLED */
502
503 /**
504 * @}
505 */
506
507 /**
508 * @}
509 */
510