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