STM32F479xx HAL User Manual
|
00001 /** 00002 ****************************************************************************** 00003 * @file stm32f4xx_hal_sai_ex.c 00004 * @author MCD Application Team 00005 * @brief SAI Extension HAL module driver. 00006 * This file provides firmware functions to manage the following 00007 * functionalities of SAI extension peripheral: 00008 * + Extension features functions 00009 * 00010 @verbatim 00011 ============================================================================== 00012 ##### SAI peripheral extension features ##### 00013 ============================================================================== 00014 00015 [..] Comparing to other previous devices, the SAI interface for STM32F446xx 00016 devices contains the following additional features : 00017 00018 (+) Possibility to be clocked from PLLR 00019 00020 ##### How to use this driver ##### 00021 ============================================================================== 00022 [..] This driver provides functions to manage several sources to clock SAI 00023 00024 @endverbatim 00025 ****************************************************************************** 00026 * @attention 00027 * 00028 * <h2><center>© Copyright (c) 2017 STMicroelectronics. 00029 * All rights reserved.</center></h2> 00030 * 00031 * This software component is licensed by ST under BSD 3-Clause license, 00032 * the "License"; You may not use this file except in compliance with the 00033 * License. You may obtain a copy of the License at: 00034 * opensource.org/licenses/BSD-3-Clause 00035 * 00036 ****************************************************************************** 00037 */ 00038 00039 /* Includes ------------------------------------------------------------------*/ 00040 #include "stm32f4xx_hal.h" 00041 00042 /** @addtogroup STM32F4xx_HAL_Driver 00043 * @{ 00044 */ 00045 00046 /** @defgroup SAIEx SAIEx 00047 * @brief SAI Extension HAL module driver 00048 * @{ 00049 */ 00050 00051 #ifdef HAL_SAI_MODULE_ENABLED 00052 00053 #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || \ 00054 defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || \ 00055 defined(STM32F423xx) 00056 00057 /* Private typedef -----------------------------------------------------------*/ 00058 /* Private define ------------------------------------------------------------*/ 00059 /* SAI registers Masks */ 00060 /* Private macro -------------------------------------------------------------*/ 00061 /* Private variables ---------------------------------------------------------*/ 00062 /* Private function prototypes -----------------------------------------------*/ 00063 /* Private functions ---------------------------------------------------------*/ 00064 00065 /** @defgroup SAI_Private_Functions SAI Private Functions 00066 * @{ 00067 */ 00068 /** 00069 * @} 00070 */ 00071 00072 /* Exported functions --------------------------------------------------------*/ 00073 /** @defgroup SAIEx_Exported_Functions SAI Extended Exported Functions 00074 * @{ 00075 */ 00076 00077 /** @defgroup SAIEx_Exported_Functions_Group1 Extension features functions 00078 * @brief Extension features functions 00079 * 00080 @verbatim 00081 =============================================================================== 00082 ##### Extension features Functions ##### 00083 =============================================================================== 00084 [..] 00085 This subsection provides a set of functions allowing to manage the possible 00086 SAI clock sources. 00087 00088 @endverbatim 00089 * @{ 00090 */ 00091 00092 /** 00093 * @brief Configure SAI Block synchronization mode 00094 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00095 * the configuration information for SAI module. 00096 * @retval SAI Clock Input 00097 */ 00098 void SAI_BlockSynchroConfig(SAI_HandleTypeDef *hsai) 00099 { 00100 uint32_t tmpregisterGCR; 00101 00102 #if defined(STM32F446xx) 00103 /* This setting must be done with both audio block (A & B) disabled */ 00104 switch (hsai->Init.SynchroExt) 00105 { 00106 case SAI_SYNCEXT_DISABLE : 00107 tmpregisterGCR = 0U; 00108 break; 00109 case SAI_SYNCEXT_OUTBLOCKA_ENABLE : 00110 tmpregisterGCR = SAI_GCR_SYNCOUT_0; 00111 break; 00112 case SAI_SYNCEXT_OUTBLOCKB_ENABLE : 00113 tmpregisterGCR = SAI_GCR_SYNCOUT_1; 00114 break; 00115 default: 00116 tmpregisterGCR = 0U; 00117 break; 00118 } 00119 00120 if ((hsai->Init.Synchro) == SAI_SYNCHRONOUS_EXT_SAI2) 00121 { 00122 tmpregisterGCR |= SAI_GCR_SYNCIN_0; 00123 } 00124 00125 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B)) 00126 { 00127 SAI1->GCR = tmpregisterGCR; 00128 } 00129 else 00130 { 00131 SAI2->GCR = tmpregisterGCR; 00132 } 00133 #endif /* STM32F446xx */ 00134 #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || \ 00135 defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || defined(STM32F423xx) 00136 /* This setting must be done with both audio block (A & B) disabled */ 00137 switch (hsai->Init.SynchroExt) 00138 { 00139 case SAI_SYNCEXT_DISABLE : 00140 tmpregisterGCR = 0U; 00141 break; 00142 case SAI_SYNCEXT_OUTBLOCKA_ENABLE : 00143 tmpregisterGCR = SAI_GCR_SYNCOUT_0; 00144 break; 00145 case SAI_SYNCEXT_OUTBLOCKB_ENABLE : 00146 tmpregisterGCR = SAI_GCR_SYNCOUT_1; 00147 break; 00148 default: 00149 tmpregisterGCR = 0U; 00150 break; 00151 } 00152 SAI1->GCR = tmpregisterGCR; 00153 #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */ 00154 } 00155 /** 00156 * @brief Get SAI Input Clock based on SAI source clock selection 00157 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00158 * the configuration information for SAI module. 00159 * @retval SAI Clock Input 00160 */ 00161 uint32_t SAI_GetInputClock(SAI_HandleTypeDef *hsai) 00162 { 00163 /* This variable used to store the SAI_CK_x (value in Hz) */ 00164 uint32_t saiclocksource = 0U; 00165 00166 #if defined(STM32F446xx) 00167 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B)) 00168 { 00169 saiclocksource = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1); 00170 } 00171 else /* SAI2_Block_A || SAI2_Block_B*/ 00172 { 00173 saiclocksource = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2); 00174 } 00175 #endif /* STM32F446xx */ 00176 #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || \ 00177 defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || defined(STM32F423xx) 00178 uint32_t vcoinput = 0U, tmpreg = 0U; 00179 00180 /* Check the SAI Block parameters */ 00181 assert_param(IS_SAI_CLK_SOURCE(hsai->Init.ClockSource)); 00182 00183 /* SAI Block clock source selection */ 00184 if (hsai->Instance == SAI1_Block_A) 00185 { 00186 __HAL_RCC_SAI_BLOCKACLKSOURCE_CONFIG(hsai->Init.ClockSource); 00187 } 00188 else 00189 { 00190 __HAL_RCC_SAI_BLOCKBCLKSOURCE_CONFIG((uint32_t)(hsai->Init.ClockSource << 2U)); 00191 } 00192 00193 /* VCO Input Clock value calculation */ 00194 if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI) 00195 { 00196 /* In Case the PLL Source is HSI (Internal Clock) */ 00197 vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); 00198 } 00199 else 00200 { 00201 /* In Case the PLL Source is HSE (External Clock) */ 00202 vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM))); 00203 } 00204 #if defined(STM32F413xx) || defined(STM32F423xx) 00205 /* SAI_CLK_x : SAI Block Clock configuration for different clock sources selected */ 00206 if (hsai->Init.ClockSource == SAI_CLKSOURCE_PLLR) 00207 { 00208 /* Configure the PLLI2S division factor */ 00209 /* PLL_VCO Input = PLL_SOURCE/PLLM */ 00210 /* PLL_VCO Output = PLL_VCO Input * PLLN */ 00211 /* SAI_CLK(first level) = PLL_VCO Output/PLLR */ 00212 tmpreg = (RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U; 00213 saiclocksource = (vcoinput * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U)) / (tmpreg); 00214 00215 /* SAI_CLK_x = SAI_CLK(first level)/PLLDIVR */ 00216 tmpreg = (((RCC->DCKCFGR & RCC_DCKCFGR_PLLDIVR) >> 8U) + 1U); 00217 00218 saiclocksource = saiclocksource / (tmpreg); 00219 00220 } 00221 else if (hsai->Init.ClockSource == SAI_CLKSOURCE_PLLI2S) 00222 { 00223 /* Configure the PLLI2S division factor */ 00224 /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */ 00225 /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ 00226 /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SR */ 00227 tmpreg = (RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U; 00228 saiclocksource = (vcoinput * ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U)) / (tmpreg); 00229 00230 /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVR */ 00231 tmpreg = ((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVR) + 1U); 00232 saiclocksource = saiclocksource / (tmpreg); 00233 } 00234 else if (hsai->Init.ClockSource == SAI_CLKSOURCE_HS) 00235 { 00236 if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) 00237 { 00238 /* Get the I2S source clock value */ 00239 saiclocksource = (uint32_t)(HSE_VALUE); 00240 } 00241 else 00242 { 00243 /* Get the I2S source clock value */ 00244 saiclocksource = (uint32_t)(HSI_VALUE); 00245 } 00246 } 00247 else /* sConfig->ClockSource == SAI_CLKSource_Ext */ 00248 { 00249 saiclocksource = EXTERNAL_CLOCK_VALUE; 00250 } 00251 #else 00252 /* SAI_CLK_x : SAI Block Clock configuration for different clock sources selected */ 00253 if (hsai->Init.ClockSource == SAI_CLKSOURCE_PLLSAI) 00254 { 00255 /* Configure the PLLI2S division factor */ 00256 /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */ 00257 /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */ 00258 /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */ 00259 tmpreg = (RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> 24U; 00260 saiclocksource = (vcoinput * ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> 6U)) / (tmpreg); 00261 00262 /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */ 00263 tmpreg = (((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> 8U) + 1U); 00264 saiclocksource = saiclocksource / (tmpreg); 00265 00266 } 00267 else if (hsai->Init.ClockSource == SAI_CLKSOURCE_PLLI2S) 00268 { 00269 /* Configure the PLLI2S division factor */ 00270 /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */ 00271 /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ 00272 /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */ 00273 tmpreg = (RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> 24U; 00274 saiclocksource = (vcoinput * ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U)) / (tmpreg); 00275 00276 /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */ 00277 tmpreg = ((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) + 1U); 00278 saiclocksource = saiclocksource / (tmpreg); 00279 } 00280 else /* sConfig->ClockSource == SAI_CLKSource_Ext */ 00281 { 00282 /* Enable the External Clock selection */ 00283 __HAL_RCC_I2S_CONFIG(RCC_I2SCLKSOURCE_EXT); 00284 00285 saiclocksource = EXTERNAL_CLOCK_VALUE; 00286 } 00287 #endif /* STM32F413xx || STM32F423xx */ 00288 #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */ 00289 /* the return result is the value of SAI clock */ 00290 return saiclocksource; 00291 } 00292 00293 /** 00294 * @} 00295 */ 00296 00297 /** 00298 * @} 00299 */ 00300 00301 #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */ 00302 #endif /* HAL_SAI_MODULE_ENABLED */ 00303 /** 00304 * @} 00305 */ 00306 00307 /** 00308 * @} 00309 */ 00310 00311 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/