|
STM32G474xx HAL用户手册
|
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 {