1 /**
2   ******************************************************************************
3   * @file    stm32f2xx_hal_rcc_ex.c
4   * @author  MCD Application Team
5   * @brief   Extension RCC HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities RCC extension peripheral:
8   *           + Extended Peripheral Control functions
9   *
10   ******************************************************************************
11   * @attention
12   *
13   * Copyright (c) 2017 STMicroelectronics.
14   * All rights reserved.
15   *
16   * This software is licensed under terms that can be found in the LICENSE file in
17   * the root directory of this software component.
18   * If no LICENSE file comes with this software, it is provided AS-IS.
19   *
20   ******************************************************************************
21   */
22 
23 /* Includes ------------------------------------------------------------------*/
24 #include "stm32f2xx_hal.h"
25 
26 /** @addtogroup STM32F2xx_HAL_Driver
27   * @{
28   */
29 
30 /** @defgroup RCCEx RCCEx
31   * @brief RCCEx HAL module driver
32   * @{
33   */
34 
35 #ifdef HAL_RCC_MODULE_ENABLED
36 
37 /* Private typedef -----------------------------------------------------------*/
38 /* Private define ------------------------------------------------------------*/
39 /** @addtogroup RCCEx_Private_Constants
40   * @{
41   */
42 /**
43   * @}
44   */
45 /* Private macro -------------------------------------------------------------*/
46 /* Private variables ---------------------------------------------------------*/
47 /* Private function prototypes -----------------------------------------------*/
48 /* Private functions ---------------------------------------------------------*/
49 /** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
50   *  @{
51   */
52 
53 /** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
54  *  @brief  Extended Peripheral Control functions
55  *
56 @verbatim
57  ===============================================================================
58                 ##### Extended Peripheral Control functions  #####
59  ===============================================================================
60     [..]
61     This subsection provides a set of functions allowing to control the RCC Clocks
62     frequencies.
63     [..]
64     (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
65         select the RTC clock source; in this case the Backup domain will be reset in
66         order to modify the RTC Clock source, as consequence RTC registers (including
67         the backup registers) and RCC_BDCR register are set to their reset values.
68 
69 @endverbatim
70   * @{
71   */
72 
73 /**
74   * @brief  Initializes the RCC extended peripherals clocks according to the specified parameters in the
75   *         RCC_PeriphCLKInitTypeDef.
76   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
77   *         contains the configuration information for the Extended Peripherals clocks(I2S and RTC clocks).
78   *
79   * @note   A caution to be taken when HAL_RCCEx_PeriphCLKConfig() is used to select RTC clock selection, in this case
80   *         the Reset of Backup domain will be applied in order to modify the RTC Clock source as consequence all backup
81   *        domain (RTC and RCC_BDCR register expect BKPSRAM) will be reset
82   *
83   * @retval HAL status
84   */
HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)85 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
86 {
87   uint32_t tickstart = 0U;
88   uint32_t tmpreg1 = 0U;
89 
90   /* Check the parameters */
91   assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
92 
93   /*---------------------------- I2S configuration ---------------------------*/
94   if(((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_I2S) == (RCC_PERIPHCLK_I2S))|| \
95      (PeriphClkInit->PeriphClockSelection == RCC_PERIPHCLK_PLLI2S))
96   {
97     /* check for Parameters */
98     assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
99     assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));
100 
101     /* Disable the PLLI2S */
102     __HAL_RCC_PLLI2S_DISABLE();
103     /* Get tick */
104     tickstart = HAL_GetTick();
105     /* Wait till PLLI2S is disabled */
106     while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
107     {
108       if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
109       {
110         /* return in case of Timeout detected */
111         return HAL_TIMEOUT;
112       }
113     }
114     /* Configure the PLLI2S division factors */
115     /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLM) */
116     /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
117     __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SR);
118 
119     /* Enable the PLLI2S */
120     __HAL_RCC_PLLI2S_ENABLE();
121     /* Get tick */
122     tickstart = HAL_GetTick();
123     /* Wait till PLLI2S is ready */
124     while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
125     {
126       if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
127       {
128         /* return in case of Timeout detected */
129         return HAL_TIMEOUT;
130       }
131     }
132   }
133   /*--------------------------------------------------------------------------*/
134 
135   /*---------------------------- RTC configuration ---------------------------*/
136   if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
137   {
138     /* Check for RTC Parameters used to output RTCCLK */
139     assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
140 
141     /* Enable Power Clock*/
142     __HAL_RCC_PWR_CLK_ENABLE();
143 
144     /* Enable write access to Backup domain */
145     PWR->CR |= PWR_CR_DBP;
146 
147     /* Get tick */
148     tickstart = HAL_GetTick();
149 
150     while((PWR->CR & PWR_CR_DBP) == RESET)
151     {
152       if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
153       {
154         return HAL_TIMEOUT;
155       }
156     }
157     /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
158     tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
159     if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
160     {
161       /* Store the content of BDCR register before the reset of Backup Domain */
162       tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
163       /* RTC Clock selection can be changed only if the Backup Domain is reset */
164       __HAL_RCC_BACKUPRESET_FORCE();
165       __HAL_RCC_BACKUPRESET_RELEASE();
166       /* Restore the Content of BDCR register */
167       RCC->BDCR = tmpreg1;
168 
169       /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
170       if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
171       {
172         /* Get tick */
173         tickstart = HAL_GetTick();
174 
175         /* Wait till LSE is ready */
176         while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
177         {
178           if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
179           {
180             return HAL_TIMEOUT;
181           }
182         }
183       }
184     }
185     __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
186   }
187   /*--------------------------------------------------------------------------*/
188 
189   return HAL_OK;
190 }
191 
192 /**
193   * @brief  Configures the RCC_OscInitStruct according to the internal
194   * RCC configuration registers.
195   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
196   * will be configured.
197   * @retval None
198   */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)199 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
200 {
201   uint32_t tempreg;
202 
203   /* Set all possible values for the extended clock type parameter------------*/
204   PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S | RCC_PERIPHCLK_RTC;
205 
206   /* Get the PLLI2S Clock configuration --------------------------------------*/
207   PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SN));
208   PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR));
209 
210   /* Get the RTC Clock configuration -----------------------------------------------*/
211   tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
212   PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));
213 
214 }
215 /**
216   * @}
217   */
218 
219 /** @defgroup RCCEx_Exported_Functions_Group2 Extended Clock management functions
220  *  @brief  Extended Clock management functions
221  *
222 @verbatim
223  ===============================================================================
224                 ##### Extended clock management functions  #####
225  ===============================================================================
226     [..]
227     This subsection provides a set of functions allowing to control the
228     activation or deactivation of PLLI2S.
229 @endverbatim
230   * @{
231   */
232 
233 /**
234   * @brief  Enable PLLI2S.
235   * @param  PLLI2SInit  pointer to an RCC_PLLI2SInitTypeDef structure that
236   *         contains the configuration information for the PLLI2S
237   * @retval HAL status
238   */
HAL_RCCEx_EnablePLLI2S(RCC_PLLI2SInitTypeDef * PLLI2SInit)239 HAL_StatusTypeDef HAL_RCCEx_EnablePLLI2S(RCC_PLLI2SInitTypeDef  *PLLI2SInit)
240 {
241   uint32_t tickstart;
242 
243   /* Check for parameters */
244   assert_param(IS_RCC_PLLI2SN_VALUE(PLLI2SInit->PLLI2SN));
245   assert_param(IS_RCC_PLLI2SR_VALUE(PLLI2SInit->PLLI2SR));
246 
247   /* Disable the PLLI2S */
248   __HAL_RCC_PLLI2S_DISABLE();
249 
250   /* Wait till PLLI2S is disabled */
251   tickstart = HAL_GetTick();
252   while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET)
253   {
254     if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
255     {
256       /* return in case of Timeout detected */
257       return HAL_TIMEOUT;
258     }
259   }
260 
261   /* Configure the PLLI2S division factors */
262   /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) x PLLI2SN */
263   /* I2SRCLK = PLLI2S_VCO / PLLI2SR */
264   __HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SN, PLLI2SInit->PLLI2SR);
265 
266   /* Enable the PLLI2S */
267   __HAL_RCC_PLLI2S_ENABLE();
268 
269   /* Wait till PLLI2S is ready */
270   tickstart = HAL_GetTick();
271   while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET)
272   {
273     if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
274     {
275       /* return in case of Timeout detected */
276       return HAL_TIMEOUT;
277     }
278   }
279 
280  return HAL_OK;
281 }
282 
283 /**
284   * @brief  Disable PLLI2S.
285   * @retval HAL status
286   */
HAL_RCCEx_DisablePLLI2S(void)287 HAL_StatusTypeDef HAL_RCCEx_DisablePLLI2S(void)
288 {
289   uint32_t tickstart;
290 
291   /* Disable the PLLI2S */
292   __HAL_RCC_PLLI2S_DISABLE();
293 
294   /* Wait till PLLI2S is disabled */
295   tickstart = HAL_GetTick();
296   while(READ_BIT(RCC->CR, RCC_CR_PLLI2SRDY) != RESET)
297   {
298     if((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
299     {
300       /* return in case of Timeout detected */
301       return HAL_TIMEOUT;
302     }
303   }
304 
305   return HAL_OK;
306 }
307 
308 /**
309   * @}
310   */
311 
312 /**
313   * @}
314   */
315 
316 #endif /* HAL_RCC_MODULE_ENABLED */
317 /**
318   * @}
319   */
320 
321 /**
322   * @}
323   */
324 
325