/** ****************************************************************************** * @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 * *

© Copyright (c) 2017 STMicroelectronics. * All rights reserved.

* * 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); } else { /* HSI used as PLL clock source */ pllvco = (uint32_t) ((((uint64_t) HSI_VALUE * ((uint64_t) ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)))) / (uint64_t)pllm); } pllp = ((((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >> RCC_PLLCFGR_PLLP_Pos) + 1U) *2U); sysclockfreq = pllvco/pllp; break; } case RCC_CFGR_SWS_PLLR: /* PLL/PLLR used as system clock source */ { /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN SYSCLK = PLL_VCO / PLLR */ 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); } else { /* HSI used as PLL clock source */ pllvco = (uint32_t) ((((uint64_t) HSI_VALUE * ((uint64_t) ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)))) / (uint64_t)pllm); } pllr = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos); sysclockfreq = pllvco/pllr; break; } default: { sysclockfreq = HSI_VALUE; break; } } return sysclockfreq; } #endif /* STM32F446xx */ /** * @} */ /** * @} */ /** * @brief Resets the RCC clock configuration to the default reset state. * @note The default reset state of the clock configuration is given below: * - HSI ON and used as system clock source * - HSE, PLL, PLLI2S and PLLSAI OFF * - AHB, APB1 and APB2 prescaler set to 1. * - CSS, MCO1 and MCO2 OFF * - All interrupts disabled * @note This function doesn't modify the configuration of the * - Peripheral clocks * - LSI, LSE and RTC clocks * @retval HAL status */ HAL_StatusTypeDef HAL_RCC_DeInit(void) { uint32_t tickstart; /* Get Start Tick */ tickstart = HAL_GetTick(); /* Set HSION bit to the reset value */ SET_BIT(RCC->CR, RCC_CR_HSION); /* Wait till HSI is ready */ while (READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET) { if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } /* Set HSITRIM[4:0] bits to the reset value */ SET_BIT(RCC->CR, RCC_CR_HSITRIM_4); /* Get Start Tick */ tickstart = HAL_GetTick(); /* Reset CFGR register */ CLEAR_REG(RCC->CFGR); /* Wait till clock switch is ready */ while (READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != RESET) { if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } /* Get Start Tick */ tickstart = HAL_GetTick(); /* Clear HSEON, HSEBYP and CSSON bits */ CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_CSSON); /* Wait till HSE is disabled */ while (READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET) { if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } /* Get Start Tick */ tickstart = HAL_GetTick(); /* Clear PLLON bit */ CLEAR_BIT(RCC->CR, RCC_CR_PLLON); /* Wait till PLL is disabled */ while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET) { if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } #if defined(RCC_PLLI2S_SUPPORT) /* Get Start Tick */ tickstart = HAL_GetTick(); /* Reset PLLI2SON bit */ CLEAR_BIT(RCC->CR, RCC_CR_PLLI2SON); /* Wait till PLLI2S is disabled */ while (READ_BIT(RCC->CR, RCC_CR_PLLI2SRDY) != RESET) { if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } #endif /* RCC_PLLI2S_SUPPORT */ #if defined(RCC_PLLSAI_SUPPORT) /* Get Start Tick */ tickstart = HAL_GetTick(); /* Reset PLLSAI bit */ CLEAR_BIT(RCC->CR, RCC_CR_PLLSAION); /* Wait till PLLSAI is disabled */ while (READ_BIT(RCC->CR, RCC_CR_PLLSAIRDY) != RESET) { if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } #endif /* RCC_PLLSAI_SUPPORT */ /* Once PLL, PLLI2S and PLLSAI are OFF, reset PLLCFGR register to default value */ #if defined(STM32F412Cx) || defined(STM32F412Rx) || defined(STM32F412Vx) || defined(STM32F412Zx) || defined(STM32F413xx) || \ defined(STM32F423xx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) RCC->PLLCFGR = RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLR_1; #elif defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) RCC->PLLCFGR = RCC_PLLCFGR_PLLR_0 | RCC_PLLCFGR_PLLR_1 | RCC_PLLCFGR_PLLR_2 | RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_0 | RCC_PLLCFGR_PLLQ_1 | RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLQ_3; #else RCC->PLLCFGR = RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_2; #endif /* STM32F412Cx || STM32F412Rx || STM32F412Vx || STM32F412Zx || STM32F413xx || STM32F423xx || STM32F446xx || STM32F469xx || STM32F479xx */ /* Reset PLLI2SCFGR register to default value */ #if defined(STM32F412Cx) || defined(STM32F412Rx) || defined(STM32F412Vx) || defined(STM32F412Zx) || defined(STM32F413xx) || \ defined(STM32F423xx) || defined(STM32F446xx) RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SM_4 | RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SQ_2 | RCC_PLLI2SCFGR_PLLI2SR_1; #elif defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SR_1; #elif defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SQ_2 | RCC_PLLI2SCFGR_PLLI2SR_1; #elif defined(STM32F411xE) RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SM_4 | RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SR_1; #endif /* STM32F412Cx || STM32F412Rx || STM32F412Vx || STM32F412Zx || STM32F413xx || STM32F423xx || STM32F446xx */ /* Reset PLLSAICFGR register */ #if defined(STM32F427xx) || defined(STM32F429xx) || defined(STM32F437xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) RCC->PLLSAICFGR = RCC_PLLSAICFGR_PLLSAIN_6 | RCC_PLLSAICFGR_PLLSAIN_7 | RCC_PLLSAICFGR_PLLSAIQ_2 | RCC_PLLSAICFGR_PLLSAIR_1; #elif defined(STM32F446xx) RCC->PLLSAICFGR = RCC_PLLSAICFGR_PLLSAIM_4 | RCC_PLLSAICFGR_PLLSAIN_6 | RCC_PLLSAICFGR_PLLSAIN_7 | RCC_PLLSAICFGR_PLLSAIQ_2; #endif /* STM32F427xx || STM32F429xx || STM32F437xx || STM32F439xx || STM32F469xx || STM32F479xx */ /* Disable all interrupts */ CLEAR_BIT(RCC->CIR, RCC_CIR_LSIRDYIE | RCC_CIR_LSERDYIE | RCC_CIR_HSIRDYIE | RCC_CIR_HSERDYIE | RCC_CIR_PLLRDYIE); #if defined(RCC_CIR_PLLI2SRDYIE) CLEAR_BIT(RCC->CIR, RCC_CIR_PLLI2SRDYIE); #endif /* RCC_CIR_PLLI2SRDYIE */ #if defined(RCC_CIR_PLLSAIRDYIE) CLEAR_BIT(RCC->CIR, RCC_CIR_PLLSAIRDYIE); #endif /* RCC_CIR_PLLSAIRDYIE */ /* Clear all interrupt flags */ SET_BIT(RCC->CIR, RCC_CIR_LSIRDYC | RCC_CIR_LSERDYC | RCC_CIR_HSIRDYC | RCC_CIR_HSERDYC | RCC_CIR_PLLRDYC | RCC_CIR_CSSC); #if defined(RCC_CIR_PLLI2SRDYC) SET_BIT(RCC->CIR, RCC_CIR_PLLI2SRDYC); #endif /* RCC_CIR_PLLI2SRDYC */ #if defined(RCC_CIR_PLLSAIRDYC) SET_BIT(RCC->CIR, RCC_CIR_PLLSAIRDYC); #endif /* RCC_CIR_PLLSAIRDYC */ /* Clear LSION bit */ CLEAR_BIT(RCC->CSR, RCC_CSR_LSION); /* Reset all CSR flags */ SET_BIT(RCC->CSR, RCC_CSR_RMVF); /* Update the SystemCoreClock global variable */ SystemCoreClock = HSI_VALUE; /* Adapt Systick interrupt period */ if(HAL_InitTick(uwTickPrio) != HAL_OK) { return HAL_ERROR; } else { return HAL_OK; } } #if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||\ defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) /** * @brief Initializes the RCC Oscillators according to the specified parameters in the * RCC_OscInitTypeDef. * @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that * contains the configuration information for the RCC Oscillators. * @note The PLL is not disabled when used as system clock. * @note Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not * supported by this API. User should request a transition to LSE Off * first and then LSE On or LSE Bypass. * @note Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not * supported by this API. User should request a transition to HSE Off * first and then HSE On or HSE Bypass. * @note This function add the PLL/PLLR factor management during PLL configuration this feature * is only available in STM32F410xx/STM32F446xx/STM32F469xx/STM32F479xx/STM32F412Zx/STM32F412Vx/STM32F412Rx/STM32F412Cx devices * @retval HAL status */ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) { uint32_t tickstart = 0U; /* Check the parameters */ assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType)); /*------------------------------- HSE Configuration ------------------------*/ if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE) { /* Check the parameters */ assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState)); /* When the HSE is used as system clock or clock source for PLL in these cases HSE will not disabled */ #if defined(STM32F446xx) if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) ||\ ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)) ||\ ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLLR) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE))) #else if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) ||\ ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE))) #endif /* STM32F446xx */ { if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF)) { return HAL_ERROR; } } else { /* Set the new HSE configuration ---------------------------------------*/ __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState); /* Check the HSE State */ if((RCC_OscInitStruct->HSEState) != RCC_HSE_OFF) { /* Get Start Tick*/ tickstart = HAL_GetTick(); /* Wait till HSE is ready */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET) { if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } else { /* Get Start Tick*/ tickstart = HAL_GetTick(); /* Wait till HSE is bypassed or disabled */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET) { if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } } } /*----------------------------- HSI Configuration --------------------------*/ if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) { /* Check the parameters */ assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState)); assert_param(IS_RCC_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue)); /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */ #if defined(STM32F446xx) if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) ||\ ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSI)) ||\ ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLLR) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSI))) #else if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) ||\ ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSI))) #endif /* STM32F446xx */ { /* When HSI is used as system clock it will not disabled */ if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState != RCC_HSI_ON)) { return HAL_ERROR; } /* Otherwise, just the calibration is allowed */ else { /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/ __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue); } } else { /* Check the HSI State */ if((RCC_OscInitStruct->HSIState)!= RCC_HSI_OFF) { /* Enable the Internal High Speed oscillator (HSI). */ __HAL_RCC_HSI_ENABLE(); /* Get Start Tick*/ tickstart = HAL_GetTick(); /* Wait till HSI is ready */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == RESET) { if((HAL_GetTick() - tickstart ) > HSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/ __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue); } else { /* Disable the Internal High Speed oscillator (HSI). */ __HAL_RCC_HSI_DISABLE(); /* Get Start Tick*/ tickstart = HAL_GetTick(); /* Wait till HSI is ready */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET) { if((HAL_GetTick() - tickstart ) > HSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } } } /*------------------------------ LSI Configuration -------------------------*/ if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) { /* Check the parameters */ assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState)); /* Check the LSI State */ if((RCC_OscInitStruct->LSIState)!= RCC_LSI_OFF) { /* Enable the Internal Low Speed oscillator (LSI). */ __HAL_RCC_LSI_ENABLE(); /* Get Start Tick*/ tickstart = HAL_GetTick(); /* Wait till LSI is ready */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == RESET) { if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } else { /* Disable the Internal Low Speed oscillator (LSI). */ __HAL_RCC_LSI_DISABLE(); /* Get Start Tick*/ tickstart = HAL_GetTick(); /* Wait till LSI is ready */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) != RESET) { if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } } /*------------------------------ LSE Configuration -------------------------*/ if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) { FlagStatus pwrclkchanged = RESET; /* Check the parameters */ assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState)); /* Update LSE configuration in Backup Domain control register */ /* Requires to enable write access to Backup Domain of necessary */ if(__HAL_RCC_PWR_IS_CLK_DISABLED()) { __HAL_RCC_PWR_CLK_ENABLE(); pwrclkchanged = SET; } if(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP)) { /* Enable write access to Backup domain */ SET_BIT(PWR->CR, PWR_CR_DBP); /* Wait for Backup domain Write protection disable */ tickstart = HAL_GetTick(); while(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP)) { if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } /* Set the new LSE configuration -----------------------------------------*/ __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState); /* Check the LSE State */ if((RCC_OscInitStruct->LSEState) != RCC_LSE_OFF) { /* Get Start 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; } } } else { /* Get Start 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; } } } /* Restore clock configuration if changed */ if(pwrclkchanged == SET) { __HAL_RCC_PWR_CLK_DISABLE(); } } /*-------------------------------- PLL Configuration -----------------------*/ /* Check the parameters */ assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState)); if ((RCC_OscInitStruct->PLL.PLLState) != RCC_PLL_NONE) { /* Check if the PLL is used as system clock or not */ if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) { if((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_ON) { /* Check the parameters */ assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource)); assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM)); assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN)); assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP)); assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ)); assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR)); /* Disable the main PLL. */ __HAL_RCC_PLL_DISABLE(); /* Get Start Tick*/ tickstart = HAL_GetTick(); /* Wait till PLL is ready */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET) { if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } /* Configure the main PLL clock source, multiplication and division factors. */ __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource, RCC_OscInitStruct->PLL.PLLM, RCC_OscInitStruct->PLL.PLLN, RCC_OscInitStruct->PLL.PLLP, RCC_OscInitStruct->PLL.PLLQ, RCC_OscInitStruct->PLL.PLLR); /* Enable the main PLL. */ __HAL_RCC_PLL_ENABLE(); /* Get Start Tick*/ tickstart = HAL_GetTick(); /* Wait till PLL is ready */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET) { if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } else { /* Disable the main PLL. */ __HAL_RCC_PLL_DISABLE(); /* Get Start Tick*/ tickstart = HAL_GetTick(); /* Wait till PLL is ready */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET) { if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } } } else { return HAL_ERROR; } } return HAL_OK; } /** * @brief Configures the RCC_OscInitStruct according to the internal * RCC configuration registers. * @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that will be configured. * * @note This function is only available in case of STM32F410xx/STM32F446xx/STM32F469xx/STM32F479xx/STM32F412Zx/STM32F412Vx/STM32F412Rx/STM32F412Cx devices. * @note This function add the PLL/PLLR factor management * @retval None */ void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) { /* Set all possible values for the Oscillator type parameter ---------------*/ RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI; /* Get the HSE configuration -----------------------------------------------*/ if((RCC->CR &RCC_CR_HSEBYP) == RCC_CR_HSEBYP) { RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS; } else if((RCC->CR &RCC_CR_HSEON) == RCC_CR_HSEON) { RCC_OscInitStruct->HSEState = RCC_HSE_ON; } else { RCC_OscInitStruct->HSEState = RCC_HSE_OFF; } /* Get the HSI configuration -----------------------------------------------*/ if((RCC->CR &RCC_CR_HSION) == RCC_CR_HSION) { RCC_OscInitStruct->HSIState = RCC_HSI_ON; } else { RCC_OscInitStruct->HSIState = RCC_HSI_OFF; } RCC_OscInitStruct->HSICalibrationValue = (uint32_t)((RCC->CR &RCC_CR_HSITRIM) >> RCC_CR_HSITRIM_Pos); /* Get the LSE configuration -----------------------------------------------*/ if((RCC->BDCR &RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP) { RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS; } else if((RCC->BDCR &RCC_BDCR_LSEON) == RCC_BDCR_LSEON) { RCC_OscInitStruct->LSEState = RCC_LSE_ON; } else { RCC_OscInitStruct->LSEState = RCC_LSE_OFF; } /* Get the LSI configuration -----------------------------------------------*/ if((RCC->CSR &RCC_CSR_LSION) == RCC_CSR_LSION) { RCC_OscInitStruct->LSIState = RCC_LSI_ON; } else { RCC_OscInitStruct->LSIState = RCC_LSI_OFF; } /* Get the PLL configuration -----------------------------------------------*/ if((RCC->CR &RCC_CR_PLLON) == RCC_CR_PLLON) { RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON; } else { RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF; } RCC_OscInitStruct->PLL.PLLSource = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); RCC_OscInitStruct->PLL.PLLM = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM); RCC_OscInitStruct->PLL.PLLN = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); RCC_OscInitStruct->PLL.PLLP = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) + RCC_PLLCFGR_PLLP_0) << 1U) >> RCC_PLLCFGR_PLLP_Pos); RCC_OscInitStruct->PLL.PLLQ = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos); RCC_OscInitStruct->PLL.PLLR = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos); } #endif /* STM32F410xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ #endif /* HAL_RCC_MODULE_ENABLED */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/