STM32G474xx HAL用户手册
stm32g4xx_hal_rcc_ex.c
转到此文件的文档。
00001 /**
00002   ******************************************************************************
00003   * @file    stm32g4xx_hal_rcc_ex.c
00004   * @author  MCD Application Team
00005   * @brief   扩展RCC HAL模块驱动程序。
00006   *          本文件提供固件函数用于管理以下
00007   *          RCC扩展外设功能:
00008   *           + 扩展外设控制函数
00009   *           + 扩展时钟管理函数
00010   *           + 扩展时钟恢复系统控制函数
00011   *
00012   ******************************************************************************
00013   * @attention
00014   *
00015   * Copyright (c) 2019 STMicroelectronics.
00016   * All rights reserved.
00017   *
00018   * This software is licensed under terms that can be found in the LICENSE file in
00019   * the root directory of this software component.
00020   * If no LICENSE file comes with this software, it is provided AS-IS.
00021   ******************************************************************************
00022   */
00023 
00024 /* Includes ------------------------------------------------------------------*/
00025 #include "stm32g4xx_hal.h"
00026 
00027 /** @addtogroup STM32G4xx_HAL_Driver
00028   * @{
00029   */
00030 
00031 /** @defgroup RCCEx RCCEx
00032   * @brief RCC扩展HAL模块驱动程序
00033   * @{
00034   */
00035 
00036 #ifdef HAL_RCC_MODULE_ENABLED
00037 
00038 /* Private typedef -----------------------------------------------------------*/
00039 /* Private defines -----------------------------------------------------------*/
00040 /** @defgroup RCCEx_Private_Constants RCCEx私有常量
00041  * @{
00042  */
00043 #define PLL_TIMEOUT_VALUE        2U                /* 2 ms (最小Tick + 1) */
00044 
00045 #define DIVIDER_P_UPDATE          0U
00046 #define DIVIDER_Q_UPDATE          1U
00047 #define DIVIDER_R_UPDATE          2U
00048 
00049 #define __LSCO_CLK_ENABLE()       __HAL_RCC_GPIOA_CLK_ENABLE()
00050 #define LSCO_GPIO_PORT            GPIOA
00051 #define LSCO_PIN                  GPIO_PIN_2
00052 /**
00053   * @}
00054   */
00055 
00056 /* Private macros ------------------------------------------------------------*/
00057 /* Private variables ---------------------------------------------------------*/
00058 /* Private function prototypes -----------------------------------------------*/
00059 /** @defgroup RCCEx_Private_Functions RCCEx私有函数
00060  * @{
00061  */
00062 
00063 /**
00064   * @}
00065   */
00066 
00067 /* Exported functions --------------------------------------------------------*/
00068 
00069 /** @defgroup RCCEx_Exported_Functions RCCEx导出函数
00070   * @{
00071   */
00072 
00073 /** @defgroup RCCEx_Exported_Functions_Group1 扩展外设控制函数
00074  *  @brief  扩展外设控制函数
00075  *
00076 @verbatim
00077  ===============================================================================
00078                 ##### 扩展外设控制函数  #####
00079  ===============================================================================
00080     [..]
00081     本小节提供一组函数,用于控制RCC时钟频率。
00082     [..]
00083     (@) 重要说明:使用HAL_RCCEx_PeriphCLKConfig()选择RTC时钟源时必须注意;
00085         在这种情况下,为了修改RTC时钟源,备份域将被复位,
00087         因此RTC寄存器(包括备份寄存器)将被设置为其复位值。
00087 
00088 @endverbatim
00089   * @{
00090   */
00092 /**
00093   * @brief  根据RCC_PeriphCLKInitTypeDef中指定的参数初始化RCC扩展外设时钟。
00094   *         参数配置RCC扩展外设时钟。
00095   * @param  PeriphClkInit  指向RCC_PeriphCLKInitTypeDef结构体的指针,包含
00096   *         字段PeriphClockSelection,可以是以下值的组合:
00097   *            @arg @ref RCC_PERIPHCLK_RTC  RTC外设时钟
00098   *            @arg @ref RCC_PERIPHCLK_USART1  USART1外设时钟
00099   *            @arg @ref RCC_PERIPHCLK_USART2  USART2外设时钟
00100   *            @arg @ref RCC_PERIPHCLK_USART3  USART3外设时钟
00101   *            @arg @ref RCC_PERIPHCLK_UART4  UART4外设时钟(仅限具有UART4的器件)
00102   *            @arg @ref RCC_PERIPHCLK_UART5  UART5外设时钟(仅限具有UART5的器件)
00103   *            @arg @ref RCC_PERIPHCLK_LPUART1  LPUART1外设时钟
00104   *            @arg @ref RCC_PERIPHCLK_I2C1  I2C1外设时钟
00105   *            @arg @ref RCC_PERIPHCLK_I2C2  I2C2外设时钟
00106   *            @arg @ref RCC_PERIPHCLK_I2C3  I2C3外设时钟
00107   *            @arg @ref RCC_PERIPHCLK_I2C4  I2C4外设时钟(仅限具有I2C4的器件)
00108   *            @arg @ref RCC_PERIPHCLK_LPTIM1  LPTIM1外设时钟
00109   *            @arg @ref RCC_PERIPHCLK_SAI1  SAI1外设时钟
00110   *            @arg @ref RCC_PERIPHCLK_I2S  I2S外设时钟
00111   *            @arg @ref RCC_PERIPHCLK_FDCAN  FDCAN外设时钟(仅限具有FDCAN的器件)
00112   *            @arg @ref RCC_PERIPHCLK_RNG  RNG外设时钟
00113   *            @arg @ref RCC_PERIPHCLK_USB  USB外设时钟(仅限具有USB的器件)
00114   *            @arg @ref RCC_PERIPHCLK_ADC12  ADC1和ADC2外设时钟
00115   *            @arg @ref RCC_PERIPHCLK_ADC345  ADC3、ADC4和ADC5外设时钟(仅限具有ADC3、ADC4、ADC5的器件)
00116   *            @arg @ref RCC_PERIPHCLK_QSPI  QuadSPI外设时钟(仅限具有QuadSPI的器件)
00117   *
00118   * @note   使用HAL_RCCEx_PeriphCLKConfig()选择RTC时钟源时必须注意:
00119   *         在这种情况下,将启用对备份域的访问。
00120   *
00121   * @retval HAL状态
00122   */
00123 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef const *PeriphClkInit)
00124 {
00125   uint32_t tmpregister;
00126   uint32_t tickstart;
00127   HAL_StatusTypeDef ret = HAL_OK;      /* 中间状态 */
00128   HAL_StatusTypeDef status = HAL_OK;   /* 最终状态 */
00129 
00130   /* 检查参数 */
00131   assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
00132 
00133   /*-------------------------- RTC时钟源配置 ----------------------*/
00134   if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
00135   {
00136     FlagStatus       pwrclkchanged = RESET;
00137     
00138     /* 检查用于输出RTCCLK的RTC参数 */
00139     assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
00140 
00141     /* 使能电源时钟 */
00142     if(__HAL_RCC_PWR_IS_CLK_DISABLED())
00143     {
00144       __HAL_RCC_PWR_CLK_ENABLE();
00145       pwrclkchanged = SET;
00146     }
00147       
00148     /* 启用对备份域的写访问 */
00149     SET_BIT(PWR->CR1, PWR_CR1_DBP);
00150 
00151     /* 等待备份域写保护禁用 */
00152     tickstart = HAL_GetTick();
00153 
00154     while((PWR->CR1 & PWR_CR1_DBP) == 0U)
00155     {
00156       if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
00157       {
00158         ret = HAL_TIMEOUT;
00159         break;
00160       }
00161     }
00162 
00163     if(ret == HAL_OK)
00164     { 
00165       /* 仅在RTC时钟源选择与默认配置不同时复位备份域 */
00166       tmpregister = READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL);
00167       
00168       if((tmpregister != RCC_RTCCLKSOURCE_NONE) && (tmpregister != PeriphClkInit->RTCClockSelection))
00169       {
00170         /* 存储备份域复位前BDCR寄存器的内容 */
00171         tmpregister = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL));
00172         /* 仅在备份域复位后可以更改RTC时钟选择 */
00173         __HAL_RCC_BACKUPRESET_FORCE();
00174         __HAL_RCC_BACKUPRESET_RELEASE();
00175         /* 恢复BDCR寄存器的内容 */
00176         RCC->BDCR = tmpregister;
00177       }
00178 
00179       /* 如果LSE在备份域复位前已使能,则等待LSE重新激活 */
00180       if (HAL_IS_BIT_SET(tmpregister, RCC_BDCR_LSEON))
00181       {
00182         /* 获取起始Tick */
00183         tickstart = HAL_GetTick();
00184 
00185         /* 等待LSE就绪 */
00186         while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U)
00187         {
00188           if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
00189           {
00190             ret = HAL_TIMEOUT;
00191             break;
00193           }
00194         }
00195       }
00195       
00196       if(ret == HAL_OK)
00197       {
</