2 ******************************************************************************
\r
3 * @file stm32l1xx_hal_rcc_ex.c
\r
4 * @author MCD Application Team
\r
5 * @brief Extended RCC HAL module driver.
\r
6 * This file provides firmware functions to manage the following
\r
7 * functionalities RCC extension peripheral:
\r
8 * + Extended Peripheral Control functions
\r
10 ******************************************************************************
\r
13 * <h2><center>© Copyright(c) 2017 STMicroelectronics.
\r
14 * All rights reserved.</center></h2>
\r
16 * This software component is licensed by ST under BSD 3-Clause license,
\r
17 * the "License"; You may not use this file except in compliance with the
\r
18 * License. You may obtain a copy of the License at:
\r
19 * opensource.org/licenses/BSD-3-Clause
\r
21 ******************************************************************************
\r
24 /* Includes ------------------------------------------------------------------*/
\r
25 #include "stm32l1xx_hal.h"
\r
27 /** @addtogroup STM32L1xx_HAL_Driver
\r
31 #ifdef HAL_RCC_MODULE_ENABLED
\r
33 /** @defgroup RCCEx RCCEx
\r
34 * @brief RCC Extension HAL module driver
\r
38 /* Private typedef -----------------------------------------------------------*/
\r
39 /* Private define ------------------------------------------------------------*/
\r
40 /** @defgroup RCCEx_Private_Constants RCCEx Private Constants
\r
47 /* Private macro -------------------------------------------------------------*/
\r
48 /** @defgroup RCCEx_Private_Macros RCCEx Private Macros
\r
55 /* Private variables ---------------------------------------------------------*/
\r
56 /* Private function prototypes -----------------------------------------------*/
\r
57 /* Private functions ---------------------------------------------------------*/
\r
59 /** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
\r
63 /** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
\r
64 * @brief Extended Peripheral Control functions
\r
67 ===============================================================================
\r
68 ##### Extended Peripheral Control functions #####
\r
69 ===============================================================================
\r
71 This subsection provides a set of functions allowing to control the RCC Clocks
\r
74 (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
\r
75 select the RTC clock source; in this case the Backup domain will be reset in
\r
76 order to modify the RTC Clock source, as consequence RTC registers (including
\r
77 the backup registers) are set to their reset values.
\r
84 * @brief Initializes the RCC extended peripherals clocks according to the specified
\r
85 * parameters in the RCC_PeriphCLKInitTypeDef.
\r
86 * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
\r
87 * contains the configuration information for the Extended Peripherals clocks(RTC/LCD clock).
\r
88 * @retval HAL status
\r
89 * @note If HAL_ERROR returned, first switch-OFF HSE clock oscillator with @ref HAL_RCC_OscConfig()
\r
90 * to possibly update HSE divider.
\r
92 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
\r
97 /* Check the parameters */
\r
98 assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
\r
100 /*------------------------------- RTC/LCD Configuration ------------------------*/
\r
101 if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
\r
103 || (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
\r
107 /* check for RTC Parameters used to output RTCCLK */
\r
108 if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
\r
110 assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
\r
114 if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
\r
116 assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->LCDClockSelection));
\r
120 FlagStatus pwrclkchanged = RESET;
\r
122 /* As soon as function is called to change RTC clock source, activation of the
\r
123 power domain is done. */
\r
124 /* Requires to enable write access to Backup Domain of necessary */
\r
125 if(__HAL_RCC_PWR_IS_CLK_DISABLED())
\r
127 __HAL_RCC_PWR_CLK_ENABLE();
\r
128 pwrclkchanged = SET;
\r
131 if(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
\r
133 /* Enable write access to Backup domain */
\r
134 SET_BIT(PWR->CR, PWR_CR_DBP);
\r
136 /* Wait for Backup domain Write protection disable */
\r
137 tickstart = HAL_GetTick();
\r
139 while(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
\r
141 if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
\r
143 return HAL_TIMEOUT;
\r
148 /* Check if user wants to change HSE RTC prescaler whereas HSE is enabled */
\r
149 temp_reg = (RCC->CR & RCC_CR_RTCPRE);
\r
150 if ((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CR_RTCPRE))
\r
152 || (temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CR_RTCPRE))
\r
155 { /* Check HSE State */
\r
156 if ((PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL) == RCC_CSR_RTCSEL_HSE)
\r
158 if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
\r
160 /* To update HSE divider, first switch-OFF HSE clock oscillator*/
\r
166 /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
\r
167 temp_reg = (RCC->CSR & RCC_CSR_RTCSEL);
\r
169 if((temp_reg != 0x00000000U) && (((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL)) \
\r
170 && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC))
\r
172 || ((temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CSR_RTCSEL)) \
\r
173 && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD))
\r
177 /* Store the content of CSR register before the reset of Backup Domain */
\r
178 temp_reg = (RCC->CSR & ~(RCC_CSR_RTCSEL));
\r
180 /* RTC Clock selection can be changed only if the Backup Domain is reset */
\r
181 __HAL_RCC_BACKUPRESET_FORCE();
\r
182 __HAL_RCC_BACKUPRESET_RELEASE();
\r
184 /* Restore the Content of CSR register */
\r
185 RCC->CSR = temp_reg;
\r
187 /* Wait for LSERDY if LSE was enabled */
\r
188 if (HAL_IS_BIT_SET(temp_reg, RCC_CSR_LSEON))
\r
190 /* Get Start Tick */
\r
191 tickstart = HAL_GetTick();
\r
193 /* Wait till LSE is ready */
\r
194 while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == 0U)
\r
196 if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
\r
198 return HAL_TIMEOUT;
\r
203 __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
\r
205 /* Require to disable power clock if necessary */
\r
206 if(pwrclkchanged == SET)
\r
208 __HAL_RCC_PWR_CLK_DISABLE();
\r
216 * @brief Get the PeriphClkInit according to the internal RCC configuration registers.
\r
217 * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
\r
218 * returns the configuration information for the Extended Peripherals clocks(RTC/LCD clocks).
\r
221 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
\r
225 /* Set all possible values for the extended clock type parameter------------*/
\r
226 PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_RTC;
\r
228 PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_LCD;
\r
231 /* Get the RTC/LCD configuration -----------------------------------------------*/
\r
232 srcclk = __HAL_RCC_GET_RTC_SOURCE();
\r
233 if (srcclk != RCC_RTCCLKSOURCE_HSE_DIV2)
\r
235 /* Source clock is LSE or LSI*/
\r
236 PeriphClkInit->RTCClockSelection = srcclk;
\r
240 /* Source clock is HSE. Need to get the prescaler value*/
\r
241 PeriphClkInit->RTCClockSelection = srcclk | (READ_BIT(RCC->CR, RCC_CR_RTCPRE));
\r
244 PeriphClkInit->LCDClockSelection = PeriphClkInit->RTCClockSelection;
\r
249 * @brief Return the peripheral clock frequency
\r
250 * @note Return 0 if peripheral clock is unknown
\r
251 * @param PeriphClk Peripheral clock identifier
\r
252 * This parameter can be one of the following values:
\r
253 * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
\r
254 * @arg @ref RCC_PERIPHCLK_LCD LCD peripheral clock (*)
\r
255 * @note (*) means that this peripheral is not present on all the devices
\r
256 * @retval Frequency in Hz (0: means that no available frequency for the peripheral)
\r
258 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
\r
260 uint32_t frequency = 0;
\r
263 /* Check the parameters */
\r
264 assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
\r
268 case RCC_PERIPHCLK_RTC:
\r
270 case RCC_PERIPHCLK_LCD:
\r
273 /* Get the current RTC source */
\r
274 srcclk = __HAL_RCC_GET_RTC_SOURCE();
\r
276 /* Check if LSE is ready if RTC clock selection is LSE */
\r
277 if (srcclk == RCC_RTCCLKSOURCE_LSE)
\r
279 if (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSERDY))
\r
281 frequency = LSE_VALUE;
\r
284 /* Check if LSI is ready if RTC clock selection is LSI */
\r
285 else if (srcclk == RCC_RTCCLKSOURCE_LSI)
\r
287 if (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))
\r
289 frequency = LSI_VALUE;
\r
292 /* Check if HSE is ready and if RTC clock selection is HSE */
\r
293 else if (srcclk == RCC_RTCCLKSOURCE_HSE_DIVX)
\r
295 if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
\r
297 /* Get the current HSE clock divider */
\r
298 switch (__HAL_RCC_GET_RTC_HSE_PRESCALER())
\r
300 case RCC_RTC_HSE_DIV_16: /* HSE DIV16 has been selected */
\r
302 frequency = HSE_VALUE / 16U;
\r
305 case RCC_RTC_HSE_DIV_8: /* HSE DIV8 has been selected */
\r
307 frequency = HSE_VALUE / 8U;
\r
310 case RCC_RTC_HSE_DIV_4: /* HSE DIV4 has been selected */
\r
312 frequency = HSE_VALUE / 4U;
\r
315 default: /* HSE DIV2 has been selected */
\r
317 frequency = HSE_VALUE / 2U;
\r
325 /* No clock source, frequency default init at 0 */
\r
337 #if defined(RCC_LSECSS_SUPPORT)
\r
339 * @brief Enables the LSE Clock Security System.
\r
340 * @note If a failure is detected on the external 32 kHz oscillator, the LSE clock is no longer supplied
\r
341 * to the RTC but no hardware action is made to the registers.
\r
342 * In Standby mode a wakeup is generated. In other modes an interrupt can be sent to wakeup
\r
343 * the software (see Section 5.3.4: Clock interrupt register (RCC_CIR) on page 104).
\r
344 * The software MUST then disable the LSECSSON bit, stop the defective 32 kHz oscillator
\r
345 * (disabling LSEON), and can change the RTC clock source (no clock or LSI or HSE, with
\r
346 * RTCSEL), or take any required action to secure the application.
\r
347 * @note LSE CSS available only for high density and medium+ devices
\r
350 void HAL_RCCEx_EnableLSECSS(void)
\r
352 *(__IO uint32_t *) CSR_LSECSSON_BB = (uint32_t)ENABLE;
\r
356 * @brief Disables the LSE Clock Security System.
\r
357 * @note Once enabled this bit cannot be disabled, except after an LSE failure detection
\r
358 * (LSECSSD=1). In that case the software MUST disable the LSECSSON bit.
\r
359 * Reset by power on reset and RTC software reset (RTCRST bit).
\r
360 * @note LSE CSS available only for high density and medium+ devices
\r
363 void HAL_RCCEx_DisableLSECSS(void)
\r
365 /* Disable LSE CSS */
\r
366 *(__IO uint32_t *) CSR_LSECSSON_BB = (uint32_t)DISABLE;
\r
368 /* Disable LSE CSS IT */
\r
369 __HAL_RCC_DISABLE_IT(RCC_IT_LSECSS);
\r
373 * @brief Enable the LSE Clock Security System IT & corresponding EXTI line.
\r
374 * @note LSE Clock Security System IT is mapped on RTC EXTI line 19
\r
377 void HAL_RCCEx_EnableLSECSS_IT(void)
\r
379 /* Enable LSE CSS */
\r
380 *(__IO uint32_t *) CSR_LSECSSON_BB = (uint32_t)ENABLE;
\r
382 /* Enable LSE CSS IT */
\r
383 __HAL_RCC_ENABLE_IT(RCC_IT_LSECSS);
\r
385 /* Enable IT on EXTI Line 19 */
\r
386 __HAL_RCC_LSECSS_EXTI_ENABLE_IT();
\r
387 __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE();
\r
391 * @brief Handle the RCC LSE Clock Security System interrupt request.
\r
394 void HAL_RCCEx_LSECSS_IRQHandler(void)
\r
396 /* Check RCC LSE CSSF flag */
\r
397 if(__HAL_RCC_GET_IT(RCC_IT_LSECSS))
\r
399 /* RCC LSE Clock Security System interrupt user callback */
\r
400 HAL_RCCEx_LSECSS_Callback();
\r
402 /* Clear RCC LSE CSS pending bit */
\r
403 __HAL_RCC_CLEAR_IT(RCC_IT_LSECSS);
\r
408 * @brief RCCEx LSE Clock Security System interrupt callback.
\r
411 __weak void HAL_RCCEx_LSECSS_Callback(void)
\r
413 /* NOTE : This function should not be modified, when the callback is needed,
\r
414 the @ref HAL_RCCEx_LSECSS_Callback should be implemented in the user file
\r
417 #endif /* RCC_LSECSS_SUPPORT */
\r
435 #endif /* HAL_RCC_MODULE_ENABLED */
\r
440 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\r