| /** |
| ****************************************************************************** |
| * @file stm32f4xx_hal_rcc_ex.c |
| * @author MCD Application Team |
| * @brief Extension 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 "stm32f4xx_hal.h" |
| |
| /** @addtogroup STM32F4xx_HAL_Driver |
| * @{ |
| */ |
| |
| /** @defgroup RCCEx RCCEx |
| * @brief RCCEx HAL module driver |
| * @{ |
| */ |
| |
| #ifdef HAL_RCC_MODULE_ENABLED |
| |
| /* Private typedef -----------------------------------------------------------*/ |
| /* Private define ------------------------------------------------------------*/ |
| /** @addtogroup RCCEx_Private_Constants |
| * @{ |
| */ |
| /** |
| * @} |
| */ |
| /* Private macro -------------------------------------------------------------*/ |
| /* 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) and RCC_BDCR register are set to their reset values. |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| #if defined(STM32F446xx) |
| /** |
| * @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(I2S, SAI, LTDC RTC and TIM). |
| * |
| * @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) and RCC_BDCR register are set to their reset values. |
| * |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tickstart = 0U; |
| uint32_t tmpreg1 = 0U; |
| uint32_t plli2sp = 0U; |
| uint32_t plli2sq = 0U; |
| uint32_t plli2sr = 0U; |
| uint32_t pllsaip = 0U; |
| uint32_t pllsaiq = 0U; |
| uint32_t plli2sused = 0U; |
| uint32_t pllsaiused = 0U; |
| |
| /* Check the peripheral clock selection parameters */ |
| assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection)); |
| |
| /*------------------------ I2S APB1 configuration --------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == (RCC_PERIPHCLK_I2S_APB1)) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_I2SAPB1CLKSOURCE(PeriphClkInit->I2sApb1ClockSelection)); |
| |
| /* Configure I2S Clock source */ |
| __HAL_RCC_I2S_APB1_CONFIG(PeriphClkInit->I2sApb1ClockSelection); |
| /* Enable the PLLI2S when it's used as clock source for I2S */ |
| if(PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S) |
| { |
| plli2sused = 1U; |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- I2S APB2 configuration ----------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == (RCC_PERIPHCLK_I2S_APB2)) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_I2SAPB2CLKSOURCE(PeriphClkInit->I2sApb2ClockSelection)); |
| |
| /* Configure I2S Clock source */ |
| __HAL_RCC_I2S_APB2_CONFIG(PeriphClkInit->I2sApb2ClockSelection); |
| /* Enable the PLLI2S when it's used as clock source for I2S */ |
| if(PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S) |
| { |
| plli2sused = 1U; |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*--------------------------- SAI1 configuration ---------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == (RCC_PERIPHCLK_SAI1)) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_SAI1CLKSOURCE(PeriphClkInit->Sai1ClockSelection)); |
| |
| /* Configure SAI1 Clock source */ |
| __HAL_RCC_SAI1_CONFIG(PeriphClkInit->Sai1ClockSelection); |
| /* Enable the PLLI2S when it's used as clock source for SAI */ |
| if(PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLI2S) |
| { |
| plli2sused = 1U; |
| } |
| /* Enable the PLLSAI when it's used as clock source for SAI */ |
| if(PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLSAI) |
| { |
| pllsaiused = 1U; |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*-------------------------- SAI2 configuration ----------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == (RCC_PERIPHCLK_SAI2)) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_SAI2CLKSOURCE(PeriphClkInit->Sai2ClockSelection)); |
| |
| /* Configure SAI2 Clock source */ |
| __HAL_RCC_SAI2_CONFIG(PeriphClkInit->Sai2ClockSelection); |
| |
| /* Enable the PLLI2S when it's used as clock source for SAI */ |
| if(PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLI2S) |
| { |
| plli2sused = 1U; |
| } |
| /* Enable the PLLSAI when it's used as clock source for SAI */ |
| if(PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLSAI) |
| { |
| pllsaiused = 1U; |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*----------------------------- RTC configuration --------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC)) |
| { |
| /* Check for RTC Parameters used to output RTCCLK */ |
| assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection)); |
| |
| /* Enable Power Clock*/ |
| __HAL_RCC_PWR_CLK_ENABLE(); |
| |
| /* Enable write access to Backup domain */ |
| PWR->CR |= PWR_CR_DBP; |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((PWR->CR & PWR_CR_DBP) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */ |
| tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL); |
| if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL))) |
| { |
| /* Store the content of BDCR register before the reset of Backup Domain */ |
| tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_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 BDCR register */ |
| RCC->BDCR = tmpreg1; |
| |
| /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */ |
| if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON)) |
| { |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| /* Wait till LSE is ready */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| } |
| __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- TIM configuration ---------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM)) |
| { |
| /* Configure Timer Prescaler */ |
| __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- FMPI2C1 Configuration -----------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_FMPI2C1) == RCC_PERIPHCLK_FMPI2C1) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_FMPI2C1CLKSOURCE(PeriphClkInit->Fmpi2c1ClockSelection)); |
| |
| /* Configure the FMPI2C1 clock source */ |
| __HAL_RCC_FMPI2C1_CONFIG(PeriphClkInit->Fmpi2c1ClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*------------------------------ CEC Configuration -------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CEC) == RCC_PERIPHCLK_CEC) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_CECCLKSOURCE(PeriphClkInit->CecClockSelection)); |
| |
| /* Configure the CEC clock source */ |
| __HAL_RCC_CEC_CONFIG(PeriphClkInit->CecClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*----------------------------- CLK48 Configuration ------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_CLK48CLKSOURCE(PeriphClkInit->Clk48ClockSelection)); |
| |
| /* Configure the CLK48 clock source */ |
| __HAL_RCC_CLK48_CONFIG(PeriphClkInit->Clk48ClockSelection); |
| |
| /* Enable the PLLSAI when it's used as clock source for CLK48 */ |
| if(PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP) |
| { |
| pllsaiused = 1U; |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*----------------------------- SDIO Configuration -------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_SDIOCLKSOURCE(PeriphClkInit->SdioClockSelection)); |
| |
| /* Configure the SDIO clock source */ |
| __HAL_RCC_SDIO_CONFIG(PeriphClkInit->SdioClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*------------------------------ SPDIFRX Configuration ---------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPDIFRX) == RCC_PERIPHCLK_SPDIFRX) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_SPDIFRXCLKSOURCE(PeriphClkInit->SpdifClockSelection)); |
| |
| /* Configure the SPDIFRX clock source */ |
| __HAL_RCC_SPDIFRX_CONFIG(PeriphClkInit->SpdifClockSelection); |
| /* Enable the PLLI2S when it's used as clock source for SPDIFRX */ |
| if(PeriphClkInit->SpdifClockSelection == RCC_SPDIFRXCLKSOURCE_PLLI2SP) |
| { |
| plli2sused = 1U; |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- PLLI2S Configuration ------------------------*/ |
| /* PLLI2S is configured when a peripheral will use it as source clock : SAI1, SAI2, I2S on APB1, |
| I2S on APB2 or SPDIFRX */ |
| if((plli2sused == 1U) || (PeriphClkInit->PeriphClockSelection == RCC_PERIPHCLK_PLLI2S)) |
| { |
| /* Disable the PLLI2S */ |
| __HAL_RCC_PLLI2S_DISABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLI2S is disabled */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| /* check for common PLLI2S Parameters */ |
| assert_param(IS_RCC_PLLI2SM_VALUE(PeriphClkInit->PLLI2S.PLLI2SM)); |
| assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN)); |
| |
| /*------ In Case of PLLI2S is selected as source clock for I2S -----------*/ |
| if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == RCC_PERIPHCLK_I2S_APB1) && (PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S)) || |
| ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == RCC_PERIPHCLK_I2S_APB2) && (PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S))) |
| { |
| /* check for Parameters */ |
| assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR)); |
| |
| /* Read PLLI2SP/PLLI2SQ value from PLLI2SCFGR register (this value is not needed for I2S configuration) */ |
| plli2sp = ((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U); |
| plli2sq = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos); |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */ |
| /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */ |
| __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN , plli2sp, plli2sq, PeriphClkInit->PLLI2S.PLLI2SR); |
| } |
| |
| /*------- In Case of PLLI2S is selected as source clock for SAI ----------*/ |
| if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) && (PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLI2S)) || |
| ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) && (PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLI2S))) |
| { |
| /* Check for PLLI2S Parameters */ |
| assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ)); |
| /* Check for PLLI2S/DIVQ parameters */ |
| assert_param(IS_RCC_PLLI2S_DIVQ_VALUE(PeriphClkInit->PLLI2SDivQ)); |
| |
| /* Read PLLI2SP/PLLI2SR value from PLLI2SCFGR register (this value is not needed for SAI configuration) */ |
| plli2sp = ((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U); |
| plli2sr = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos); |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */ |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */ |
| __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN , plli2sp, PeriphClkInit->PLLI2S.PLLI2SQ, plli2sr); |
| |
| /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */ |
| __HAL_RCC_PLLI2S_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLI2SDivQ); |
| } |
| |
| /*------ In Case of PLLI2S is selected as source clock for SPDIFRX -------*/ |
| if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPDIFRX) == RCC_PERIPHCLK_SPDIFRX) && (PeriphClkInit->SpdifClockSelection == RCC_SPDIFRXCLKSOURCE_PLLI2SP)) |
| { |
| /* check for Parameters */ |
| assert_param(IS_RCC_PLLI2SP_VALUE(PeriphClkInit->PLLI2S.PLLI2SP)); |
| /* Read PLLI2SR value from PLLI2SCFGR register (this value is not need for SAI configuration) */ |
| plli2sq = ((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U); |
| plli2sr = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos); |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */ |
| /* SPDIFRXCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SP */ |
| __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SP, plli2sq, plli2sr); |
| } |
| |
| /*----------------- In Case of PLLI2S is just selected -----------------*/ |
| if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S) |
| { |
| /* Check for Parameters */ |
| assert_param(IS_RCC_PLLI2SP_VALUE(PeriphClkInit->PLLI2S.PLLI2SP)); |
| assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR)); |
| assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ)); |
| |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */ |
| __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SP, PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR); |
| } |
| |
| /* Enable the PLLI2S */ |
| __HAL_RCC_PLLI2S_ENABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLI2S is ready */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*----------------------------- PLLSAI Configuration -----------------------*/ |
| /* PLLSAI is configured when a peripheral will use it as source clock : SAI1, SAI2, CLK48 or SDIO */ |
| if(pllsaiused == 1U) |
| { |
| /* Disable PLLSAI Clock */ |
| __HAL_RCC_PLLSAI_DISABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLSAI is disabled */ |
| while(__HAL_RCC_PLLSAI_GET_FLAG() != RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| /* Check the PLLSAI division factors */ |
| assert_param(IS_RCC_PLLSAIM_VALUE(PeriphClkInit->PLLSAI.PLLSAIM)); |
| assert_param(IS_RCC_PLLSAIN_VALUE(PeriphClkInit->PLLSAI.PLLSAIN)); |
| |
| /*------ In Case of PLLSAI is selected as source clock for SAI -----------*/ |
| if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) && (PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLSAI)) || |
| ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) && (PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLSAI))) |
| { |
| /* check for PLLSAIQ Parameter */ |
| assert_param(IS_RCC_PLLSAIQ_VALUE(PeriphClkInit->PLLSAI.PLLSAIQ)); |
| /* check for PLLSAI/DIVQ Parameter */ |
| assert_param(IS_RCC_PLLSAI_DIVQ_VALUE(PeriphClkInit->PLLSAIDivQ)); |
| |
| /* Read PLLSAIP value from PLLSAICFGR register (this value is not needed for SAI configuration) */ |
| pllsaip = ((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U); |
| /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */ |
| /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */ |
| /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */ |
| __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIM, PeriphClkInit->PLLSAI.PLLSAIN , pllsaip, PeriphClkInit->PLLSAI.PLLSAIQ, 0U); |
| |
| /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */ |
| __HAL_RCC_PLLSAI_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLSAIDivQ); |
| } |
| |
| /*------ In Case of PLLSAI is selected as source clock for CLK48 ---------*/ |
| /* In Case of PLLI2S is selected as source clock for CLK48 */ |
| if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48) && (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP)) |
| { |
| /* check for Parameters */ |
| assert_param(IS_RCC_PLLSAIP_VALUE(PeriphClkInit->PLLSAI.PLLSAIP)); |
| /* Read PLLSAIQ value from PLLI2SCFGR register (this value is not need for SAI configuration) */ |
| pllsaiq = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos); |
| /* Configure the PLLSAI division factors */ |
| /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) * (PLLI2SN/PLLSAIM) */ |
| /* 48CLK = f(PLLSAI clock output) = f(VCO clock) / PLLSAIP */ |
| __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIM, PeriphClkInit->PLLSAI.PLLSAIN , PeriphClkInit->PLLSAI.PLLSAIP, pllsaiq, 0U); |
| } |
| |
| /* Enable PLLSAI Clock */ |
| __HAL_RCC_PLLSAI_ENABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLSAI is ready */ |
| while(__HAL_RCC_PLLSAI_GET_FLAG() == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Get the RCC_PeriphCLKInitTypeDef according to the internal |
| * RCC configuration registers. |
| * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that |
| * will be configured. |
| * @retval None |
| */ |
| void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tempreg; |
| |
| /* Set all possible values for the extended clock type parameter------------*/ |
| PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_I2S_APB2 |\ |
| RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 |\ |
| RCC_PERIPHCLK_TIM | RCC_PERIPHCLK_RTC |\ |
| RCC_PERIPHCLK_CEC | RCC_PERIPHCLK_FMPI2C1 |\ |
| RCC_PERIPHCLK_CLK48 | RCC_PERIPHCLK_SDIO |\ |
| RCC_PERIPHCLK_SPDIFRX; |
| |
| /* Get the PLLI2S Clock configuration --------------------------------------*/ |
| PeriphClkInit->PLLI2S.PLLI2SM = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM) >> RCC_PLLI2SCFGR_PLLI2SM_Pos); |
| PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos); |
| PeriphClkInit->PLLI2S.PLLI2SP = (uint32_t)((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U); |
| PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos); |
| PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos); |
| /* Get the PLLSAI Clock configuration --------------------------------------*/ |
| PeriphClkInit->PLLSAI.PLLSAIM = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIM) >> RCC_PLLSAICFGR_PLLSAIM_Pos); |
| PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> RCC_PLLSAICFGR_PLLSAIN_Pos); |
| PeriphClkInit->PLLSAI.PLLSAIP = (uint32_t)((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U); |
| PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos); |
| /* Get the PLLSAI/PLLI2S division factors ----------------------------------*/ |
| PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> RCC_DCKCFGR_PLLI2SDIVQ_Pos); |
| PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> RCC_DCKCFGR_PLLSAIDIVQ_Pos); |
| |
| /* Get the SAI1 clock configuration ----------------------------------------*/ |
| PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE(); |
| |
| /* Get the SAI2 clock configuration ----------------------------------------*/ |
| PeriphClkInit->Sai2ClockSelection = __HAL_RCC_GET_SAI2_SOURCE(); |
| |
| /* Get the I2S APB1 clock configuration ------------------------------------*/ |
| PeriphClkInit->I2sApb1ClockSelection = __HAL_RCC_GET_I2S_APB1_SOURCE(); |
| |
| /* Get the I2S APB2 clock configuration ------------------------------------*/ |
| PeriphClkInit->I2sApb2ClockSelection = __HAL_RCC_GET_I2S_APB2_SOURCE(); |
| |
| /* Get the RTC Clock configuration -----------------------------------------*/ |
| tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE); |
| PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL)); |
| |
| /* Get the CEC clock configuration -----------------------------------------*/ |
| PeriphClkInit->CecClockSelection = __HAL_RCC_GET_CEC_SOURCE(); |
| |
| /* Get the FMPI2C1 clock configuration -------------------------------------*/ |
| PeriphClkInit->Fmpi2c1ClockSelection = __HAL_RCC_GET_FMPI2C1_SOURCE(); |
| |
| /* Get the CLK48 clock configuration ----------------------------------------*/ |
| PeriphClkInit->Clk48ClockSelection = __HAL_RCC_GET_CLK48_SOURCE(); |
| |
| /* Get the SDIO clock configuration ----------------------------------------*/ |
| PeriphClkInit->SdioClockSelection = __HAL_RCC_GET_SDIO_SOURCE(); |
| |
| /* Get the SPDIFRX clock configuration -------------------------------------*/ |
| PeriphClkInit->SpdifClockSelection = __HAL_RCC_GET_SPDIFRX_SOURCE(); |
| |
| /* Get the TIM Prescaler configuration -------------------------------------*/ |
| if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET) |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED; |
| } |
| else |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED; |
| } |
| } |
| |
| /** |
| * @brief Return the peripheral clock frequency for a given peripheral(SAI..) |
| * @note Return 0 if peripheral clock identifier not managed by this API |
| * @param PeriphClk Peripheral clock identifier |
| * This parameter can be one of the following values: |
| * @arg RCC_PERIPHCLK_SAI1: SAI1 peripheral clock |
| * @arg RCC_PERIPHCLK_SAI2: SAI2 peripheral clock |
| * @arg RCC_PERIPHCLK_I2S_APB1: I2S APB1 peripheral clock |
| * @arg RCC_PERIPHCLK_I2S_APB2: I2S APB2 peripheral clock |
| * @retval Frequency in KHz |
| */ |
| uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) |
| { |
| uint32_t tmpreg1 = 0U; |
| /* This variable used to store the SAI clock frequency (value in Hz) */ |
| uint32_t frequency = 0U; |
| /* This variable used to store the VCO Input (value in Hz) */ |
| uint32_t vcoinput = 0U; |
| /* This variable used to store the SAI clock source */ |
| uint32_t saiclocksource = 0U; |
| uint32_t srcclk = 0U; |
| /* This variable used to store the VCO Output (value in Hz) */ |
| uint32_t vcooutput = 0U; |
| switch (PeriphClk) |
| { |
| case RCC_PERIPHCLK_SAI1: |
| case RCC_PERIPHCLK_SAI2: |
| { |
| saiclocksource = RCC->DCKCFGR; |
| saiclocksource &= (RCC_DCKCFGR_SAI1SRC | RCC_DCKCFGR_SAI2SRC); |
| switch (saiclocksource) |
| { |
| case 0U: /* PLLSAI is the clock source for SAI*/ |
| { |
| /* Configure the PLLSAI division factor */ |
| /* PLLSAI_VCO Input = PLL_SOURCE/PLLSAIM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI) |
| { |
| /* In Case the PLL Source is HSI (Internal Clock) */ |
| vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIM)); |
| } |
| else |
| { |
| /* In Case the PLL Source is HSE (External Clock) */ |
| vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIM))); |
| } |
| /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */ |
| /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */ |
| tmpreg1 = (RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> 24U; |
| frequency = (vcoinput * ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> 6U))/(tmpreg1); |
| |
| /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */ |
| tmpreg1 = (((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> 8U) + 1U); |
| frequency = frequency/(tmpreg1); |
| break; |
| } |
| case RCC_DCKCFGR_SAI1SRC_0: /* PLLI2S is the clock source for SAI*/ |
| case RCC_DCKCFGR_SAI2SRC_0: /* PLLI2S is the clock source for SAI*/ |
| { |
| /* Configure the PLLI2S division factor */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI) |
| { |
| /* In Case the PLL Source is HSI (Internal Clock) */ |
| vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| else |
| { |
| /* In Case the PLL Source is HSE (External Clock) */ |
| vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM))); |
| } |
| |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */ |
| tmpreg1 = (RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> 24U; |
| frequency = (vcoinput * ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U))/(tmpreg1); |
| |
| /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */ |
| tmpreg1 = ((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) + 1U); |
| frequency = frequency/(tmpreg1); |
| break; |
| } |
| case RCC_DCKCFGR_SAI1SRC_1: /* PLLR is the clock source for SAI*/ |
| case RCC_DCKCFGR_SAI2SRC_1: /* PLLR is the clock source for SAI*/ |
| { |
| /* Configure the PLLI2S division factor */ |
| /* PLL_VCO Input = PLL_SOURCE/PLLM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI) |
| { |
| /* In Case the PLL Source is HSI (Internal Clock) */ |
| vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| else |
| { |
| /* In Case the PLL Source is HSE (External Clock) */ |
| vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM))); |
| } |
| |
| /* PLL_VCO Output = PLL_VCO Input * PLLN */ |
| /* SAI_CLK_x = PLL_VCO Output/PLLR */ |
| tmpreg1 = (RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U; |
| frequency = (vcoinput * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U))/(tmpreg1); |
| break; |
| } |
| case RCC_DCKCFGR_SAI1SRC: /* External clock is the clock source for SAI*/ |
| { |
| frequency = EXTERNAL_CLOCK_VALUE; |
| break; |
| } |
| case RCC_DCKCFGR_SAI2SRC: /* PLLSRC(HSE or HSI) is the clock source for SAI*/ |
| { |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI) |
| { |
| /* In Case the PLL Source is HSI (Internal Clock) */ |
| frequency = (uint32_t)(HSI_VALUE); |
| } |
| else |
| { |
| /* In Case the PLL Source is HSE (External Clock) */ |
| frequency = (uint32_t)(HSE_VALUE); |
| } |
| break; |
| } |
| default : |
| { |
| break; |
| } |
| } |
| break; |
| } |
| case RCC_PERIPHCLK_I2S_APB1: |
| { |
| /* Get the current I2S source */ |
| srcclk = __HAL_RCC_GET_I2S_APB1_SOURCE(); |
| switch (srcclk) |
| { |
| /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */ |
| case RCC_I2SAPB1CLKSOURCE_EXT: |
| { |
| /* Set the I2S clock to the external clock value */ |
| frequency = EXTERNAL_CLOCK_VALUE; |
| break; |
| } |
| /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */ |
| case RCC_I2SAPB1CLKSOURCE_PLLI2S: |
| { |
| /* Configure the PLLI2S division factor */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U))); |
| /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U))); |
| break; |
| } |
| /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */ |
| case RCC_I2SAPB1CLKSOURCE_PLLR: |
| { |
| /* Configure the PLL division factor R */ |
| /* PLL_VCO Input = PLL_SOURCE/PLLM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| |
| /* PLL_VCO Output = PLL_VCO Input * PLLN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U))); |
| /* I2S_CLK = PLL_VCO Output/PLLR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U))); |
| break; |
| } |
| /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */ |
| case RCC_I2SAPB1CLKSOURCE_PLLSRC: |
| { |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| frequency = HSE_VALUE; |
| } |
| else |
| { |
| frequency = HSI_VALUE; |
| } |
| break; |
| } |
| /* Clock not enabled for I2S*/ |
| default: |
| { |
| frequency = 0U; |
| break; |
| } |
| } |
| break; |
| } |
| case RCC_PERIPHCLK_I2S_APB2: |
| { |
| /* Get the current I2S source */ |
| srcclk = __HAL_RCC_GET_I2S_APB2_SOURCE(); |
| switch (srcclk) |
| { |
| /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */ |
| case RCC_I2SAPB2CLKSOURCE_EXT: |
| { |
| /* Set the I2S clock to the external clock value */ |
| frequency = EXTERNAL_CLOCK_VALUE; |
| break; |
| } |
| /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */ |
| case RCC_I2SAPB2CLKSOURCE_PLLI2S: |
| { |
| /* Configure the PLLI2S division factor */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U))); |
| /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U))); |
| break; |
| } |
| /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */ |
| case RCC_I2SAPB2CLKSOURCE_PLLR: |
| { |
| /* Configure the PLL division factor R */ |
| /* PLL_VCO Input = PLL_SOURCE/PLLM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| |
| /* PLL_VCO Output = PLL_VCO Input * PLLN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U))); |
| /* I2S_CLK = PLL_VCO Output/PLLR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U))); |
| break; |
| } |
| /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */ |
| case RCC_I2SAPB2CLKSOURCE_PLLSRC: |
| { |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| frequency = HSE_VALUE; |
| } |
| else |
| { |
| frequency = HSI_VALUE; |
| } |
| break; |
| } |
| /* Clock not enabled for I2S*/ |
| default: |
| { |
| frequency = 0U; |
| break; |
| } |
| } |
| break; |
| } |
| } |
| return frequency; |
| } |
| #endif /* STM32F446xx */ |
| |
| #if defined(STM32F469xx) || defined(STM32F479xx) |
| /** |
| * @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(I2S, SAI, LTDC, RTC and TIM). |
| * |
| * @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) and RCC_BDCR register are set to their reset values. |
| * |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tickstart = 0U; |
| uint32_t tmpreg1 = 0U; |
| uint32_t pllsaip = 0U; |
| uint32_t pllsaiq = 0U; |
| uint32_t pllsair = 0U; |
| |
| /* Check the parameters */ |
| assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection)); |
| |
| /*--------------------------- CLK48 Configuration --------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_CLK48CLKSOURCE(PeriphClkInit->Clk48ClockSelection)); |
| |
| /* Configure the CLK48 clock source */ |
| __HAL_RCC_CLK48_CONFIG(PeriphClkInit->Clk48ClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*------------------------------ SDIO Configuration ------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_SDIOCLKSOURCE(PeriphClkInit->SdioClockSelection)); |
| |
| /* Configure the SDIO clock source */ |
| __HAL_RCC_SDIO_CONFIG(PeriphClkInit->SdioClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*----------------------- SAI/I2S Configuration (PLLI2S) -------------------*/ |
| /*------------------- Common configuration SAI/I2S -------------------------*/ |
| /* In Case of SAI or I2S Clock Configuration through PLLI2S, PLLI2SN division |
| factor is common parameters for both peripherals */ |
| if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S) || |
| (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == RCC_PERIPHCLK_SAI_PLLI2S) || |
| (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)) |
| { |
| /* check for Parameters */ |
| assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN)); |
| |
| /* Disable the PLLI2S */ |
| __HAL_RCC_PLLI2S_DISABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLI2S is disabled */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| /*---------------------- I2S configuration -------------------------------*/ |
| /* In Case of I2S Clock Configuration through PLLI2S, PLLI2SR must be added |
| only for I2S configuration */ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == (RCC_PERIPHCLK_I2S)) |
| { |
| /* check for Parameters */ |
| assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR)); |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) x (PLLI2SN/PLLM) */ |
| /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */ |
| __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SR); |
| } |
| |
| /*---------------------------- SAI configuration -------------------------*/ |
| /* In Case of SAI Clock Configuration through PLLI2S, PLLI2SQ and PLLI2S_DIVQ must |
| be added only for SAI configuration */ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == (RCC_PERIPHCLK_SAI_PLLI2S)) |
| { |
| /* Check the PLLI2S division factors */ |
| assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ)); |
| assert_param(IS_RCC_PLLI2S_DIVQ_VALUE(PeriphClkInit->PLLI2SDivQ)); |
| |
| /* Read PLLI2SR value from PLLI2SCFGR register (this value is not need for SAI configuration) */ |
| tmpreg1 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos); |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */ |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */ |
| __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SQ , tmpreg1); |
| /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */ |
| __HAL_RCC_PLLI2S_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLI2SDivQ); |
| } |
| |
| /*----------------- In Case of PLLI2S is just selected -----------------*/ |
| if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S) |
| { |
| /* Check for Parameters */ |
| assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ)); |
| assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR)); |
| |
| /* Configure the PLLI2S multiplication and division factors */ |
| __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR); |
| } |
| |
| /* Enable the PLLI2S */ |
| __HAL_RCC_PLLI2S_ENABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLI2S is ready */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*----------------------- SAI/LTDC Configuration (PLLSAI) ------------------*/ |
| /*----------------------- Common configuration SAI/LTDC --------------------*/ |
| /* In Case of SAI, LTDC or CLK48 Clock Configuration through PLLSAI, PLLSAIN division |
| factor is common parameters for these peripherals */ |
| if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == RCC_PERIPHCLK_SAI_PLLSAI) || |
| (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC) || |
| ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48) && |
| (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP))) |
| { |
| /* Check the PLLSAI division factors */ |
| assert_param(IS_RCC_PLLSAIN_VALUE(PeriphClkInit->PLLSAI.PLLSAIN)); |
| |
| /* Disable PLLSAI Clock */ |
| __HAL_RCC_PLLSAI_DISABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLSAI is disabled */ |
| while(__HAL_RCC_PLLSAI_GET_FLAG() != RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| /*---------------------------- SAI configuration -------------------------*/ |
| /* In Case of SAI Clock Configuration through PLLSAI, PLLSAIQ and PLLSAI_DIVQ must |
| be added only for SAI configuration */ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == (RCC_PERIPHCLK_SAI_PLLSAI)) |
| { |
| assert_param(IS_RCC_PLLSAIQ_VALUE(PeriphClkInit->PLLSAI.PLLSAIQ)); |
| assert_param(IS_RCC_PLLSAI_DIVQ_VALUE(PeriphClkInit->PLLSAIDivQ)); |
| |
| /* Read PLLSAIP value from PLLSAICFGR register (this value is not needed for SAI configuration) */ |
| pllsaip = ((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U); |
| /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */ |
| pllsair = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos); |
| /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */ |
| /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */ |
| /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */ |
| __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, pllsaip, PeriphClkInit->PLLSAI.PLLSAIQ, pllsair); |
| /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */ |
| __HAL_RCC_PLLSAI_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLSAIDivQ); |
| } |
| |
| /*---------------------------- LTDC configuration ------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == (RCC_PERIPHCLK_LTDC)) |
| { |
| assert_param(IS_RCC_PLLSAIR_VALUE(PeriphClkInit->PLLSAI.PLLSAIR)); |
| assert_param(IS_RCC_PLLSAI_DIVR_VALUE(PeriphClkInit->PLLSAIDivR)); |
| |
| /* Read PLLSAIP value from PLLSAICFGR register (this value is not needed for SAI configuration) */ |
| pllsaip = ((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U); |
| /* Read PLLSAIQ value from PLLSAICFGR register (this value is not need for SAI configuration) */ |
| pllsaiq = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos); |
| /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */ |
| /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */ |
| /* LTDC_CLK(first level) = PLLSAI_VCO Output/PLLSAIR */ |
| __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, pllsaip, pllsaiq, PeriphClkInit->PLLSAI.PLLSAIR); |
| /* LTDC_CLK = LTDC_CLK(first level)/PLLSAIDIVR */ |
| __HAL_RCC_PLLSAI_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLSAIDivR); |
| } |
| |
| /*---------------------------- CLK48 configuration ------------------------*/ |
| /* Configure the PLLSAI when it is used as clock source for CLK48 */ |
| if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == (RCC_PERIPHCLK_CLK48)) && |
| (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP)) |
| { |
| assert_param(IS_RCC_PLLSAIP_VALUE(PeriphClkInit->PLLSAI.PLLSAIP)); |
| |
| /* Read PLLSAIQ value from PLLSAICFGR register (this value is not need for SAI configuration) */ |
| pllsaiq = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos); |
| /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */ |
| pllsair = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos); |
| /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */ |
| /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */ |
| /* CLK48_CLK(first level) = PLLSAI_VCO Output/PLLSAIP */ |
| __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, PeriphClkInit->PLLSAI.PLLSAIP, pllsaiq, pllsair); |
| } |
| |
| /* Enable PLLSAI Clock */ |
| __HAL_RCC_PLLSAI_ENABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLSAI is ready */ |
| while(__HAL_RCC_PLLSAI_GET_FLAG() == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- RTC configuration ---------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC)) |
| { |
| /* Check for RTC Parameters used to output RTCCLK */ |
| assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection)); |
| |
| /* Enable Power Clock*/ |
| __HAL_RCC_PWR_CLK_ENABLE(); |
| |
| /* Enable write access to Backup domain */ |
| PWR->CR |= PWR_CR_DBP; |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((PWR->CR & PWR_CR_DBP) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */ |
| tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL); |
| if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL))) |
| { |
| /* Store the content of BDCR register before the reset of Backup Domain */ |
| tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_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 BDCR register */ |
| RCC->BDCR = tmpreg1; |
| |
| /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */ |
| if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON)) |
| { |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| /* Wait till LSE is ready */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| } |
| __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- TIM configuration ---------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM)) |
| { |
| __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection); |
| } |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Configures the RCC_PeriphCLKInitTypeDef according to the internal |
| * RCC configuration registers. |
| * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that |
| * will be configured. |
| * @retval None |
| */ |
| void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tempreg; |
| |
| /* Set all possible values for the extended clock type parameter------------*/ |
| PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S | RCC_PERIPHCLK_SAI_PLLSAI |\ |
| RCC_PERIPHCLK_SAI_PLLI2S | RCC_PERIPHCLK_LTDC |\ |
| RCC_PERIPHCLK_TIM | RCC_PERIPHCLK_RTC |\ |
| RCC_PERIPHCLK_CLK48 | RCC_PERIPHCLK_SDIO; |
| |
| /* Get the PLLI2S Clock configuration --------------------------------------*/ |
| PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos); |
| PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos); |
| PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos); |
| /* Get the PLLSAI Clock configuration --------------------------------------*/ |
| PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> RCC_PLLSAICFGR_PLLSAIN_Pos); |
| PeriphClkInit->PLLSAI.PLLSAIR = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos); |
| PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos); |
| /* Get the PLLSAI/PLLI2S division factors ----------------------------------*/ |
| PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> RCC_DCKCFGR_PLLI2SDIVQ_Pos); |
| PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> RCC_DCKCFGR_PLLSAIDIVQ_Pos); |
| PeriphClkInit->PLLSAIDivR = (uint32_t)(RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVR); |
| /* Get the RTC Clock configuration -----------------------------------------*/ |
| tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE); |
| PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL)); |
| |
| /* Get the CLK48 clock configuration -------------------------------------*/ |
| PeriphClkInit->Clk48ClockSelection = __HAL_RCC_GET_CLK48_SOURCE(); |
| |
| /* Get the SDIO clock configuration ----------------------------------------*/ |
| PeriphClkInit->SdioClockSelection = __HAL_RCC_GET_SDIO_SOURCE(); |
| |
| if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET) |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED; |
| } |
| else |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED; |
| } |
| } |
| |
| /** |
| * @brief Return the peripheral clock frequency for a given peripheral(SAI..) |
| * @note Return 0 if peripheral clock identifier not managed by this API |
| * @param PeriphClk Peripheral clock identifier |
| * This parameter can be one of the following values: |
| * @arg RCC_PERIPHCLK_I2S: I2S peripheral clock |
| * @retval Frequency in KHz |
| */ |
| uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) |
| { |
| /* This variable used to store the I2S clock frequency (value in Hz) */ |
| uint32_t frequency = 0U; |
| /* This variable used to store the VCO Input (value in Hz) */ |
| uint32_t vcoinput = 0U; |
| uint32_t srcclk = 0U; |
| /* This variable used to store the VCO Output (value in Hz) */ |
| uint32_t vcooutput = 0U; |
| switch (PeriphClk) |
| { |
| case RCC_PERIPHCLK_I2S: |
| { |
| /* Get the current I2S source */ |
| srcclk = __HAL_RCC_GET_I2S_SOURCE(); |
| switch (srcclk) |
| { |
| /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */ |
| case RCC_I2SCLKSOURCE_EXT: |
| { |
| /* Set the I2S clock to the external clock value */ |
| frequency = EXTERNAL_CLOCK_VALUE; |
| break; |
| } |
| /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */ |
| case RCC_I2SCLKSOURCE_PLLI2S: |
| { |
| /* Configure the PLLI2S division factor */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U))); |
| /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U))); |
| break; |
| } |
| /* Clock not enabled for I2S*/ |
| default: |
| { |
| frequency = 0U; |
| break; |
| } |
| } |
| break; |
| } |
| } |
| return frequency; |
| } |
| #endif /* STM32F469xx || STM32F479xx */ |
| |
| #if defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) |
| /** |
| * @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(I2S, LTDC RTC and TIM). |
| * |
| * @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) and RCC_BDCR register are set to their reset values. |
| * |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tickstart = 0U; |
| uint32_t tmpreg1 = 0U; |
| #if defined(STM32F413xx) || defined(STM32F423xx) |
| uint32_t plli2sq = 0U; |
| #endif /* STM32F413xx || STM32F423xx */ |
| uint32_t plli2sused = 0U; |
| |
| /* Check the peripheral clock selection parameters */ |
| assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection)); |
| |
| /*----------------------------------- I2S APB1 configuration ---------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == (RCC_PERIPHCLK_I2S_APB1)) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_I2SAPB1CLKSOURCE(PeriphClkInit->I2sApb1ClockSelection)); |
| |
| /* Configure I2S Clock source */ |
| __HAL_RCC_I2S_APB1_CONFIG(PeriphClkInit->I2sApb1ClockSelection); |
| /* Enable the PLLI2S when it's used as clock source for I2S */ |
| if(PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S) |
| { |
| plli2sused = 1U; |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*----------------------------------- I2S APB2 configuration ---------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == (RCC_PERIPHCLK_I2S_APB2)) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_I2SAPB2CLKSOURCE(PeriphClkInit->I2sApb2ClockSelection)); |
| |
| /* Configure I2S Clock source */ |
| __HAL_RCC_I2S_APB2_CONFIG(PeriphClkInit->I2sApb2ClockSelection); |
| /* Enable the PLLI2S when it's used as clock source for I2S */ |
| if(PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S) |
| { |
| plli2sused = 1U; |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| #if defined(STM32F413xx) || defined(STM32F423xx) |
| /*----------------------- SAI1 Block A configuration -----------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIA) == (RCC_PERIPHCLK_SAIA)) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_SAIACLKSOURCE(PeriphClkInit->SaiAClockSelection)); |
| |
| /* Configure SAI1 Clock source */ |
| __HAL_RCC_SAI_BLOCKACLKSOURCE_CONFIG(PeriphClkInit->SaiAClockSelection); |
| /* Enable the PLLI2S when it's used as clock source for SAI */ |
| if(PeriphClkInit->SaiAClockSelection == RCC_SAIACLKSOURCE_PLLI2SR) |
| { |
| plli2sused = 1U; |
| } |
| /* Enable the PLLSAI when it's used as clock source for SAI */ |
| if(PeriphClkInit->SaiAClockSelection == RCC_SAIACLKSOURCE_PLLR) |
| { |
| /* Check for PLL/DIVR parameters */ |
| assert_param(IS_RCC_PLL_DIVR_VALUE(PeriphClkInit->PLLDivR)); |
| |
| /* SAI_CLK_x = SAI_CLK(first level)/PLLDIVR */ |
| __HAL_RCC_PLL_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLDivR); |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------- SAI1 Block B configuration ------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIB) == (RCC_PERIPHCLK_SAIB)) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_SAIBCLKSOURCE(PeriphClkInit->SaiBClockSelection)); |
| |
| /* Configure SAI1 Clock source */ |
| __HAL_RCC_SAI_BLOCKBCLKSOURCE_CONFIG(PeriphClkInit->SaiBClockSelection); |
| /* Enable the PLLI2S when it's used as clock source for SAI */ |
| if(PeriphClkInit->SaiBClockSelection == RCC_SAIBCLKSOURCE_PLLI2SR) |
| { |
| plli2sused = 1U; |
| } |
| /* Enable the PLLSAI when it's used as clock source for SAI */ |
| if(PeriphClkInit->SaiBClockSelection == RCC_SAIBCLKSOURCE_PLLR) |
| { |
| /* Check for PLL/DIVR parameters */ |
| assert_param(IS_RCC_PLL_DIVR_VALUE(PeriphClkInit->PLLDivR)); |
| |
| /* SAI_CLK_x = SAI_CLK(first level)/PLLDIVR */ |
| __HAL_RCC_PLL_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLDivR); |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| #endif /* STM32F413xx || STM32F423xx */ |
| |
| /*------------------------------------ RTC configuration -------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC)) |
| { |
| /* Check for RTC Parameters used to output RTCCLK */ |
| assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection)); |
| |
| /* Enable Power Clock*/ |
| __HAL_RCC_PWR_CLK_ENABLE(); |
| |
| /* Enable write access to Backup domain */ |
| PWR->CR |= PWR_CR_DBP; |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((PWR->CR & PWR_CR_DBP) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */ |
| tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL); |
| if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL))) |
| { |
| /* Store the content of BDCR register before the reset of Backup Domain */ |
| tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_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 BDCR register */ |
| RCC->BDCR = tmpreg1; |
| |
| /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */ |
| if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON)) |
| { |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| /* Wait till LSE is ready */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| } |
| __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*------------------------------------ TIM configuration -------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM)) |
| { |
| /* Configure Timer Prescaler */ |
| __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*------------------------------------- FMPI2C1 Configuration --------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_FMPI2C1) == RCC_PERIPHCLK_FMPI2C1) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_FMPI2C1CLKSOURCE(PeriphClkInit->Fmpi2c1ClockSelection)); |
| |
| /* Configure the FMPI2C1 clock source */ |
| __HAL_RCC_FMPI2C1_CONFIG(PeriphClkInit->Fmpi2c1ClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*------------------------------------- CLK48 Configuration ----------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_CLK48CLKSOURCE(PeriphClkInit->Clk48ClockSelection)); |
| |
| /* Configure the SDIO clock source */ |
| __HAL_RCC_CLK48_CONFIG(PeriphClkInit->Clk48ClockSelection); |
| |
| /* Enable the PLLI2S when it's used as clock source for CLK48 */ |
| if(PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLI2SQ) |
| { |
| plli2sused = 1U; |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*------------------------------------- SDIO Configuration -----------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_SDIOCLKSOURCE(PeriphClkInit->SdioClockSelection)); |
| |
| /* Configure the SDIO clock source */ |
| __HAL_RCC_SDIO_CONFIG(PeriphClkInit->SdioClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*-------------------------------------- PLLI2S Configuration --------------*/ |
| /* PLLI2S is configured when a peripheral will use it as source clock : I2S on APB1 or |
| I2S on APB2*/ |
| if((plli2sused == 1U) || (PeriphClkInit->PeriphClockSelection == RCC_PERIPHCLK_PLLI2S)) |
| { |
| /* Disable the PLLI2S */ |
| __HAL_RCC_PLLI2S_DISABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLI2S is disabled */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| /* check for common PLLI2S Parameters */ |
| assert_param(IS_RCC_PLLI2SCLKSOURCE(PeriphClkInit->PLLI2SSelection)); |
| assert_param(IS_RCC_PLLI2SM_VALUE(PeriphClkInit->PLLI2S.PLLI2SM)); |
| assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN)); |
| /*-------------------- Set the PLL I2S clock -----------------------------*/ |
| __HAL_RCC_PLL_I2S_CONFIG(PeriphClkInit->PLLI2SSelection); |
| |
| /*------- In Case of PLLI2S is selected as source clock for I2S ----------*/ |
| if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == RCC_PERIPHCLK_I2S_APB1) && (PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S)) || |
| ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == RCC_PERIPHCLK_I2S_APB2) && (PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S)) || |
| ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48) && (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLI2SQ)) || |
| ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO) && (PeriphClkInit->SdioClockSelection == RCC_SDIOCLKSOURCE_CLK48) && (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLI2SQ))) |
| { |
| /* check for Parameters */ |
| assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR)); |
| assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ)); |
| |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM)*/ |
| /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */ |
| __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR); |
| } |
| |
| #if defined(STM32F413xx) || defined(STM32F423xx) |
| /*------- In Case of PLLI2S is selected as source clock for SAI ----------*/ |
| if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIA) == RCC_PERIPHCLK_SAIA) && (PeriphClkInit->SaiAClockSelection == RCC_SAIACLKSOURCE_PLLI2SR)) || |
| ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIB) == RCC_PERIPHCLK_SAIB) && (PeriphClkInit->SaiBClockSelection == RCC_SAIBCLKSOURCE_PLLI2SR))) |
| { |
| /* Check for PLLI2S Parameters */ |
| assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR)); |
| /* Check for PLLI2S/DIVR parameters */ |
| assert_param(IS_RCC_PLLI2S_DIVR_VALUE(PeriphClkInit->PLLI2SDivR)); |
| |
| /* Read PLLI2SQ value from PLLI2SCFGR register (this value is not needed for SAI configuration) */ |
| plli2sq = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos); |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */ |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */ |
| __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, plli2sq, PeriphClkInit->PLLI2S.PLLI2SR); |
| |
| /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVR */ |
| __HAL_RCC_PLLI2S_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLI2SDivR); |
| } |
| #endif /* STM32F413xx || STM32F423xx */ |
| |
| /*----------------- In Case of PLLI2S is just selected ------------------*/ |
| if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S) |
| { |
| /* Check for Parameters */ |
| assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR)); |
| assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ)); |
| |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM)*/ |
| /* SPDIFRXCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SP */ |
| __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR); |
| } |
| |
| /* Enable the PLLI2S */ |
| __HAL_RCC_PLLI2S_ENABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLI2S is ready */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*-------------------- DFSDM1 clock source configuration -------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_DFSDM1CLKSOURCE(PeriphClkInit->Dfsdm1ClockSelection)); |
| |
| /* Configure the DFSDM1 interface clock source */ |
| __HAL_RCC_DFSDM1_CONFIG(PeriphClkInit->Dfsdm1ClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*-------------------- DFSDM1 Audio clock source configuration -------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1_AUDIO) == RCC_PERIPHCLK_DFSDM1_AUDIO) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_DFSDM1AUDIOCLKSOURCE(PeriphClkInit->Dfsdm1AudioClockSelection)); |
| |
| /* Configure the DFSDM1 Audio interface clock source */ |
| __HAL_RCC_DFSDM1AUDIO_CONFIG(PeriphClkInit->Dfsdm1AudioClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| #if defined(STM32F413xx) || defined(STM32F423xx) |
| /*-------------------- DFSDM2 clock source configuration -------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM2) == RCC_PERIPHCLK_DFSDM2) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_DFSDM2CLKSOURCE(PeriphClkInit->Dfsdm2ClockSelection)); |
| |
| /* Configure the DFSDM1 interface clock source */ |
| __HAL_RCC_DFSDM2_CONFIG(PeriphClkInit->Dfsdm2ClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*-------------------- DFSDM2 Audio clock source configuration -------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM2_AUDIO) == RCC_PERIPHCLK_DFSDM2_AUDIO) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_DFSDM2AUDIOCLKSOURCE(PeriphClkInit->Dfsdm2AudioClockSelection)); |
| |
| /* Configure the DFSDM1 Audio interface clock source */ |
| __HAL_RCC_DFSDM2AUDIO_CONFIG(PeriphClkInit->Dfsdm2AudioClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- LPTIM1 Configuration ------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_LPTIM1CLKSOURCE(PeriphClkInit->Lptim1ClockSelection)); |
| |
| /* Configure the LPTIM1 clock source */ |
| __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| #endif /* STM32F413xx || STM32F423xx */ |
| |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Get the RCC_PeriphCLKInitTypeDef according to the internal |
| * RCC configuration registers. |
| * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that |
| * will be configured. |
| * @retval None |
| */ |
| void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tempreg; |
| |
| /* Set all possible values for the extended clock type parameter------------*/ |
| #if defined(STM32F413xx) || defined(STM32F423xx) |
| PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_I2S_APB2 |\ |
| RCC_PERIPHCLK_TIM | RCC_PERIPHCLK_RTC |\ |
| RCC_PERIPHCLK_FMPI2C1 | RCC_PERIPHCLK_CLK48 |\ |
| RCC_PERIPHCLK_SDIO | RCC_PERIPHCLK_DFSDM1 |\ |
| RCC_PERIPHCLK_DFSDM1_AUDIO | RCC_PERIPHCLK_DFSDM2 |\ |
| RCC_PERIPHCLK_DFSDM2_AUDIO | RCC_PERIPHCLK_LPTIM1 |\ |
| RCC_PERIPHCLK_SAIA | RCC_PERIPHCLK_SAIB; |
| #else /* STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx */ |
| PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_I2S_APB2 |\ |
| RCC_PERIPHCLK_TIM | RCC_PERIPHCLK_RTC |\ |
| RCC_PERIPHCLK_FMPI2C1 | RCC_PERIPHCLK_CLK48 |\ |
| RCC_PERIPHCLK_SDIO | RCC_PERIPHCLK_DFSDM1 |\ |
| RCC_PERIPHCLK_DFSDM1_AUDIO; |
| #endif /* STM32F413xx || STM32F423xx */ |
| |
| |
| |
| /* Get the PLLI2S Clock configuration --------------------------------------*/ |
| PeriphClkInit->PLLI2S.PLLI2SM = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM) >> RCC_PLLI2SCFGR_PLLI2SM_Pos); |
| PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos); |
| PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos); |
| PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos); |
| #if defined(STM32F413xx) || defined(STM32F423xx) |
| /* Get the PLL/PLLI2S division factors -------------------------------------*/ |
| PeriphClkInit->PLLI2SDivR = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVR) >> RCC_DCKCFGR_PLLI2SDIVR_Pos); |
| PeriphClkInit->PLLDivR = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLDIVR) >> RCC_DCKCFGR_PLLDIVR_Pos); |
| #endif /* STM32F413xx || STM32F423xx */ |
| |
| /* Get the I2S APB1 clock configuration ------------------------------------*/ |
| PeriphClkInit->I2sApb1ClockSelection = __HAL_RCC_GET_I2S_APB1_SOURCE(); |
| |
| /* Get the I2S APB2 clock configuration ------------------------------------*/ |
| PeriphClkInit->I2sApb2ClockSelection = __HAL_RCC_GET_I2S_APB2_SOURCE(); |
| |
| /* Get the RTC Clock configuration -----------------------------------------*/ |
| tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE); |
| PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL)); |
| |
| /* Get the FMPI2C1 clock configuration -------------------------------------*/ |
| PeriphClkInit->Fmpi2c1ClockSelection = __HAL_RCC_GET_FMPI2C1_SOURCE(); |
| |
| /* Get the CLK48 clock configuration ---------------------------------------*/ |
| PeriphClkInit->Clk48ClockSelection = __HAL_RCC_GET_CLK48_SOURCE(); |
| |
| /* Get the SDIO clock configuration ----------------------------------------*/ |
| PeriphClkInit->SdioClockSelection = __HAL_RCC_GET_SDIO_SOURCE(); |
| |
| /* Get the DFSDM1 clock configuration --------------------------------------*/ |
| PeriphClkInit->Dfsdm1ClockSelection = __HAL_RCC_GET_DFSDM1_SOURCE(); |
| |
| /* Get the DFSDM1 Audio clock configuration --------------------------------*/ |
| PeriphClkInit->Dfsdm1AudioClockSelection = __HAL_RCC_GET_DFSDM1AUDIO_SOURCE(); |
| |
| #if defined(STM32F413xx) || defined(STM32F423xx) |
| /* Get the DFSDM2 clock configuration --------------------------------------*/ |
| PeriphClkInit->Dfsdm2ClockSelection = __HAL_RCC_GET_DFSDM2_SOURCE(); |
| |
| /* Get the DFSDM2 Audio clock configuration --------------------------------*/ |
| PeriphClkInit->Dfsdm2AudioClockSelection = __HAL_RCC_GET_DFSDM2AUDIO_SOURCE(); |
| |
| /* Get the LPTIM1 clock configuration --------------------------------------*/ |
| PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE(); |
| |
| /* Get the SAI1 Block Aclock configuration ---------------------------------*/ |
| PeriphClkInit->SaiAClockSelection = __HAL_RCC_GET_SAI_BLOCKA_SOURCE(); |
| |
| /* Get the SAI1 Block B clock configuration --------------------------------*/ |
| PeriphClkInit->SaiBClockSelection = __HAL_RCC_GET_SAI_BLOCKB_SOURCE(); |
| #endif /* STM32F413xx || STM32F423xx */ |
| |
| /* Get the TIM Prescaler configuration -------------------------------------*/ |
| if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET) |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED; |
| } |
| else |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED; |
| } |
| } |
| |
| /** |
| * @brief Return the peripheral clock frequency for a given peripheral(I2S..) |
| * @note Return 0 if peripheral clock identifier not managed by this API |
| * @param PeriphClk Peripheral clock identifier |
| * This parameter can be one of the following values: |
| * @arg RCC_PERIPHCLK_I2S_APB1: I2S APB1 peripheral clock |
| * @arg RCC_PERIPHCLK_I2S_APB2: I2S APB2 peripheral clock |
| * @retval Frequency in KHz |
| */ |
| uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) |
| { |
| /* This variable used to store the I2S clock frequency (value in Hz) */ |
| uint32_t frequency = 0U; |
| /* This variable used to store the VCO Input (value in Hz) */ |
| uint32_t vcoinput = 0U; |
| uint32_t srcclk = 0U; |
| /* This variable used to store the VCO Output (value in Hz) */ |
| uint32_t vcooutput = 0U; |
| switch (PeriphClk) |
| { |
| case RCC_PERIPHCLK_I2S_APB1: |
| { |
| /* Get the current I2S source */ |
| srcclk = __HAL_RCC_GET_I2S_APB1_SOURCE(); |
| switch (srcclk) |
| { |
| /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */ |
| case RCC_I2SAPB1CLKSOURCE_EXT: |
| { |
| /* Set the I2S clock to the external clock value */ |
| frequency = EXTERNAL_CLOCK_VALUE; |
| break; |
| } |
| /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */ |
| case RCC_I2SAPB1CLKSOURCE_PLLI2S: |
| { |
| if((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SSRC) == RCC_PLLI2SCFGR_PLLI2SSRC) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(EXTERNAL_CLOCK_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| else |
| { |
| /* Configure the PLLI2S division factor */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| } |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U))); |
| /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U))); |
| break; |
| } |
| /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */ |
| case RCC_I2SAPB1CLKSOURCE_PLLR: |
| { |
| /* Configure the PLL division factor R */ |
| /* PLL_VCO Input = PLL_SOURCE/PLLM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| |
| /* PLL_VCO Output = PLL_VCO Input * PLLN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U))); |
| /* I2S_CLK = PLL_VCO Output/PLLR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U))); |
| break; |
| } |
| /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */ |
| case RCC_I2SAPB1CLKSOURCE_PLLSRC: |
| { |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| frequency = HSE_VALUE; |
| } |
| else |
| { |
| frequency = HSI_VALUE; |
| } |
| break; |
| } |
| /* Clock not enabled for I2S*/ |
| default: |
| { |
| frequency = 0U; |
| break; |
| } |
| } |
| break; |
| } |
| case RCC_PERIPHCLK_I2S_APB2: |
| { |
| /* Get the current I2S source */ |
| srcclk = __HAL_RCC_GET_I2S_APB2_SOURCE(); |
| switch (srcclk) |
| { |
| /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */ |
| case RCC_I2SAPB2CLKSOURCE_EXT: |
| { |
| /* Set the I2S clock to the external clock value */ |
| frequency = EXTERNAL_CLOCK_VALUE; |
| break; |
| } |
| /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */ |
| case RCC_I2SAPB2CLKSOURCE_PLLI2S: |
| { |
| if((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SSRC) == RCC_PLLI2SCFGR_PLLI2SSRC) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(EXTERNAL_CLOCK_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| else |
| { |
| /* Configure the PLLI2S division factor */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| } |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U))); |
| /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U))); |
| break; |
| } |
| /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */ |
| case RCC_I2SAPB2CLKSOURCE_PLLR: |
| { |
| /* Configure the PLL division factor R */ |
| /* PLL_VCO Input = PLL_SOURCE/PLLM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| |
| /* PLL_VCO Output = PLL_VCO Input * PLLN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U))); |
| /* I2S_CLK = PLL_VCO Output/PLLR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U))); |
| break; |
| } |
| /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */ |
| case RCC_I2SAPB2CLKSOURCE_PLLSRC: |
| { |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| frequency = HSE_VALUE; |
| } |
| else |
| { |
| frequency = HSI_VALUE; |
| } |
| break; |
| } |
| /* Clock not enabled for I2S*/ |
| default: |
| { |
| frequency = 0U; |
| break; |
| } |
| } |
| break; |
| } |
| } |
| return frequency; |
| } |
| #endif /* STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ |
| |
| #if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) |
| /** |
| * @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(I2S and RTC clocks). |
| * |
| * @note A caution to be taken when HAL_RCCEx_PeriphCLKConfig() is used to select RTC clock selection, in this case |
| * the Reset of Backup domain will be applied in order to modify the RTC Clock source as consequence all backup |
| * domain (RTC and RCC_BDCR register expect BKPSRAM) will be reset |
| * |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tickstart = 0U; |
| uint32_t tmpreg1 = 0U; |
| |
| /* Check the parameters */ |
| assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection)); |
| |
| /*---------------------------- RTC configuration ---------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC)) |
| { |
| /* Check for RTC Parameters used to output RTCCLK */ |
| assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection)); |
| |
| /* Enable Power Clock*/ |
| __HAL_RCC_PWR_CLK_ENABLE(); |
| |
| /* Enable write access to Backup domain */ |
| PWR->CR |= PWR_CR_DBP; |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((PWR->CR & PWR_CR_DBP) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */ |
| tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL); |
| if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL))) |
| { |
| /* Store the content of BDCR register before the reset of Backup Domain */ |
| tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_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 BDCR register */ |
| RCC->BDCR = tmpreg1; |
| |
| /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */ |
| if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON)) |
| { |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| /* Wait till LSE is ready */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| } |
| __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- TIM configuration ---------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM)) |
| { |
| __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- FMPI2C1 Configuration -----------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_FMPI2C1) == RCC_PERIPHCLK_FMPI2C1) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_FMPI2C1CLKSOURCE(PeriphClkInit->Fmpi2c1ClockSelection)); |
| |
| /* Configure the FMPI2C1 clock source */ |
| __HAL_RCC_FMPI2C1_CONFIG(PeriphClkInit->Fmpi2c1ClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- LPTIM1 Configuration ------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_LPTIM1CLKSOURCE(PeriphClkInit->Lptim1ClockSelection)); |
| |
| /* Configure the LPTIM1 clock source */ |
| __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection); |
| } |
| |
| /*---------------------------- I2S Configuration ---------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_I2SAPBCLKSOURCE(PeriphClkInit->I2SClockSelection)); |
| |
| /* Configure the I2S clock source */ |
| __HAL_RCC_I2S_CONFIG(PeriphClkInit->I2SClockSelection); |
| } |
| |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Configures the RCC_OscInitStruct according to the internal |
| * RCC configuration registers. |
| * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that |
| * will be configured. |
| * @retval None |
| */ |
| void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tempreg; |
| |
| /* Set all possible values for the extended clock type parameter------------*/ |
| PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_FMPI2C1 | RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_TIM | RCC_PERIPHCLK_RTC; |
| |
| tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE); |
| PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL)); |
| |
| if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET) |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED; |
| } |
| else |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED; |
| } |
| /* Get the FMPI2C1 clock configuration -------------------------------------*/ |
| PeriphClkInit->Fmpi2c1ClockSelection = __HAL_RCC_GET_FMPI2C1_SOURCE(); |
| |
| /* Get the I2S clock configuration -----------------------------------------*/ |
| PeriphClkInit->I2SClockSelection = __HAL_RCC_GET_I2S_SOURCE(); |
| |
| |
| } |
| /** |
| * @brief Return the peripheral clock frequency for a given peripheral(SAI..) |
| * @note Return 0 if peripheral clock identifier not managed by this API |
| * @param PeriphClk Peripheral clock identifier |
| * This parameter can be one of the following values: |
| * @arg RCC_PERIPHCLK_I2S: I2S peripheral clock |
| * @retval Frequency in KHz |
| */ |
| uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) |
| { |
| /* This variable used to store the I2S clock frequency (value in Hz) */ |
| uint32_t frequency = 0U; |
| /* This variable used to store the VCO Input (value in Hz) */ |
| uint32_t vcoinput = 0U; |
| uint32_t srcclk = 0U; |
| /* This variable used to store the VCO Output (value in Hz) */ |
| uint32_t vcooutput = 0U; |
| switch (PeriphClk) |
| { |
| case RCC_PERIPHCLK_I2S: |
| { |
| /* Get the current I2S source */ |
| srcclk = __HAL_RCC_GET_I2S_SOURCE(); |
| switch (srcclk) |
| { |
| /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */ |
| case RCC_I2SAPBCLKSOURCE_EXT: |
| { |
| /* Set the I2S clock to the external clock value */ |
| frequency = EXTERNAL_CLOCK_VALUE; |
| break; |
| } |
| /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */ |
| case RCC_I2SAPBCLKSOURCE_PLLR: |
| { |
| /* Configure the PLL division factor R */ |
| /* PLL_VCO Input = PLL_SOURCE/PLLM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| |
| /* PLL_VCO Output = PLL_VCO Input * PLLN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U))); |
| /* I2S_CLK = PLL_VCO Output/PLLR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U))); |
| break; |
| } |
| /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */ |
| case RCC_I2SAPBCLKSOURCE_PLLSRC: |
| { |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| frequency = HSE_VALUE; |
| } |
| else |
| { |
| frequency = HSI_VALUE; |
| } |
| break; |
| } |
| /* Clock not enabled for I2S*/ |
| default: |
| { |
| frequency = 0U; |
| break; |
| } |
| } |
| break; |
| } |
| } |
| return frequency; |
| } |
| #endif /* STM32F410Tx || STM32F410Cx || STM32F410Rx */ |
| |
| #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) |
| /** |
| * @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(I2S, SAI, LTDC RTC and TIM). |
| * |
| * @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) and RCC_BDCR register are set to their reset values. |
| * |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tickstart = 0U; |
| uint32_t tmpreg1 = 0U; |
| |
| /* Check the parameters */ |
| assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection)); |
| |
| /*----------------------- SAI/I2S Configuration (PLLI2S) -------------------*/ |
| /*----------------------- Common configuration SAI/I2S ---------------------*/ |
| /* In Case of SAI or I2S Clock Configuration through PLLI2S, PLLI2SN division |
| factor is common parameters for both peripherals */ |
| if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S) || |
| (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == RCC_PERIPHCLK_SAI_PLLI2S) || |
| (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)) |
| { |
| /* check for Parameters */ |
| assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN)); |
| |
| /* Disable the PLLI2S */ |
| __HAL_RCC_PLLI2S_DISABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLI2S is disabled */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| /*---------------------------- I2S configuration -------------------------*/ |
| /* In Case of I2S Clock Configuration through PLLI2S, PLLI2SR must be added |
| only for I2S configuration */ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == (RCC_PERIPHCLK_I2S)) |
| { |
| /* check for Parameters */ |
| assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR)); |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLM) */ |
| /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */ |
| __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SR); |
| } |
| |
| /*---------------------------- SAI configuration -------------------------*/ |
| /* In Case of SAI Clock Configuration through PLLI2S, PLLI2SQ and PLLI2S_DIVQ must |
| be added only for SAI configuration */ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == (RCC_PERIPHCLK_SAI_PLLI2S)) |
| { |
| /* Check the PLLI2S division factors */ |
| assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ)); |
| assert_param(IS_RCC_PLLI2S_DIVQ_VALUE(PeriphClkInit->PLLI2SDivQ)); |
| |
| /* Read PLLI2SR value from PLLI2SCFGR register (this value is not need for SAI configuration) */ |
| tmpreg1 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos); |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */ |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */ |
| __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SQ , tmpreg1); |
| /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */ |
| __HAL_RCC_PLLI2S_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLI2SDivQ); |
| } |
| |
| /*----------------- In Case of PLLI2S is just selected -----------------*/ |
| if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S) |
| { |
| /* Check for Parameters */ |
| assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ)); |
| assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR)); |
| |
| /* Configure the PLLI2S multiplication and division factors */ |
| __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR); |
| } |
| |
| /* Enable the PLLI2S */ |
| __HAL_RCC_PLLI2S_ENABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLI2S is ready */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*----------------------- SAI/LTDC Configuration (PLLSAI) ------------------*/ |
| /*----------------------- Common configuration SAI/LTDC --------------------*/ |
| /* In Case of SAI or LTDC Clock Configuration through PLLSAI, PLLSAIN division |
| factor is common parameters for both peripherals */ |
| if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == RCC_PERIPHCLK_SAI_PLLSAI) || |
| (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC)) |
| { |
| /* Check the PLLSAI division factors */ |
| assert_param(IS_RCC_PLLSAIN_VALUE(PeriphClkInit->PLLSAI.PLLSAIN)); |
| |
| /* Disable PLLSAI Clock */ |
| __HAL_RCC_PLLSAI_DISABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLSAI is disabled */ |
| while(__HAL_RCC_PLLSAI_GET_FLAG() != RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| /*---------------------------- SAI configuration -------------------------*/ |
| /* In Case of SAI Clock Configuration through PLLSAI, PLLSAIQ and PLLSAI_DIVQ must |
| be added only for SAI configuration */ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == (RCC_PERIPHCLK_SAI_PLLSAI)) |
| { |
| assert_param(IS_RCC_PLLSAIQ_VALUE(PeriphClkInit->PLLSAI.PLLSAIQ)); |
| assert_param(IS_RCC_PLLSAI_DIVQ_VALUE(PeriphClkInit->PLLSAIDivQ)); |
| |
| /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */ |
| tmpreg1 = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos); |
| /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */ |
| /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */ |
| /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */ |
| __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN , PeriphClkInit->PLLSAI.PLLSAIQ, tmpreg1); |
| /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */ |
| __HAL_RCC_PLLSAI_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLSAIDivQ); |
| } |
| |
| /*---------------------------- LTDC configuration ------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == (RCC_PERIPHCLK_LTDC)) |
| { |
| assert_param(IS_RCC_PLLSAIR_VALUE(PeriphClkInit->PLLSAI.PLLSAIR)); |
| assert_param(IS_RCC_PLLSAI_DIVR_VALUE(PeriphClkInit->PLLSAIDivR)); |
| |
| /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */ |
| tmpreg1 = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos); |
| /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */ |
| /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */ |
| /* LTDC_CLK(first level) = PLLSAI_VCO Output/PLLSAIR */ |
| __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN , tmpreg1, PeriphClkInit->PLLSAI.PLLSAIR); |
| /* LTDC_CLK = LTDC_CLK(first level)/PLLSAIDIVR */ |
| __HAL_RCC_PLLSAI_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLSAIDivR); |
| } |
| /* Enable PLLSAI Clock */ |
| __HAL_RCC_PLLSAI_ENABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLSAI is ready */ |
| while(__HAL_RCC_PLLSAI_GET_FLAG() == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- RTC configuration ---------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC)) |
| { |
| /* Check for RTC Parameters used to output RTCCLK */ |
| assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection)); |
| |
| /* Enable Power Clock*/ |
| __HAL_RCC_PWR_CLK_ENABLE(); |
| |
| /* Enable write access to Backup domain */ |
| PWR->CR |= PWR_CR_DBP; |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((PWR->CR & PWR_CR_DBP) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */ |
| tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL); |
| if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL))) |
| { |
| /* Store the content of BDCR register before the reset of Backup Domain */ |
| tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_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 BDCR register */ |
| RCC->BDCR = tmpreg1; |
| |
| /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */ |
| if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON)) |
| { |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| /* Wait till LSE is ready */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| } |
| __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection); |
| } |
| /*--------------------------------------------------------------------------*/ |
| |
| /*---------------------------- TIM configuration ---------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM)) |
| { |
| __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection); |
| } |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Configures the PeriphClkInit according to the internal |
| * RCC configuration registers. |
| * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that |
| * will be configured. |
| * @retval None |
| */ |
| void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tempreg; |
| |
| /* Set all possible values for the extended clock type parameter------------*/ |
| PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S | RCC_PERIPHCLK_SAI_PLLSAI | RCC_PERIPHCLK_SAI_PLLI2S | RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_TIM | RCC_PERIPHCLK_RTC; |
| |
| /* Get the PLLI2S Clock configuration -----------------------------------------------*/ |
| PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos); |
| PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos); |
| PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos); |
| /* Get the PLLSAI Clock configuration -----------------------------------------------*/ |
| PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> RCC_PLLSAICFGR_PLLSAIN_Pos); |
| PeriphClkInit->PLLSAI.PLLSAIR = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos); |
| PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos); |
| /* Get the PLLSAI/PLLI2S division factors -----------------------------------------------*/ |
| PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> RCC_DCKCFGR_PLLI2SDIVQ_Pos); |
| PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> RCC_DCKCFGR_PLLSAIDIVQ_Pos); |
| PeriphClkInit->PLLSAIDivR = (uint32_t)(RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVR); |
| /* Get the RTC Clock configuration -----------------------------------------------*/ |
| tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE); |
| PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL)); |
| |
| if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET) |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED; |
| } |
| else |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED; |
| } |
| } |
| |
| /** |
| * @brief Return the peripheral clock frequency for a given peripheral(SAI..) |
| * @note Return 0 if peripheral clock identifier not managed by this API |
| * @param PeriphClk Peripheral clock identifier |
| * This parameter can be one of the following values: |
| * @arg RCC_PERIPHCLK_I2S: I2S peripheral clock |
| * @retval Frequency in KHz |
| */ |
| uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) |
| { |
| /* This variable used to store the I2S clock frequency (value in Hz) */ |
| uint32_t frequency = 0U; |
| /* This variable used to store the VCO Input (value in Hz) */ |
| uint32_t vcoinput = 0U; |
| uint32_t srcclk = 0U; |
| /* This variable used to store the VCO Output (value in Hz) */ |
| uint32_t vcooutput = 0U; |
| switch (PeriphClk) |
| { |
| case RCC_PERIPHCLK_I2S: |
| { |
| /* Get the current I2S source */ |
| srcclk = __HAL_RCC_GET_I2S_SOURCE(); |
| switch (srcclk) |
| { |
| /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */ |
| case RCC_I2SCLKSOURCE_EXT: |
| { |
| /* Set the I2S clock to the external clock value */ |
| frequency = EXTERNAL_CLOCK_VALUE; |
| break; |
| } |
| /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */ |
| case RCC_I2SCLKSOURCE_PLLI2S: |
| { |
| /* Configure the PLLI2S division factor */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U))); |
| /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U))); |
| break; |
| } |
| /* Clock not enabled for I2S*/ |
| default: |
| { |
| frequency = 0U; |
| break; |
| } |
| } |
| break; |
| } |
| } |
| return frequency; |
| } |
| #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ |
| |
| #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx) ||\ |
| defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) |
| /** |
| * @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(I2S and RTC clocks). |
| * |
| * @note A caution to be taken when HAL_RCCEx_PeriphCLKConfig() is used to select RTC clock selection, in this case |
| * the Reset of Backup domain will be applied in order to modify the RTC Clock source as consequence all backup |
| * domain (RTC and RCC_BDCR register expect BKPSRAM) will be reset |
| * |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tickstart = 0U; |
| uint32_t tmpreg1 = 0U; |
| |
| /* Check the parameters */ |
| assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection)); |
| |
| /*---------------------------- I2S configuration ---------------------------*/ |
| if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S) || |
| (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)) |
| { |
| /* check for Parameters */ |
| assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR)); |
| assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN)); |
| #if defined(STM32F411xE) |
| assert_param(IS_RCC_PLLI2SM_VALUE(PeriphClkInit->PLLI2S.PLLI2SM)); |
| #endif /* STM32F411xE */ |
| /* Disable the PLLI2S */ |
| __HAL_RCC_PLLI2S_DISABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLI2S is disabled */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| #if defined(STM32F411xE) |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */ |
| /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */ |
| __HAL_RCC_PLLI2S_I2SCLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SR); |
| #else |
| /* Configure the PLLI2S division factors */ |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLM) */ |
| /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */ |
| __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SR); |
| #endif /* STM32F411xE */ |
| |
| /* Enable the PLLI2S */ |
| __HAL_RCC_PLLI2S_ENABLE(); |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| /* Wait till PLLI2S is ready */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| |
| /*---------------------------- RTC configuration ---------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC)) |
| { |
| /* Check for RTC Parameters used to output RTCCLK */ |
| assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection)); |
| |
| /* Enable Power Clock*/ |
| __HAL_RCC_PWR_CLK_ENABLE(); |
| |
| /* Enable write access to Backup domain */ |
| PWR->CR |= PWR_CR_DBP; |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((PWR->CR & PWR_CR_DBP) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */ |
| tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL); |
| if((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL))) |
| { |
| /* Store the content of BDCR register before the reset of Backup Domain */ |
| tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_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 BDCR register */ |
| RCC->BDCR = tmpreg1; |
| |
| /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */ |
| if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON)) |
| { |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| /* Wait till LSE is ready */ |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| } |
| __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection); |
| } |
| #if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) |
| /*---------------------------- TIM configuration ---------------------------*/ |
| if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM)) |
| { |
| __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection); |
| } |
| #endif /* STM32F401xC || STM32F401xE || STM32F411xE */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Configures the RCC_OscInitStruct according to the internal |
| * RCC configuration registers. |
| * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that |
| * will be configured. |
| * @retval None |
| */ |
| void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) |
| { |
| uint32_t tempreg; |
| |
| /* Set all possible values for the extended clock type parameter------------*/ |
| PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S | RCC_PERIPHCLK_RTC; |
| |
| /* Get the PLLI2S Clock configuration --------------------------------------*/ |
| PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos); |
| PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos); |
| #if defined(STM32F411xE) |
| PeriphClkInit->PLLI2S.PLLI2SM = (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM); |
| #endif /* STM32F411xE */ |
| /* Get the RTC Clock configuration -----------------------------------------*/ |
| tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE); |
| PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL)); |
| |
| #if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) |
| /* Get the TIM Prescaler configuration -------------------------------------*/ |
| if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET) |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED; |
| } |
| else |
| { |
| PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED; |
| } |
| #endif /* STM32F401xC || STM32F401xE || STM32F411xE */ |
| } |
| |
| /** |
| * @brief Return the peripheral clock frequency for a given peripheral(SAI..) |
| * @note Return 0 if peripheral clock identifier not managed by this API |
| * @param PeriphClk Peripheral clock identifier |
| * This parameter can be one of the following values: |
| * @arg RCC_PERIPHCLK_I2S: I2S peripheral clock |
| * @retval Frequency in KHz |
| */ |
| uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) |
| { |
| /* This variable used to store the I2S clock frequency (value in Hz) */ |
| uint32_t frequency = 0U; |
| /* This variable used to store the VCO Input (value in Hz) */ |
| uint32_t vcoinput = 0U; |
| uint32_t srcclk = 0U; |
| /* This variable used to store the VCO Output (value in Hz) */ |
| uint32_t vcooutput = 0U; |
| switch (PeriphClk) |
| { |
| case RCC_PERIPHCLK_I2S: |
| { |
| /* Get the current I2S source */ |
| srcclk = __HAL_RCC_GET_I2S_SOURCE(); |
| switch (srcclk) |
| { |
| /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */ |
| case RCC_I2SCLKSOURCE_EXT: |
| { |
| /* Set the I2S clock to the external clock value */ |
| frequency = EXTERNAL_CLOCK_VALUE; |
| break; |
| } |
| /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */ |
| case RCC_I2SCLKSOURCE_PLLI2S: |
| { |
| #if defined(STM32F411xE) |
| /* Configure the PLLI2S division factor */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); |
| } |
| #else |
| /* Configure the PLLI2S division factor */ |
| /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */ |
| if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| else |
| { |
| /* Get the I2S source clock value */ |
| vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); |
| } |
| #endif /* STM32F411xE */ |
| /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ |
| vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U))); |
| /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */ |
| frequency = (uint32_t)(vcooutput /(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U))); |
| break; |
| } |
| /* Clock not enabled for I2S*/ |
| default: |
| { |
| frequency = 0U; |
| break; |
| } |
| } |
| break; |
| } |
| } |
| return frequency; |
| } |
| #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F401xC || STM32F401xE || STM32F411xE */ |
| |
| #if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) || defined(STM32F411xE) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||\ |
| defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) |
| /** |
| * @brief Select LSE mode |
| * |
| * @note This mode is only available for STM32F410xx/STM32F411xx/STM32F446xx/STM32F469xx/STM32F479xx/STM32F412Zx/STM32F412Vx/STM32F412Rx/STM32F412Cx devices. |
| * |
| * @param Mode specifies the LSE mode. |
| * This parameter can be one of the following values: |
| * @arg RCC_LSE_LOWPOWER_MODE: LSE oscillator in low power mode selection |
| * @arg RCC_LSE_HIGHDRIVE_MODE: LSE oscillator in High Drive mode selection |
| * @retval None |
| */ |
| void HAL_RCCEx_SelectLSEMode(uint8_t Mode) |
| { |
| /* Check the parameters */ |
| assert_param(IS_RCC_LSE_MODE(Mode)); |
| if(Mode == RCC_LSE_HIGHDRIVE_MODE) |
| { |
| SET_BIT(RCC->BDCR, RCC_BDCR_LSEMOD); |
| } |
| else |
| { |
| CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEMOD); |
| } |
| } |
| |
| #endif /* STM32F410xx || STM32F411xE || STM32F446xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ |
| |
| /** @defgroup RCCEx_Exported_Functions_Group2 Extended Clock management functions |
| * @brief Extended Clock management functions |
| * |
| @verbatim |
| =============================================================================== |
| ##### Extended clock management functions ##### |
| =============================================================================== |
| [..] |
| This subsection provides a set of functions allowing to control the |
| activation or deactivation of PLLI2S, PLLSAI. |
| @endverbatim |
| * @{ |
| */ |
| |
| #if defined(RCC_PLLI2S_SUPPORT) |
| /** |
| * @brief Enable PLLI2S. |
| * @param PLLI2SInit pointer to an RCC_PLLI2SInitTypeDef structure that |
| * contains the configuration information for the PLLI2S |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_RCCEx_EnablePLLI2S(RCC_PLLI2SInitTypeDef *PLLI2SInit) |
| { |
| uint32_t tickstart; |
| |
| /* Check for parameters */ |
| assert_param(IS_RCC_PLLI2SN_VALUE(PLLI2SInit->PLLI2SN)); |
| assert_param(IS_RCC_PLLI2SR_VALUE(PLLI2SInit->PLLI2SR)); |
| #if defined(RCC_PLLI2SCFGR_PLLI2SM) |
| assert_param(IS_RCC_PLLI2SM_VALUE(PLLI2SInit->PLLI2SM)); |
| #endif /* RCC_PLLI2SCFGR_PLLI2SM */ |
| #if defined(RCC_PLLI2SCFGR_PLLI2SP) |
| assert_param(IS_RCC_PLLI2SP_VALUE(PLLI2SInit->PLLI2SP)); |
| #endif /* RCC_PLLI2SCFGR_PLLI2SP */ |
| #if defined(RCC_PLLI2SCFGR_PLLI2SQ) |
| assert_param(IS_RCC_PLLI2SQ_VALUE(PLLI2SInit->PLLI2SQ)); |
| #endif /* RCC_PLLI2SCFGR_PLLI2SQ */ |
| |
| /* Disable the PLLI2S */ |
| __HAL_RCC_PLLI2S_DISABLE(); |
| |
| /* Wait till PLLI2S is disabled */ |
| tickstart = HAL_GetTick(); |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| /* Configure the PLLI2S division factors */ |
| #if defined(STM32F446xx) |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */ |
| /* I2SPCLK = PLLI2S_VCO / PLLI2SP */ |
| /* I2SQCLK = PLLI2S_VCO / PLLI2SQ */ |
| /* I2SRCLK = PLLI2S_VCO / PLLI2SR */ |
| __HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SM, PLLI2SInit->PLLI2SN, \ |
| PLLI2SInit->PLLI2SP, PLLI2SInit->PLLI2SQ, PLLI2SInit->PLLI2SR); |
| #elif defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) ||\ |
| defined(STM32F413xx) || defined(STM32F423xx) |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM)*/ |
| /* I2SQCLK = PLLI2S_VCO / PLLI2SQ */ |
| /* I2SRCLK = PLLI2S_VCO / PLLI2SR */ |
| __HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SM, PLLI2SInit->PLLI2SN, \ |
| PLLI2SInit->PLLI2SQ, PLLI2SInit->PLLI2SR); |
| #elif defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ |
| defined(STM32F469xx) || defined(STM32F479xx) |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * PLLI2SN */ |
| /* I2SQCLK = PLLI2S_VCO / PLLI2SQ */ |
| /* I2SRCLK = PLLI2S_VCO / PLLI2SR */ |
| __HAL_RCC_PLLI2S_SAICLK_CONFIG(PLLI2SInit->PLLI2SN, PLLI2SInit->PLLI2SQ, PLLI2SInit->PLLI2SR); |
| #elif defined(STM32F411xE) |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */ |
| /* I2SRCLK = PLLI2S_VCO / PLLI2SR */ |
| __HAL_RCC_PLLI2S_I2SCLK_CONFIG(PLLI2SInit->PLLI2SM, PLLI2SInit->PLLI2SN, PLLI2SInit->PLLI2SR); |
| #else |
| /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) x PLLI2SN */ |
| /* I2SRCLK = PLLI2S_VCO / PLLI2SR */ |
| __HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SN, PLLI2SInit->PLLI2SR); |
| #endif /* STM32F446xx */ |
| |
| /* Enable the PLLI2S */ |
| __HAL_RCC_PLLI2S_ENABLE(); |
| |
| /* Wait till PLLI2S is ready */ |
| tickstart = HAL_GetTick(); |
| while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Disable PLLI2S. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_RCCEx_DisablePLLI2S(void) |
| { |
| uint32_t tickstart; |
| |
| /* Disable the PLLI2S */ |
| __HAL_RCC_PLLI2S_DISABLE(); |
| |
| /* Wait till PLLI2S is disabled */ |
| tickstart = HAL_GetTick(); |
| while(READ_BIT(RCC->CR, RCC_CR_PLLI2SRDY) != RESET) |
| { |
| if((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| return HAL_OK; |
| } |
| |
| #endif /* RCC_PLLI2S_SUPPORT */ |
| |
| #if defined(RCC_PLLSAI_SUPPORT) |
| /** |
| * @brief Enable PLLSAI. |
| * @param PLLSAIInit pointer to an RCC_PLLSAIInitTypeDef structure that |
| * contains the configuration information for the PLLSAI |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI(RCC_PLLSAIInitTypeDef *PLLSAIInit) |
| { |
| uint32_t tickstart; |
| |
| /* Check for parameters */ |
| assert_param(IS_RCC_PLLSAIN_VALUE(PLLSAIInit->PLLSAIN)); |
| assert_param(IS_RCC_PLLSAIQ_VALUE(PLLSAIInit->PLLSAIQ)); |
| #if defined(RCC_PLLSAICFGR_PLLSAIM) |
| assert_param(IS_RCC_PLLSAIM_VALUE(PLLSAIInit->PLLSAIM)); |
| #endif /* RCC_PLLSAICFGR_PLLSAIM */ |
| #if defined(RCC_PLLSAICFGR_PLLSAIP) |
| assert_param(IS_RCC_PLLSAIP_VALUE(PLLSAIInit->PLLSAIP)); |
| #endif /* RCC_PLLSAICFGR_PLLSAIP */ |
| #if defined(RCC_PLLSAICFGR_PLLSAIR) |
| assert_param(IS_RCC_PLLSAIR_VALUE(PLLSAIInit->PLLSAIR)); |
| #endif /* RCC_PLLSAICFGR_PLLSAIR */ |
| |
| /* Disable the PLLSAI */ |
| __HAL_RCC_PLLSAI_DISABLE(); |
| |
| /* Wait till PLLSAI is disabled */ |
| tickstart = HAL_GetTick(); |
| while(__HAL_RCC_PLLSAI_GET_FLAG() != RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| /* Configure the PLLSAI division factors */ |
| #if defined(STM32F446xx) |
| /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) * (PLLSAIN/PLLSAIM) */ |
| /* SAIPCLK = PLLSAI_VCO / PLLSAIP */ |
| /* SAIQCLK = PLLSAI_VCO / PLLSAIQ */ |
| /* SAIRCLK = PLLSAI_VCO / PLLSAIR */ |
| __HAL_RCC_PLLSAI_CONFIG(PLLSAIInit->PLLSAIM, PLLSAIInit->PLLSAIN, \ |
| PLLSAIInit->PLLSAIP, PLLSAIInit->PLLSAIQ, 0U); |
| #elif defined(STM32F469xx) || defined(STM32F479xx) |
| /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) * PLLSAIN */ |
| /* SAIPCLK = PLLSAI_VCO / PLLSAIP */ |
| /* SAIQCLK = PLLSAI_VCO / PLLSAIQ */ |
| /* SAIRCLK = PLLSAI_VCO / PLLSAIR */ |
| __HAL_RCC_PLLSAI_CONFIG(PLLSAIInit->PLLSAIN, PLLSAIInit->PLLSAIP, \ |
| PLLSAIInit->PLLSAIQ, PLLSAIInit->PLLSAIR); |
| #else |
| /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) x PLLSAIN */ |
| /* SAIQCLK = PLLSAI_VCO / PLLSAIQ */ |
| /* SAIRCLK = PLLSAI_VCO / PLLSAIR */ |
| __HAL_RCC_PLLSAI_CONFIG(PLLSAIInit->PLLSAIN, PLLSAIInit->PLLSAIQ, PLLSAIInit->PLLSAIR); |
| #endif /* STM32F446xx */ |
| |
| /* Enable the PLLSAI */ |
| __HAL_RCC_PLLSAI_ENABLE(); |
| |
| /* Wait till PLLSAI is ready */ |
| tickstart = HAL_GetTick(); |
| while(__HAL_RCC_PLLSAI_GET_FLAG() == RESET) |
| { |
| if((HAL_GetTick() - tickstart ) > PLLSAI_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Disable PLLSAI. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI(void) |
| { |
| uint32_t tickstart; |
| |
| /* Disable the PLLSAI */ |
| __HAL_RCC_PLLSAI_DISABLE(); |
| |
| /* Wait till PLLSAI is disabled */ |
| tickstart = HAL_GetTick(); |
| while(__HAL_RCC_PLLSAI_GET_FLAG() != RESET) |
| { |
| if((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE) |
| { |
| /* return in case of Timeout detected */ |
| return HAL_TIMEOUT; |
| } |
| } |
| |
| return HAL_OK; |
| } |
| |
| #endif /* RCC_PLLSAI_SUPPORT */ |
| |
| /** |
| * @} |
| */ |
| |
| #if defined(STM32F446xx) |
| /** |
| * @brief Returns the SYSCLK frequency |
| * |
| * @note This function implementation is valid only for STM32F446xx devices. |
| * @note This function add the PLL/PLLR System clock source |
| * |
| * @note The system frequency computed by this function is not the real |
| * frequency in the chip. It is calculated based on the predefined |
| * constant and the selected clock source: |
| * @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(*) |
| * @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(**) |
| * @note If SYSCLK source is PLL or PLLR, function returns values based on HSE_VALUE(**) |
| * or HSI_VALUE(*) multiplied/divided by the PLL factors. |
| * @note (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value |
| * 16 MHz) but the real value may vary depending on the variations |
| * in voltage and temperature. |
| * @note (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value |
| * 25 MHz), user has to ensure that HSE_VALUE is same as the real |
| * frequency of the crystal used. Otherwise, this function may |
| * have wrong result. |
| * |
| * @note The result of this function could be not correct when using fractional |
| * value for HSE crystal. |
| * |
| * @note This function can be used by the user application to compute the |
| * baudrate for the communication peripherals or configure other parameters. |
| * |
| * @note Each time SYSCLK changes, this function must be called to update the |
| * right SYSCLK value. Otherwise, any configuration based on this function will be incorrect. |
| * |
| * |
| * @retval SYSCLK frequency |
| */ |
| uint32_t HAL_RCC_GetSysClockFreq(void) |
| { |
| uint32_t pllm = 0U; |
| uint32_t pllvco = 0U; |
| uint32_t pllp = 0U; |
| uint32_t pllr = 0U; |
| uint32_t sysclockfreq = 0U; |
| |
| /* Get SYSCLK source -------------------------------------------------------*/ |
| switch (RCC->CFGR & RCC_CFGR_SWS) |
| { |
| case RCC_CFGR_SWS_HSI: /* HSI used as system clock source */ |
| { |
| sysclockfreq = HSI_VALUE; |
| break; |
| } |
| case RCC_CFGR_SWS_HSE: /* HSE used as system clock source */ |
| { |
| sysclockfreq = HSE_VALUE; |
| break; |
| } |
| case RCC_CFGR_SWS_PLL: /* PLL/PLLP used as system clock source */ |
| { |
| /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN |
| SYSCLK = PLL_VCO / PLLP */ |
| pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; |
| if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_HSI) |
| { |
| /* HSE used as PLL clock source */ |
| pllvco = (uint32_t) ((((uint64_t) HSE_VALUE * ((uint64_t) ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)))) / (uint64_t)pllm); |
|