|
- /**
- ******************************************************************************
- * @file stm32l1xx_hal_rcc_ex.c
- * @author MCD Application Team
- * @brief Extended RCC HAL module driver.
- * This file provides firmware functions to manage the following
- * functionalities RCC extension peripheral:
- * + Extended Peripheral Control functions
- *
- ******************************************************************************
- * @attention
- *
- * <h2><center>© Copyright(c) 2017 STMicroelectronics.
- * All rights reserved.</center></h2>
- *
- * This software component is licensed by ST under BSD 3-Clause license,
- * the "License"; You may not use this file except in compliance with the
- * License. You may obtain a copy of the License at:
- * opensource.org/licenses/BSD-3-Clause
- *
- ******************************************************************************
- */
-
- /* Includes ------------------------------------------------------------------*/
- #include "stm32l1xx_hal.h"
-
- /** @addtogroup STM32L1xx_HAL_Driver
- * @{
- */
-
- #ifdef HAL_RCC_MODULE_ENABLED
-
- /** @defgroup RCCEx RCCEx
- * @brief RCC Extension HAL module driver
- * @{
- */
-
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- /** @defgroup RCCEx_Private_Constants RCCEx Private Constants
- * @{
- */
- /**
- * @}
- */
-
- /* Private macro -------------------------------------------------------------*/
- /** @defgroup RCCEx_Private_Macros RCCEx Private Macros
- * @{
- */
- /**
- * @}
- */
-
- /* Private variables ---------------------------------------------------------*/
- /* Private function prototypes -----------------------------------------------*/
- /* Private functions ---------------------------------------------------------*/
-
- /** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
- * @{
- */
-
- /** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
- * @brief Extended Peripheral Control functions
- *
- @verbatim
- ===============================================================================
- ##### Extended Peripheral Control functions #####
- ===============================================================================
- [..]
- This subsection provides a set of functions allowing to control the RCC Clocks
- frequencies.
- [..]
- (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
- select the RTC clock source; in this case the Backup domain will be reset in
- order to modify the RTC Clock source, as consequence RTC registers (including
- the backup registers) are set to their reset values.
-
- @endverbatim
- * @{
- */
-
- /**
- * @brief Initializes the RCC extended peripherals clocks according to the specified
- * parameters in the RCC_PeriphCLKInitTypeDef.
- * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
- * contains the configuration information for the Extended Peripherals clocks(RTC/LCD clock).
- * @retval HAL status
- * @note If HAL_ERROR returned, first switch-OFF HSE clock oscillator with @ref HAL_RCC_OscConfig()
- * to possibly update HSE divider.
- */
- HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
- {
- uint32_t tickstart;
- uint32_t temp_reg;
-
- /* Check the parameters */
- assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
-
- /*------------------------------- RTC/LCD Configuration ------------------------*/
- if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
- #if defined(LCD)
- || (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
- #endif /* LCD */
- )
- {
- /* check for RTC Parameters used to output RTCCLK */
- if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
- {
- assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
- }
-
- #if defined(LCD)
- if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
- {
- assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->LCDClockSelection));
- }
- #endif /* LCD */
-
- FlagStatus pwrclkchanged = RESET;
-
- /* As soon as function is called to change RTC clock source, activation of the
- power domain is done. */
- /* Requires to enable write access to Backup Domain of necessary */
- if(__HAL_RCC_PWR_IS_CLK_DISABLED())
- {
- __HAL_RCC_PWR_CLK_ENABLE();
- pwrclkchanged = SET;
- }
-
- if(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
- {
- /* Enable write access to Backup domain */
- SET_BIT(PWR->CR, PWR_CR_DBP);
-
- /* Wait for Backup domain Write protection disable */
- tickstart = HAL_GetTick();
-
- while(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
- {
- if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
- {
- return HAL_TIMEOUT;
- }
- }
- }
-
- /* Check if user wants to change HSE RTC prescaler whereas HSE is enabled */
- temp_reg = (RCC->CR & RCC_CR_RTCPRE);
- if ((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CR_RTCPRE))
- #if defined (LCD)
- || (temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CR_RTCPRE))
- #endif /* LCD */
- )
- { /* Check HSE State */
- if ((PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL) == RCC_CSR_RTCSEL_HSE)
- {
- if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
- {
- /* To update HSE divider, first switch-OFF HSE clock oscillator*/
- return HAL_ERROR;
- }
- }
- }
-
- /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
- temp_reg = (RCC->CSR & RCC_CSR_RTCSEL);
-
- if((temp_reg != 0x00000000U) && (((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL)) \
- && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC))
- #if defined(LCD)
- || ((temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CSR_RTCSEL)) \
- && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD))
- #endif /* LCD */
- ))
- {
- /* Store the content of CSR register before the reset of Backup Domain */
- temp_reg = (RCC->CSR & ~(RCC_CSR_RTCSEL));
-
- /* RTC Clock selection can be changed only if the Backup Domain is reset */
- __HAL_RCC_BACKUPRESET_FORCE();
- __HAL_RCC_BACKUPRESET_RELEASE();
-
- /* Restore the Content of CSR register */
- RCC->CSR = temp_reg;
-
- /* Wait for LSERDY if LSE was enabled */
- if (HAL_IS_BIT_SET(temp_reg, RCC_CSR_LSEON))
- {
- /* Get Start Tick */
- tickstart = HAL_GetTick();
-
- /* Wait till LSE is ready */
- while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == 0U)
- {
- if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
- {
- return HAL_TIMEOUT;
- }
- }
- }
- }
- __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
-
- /* Require to disable power clock if necessary */
- if(pwrclkchanged == SET)
- {
- __HAL_RCC_PWR_CLK_DISABLE();
- }
- }
-
- return HAL_OK;
- }
-
- /**
- * @brief Get the PeriphClkInit according to the internal RCC configuration registers.
- * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
- * returns the configuration information for the Extended Peripherals clocks(RTC/LCD clocks).
- * @retval None
- */
- void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
- {
- uint32_t srcclk;
-
- /* Set all possible values for the extended clock type parameter------------*/
- PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_RTC;
- #if defined(LCD)
- PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_LCD;
- #endif /* LCD */
-
- /* Get the RTC/LCD configuration -----------------------------------------------*/
- srcclk = __HAL_RCC_GET_RTC_SOURCE();
- if (srcclk != RCC_RTCCLKSOURCE_HSE_DIV2)
- {
- /* Source clock is LSE or LSI*/
- PeriphClkInit->RTCClockSelection = srcclk;
- }
- else
- {
- /* Source clock is HSE. Need to get the prescaler value*/
- PeriphClkInit->RTCClockSelection = srcclk | (READ_BIT(RCC->CR, RCC_CR_RTCPRE));
- }
- #if defined(LCD)
- PeriphClkInit->LCDClockSelection = PeriphClkInit->RTCClockSelection;
- #endif /* LCD */
- }
-
- /**
- * @brief Return the peripheral clock frequency
- * @note Return 0 if peripheral clock is unknown
- * @param PeriphClk Peripheral clock identifier
- * This parameter can be one of the following values:
- * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
- * @arg @ref RCC_PERIPHCLK_LCD LCD peripheral clock (*)
- * @note (*) means that this peripheral is not present on all the devices
- * @retval Frequency in Hz (0: means that no available frequency for the peripheral)
- */
- uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
- {
- uint32_t frequency = 0;
- uint32_t srcclk;
-
- /* Check the parameters */
- assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
-
- switch (PeriphClk)
- {
- case RCC_PERIPHCLK_RTC:
- #if defined(LCD)
- case RCC_PERIPHCLK_LCD:
- #endif /* LCD */
- {
- /* Get the current RTC source */
- srcclk = __HAL_RCC_GET_RTC_SOURCE();
-
- /* Check if LSE is ready if RTC clock selection is LSE */
- if (srcclk == RCC_RTCCLKSOURCE_LSE)
- {
- if (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSERDY))
- {
- frequency = LSE_VALUE;
- }
- }
- /* Check if LSI is ready if RTC clock selection is LSI */
- else if (srcclk == RCC_RTCCLKSOURCE_LSI)
- {
- if (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))
- {
- frequency = LSI_VALUE;
- }
- }
- /* Check if HSE is ready and if RTC clock selection is HSE */
- else if (srcclk == RCC_RTCCLKSOURCE_HSE_DIVX)
- {
- if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
- {
- /* Get the current HSE clock divider */
- switch (__HAL_RCC_GET_RTC_HSE_PRESCALER())
- {
- case RCC_RTC_HSE_DIV_16: /* HSE DIV16 has been selected */
- {
- frequency = HSE_VALUE / 16U;
- break;
- }
- case RCC_RTC_HSE_DIV_8: /* HSE DIV8 has been selected */
- {
- frequency = HSE_VALUE / 8U;
- break;
- }
- case RCC_RTC_HSE_DIV_4: /* HSE DIV4 has been selected */
- {
- frequency = HSE_VALUE / 4U;
- break;
- }
- default: /* HSE DIV2 has been selected */
- {
- frequency = HSE_VALUE / 2U;
- break;
- }
- }
- }
- }
- else
- {
- /* No clock source, frequency default init at 0 */
- }
- break;
- }
-
- default:
- break;
- }
-
- return(frequency);
- }
-
- #if defined(RCC_LSECSS_SUPPORT)
- /**
- * @brief Enables the LSE Clock Security System.
- * @note If a failure is detected on the external 32 kHz oscillator, the LSE clock is no longer supplied
- * to the RTC but no hardware action is made to the registers.
- * In Standby mode a wakeup is generated. In other modes an interrupt can be sent to wakeup
- * the software (see Section 5.3.4: Clock interrupt register (RCC_CIR) on page 104).
- * The software MUST then disable the LSECSSON bit, stop the defective 32 kHz oscillator
- * (disabling LSEON), and can change the RTC clock source (no clock or LSI or HSE, with
- * RTCSEL), or take any required action to secure the application.
- * @note LSE CSS available only for high density and medium+ devices
- * @retval None
- */
- void HAL_RCCEx_EnableLSECSS(void)
- {
- *(__IO uint32_t *) CSR_LSECSSON_BB = (uint32_t)ENABLE;
- }
-
- /**
- * @brief Disables the LSE Clock Security System.
- * @note Once enabled this bit cannot be disabled, except after an LSE failure detection
- * (LSECSSD=1). In that case the software MUST disable the LSECSSON bit.
- * Reset by power on reset and RTC software reset (RTCRST bit).
- * @note LSE CSS available only for high density and medium+ devices
- * @retval None
- */
- void HAL_RCCEx_DisableLSECSS(void)
- {
- /* Disable LSE CSS */
- *(__IO uint32_t *) CSR_LSECSSON_BB = (uint32_t)DISABLE;
-
- /* Disable LSE CSS IT */
- __HAL_RCC_DISABLE_IT(RCC_IT_LSECSS);
- }
-
- /**
- * @brief Enable the LSE Clock Security System IT & corresponding EXTI line.
- * @note LSE Clock Security System IT is mapped on RTC EXTI line 19
- * @retval None
- */
- void HAL_RCCEx_EnableLSECSS_IT(void)
- {
- /* Enable LSE CSS */
- *(__IO uint32_t *) CSR_LSECSSON_BB = (uint32_t)ENABLE;
-
- /* Enable LSE CSS IT */
- __HAL_RCC_ENABLE_IT(RCC_IT_LSECSS);
-
- /* Enable IT on EXTI Line 19 */
- __HAL_RCC_LSECSS_EXTI_ENABLE_IT();
- __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE();
- }
-
- /**
- * @brief Handle the RCC LSE Clock Security System interrupt request.
- * @retval None
- */
- void HAL_RCCEx_LSECSS_IRQHandler(void)
- {
- /* Check RCC LSE CSSF flag */
- if(__HAL_RCC_GET_IT(RCC_IT_LSECSS))
- {
- /* RCC LSE Clock Security System interrupt user callback */
- HAL_RCCEx_LSECSS_Callback();
-
- /* Clear RCC LSE CSS pending bit */
- __HAL_RCC_CLEAR_IT(RCC_IT_LSECSS);
- }
- }
-
- /**
- * @brief RCCEx LSE Clock Security System interrupt callback.
- * @retval none
- */
- __weak void HAL_RCCEx_LSECSS_Callback(void)
- {
- /* NOTE : This function should not be modified, when the callback is needed,
- the @ref HAL_RCCEx_LSECSS_Callback should be implemented in the user file
- */
- }
- #endif /* RCC_LSECSS_SUPPORT */
-
- /**
- * @}
- */
-
- /**
- * @}
- */
-
- /**
- * @}
- */
-
- /**
- * @}
- */
-
- #endif /* HAL_RCC_MODULE_ENABLED */
- /**
- * @}
- */
-
- /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|