/** | |
****************************************************************************** | |
* @file stm32f4xx_hal_rcc_ex.c | |
* @author MCD Application Team | |
* @version V1.7.1 | |
* @date 14-April-2017 | |
* @brief Extension RCC HAL module driver. | |
* This file provides firmware functions to manage the following | |
* functionalities RCC extension peripheral: | |
* + Extended Peripheral Control functions | |
* | |
****************************************************************************** | |
* @attention | |
* | |
* <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> | |
* | |
* Redistribution and use in source and binary forms, with or without modification, | |
* are permitted provided that the following conditions are met: | |
* 1. Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright notice, | |
* this list of conditions and the following disclaimer in the documentation | |
* and/or other materials provided with the distribution. | |
* 3. Neither the name of STMicroelectronics nor the names of its contributors | |
* may be used to endorse or promote products derived from this software | |
* without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
* | |
****************************************************************************** | |
*/ | |
/* 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) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SP)) + 1U) << 1U); | |
plli2sq = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> POSITION_VAL(RCC_PLLI2SCFGR_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 , 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) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SP)) + 1U) << 1U); | |
plli2sr = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR)); | |
/* 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) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SP)) + 1U) << 1U); | |
plli2sr = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR)); | |
/* 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) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIP)) + 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) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIQ)); | |
/* 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) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SM)); | |
PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SN)); | |
PeriphClkInit->PLLI2S.PLLI2SP = (uint32_t)((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SP)) + 1U) << 1U); | |
PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SQ)); | |
PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR)); | |
/* Get the PLLSAI Clock configuration --------------------------------------*/ | |
PeriphClkInit->PLLSAI.PLLSAIM = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIM) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIM)); | |
PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIN)); | |
PeriphClkInit->PLLSAI.PLLSAIP = (uint32_t)((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIP)) + 1U) << 1U); | |
PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIQ)); | |
/* Get the PLLSAI/PLLI2S division factors ----------------------------------*/ | |
PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> POSITION_VAL(RCC_DCKCFGR_PLLI2SDIVQ)); | |
PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> POSITION_VAL(RCC_DCKCFGR_PLLSAIDIVQ)); | |
/* 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) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR)); | |
/* 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) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIP)) + 1U) << 1U); | |
/* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */ | |
pllsair = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIR)); | |
/* 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) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIP)) + 1U) << 1U); | |
/* Read PLLSAIQ value from PLLSAICFGR register (this value is not need for SAI configuration) */ | |
pllsaiq = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIQ)); | |
/* 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) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIQ)); | |
/* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */ | |
pllsair = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIR)); | |
/* 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) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SN)); | |
PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR)); | |
PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SQ)); | |
/* Get the PLLSAI Clock configuration --------------------------------------*/ | |
PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIN)); | |
PeriphClkInit->PLLSAI.PLLSAIR = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIR)); | |
PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIQ)); | |
/* Get the PLLSAI/PLLI2S division factors ----------------------------------*/ | |
PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> POSITION_VAL(RCC_DCKCFGR_PLLI2SDIVQ)); | |
PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> POSITION_VAL(RCC_DCKCFGR_PLLSAIDIVQ)); | |
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) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SQ)); | |
/* 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) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SM)); | |
PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SN)); | |
PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SQ)); | |
PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR)); | |
#if defined(STM32F413xx) || defined(STM32F423xx) | |
/* Get the PLL/PLLI2S division factors -------------------------------------*/ | |
PeriphClkInit->PLLI2SDivR = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVR) >> POSITION_VAL(RCC_DCKCFGR_PLLI2SDIVR)); | |
PeriphClkInit->PLLDivR = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLDIVR) >> POSITION_VAL(RCC_DCKCFGR_PLLDIVR)); | |
#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)) | |
{ | |
/* 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) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR)); | |
/* 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); | |
} | |
/* 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) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIR)); | |
/* 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) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIQ)); | |
/* 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) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SN)); | |
PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR)); | |
PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SQ)); | |
/* Get the PLLSAI Clock configuration -----------------------------------------------*/ | |
PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIN)); | |
PeriphClkInit->PLLSAI.PLLSAIR = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIR)); | |
PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIQ)); | |
/* Get the PLLSAI/PLLI2S division factors -----------------------------------------------*/ | |
PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> POSITION_VAL(RCC_DCKCFGR_PLLI2SDIVQ)); | |
PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> POSITION_VAL(RCC_DCKCFGR_PLLSAIDIVQ)); | |
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) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SN)); | |
PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR)); | |
#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 */ | |
#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 = ((HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN))); | |
} | |
else | |
{ | |
/* HSI used as PLL clock source */ | |
pllvco = ((HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN))); | |
} | |
pllp = ((((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >> POSITION_VAL(RCC_PLLCFGR_PLLP)) + 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 = ((HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN))); | |
} | |
else | |
{ | |
/* HSI used as PLL clock source */ | |
pllvco = ((HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN))); | |
} | |
pllr = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> POSITION_VAL(RCC_PLLCFGR_PLLR)); | |
sysclockfreq = pllvco/pllr; | |
break; | |
} | |
default: | |
{ | |
sysclockfreq = HSI_VALUE; | |
break; | |
} | |
} | |
return sysclockfreq; | |
} | |
#endif /* STM32F446xx */ | |
/** | |
* @} | |
*/ | |
/** | |
* @} | |
*/ | |
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || \ | |
defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || \ | |
defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F446xx) || \ | |
defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || \ | |
defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) | |
/** | |
* @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 None | |
*/ | |
void HAL_RCC_DeInit(void) | |
{ | |
/* Set HSION bit */ | |
SET_BIT(RCC->CR, RCC_CR_HSION | RCC_CR_HSITRIM_4); | |
/* Reset CFGR register */ | |
CLEAR_REG(RCC->CFGR); | |
/* Reset HSEON, CSSON, PLLON, PLLI2S bits */ | |
CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_CSSON | RCC_CR_PLLON | RCC_CR_PLLI2SON); | |
#if defined(STM32F427xx) || defined(STM32F429xx) || defined(STM32F437xx) || defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) | |
/* Reset PLLSAI bit */ | |
CLEAR_BIT(RCC->CR, RCC_CR_PLLSAION); | |
#endif /* STM32F427xx || STM32F429xx || STM32F437xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ | |
/* Reset PLLCFGR register */ | |
CLEAR_REG(RCC->PLLCFGR); | |
#if defined(STM32F412Cx) || defined(STM32F412Rx) || defined(STM32F412Vx) || defined(STM32F412Zx) || defined(STM32F413xx) || \ | |
defined(STM32F423xx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) | |
SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLR_1); | |
#else | |
SET_BIT(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 */ | |
CLEAR_REG(RCC->PLLI2SCFGR); | |
#if defined(STM32F412Cx) || defined(STM32F412Rx) || defined(STM32F412Vx) || defined(STM32F412Zx) || defined(STM32F413xx) || \ | |
defined(STM32F423xx) || defined(STM32F446xx) | |
SET_BIT(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) | |
SET_BIT(RCC->PLLI2SCFGR, RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SR_1); | |
#elif defined(STM32F411xE) | |
SET_BIT(RCC->PLLI2SCFGR, RCC_PLLI2SCFGR_PLLI2SM_4 | RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SR_1); | |
#else | |
SET_BIT(RCC->PLLI2SCFGR, RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SQ_2 | 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) | |
CLEAR_REG(RCC->PLLSAICFGR); | |
SET_BIT(RCC->PLLSAICFGR, RCC_PLLSAICFGR_PLLSAIN_6 | RCC_PLLSAICFGR_PLLSAIN_7 | RCC_PLLSAICFGR_PLLSAIQ_2 | RCC_PLLSAICFGR_PLLSAIR_1); | |
#elif defined(STM32F446xx) | |
CLEAR_REG(RCC->PLLSAICFGR); | |
SET_BIT(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_REG(RCC->CIR); | |
/* Update the SystemCoreClock global variable */ | |
SystemCoreClock = HSI_VALUE; | |
} | |
#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || | |
STM32F401xC || STM32F401xE || STM32F411xE || STM32F446xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx || | |
STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ | |
#if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) | |
/** | |
* @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 and PLL 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 None | |
*/ | |
void HAL_RCC_DeInit(void) | |
{ | |
/* Set HSION bit */ | |
SET_BIT(RCC->CR, RCC_CR_HSION | RCC_CR_HSITRIM_4); | |
/* Reset CFGR register */ | |
CLEAR_REG(RCC->CFGR); | |
/* Reset HSEON, HSEBYP, CSSON, PLLON */ | |
CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_CSSON | RCC_CR_PLLON); | |
/* Reset PLLCFGR register */ | |
CLEAR_REG(RCC->PLLCFGR); | |
SET_BIT(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); | |
/* Disable all interrupts */ | |
CLEAR_REG(RCC->CIR); | |
/* Update the SystemCoreClock global variable */ | |
SystemCoreClock = HSI_VALUE; | |
} | |
#endif /* STM32F410Tx || STM32F410Cx || STM32F410Rx */ | |
#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) | |
{ | |
/* Check the parameters */ | |
assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState)); | |
/* Enable Power Clock*/ | |
__HAL_RCC_PWR_CLK_ENABLE(); | |
/* Enable write access to Backup domain */ | |
PWR->CR |= PWR_CR_DBP; | |
/* Wait for Backup domain Write protection disable */ | |
tickstart = HAL_GetTick(); | |
while((PWR->CR & PWR_CR_DBP) == RESET) | |
{ | |
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; | |
} | |
} | |
} | |
} | |
/*-------------------------------- 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) >> POSITION_VAL(RCC_CR_HSITRIM)); | |
/* 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) >> POSITION_VAL(RCC_PLLCFGR_PLLN)); | |
RCC_OscInitStruct->PLL.PLLP = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) + RCC_PLLCFGR_PLLP_0) << 1U) >> POSITION_VAL(RCC_PLLCFGR_PLLP)); | |
RCC_OscInitStruct->PLL.PLLQ = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLQ) >> POSITION_VAL(RCC_PLLCFGR_PLLQ)); | |
RCC_OscInitStruct->PLL.PLLR = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> POSITION_VAL(RCC_PLLCFGR_PLLR)); | |
} | |
#endif /* STM32F410xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ | |
#endif /* HAL_RCC_MODULE_ENABLED */ | |
/** | |
* @} | |
*/ | |
/** | |
* @} | |
*/ | |
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |