STM32F439xx HAL User Manual
|
00001 /** 00002 ****************************************************************************** 00003 * @file stm32f4xx_hal_sai.c 00004 * @author MCD Application Team 00005 * @brief SAI HAL module driver. 00006 * This file provides firmware functions to manage the following 00007 * functionalities of the Serial Audio Interface (SAI) peripheral: 00008 * + Initialization/de-initialization functions 00009 * + I/O operation functions 00010 * + Peripheral Control functions 00011 * + Peripheral State functions 00012 * 00013 @verbatim 00014 ============================================================================== 00015 ##### How to use this driver ##### 00016 ============================================================================== 00017 00018 [..] 00019 The SAI HAL driver can be used as follows: 00020 00021 (#) Declare a SAI_HandleTypeDef handle structure (eg. SAI_HandleTypeDef hsai). 00022 (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API: 00023 (##) Enable the SAI interface clock. 00024 (##) SAI pins configuration: 00025 (+++) Enable the clock for the SAI GPIOs. 00026 (+++) Configure these SAI pins as alternate function pull-up. 00027 (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT() 00028 and HAL_SAI_Receive_IT() APIs): 00029 (+++) Configure the SAI interrupt priority. 00030 (+++) Enable the NVIC SAI IRQ handle. 00031 00032 (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA() 00033 and HAL_SAI_Receive_DMA() APIs): 00034 (+++) Declare a DMA handle structure for the Tx/Rx stream. 00035 (+++) Enable the DMAx interface clock. 00036 (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters. 00037 (+++) Configure the DMA Tx/Rx Stream. 00038 (+++) Associate the initialized DMA handle to the SAI DMA Tx/Rx handle. 00039 (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the 00040 DMA Tx/Rx Stream. 00041 00042 (#) The initialization can be done by two ways 00043 (##) Expert mode : Initialize the structures Init, FrameInit and SlotInit and call HAL_SAI_Init(). 00044 (##) Simplified mode : Initialize the high part of Init Structure and call HAL_SAI_InitProtocol(). 00045 00046 [..] 00047 (@) The specific SAI interrupts (FIFO request and Overrun underrun interrupt) 00048 will be managed using the macros __HAL_SAI_ENABLE_IT() and __HAL_SAI_DISABLE_IT() 00049 inside the transmit and receive process. 00050 00051 [..] 00052 (@) SAI Clock Source configuration is managed differently depending on the selected 00053 STM32F4 devices : 00054 (+@) For STM32F446xx devices, the configuration is managed through RCCEx_PeriphCLKConfig() 00055 function in the HAL RCC drivers 00056 (+@) For STM32F439xx/STM32F437xx/STM32F429xx/STM32F427xx devices, the configuration 00057 is managed within HAL SAI drivers through HAL_SAI_Init() function using 00058 ClockSource field of SAI_InitTypeDef structure. 00059 [..] 00060 (@) Make sure that either: 00061 (+@) I2S PLL is configured or 00062 (+@) SAI PLL is configured or 00063 (+@) External clock source is configured after setting correctly 00064 the define constant EXTERNAL_CLOCK_VALUE in the stm32f4xx_hal_conf.h file. 00065 [..] 00066 (@) In master Tx mode: enabling the audio block immediately generates the bit clock 00067 for the external slaves even if there is no data in the FIFO, However FS signal 00068 generation is conditioned by the presence of data in the FIFO. 00069 00070 [..] 00071 (@) In master Rx mode: enabling the audio block immediately generates the bit clock 00072 and FS signal for the external slaves. 00073 00074 [..] 00075 (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior: 00076 (+@) First bit Offset <= (SLOT size - Data size) 00077 (+@) Data size <= SLOT size 00078 (+@) Number of SLOT x SLOT size = Frame length 00079 (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected. 00080 00081 [..] 00082 Three operation modes are available within this driver : 00083 00084 *** Polling mode IO operation *** 00085 ================================= 00086 [..] 00087 (+) Send an amount of data in blocking mode using HAL_SAI_Transmit() 00088 (+) Receive an amount of data in blocking mode using HAL_SAI_Receive() 00089 00090 *** Interrupt mode IO operation *** 00091 =================================== 00092 [..] 00093 (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT() 00094 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can 00095 add his own code by customization of function pointer HAL_SAI_TxCpltCallback() 00096 (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT() 00097 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can 00098 add his own code by customization of function pointer HAL_SAI_RxCpltCallback() 00099 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can 00100 add his own code by customization of function pointer HAL_SAI_ErrorCallback() 00101 00102 *** DMA mode IO operation *** 00103 ============================= 00104 [..] 00105 (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA() 00106 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can 00107 add his own code by customization of function pointer HAL_SAI_TxCpltCallback() 00108 (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA() 00109 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can 00110 add his own code by customization of function pointer HAL_SAI_RxCpltCallback() 00111 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can 00112 add his own code by customization of function pointer HAL_SAI_ErrorCallback() 00113 (+) Pause the DMA Transfer using HAL_SAI_DMAPause() 00114 (+) Resume the DMA Transfer using HAL_SAI_DMAResume() 00115 (+) Stop the DMA Transfer using HAL_SAI_DMAStop() 00116 00117 *** SAI HAL driver additional function list *** 00118 =============================================== 00119 [..] 00120 Below the list the others API available SAI HAL driver : 00121 00122 (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode 00123 (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode 00124 (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode 00125 (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode 00126 (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo. 00127 (+) HAL_SAI_Abort(): Abort the current transfer 00128 00129 *** SAI HAL driver macros list *** 00130 ================================== 00131 [..] 00132 Below the list of most used macros in SAI HAL driver : 00133 00134 (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral 00135 (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral 00136 (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts 00137 (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts 00138 (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is 00139 enabled or disabled 00140 (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not 00141 00142 @endverbatim 00143 ****************************************************************************** 00144 * @attention 00145 * 00146 * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> 00147 * 00148 * Redistribution and use in source and binary forms, with or without modification, 00149 * are permitted provided that the following conditions are met: 00150 * 1. Redistributions of source code must retain the above copyright notice, 00151 * this list of conditions and the following disclaimer. 00152 * 2. Redistributions in binary form must reproduce the above copyright notice, 00153 * this list of conditions and the following disclaimer in the documentation 00154 * and/or other materials provided with the distribution. 00155 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00156 * may be used to endorse or promote products derived from this software 00157 * without specific prior written permission. 00158 * 00159 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00160 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00161 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00162 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00163 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00164 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00165 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00166 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00167 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00168 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00169 * 00170 ****************************************************************************** 00171 */ 00172 00173 /* Includes ------------------------------------------------------------------*/ 00174 #include "stm32f4xx_hal.h" 00175 00176 /** @addtogroup STM32F4xx_HAL_Driver 00177 * @{ 00178 */ 00179 00180 /** @defgroup SAI SAI 00181 * @brief SAI HAL module driver 00182 * @{ 00183 */ 00184 00185 #ifdef HAL_SAI_MODULE_ENABLED 00186 00187 #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ 00188 defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) ||\ 00189 defined(STM32F423xx) 00190 00191 /** @defgroup SAI_Private_Typedefs SAI Private Typedefs 00192 * @{ 00193 */ 00194 typedef enum { 00195 SAI_MODE_DMA, 00196 SAI_MODE_IT 00197 }SAI_ModeTypedef; 00198 /** 00199 * @} 00200 */ 00201 00202 /* Private define ------------------------------------------------------------*/ 00203 00204 /** @defgroup SAI_Private_Constants SAI Private Constants 00205 * @{ 00206 */ 00207 #define SAI_FIFO_SIZE 8U 00208 #define SAI_DEFAULT_TIMEOUT 4U /* 4ms */ 00209 /** 00210 * @} 00211 */ 00212 00213 /* Private macro -------------------------------------------------------------*/ 00214 /* Private variables ---------------------------------------------------------*/ 00215 /* Private function prototypes -----------------------------------------------*/ 00216 00217 /** @defgroup SAI_Private_Functions SAI Private Functions 00218 * @{ 00219 */ 00220 static void SAI_FillFifo(SAI_HandleTypeDef *hsai); 00221 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode); 00222 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot); 00223 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot); 00224 00225 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai); 00226 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai); 00227 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai); 00228 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai); 00229 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai); 00230 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai); 00231 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai); 00232 00233 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma); 00234 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma); 00235 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma); 00236 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma); 00237 static void SAI_DMAError(DMA_HandleTypeDef *hdma); 00238 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma); 00239 /** 00240 * @} 00241 */ 00242 00243 /* Exported functions ---------------------------------------------------------*/ 00244 00245 /** @defgroup SAI_Exported_Functions SAI Exported Functions 00246 * @{ 00247 */ 00248 00249 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions 00250 * @brief Initialization and Configuration functions 00251 * 00252 @verbatim 00253 =============================================================================== 00254 ##### Initialization and de-initialization functions ##### 00255 =============================================================================== 00256 [..] This subsection provides a set of functions allowing to initialize and 00257 de-initialize the SAIx peripheral: 00258 00259 (+) User must implement HAL_SAI_MspInit() function in which he configures 00260 all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ). 00261 00262 (+) Call the function HAL_SAI_Init() to configure the selected device with 00263 the selected configuration: 00264 (++) Mode (Master/slave TX/RX) 00265 (++) Protocol 00266 (++) Data Size 00267 (++) MCLK Output 00268 (++) Audio frequency 00269 (++) FIFO Threshold 00270 (++) Frame Config 00271 (++) Slot Config 00272 00273 (+) Call the function HAL_SAI_DeInit() to restore the default configuration 00274 of the selected SAI peripheral. 00275 00276 @endverbatim 00277 * @{ 00278 */ 00279 00280 /** 00281 * @brief Initialize the structure FrameInit, SlotInit and the low part of 00282 * Init according to the specified parameters and call the function 00283 * HAL_SAI_Init to initialize the SAI block. 00284 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00285 * the configuration information for SAI module. 00286 * @param protocol one of the supported protocol @ref SAI_Protocol 00287 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize 00288 * the configuration information for SAI module. 00289 * @param nbslot Number of slot. 00290 * @retval HAL status 00291 */ 00292 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot) 00293 { 00294 HAL_StatusTypeDef status = HAL_OK; 00295 00296 /* Check the parameters */ 00297 assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol)); 00298 assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize)); 00299 00300 switch(protocol) 00301 { 00302 case SAI_I2S_STANDARD : 00303 case SAI_I2S_MSBJUSTIFIED : 00304 case SAI_I2S_LSBJUSTIFIED : 00305 status = SAI_InitI2S(hsai, protocol, datasize, nbslot); 00306 break; 00307 case SAI_PCM_LONG : 00308 case SAI_PCM_SHORT : 00309 status = SAI_InitPCM(hsai, protocol, datasize, nbslot); 00310 break; 00311 default : 00312 status = HAL_ERROR; 00313 break; 00314 } 00315 00316 if(status == HAL_OK) 00317 { 00318 status = HAL_SAI_Init(hsai); 00319 } 00320 00321 return status; 00322 } 00323 00324 /** 00325 * @brief Initialize the SAI according to the specified parameters. 00326 * in the SAI_InitTypeDef structure and initialize the associated handle. 00327 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00328 * the configuration information for SAI module. 00329 * @retval HAL status 00330 */ 00331 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai) 00332 { 00333 uint32_t tmpregisterGCR = 0U; 00334 00335 /* This variable used to store the SAI_CK_x (value in Hz) */ 00336 uint32_t freq = 0U; 00337 00338 /* This variable is used to compute CKSTR bits of SAI CR1 according to 00339 ClockStrobing and AudioMode fields */ 00340 uint32_t ckstr_bits = 0U; 00341 uint32_t syncen_bits = 0U; 00342 00343 /* Check the SAI handle allocation */ 00344 if(hsai == NULL) 00345 { 00346 return HAL_ERROR; 00347 } 00348 00349 /* check the instance */ 00350 assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance)); 00351 00352 /* Check the SAI Block parameters */ 00353 assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency)); 00354 assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol)); 00355 assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode)); 00356 assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt)); 00357 assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize)); 00358 assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit)); 00359 assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing)); 00360 assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro)); 00361 assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive)); 00362 assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider)); 00363 assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold)); 00364 assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode)); 00365 assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode)); 00366 assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState)); 00367 00368 /* Check the SAI Block Frame parameters */ 00369 assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength)); 00370 assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength)); 00371 assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition)); 00372 assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity)); 00373 assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset)); 00374 00375 /* Check the SAI Block Slot parameters */ 00376 assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset)); 00377 assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize)); 00378 assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber)); 00379 assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive)); 00380 00381 if(hsai->State == HAL_SAI_STATE_RESET) 00382 { 00383 /* Allocate lock resource and initialize it */ 00384 hsai->Lock = HAL_UNLOCKED; 00385 00386 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ 00387 HAL_SAI_MspInit(hsai); 00388 } 00389 00390 hsai->State = HAL_SAI_STATE_BUSY; 00391 00392 /* Disable the selected SAI peripheral */ 00393 SAI_Disable(hsai); 00394 00395 /* SAI Block Synchro Configuration -----------------------------------------*/ 00396 SAI_BlockSynchroConfig(hsai); 00397 00398 /* Configure Master Clock using the following formula : 00399 MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS 00400 FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256 00401 MCKDIV[3:0] = SAI_CK_x / FS * 512 */ 00402 if(hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV) 00403 { 00404 /* Get SAI clock source based on Source clock selection from RCC */ 00405 freq = SAI_GetInputClock(hsai); 00406 00407 /* (saiclocksource x 10) to keep Significant digits */ 00408 tmpregisterGCR = (((freq * 10U) / ((hsai->Init.AudioFrequency) * 512U))); 00409 00410 hsai->Init.Mckdiv = tmpregisterGCR / 10U; 00411 00412 /* Round result to the nearest integer */ 00413 if((tmpregisterGCR % 10U) > 8U) 00414 { 00415 hsai->Init.Mckdiv+= 1U; 00416 } 00417 } 00418 00419 /* Compute CKSTR bits of SAI CR1 according to ClockStrobing and AudioMode */ 00420 if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) 00421 { 00422 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U: SAI_xCR1_CKSTR; 00423 } 00424 else 00425 { 00426 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR: 0U; 00427 } 00428 00429 /* SAI Block Configuration -------------------------------------------------*/ 00430 switch(hsai->Init.Synchro) 00431 { 00432 case SAI_ASYNCHRONOUS : 00433 { 00434 syncen_bits = 0U; 00435 } 00436 break; 00437 case SAI_SYNCHRONOUS : 00438 { 00439 syncen_bits = SAI_xCR1_SYNCEN_0; 00440 } 00441 break; 00442 case SAI_SYNCHRONOUS_EXT_SAI1 : 00443 case SAI_SYNCHRONOUS_EXT_SAI2 : 00444 { 00445 syncen_bits = SAI_xCR1_SYNCEN_1; 00446 } 00447 break; 00448 default: 00449 break; 00450 } 00451 /* SAI CR1 Configuration */ 00452 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \ 00453 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN |\ 00454 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \ 00455 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV); 00456 00457 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \ 00458 hsai->Init.DataSize | hsai->Init.FirstBit | \ 00459 ckstr_bits | syncen_bits | \ 00460 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \ 00461 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20U)); 00462 00463 /* SAI CR2 Configuration */ 00464 hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL); 00465 hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState); 00466 00467 /* SAI Frame Configuration -----------------------------------------*/ 00468 hsai->Instance->FRCR&=(~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \ 00469 SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF)); 00470 hsai->Instance->FRCR|=((hsai->FrameInit.FrameLength - 1U) | 00471 hsai->FrameInit.FSOffset | 00472 hsai->FrameInit.FSDefinition | 00473 hsai->FrameInit.FSPolarity | 00474 ((hsai->FrameInit.ActiveFrameLength - 1U) << 8U)); 00475 00476 /* SAI Block_x SLOT Configuration ------------------------------------------*/ 00477 /* This register has no meaning in AC 97 and SPDIF audio protocol */ 00478 hsai->Instance->SLOTR &= ~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \ 00479 SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN ); 00480 00481 hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \ 00482 (hsai->SlotInit.SlotActive << 16U) | ((hsai->SlotInit.SlotNumber - 1U) << 8U); 00483 00484 /* Initialize the error code */ 00485 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 00486 00487 /* Initialize the SAI state */ 00488 hsai->State= HAL_SAI_STATE_READY; 00489 00490 /* Release Lock */ 00491 __HAL_UNLOCK(hsai); 00492 00493 return HAL_OK; 00494 } 00495 00496 /** 00497 * @brief DeInitialize the SAI peripheral. 00498 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00499 * the configuration information for SAI module. 00500 * @retval HAL status 00501 */ 00502 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai) 00503 { 00504 /* Check the SAI handle allocation */ 00505 if(hsai == NULL) 00506 { 00507 return HAL_ERROR; 00508 } 00509 00510 hsai->State = HAL_SAI_STATE_BUSY; 00511 00512 /* Disabled All interrupt and clear all the flag */ 00513 hsai->Instance->IMR = 0U; 00514 hsai->Instance->CLRFR = 0xFFFFFFFFU; 00515 00516 /* Disable the SAI */ 00517 SAI_Disable(hsai); 00518 00519 /* Flush the fifo */ 00520 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 00521 00522 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */ 00523 HAL_SAI_MspDeInit(hsai); 00524 00525 /* Initialize the error code */ 00526 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 00527 00528 /* Initialize the SAI state */ 00529 hsai->State = HAL_SAI_STATE_RESET; 00530 00531 /* Release Lock */ 00532 __HAL_UNLOCK(hsai); 00533 00534 return HAL_OK; 00535 } 00536 00537 /** 00538 * @brief Initialize the SAI MSP. 00539 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00540 * the configuration information for SAI module. 00541 * @retval None 00542 */ 00543 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai) 00544 { 00545 /* Prevent unused argument(s) compilation warning */ 00546 UNUSED(hsai); 00547 00548 /* NOTE : This function should not be modified, when the callback is needed, 00549 the HAL_SAI_MspInit could be implemented in the user file 00550 */ 00551 } 00552 00553 /** 00554 * @brief DeInitialize the SAI MSP. 00555 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00556 * the configuration information for SAI module. 00557 * @retval None 00558 */ 00559 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai) 00560 { 00561 /* Prevent unused argument(s) compilation warning */ 00562 UNUSED(hsai); 00563 00564 /* NOTE : This function should not be modified, when the callback is needed, 00565 the HAL_SAI_MspDeInit could be implemented in the user file 00566 */ 00567 } 00568 00569 /** 00570 * @} 00571 */ 00572 00573 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions 00574 * @brief Data transfers functions 00575 * 00576 @verbatim 00577 ============================================================================== 00578 ##### IO operation functions ##### 00579 ============================================================================== 00580 [..] 00581 This subsection provides a set of functions allowing to manage the SAI data 00582 transfers. 00583 00584 (+) There are two modes of transfer: 00585 (++) Blocking mode : The communication is performed in the polling mode. 00586 The status of all data processing is returned by the same function 00587 after finishing transfer. 00588 (++) No-Blocking mode : The communication is performed using Interrupts 00589 or DMA. These functions return the status of the transfer startup. 00590 The end of the data processing will be indicated through the 00591 dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when 00592 using DMA mode. 00593 00594 (+) Blocking mode functions are : 00595 (++) HAL_SAI_Transmit() 00596 (++) HAL_SAI_Receive() 00597 00598 (+) Non Blocking mode functions with Interrupt are : 00599 (++) HAL_SAI_Transmit_IT() 00600 (++) HAL_SAI_Receive_IT() 00601 00602 (+) Non Blocking mode functions with DMA are : 00603 (++) HAL_SAI_Transmit_DMA() 00604 (++) HAL_SAI_Receive_DMA() 00605 00606 (+) A set of Transfer Complete Callbacks are provided in non Blocking mode: 00607 (++) HAL_SAI_TxCpltCallback() 00608 (++) HAL_SAI_RxCpltCallback() 00609 (++) HAL_SAI_ErrorCallback() 00610 00611 @endverbatim 00612 * @{ 00613 */ 00614 00615 /** 00616 * @brief Transmit an amount of data in blocking mode. 00617 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00618 * the configuration information for SAI module. 00619 * @param pData Pointer to data buffer 00620 * @param Size Amount of data to be sent 00621 * @param Timeout Timeout duration 00622 * @retval HAL status 00623 */ 00624 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t* pData, uint16_t Size, uint32_t Timeout) 00625 { 00626 uint32_t tickstart = HAL_GetTick(); 00627 00628 if((pData == NULL ) || (Size == 0)) 00629 { 00630 return HAL_ERROR; 00631 } 00632 00633 if(hsai->State == HAL_SAI_STATE_READY) 00634 { 00635 /* Process Locked */ 00636 __HAL_LOCK(hsai); 00637 00638 hsai->XferSize = Size; 00639 hsai->XferCount = Size; 00640 hsai->pBuffPtr = pData; 00641 hsai->State = HAL_SAI_STATE_BUSY_TX; 00642 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 00643 00644 /* Check if the SAI is already enabled */ 00645 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) 00646 { 00647 /* fill the fifo with data before to enabled the SAI */ 00648 SAI_FillFifo(hsai); 00649 /* Enable SAI peripheral */ 00650 __HAL_SAI_ENABLE(hsai); 00651 } 00652 00653 while(hsai->XferCount > 0U) 00654 { 00655 /* Write data if the FIFO is not full */ 00656 if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) 00657 { 00658 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) 00659 { 00660 hsai->Instance->DR = (*hsai->pBuffPtr++); 00661 } 00662 else if(hsai->Init.DataSize <= SAI_DATASIZE_16) 00663 { 00664 hsai->Instance->DR = *((uint16_t *)hsai->pBuffPtr); 00665 hsai->pBuffPtr+= 2U; 00666 } 00667 else 00668 { 00669 hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr); 00670 hsai->pBuffPtr+= 4U; 00671 } 00672 hsai->XferCount--; 00673 } 00674 else 00675 { 00676 /* Check for the Timeout */ 00677 if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U)||((HAL_GetTick() - tickstart) > Timeout))) 00678 { 00679 /* Update error code */ 00680 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT; 00681 00682 /* Clear all the flags */ 00683 hsai->Instance->CLRFR = 0xFFFFFFFFU; 00684 00685 /* Disable SAI peripheral */ 00686 SAI_Disable(hsai); 00687 00688 /* Flush the fifo */ 00689 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 00690 00691 /* Change the SAI state */ 00692 hsai->State = HAL_SAI_STATE_READY; 00693 00694 /* Process Unlocked */ 00695 __HAL_UNLOCK(hsai); 00696 00697 return HAL_ERROR; 00698 } 00699 } 00700 } 00701 00702 hsai->State = HAL_SAI_STATE_READY; 00703 00704 /* Process Unlocked */ 00705 __HAL_UNLOCK(hsai); 00706 00707 return HAL_OK; 00708 } 00709 else 00710 { 00711 return HAL_BUSY; 00712 } 00713 } 00714 00715 /** 00716 * @brief Receive an amount of data in blocking mode. 00717 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00718 * the configuration information for SAI module. 00719 * @param pData Pointer to data buffer 00720 * @param Size Amount of data to be received 00721 * @param Timeout Timeout duration 00722 * @retval HAL status 00723 */ 00724 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout) 00725 { 00726 uint32_t tickstart = HAL_GetTick(); 00727 00728 if((pData == NULL ) || (Size == 0)) 00729 { 00730 return HAL_ERROR; 00731 } 00732 00733 if(hsai->State == HAL_SAI_STATE_READY) 00734 { 00735 /* Process Locked */ 00736 __HAL_LOCK(hsai); 00737 00738 hsai->pBuffPtr = pData; 00739 hsai->XferSize = Size; 00740 hsai->XferCount = Size; 00741 hsai->State = HAL_SAI_STATE_BUSY_RX; 00742 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 00743 00744 /* Check if the SAI is already enabled */ 00745 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) 00746 { 00747 /* Enable SAI peripheral */ 00748 __HAL_SAI_ENABLE(hsai); 00749 } 00750 00751 /* Receive data */ 00752 while(hsai->XferCount > 0U) 00753 { 00754 if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY) 00755 { 00756 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) 00757 { 00758 (*hsai->pBuffPtr++) = hsai->Instance->DR; 00759 } 00760 else if(hsai->Init.DataSize <= SAI_DATASIZE_16) 00761 { 00762 *((uint16_t*)hsai->pBuffPtr) = hsai->Instance->DR; 00763 hsai->pBuffPtr+= 2U; 00764 } 00765 else 00766 { 00767 *((uint32_t*)hsai->pBuffPtr) = hsai->Instance->DR; 00768 hsai->pBuffPtr+= 4U; 00769 } 00770 hsai->XferCount--; 00771 } 00772 else 00773 { 00774 /* Check for the Timeout */ 00775 if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))) 00776 { 00777 /* Update error code */ 00778 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT; 00779 00780 /* Clear all the flags */ 00781 hsai->Instance->CLRFR = 0xFFFFFFFFU; 00782 00783 /* Disable SAI peripheral */ 00784 SAI_Disable(hsai); 00785 00786 /* Flush the fifo */ 00787 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 00788 00789 /* Change the SAI state */ 00790 hsai->State = HAL_SAI_STATE_READY; 00791 00792 /* Process Unlocked */ 00793 __HAL_UNLOCK(hsai); 00794 00795 return HAL_ERROR; 00796 } 00797 } 00798 } 00799 00800 hsai->State = HAL_SAI_STATE_READY; 00801 00802 /* Process Unlocked */ 00803 __HAL_UNLOCK(hsai); 00804 00805 return HAL_OK; 00806 } 00807 else 00808 { 00809 return HAL_BUSY; 00810 } 00811 } 00812 00813 /** 00814 * @brief Transmit an amount of data in non-blocking mode with Interrupt. 00815 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00816 * the configuration information for SAI module. 00817 * @param pData Pointer to data buffer 00818 * @param Size Amount of data to be sent 00819 * @retval HAL status 00820 */ 00821 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) 00822 { 00823 if((pData == NULL) || (Size == 0)) 00824 { 00825 return HAL_ERROR; 00826 } 00827 00828 if(hsai->State == HAL_SAI_STATE_READY) 00829 { 00830 /* Process Locked */ 00831 __HAL_LOCK(hsai); 00832 00833 hsai->pBuffPtr = pData; 00834 hsai->XferSize = Size; 00835 hsai->XferCount = Size; 00836 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 00837 hsai->State = HAL_SAI_STATE_BUSY_TX; 00838 00839 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) 00840 { 00841 hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit; 00842 } 00843 else if(hsai->Init.DataSize <= SAI_DATASIZE_16) 00844 { 00845 hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit; 00846 } 00847 else 00848 { 00849 hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit; 00850 } 00851 00852 /* Fill the fifo before starting the communication */ 00853 SAI_FillFifo(hsai); 00854 00855 /* Enable FRQ and OVRUDR interrupts */ 00856 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 00857 00858 /* Check if the SAI is already enabled */ 00859 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) 00860 { 00861 /* Enable SAI peripheral */ 00862 __HAL_SAI_ENABLE(hsai); 00863 } 00864 /* Process Unlocked */ 00865 __HAL_UNLOCK(hsai); 00866 00867 return HAL_OK; 00868 } 00869 else 00870 { 00871 return HAL_BUSY; 00872 } 00873 } 00874 00875 /** 00876 * @brief Receive an amount of data in non-blocking mode with Interrupt. 00877 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00878 * the configuration information for SAI module. 00879 * @param pData Pointer to data buffer 00880 * @param Size Amount of data to be received 00881 * @retval HAL status 00882 */ 00883 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) 00884 { 00885 if((pData == NULL) || (Size == 0)) 00886 { 00887 return HAL_ERROR; 00888 } 00889 00890 if(hsai->State == HAL_SAI_STATE_READY) 00891 { 00892 /* Process Locked */ 00893 __HAL_LOCK(hsai); 00894 00895 hsai->pBuffPtr = pData; 00896 hsai->XferSize = Size; 00897 hsai->XferCount = Size; 00898 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 00899 hsai->State = HAL_SAI_STATE_BUSY_RX; 00900 00901 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) 00902 { 00903 hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit; 00904 } 00905 else if(hsai->Init.DataSize <= SAI_DATASIZE_16) 00906 { 00907 hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit; 00908 } 00909 else 00910 { 00911 hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit; 00912 } 00913 00914 /* Enable TXE and OVRUDR interrupts */ 00915 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 00916 00917 /* Check if the SAI is already enabled */ 00918 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) 00919 { 00920 /* Enable SAI peripheral */ 00921 __HAL_SAI_ENABLE(hsai); 00922 } 00923 00924 /* Process Unlocked */ 00925 __HAL_UNLOCK(hsai); 00926 00927 return HAL_OK; 00928 } 00929 else 00930 { 00931 return HAL_BUSY; 00932 } 00933 } 00934 00935 /** 00936 * @brief Pause the audio stream playing from the Media. 00937 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00938 * the configuration information for SAI module. 00939 * @retval HAL status 00940 */ 00941 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai) 00942 { 00943 /* Process Locked */ 00944 __HAL_LOCK(hsai); 00945 00946 /* Pause the audio file playing by disabling the SAI DMA requests */ 00947 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; 00948 00949 /* Process Unlocked */ 00950 __HAL_UNLOCK(hsai); 00951 00952 return HAL_OK; 00953 } 00954 00955 /** 00956 * @brief Resume the audio stream playing from the Media. 00957 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00958 * the configuration information for SAI module. 00959 * @retval HAL status 00960 */ 00961 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai) 00962 { 00963 /* Process Locked */ 00964 __HAL_LOCK(hsai); 00965 00966 /* Enable the SAI DMA requests */ 00967 hsai->Instance->CR1 |= SAI_xCR1_DMAEN; 00968 00969 /* If the SAI peripheral is still not enabled, enable it */ 00970 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) 00971 { 00972 /* Enable SAI peripheral */ 00973 __HAL_SAI_ENABLE(hsai); 00974 } 00975 00976 /* Process Unlocked */ 00977 __HAL_UNLOCK(hsai); 00978 00979 return HAL_OK; 00980 } 00981 00982 /** 00983 * @brief Stop the audio stream playing from the Media. 00984 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00985 * the configuration information for SAI module. 00986 * @retval HAL status 00987 */ 00988 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai) 00989 { 00990 /* Process Locked */ 00991 __HAL_LOCK(hsai); 00992 00993 /* Disable the SAI DMA request */ 00994 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; 00995 00996 /* Abort the SAI DMA Streams */ 00997 if(hsai->hdmatx != NULL) 00998 { 00999 if(HAL_DMA_Abort(hsai->hdmatx) != HAL_OK) 01000 { 01001 return HAL_ERROR; 01002 } 01003 } 01004 01005 if(hsai->hdmarx != NULL) 01006 { 01007 if(HAL_DMA_Abort(hsai->hdmarx) != HAL_OK) 01008 { 01009 return HAL_ERROR; 01010 } 01011 } 01012 01013 /* Disable SAI peripheral */ 01014 SAI_Disable(hsai); 01015 01016 /* Flush the fifo */ 01017 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 01018 01019 hsai->State = HAL_SAI_STATE_READY; 01020 01021 /* Process Unlocked */ 01022 __HAL_UNLOCK(hsai); 01023 01024 return HAL_OK; 01025 } 01026 01027 /** 01028 * @brief Abort the current transfer and disable the SAI. 01029 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01030 * the configuration information for SAI module. 01031 * @retval HAL status 01032 */ 01033 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai) 01034 { 01035 /* Process Locked */ 01036 __HAL_LOCK(hsai); 01037 01038 /* Check SAI DMA is enabled or not */ 01039 if((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) 01040 { 01041 /* Disable the SAI DMA request */ 01042 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; 01043 01044 /* Abort the SAI DMA Streams */ 01045 if(hsai->hdmatx != NULL) 01046 { 01047 if(HAL_DMA_Abort(hsai->hdmatx) != HAL_OK) 01048 { 01049 return HAL_ERROR; 01050 } 01051 } 01052 01053 if(hsai->hdmarx != NULL) 01054 { 01055 if(HAL_DMA_Abort(hsai->hdmarx) != HAL_OK) 01056 { 01057 return HAL_ERROR; 01058 } 01059 } 01060 } 01061 01062 /* Disabled All interrupt and clear all the flag */ 01063 hsai->Instance->IMR = 0U; 01064 hsai->Instance->CLRFR = 0xFFFFFFFFU; 01065 01066 /* Disable SAI peripheral */ 01067 SAI_Disable(hsai); 01068 01069 /* Flush the fifo */ 01070 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 01071 01072 hsai->State = HAL_SAI_STATE_READY; 01073 01074 /* Process Unlocked */ 01075 __HAL_UNLOCK(hsai); 01076 01077 return HAL_OK; 01078 } 01079 01080 /** 01081 * @brief Transmit an amount of data in non-blocking mode with DMA. 01082 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01083 * the configuration information for SAI module. 01084 * @param pData Pointer to data buffer 01085 * @param Size Amount of data to be sent 01086 * @retval HAL status 01087 */ 01088 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) 01089 { 01090 if((pData == NULL) || (Size == 0)) 01091 { 01092 return HAL_ERROR; 01093 } 01094 01095 if(hsai->State == HAL_SAI_STATE_READY) 01096 { 01097 /* Process Locked */ 01098 __HAL_LOCK(hsai); 01099 01100 hsai->pBuffPtr = pData; 01101 hsai->XferSize = Size; 01102 hsai->XferCount = Size; 01103 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 01104 hsai->State = HAL_SAI_STATE_BUSY_TX; 01105 01106 /* Set the SAI Tx DMA Half transfer complete callback */ 01107 hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt; 01108 01109 /* Set the SAI TxDMA transfer complete callback */ 01110 hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt; 01111 01112 /* Set the DMA error callback */ 01113 hsai->hdmatx->XferErrorCallback = SAI_DMAError; 01114 01115 /* Set the DMA Tx abort callback */ 01116 hsai->hdmatx->XferAbortCallback = NULL; 01117 01118 /* Enable the Tx DMA Stream */ 01119 if(HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK) 01120 { 01121 __HAL_UNLOCK(hsai); 01122 return HAL_ERROR; 01123 } 01124 01125 /* Check if the SAI is already enabled */ 01126 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) 01127 { 01128 /* Enable SAI peripheral */ 01129 __HAL_SAI_ENABLE(hsai); 01130 } 01131 01132 /* Enable the interrupts for error handling */ 01133 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); 01134 01135 /* Enable SAI Tx DMA Request */ 01136 hsai->Instance->CR1 |= SAI_xCR1_DMAEN; 01137 01138 /* Process Unlocked */ 01139 __HAL_UNLOCK(hsai); 01140 01141 return HAL_OK; 01142 } 01143 else 01144 { 01145 return HAL_BUSY; 01146 } 01147 } 01148 01149 /** 01150 * @brief Receive an amount of data in non-blocking mode with DMA. 01151 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01152 * the configuration information for SAI module. 01153 * @param pData Pointer to data buffer 01154 * @param Size Amount of data to be received 01155 * @retval HAL status 01156 */ 01157 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) 01158 { 01159 if((pData == NULL) || (Size == 0)) 01160 { 01161 return HAL_ERROR; 01162 } 01163 01164 if(hsai->State == HAL_SAI_STATE_READY) 01165 { 01166 /* Process Locked */ 01167 __HAL_LOCK(hsai); 01168 01169 hsai->pBuffPtr = pData; 01170 hsai->XferSize = Size; 01171 hsai->XferCount = Size; 01172 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 01173 hsai->State = HAL_SAI_STATE_BUSY_RX; 01174 01175 /* Set the SAI Rx DMA Half transfer complete callback */ 01176 hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt; 01177 01178 /* Set the SAI Rx DMA transfer complete callback */ 01179 hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt; 01180 01181 /* Set the DMA error callback */ 01182 hsai->hdmarx->XferErrorCallback = SAI_DMAError; 01183 01184 /* Set the DMA Rx abort callback */ 01185 hsai->hdmarx->XferAbortCallback = NULL; 01186 01187 /* Enable the Rx DMA Stream */ 01188 if(HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK) 01189 { 01190 __HAL_UNLOCK(hsai); 01191 return HAL_ERROR; 01192 } 01193 01194 /* Check if the SAI is already enabled */ 01195 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) 01196 { 01197 /* Enable SAI peripheral */ 01198 __HAL_SAI_ENABLE(hsai); 01199 } 01200 01201 /* Enable the interrupts for error handling */ 01202 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); 01203 01204 /* Enable SAI Rx DMA Request */ 01205 hsai->Instance->CR1 |= SAI_xCR1_DMAEN; 01206 01207 /* Process Unlocked */ 01208 __HAL_UNLOCK(hsai); 01209 01210 return HAL_OK; 01211 } 01212 else 01213 { 01214 return HAL_BUSY; 01215 } 01216 } 01217 01218 /** 01219 * @brief Enable the Tx mute mode. 01220 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01221 * the configuration information for SAI module. 01222 * @param val value sent during the mute @ref SAI_Block_Mute_Value 01223 * @retval HAL status 01224 */ 01225 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val) 01226 { 01227 assert_param(IS_SAI_BLOCK_MUTE_VALUE(val)); 01228 01229 if(hsai->State != HAL_SAI_STATE_RESET) 01230 { 01231 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE); 01232 SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | val); 01233 return HAL_OK; 01234 } 01235 return HAL_ERROR; 01236 } 01237 01238 /** 01239 * @brief Disable the Tx mute mode. 01240 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01241 * the configuration information for SAI module. 01242 * @retval HAL status 01243 */ 01244 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai) 01245 { 01246 if(hsai->State != HAL_SAI_STATE_RESET) 01247 { 01248 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE); 01249 return HAL_OK; 01250 } 01251 return HAL_ERROR; 01252 } 01253 01254 /** 01255 * @brief Enable the Rx mute detection. 01256 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01257 * the configuration information for SAI module. 01258 * @param callback function called when the mute is detected. 01259 * @param counter number a data before mute detection max 63. 01260 * @retval HAL status 01261 */ 01262 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter) 01263 { 01264 assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter)); 01265 01266 if(hsai->State != HAL_SAI_STATE_RESET) 01267 { 01268 /* set the mute counter */ 01269 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT); 01270 SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos)); 01271 hsai->mutecallback = callback; 01272 /* enable the IT interrupt */ 01273 __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET); 01274 return HAL_OK; 01275 } 01276 return HAL_ERROR; 01277 } 01278 01279 /** 01280 * @brief Disable the Rx mute detection. 01281 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01282 * the configuration information for SAI module. 01283 * @retval HAL status 01284 */ 01285 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai) 01286 { 01287 if(hsai->State != HAL_SAI_STATE_RESET) 01288 { 01289 /* set the mutecallback to NULL */ 01290 hsai->mutecallback = (SAIcallback)NULL; 01291 /* enable the IT interrupt */ 01292 __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET); 01293 return HAL_OK; 01294 } 01295 return HAL_ERROR; 01296 } 01297 01298 /** 01299 * @brief Handle SAI interrupt request. 01300 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01301 * the configuration information for SAI module. 01302 * @retval None 01303 */ 01304 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai) 01305 { 01306 if(hsai->State != HAL_SAI_STATE_RESET) 01307 { 01308 uint32_t itflags = hsai->Instance->SR; 01309 uint32_t itsources = hsai->Instance->IMR; 01310 uint32_t cr1config = hsai->Instance->CR1; 01311 uint32_t tmperror; 01312 01313 /* SAI Fifo request interrupt occured ------------------------------------*/ 01314 if(((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ)) 01315 { 01316 hsai->InterruptServiceRoutine(hsai); 01317 } 01318 /* SAI Overrun error interrupt occurred ----------------------------------*/ 01319 else if(((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR)) 01320 { 01321 /* Clear the SAI Overrun flag */ 01322 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); 01323 01324 /* Get the SAI error code */ 01325 tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR); 01326 01327 /* Change the SAI error code */ 01328 hsai->ErrorCode |= tmperror; 01329 01330 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */ 01331 HAL_SAI_ErrorCallback(hsai); 01332 } 01333 /* SAI mutedet interrupt occurred ----------------------------------*/ 01334 else if(((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET)) 01335 { 01336 /* Clear the SAI mutedet flag */ 01337 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET); 01338 01339 /* call the call back function */ 01340 if(hsai->mutecallback != (SAIcallback)NULL) 01341 { 01342 /* inform the user that an RX mute event has been detected */ 01343 hsai->mutecallback(); 01344 } 01345 } 01346 /* SAI AFSDET interrupt occurred ----------------------------------*/ 01347 else if(((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET)) 01348 { 01349 /* Change the SAI error code */ 01350 hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET; 01351 01352 /* Check SAI DMA is enabled or not */ 01353 if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) 01354 { 01355 /* Abort the SAI DMA Streams */ 01356 if(hsai->hdmatx != NULL) 01357 { 01358 /* Set the DMA Tx abort callback */ 01359 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort; 01360 01361 /* Abort DMA in IT mode */ 01362 HAL_DMA_Abort_IT(hsai->hdmatx); 01363 } 01364 else if(hsai->hdmarx != NULL) 01365 { 01366 /* Set the DMA Rx abort callback */ 01367 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort; 01368 01369 /* Abort DMA in IT mode */ 01370 HAL_DMA_Abort_IT(hsai->hdmarx); 01371 } 01372 } 01373 else 01374 { 01375 /* Abort SAI */ 01376 HAL_SAI_Abort(hsai); 01377 01378 /* Set error callback */ 01379 HAL_SAI_ErrorCallback(hsai); 01380 } 01381 } 01382 /* SAI LFSDET interrupt occurred ----------------------------------*/ 01383 else if(((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET)) 01384 { 01385 /* Change the SAI error code */ 01386 hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET; 01387 01388 /* Check SAI DMA is enabled or not */ 01389 if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) 01390 { 01391 /* Abort the SAI DMA Streams */ 01392 if(hsai->hdmatx != NULL) 01393 { 01394 /* Set the DMA Tx abort callback */ 01395 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort; 01396 01397 /* Abort DMA in IT mode */ 01398 HAL_DMA_Abort_IT(hsai->hdmatx); 01399 } 01400 else if(hsai->hdmarx != NULL) 01401 { 01402 /* Set the DMA Rx abort callback */ 01403 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort; 01404 01405 /* Abort DMA in IT mode */ 01406 HAL_DMA_Abort_IT(hsai->hdmarx); 01407 } 01408 } 01409 else 01410 { 01411 /* Abort SAI */ 01412 HAL_SAI_Abort(hsai); 01413 01414 /* Set error callback */ 01415 HAL_SAI_ErrorCallback(hsai); 01416 } 01417 } 01418 /* SAI WCKCFG interrupt occurred ----------------------------------*/ 01419 else if(((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG)) 01420 { 01421 /* Change the SAI error code */ 01422 hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG; 01423 01424 /* Check SAI DMA is enabled or not */ 01425 if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) 01426 { 01427 /* Abort the SAI DMA Streams */ 01428 if(hsai->hdmatx != NULL) 01429 { 01430 /* Set the DMA Tx abort callback */ 01431 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort; 01432 01433 /* Abort DMA in IT mode */ 01434 HAL_DMA_Abort_IT(hsai->hdmatx); 01435 } 01436 else if(hsai->hdmarx != NULL) 01437 { 01438 /* Set the DMA Rx abort callback */ 01439 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort; 01440 01441 /* Abort DMA in IT mode */ 01442 HAL_DMA_Abort_IT(hsai->hdmarx); 01443 } 01444 } 01445 else 01446 { 01447 /* If WCKCFG occurs, SAI audio block is automatically disabled */ 01448 /* Disable all interrupts and clear all flags */ 01449 hsai->Instance->IMR = 0U; 01450 hsai->Instance->CLRFR = 0xFFFFFFFFU; 01451 01452 /* Set the SAI state to ready to be able to start again the process */ 01453 hsai->State = HAL_SAI_STATE_READY; 01454 01455 /* Initialize XferCount */ 01456 hsai->XferCount = 0U; 01457 01458 /* SAI error Callback */ 01459 HAL_SAI_ErrorCallback(hsai); 01460 } 01461 } 01462 /* SAI CNRDY interrupt occurred ----------------------------------*/ 01463 else if(((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY)) 01464 { 01465 /* Clear the SAI CNRDY flag */ 01466 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY); 01467 01468 /* Change the SAI error code */ 01469 hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY; 01470 01471 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */ 01472 HAL_SAI_ErrorCallback(hsai); 01473 } 01474 else 01475 { 01476 /* Nothing to do */ 01477 } 01478 } 01479 } 01480 01481 /** 01482 * @brief Tx Transfer completed callback. 01483 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01484 * the configuration information for SAI module. 01485 * @retval None 01486 */ 01487 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 01488 { 01489 /* Prevent unused argument(s) compilation warning */ 01490 UNUSED(hsai); 01491 01492 /* NOTE : This function should not be modified, when the callback is needed, 01493 the HAL_SAI_TxCpltCallback could be implemented in the user file 01494 */ 01495 } 01496 01497 /** 01498 * @brief Tx Transfer Half completed callback. 01499 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01500 * the configuration information for SAI module. 01501 * @retval None 01502 */ 01503 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 01504 { 01505 /* Prevent unused argument(s) compilation warning */ 01506 UNUSED(hsai); 01507 01508 /* NOTE : This function should not be modified, when the callback is needed, 01509 the HAL_SAI_TxHalfCpltCallback could be implemented in the user file 01510 */ 01511 } 01512 01513 /** 01514 * @brief Rx Transfer completed callback. 01515 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01516 * the configuration information for SAI module. 01517 * @retval None 01518 */ 01519 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) 01520 { 01521 /* Prevent unused argument(s) compilation warning */ 01522 UNUSED(hsai); 01523 01524 /* NOTE : This function should not be modified, when the callback is needed, 01525 the HAL_SAI_RxCpltCallback could be implemented in the user file 01526 */ 01527 } 01528 01529 /** 01530 * @brief Rx Transfer half completed callback. 01531 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01532 * the configuration information for SAI module. 01533 * @retval None 01534 */ 01535 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) 01536 { 01537 /* Prevent unused argument(s) compilation warning */ 01538 UNUSED(hsai); 01539 01540 /* NOTE : This function should not be modified, when the callback is needed, 01541 the HAL_SAI_RxHalfCpltCallback could be implemented in the user file 01542 */ 01543 } 01544 01545 /** 01546 * @brief SAI error callback. 01547 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01548 * the configuration information for SAI module. 01549 * @retval None 01550 */ 01551 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 01552 { 01553 /* Prevent unused argument(s) compilation warning */ 01554 UNUSED(hsai); 01555 01556 /* NOTE : This function should not be modified, when the callback is needed, 01557 the HAL_SAI_ErrorCallback could be implemented in the user file 01558 */ 01559 } 01560 01561 /** 01562 * @} 01563 */ 01564 01565 01566 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions 01567 * @brief Peripheral State functions 01568 * 01569 @verbatim 01570 =============================================================================== 01571 ##### Peripheral State and Errors functions ##### 01572 =============================================================================== 01573 [..] 01574 This subsection permits to get in run-time the status of the peripheral 01575 and the data flow. 01576 01577 @endverbatim 01578 * @{ 01579 */ 01580 01581 /** 01582 * @brief Return the SAI handle state. 01583 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01584 * the configuration information for SAI module. 01585 * @retval HAL state 01586 */ 01587 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai) 01588 { 01589 return hsai->State; 01590 } 01591 01592 /** 01593 * @brief Return the SAI error code. 01594 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01595 * the configuration information for the specified SAI Block. 01596 * @retval SAI Error Code 01597 */ 01598 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai) 01599 { 01600 return hsai->ErrorCode; 01601 } 01602 /** 01603 * @} 01604 */ 01605 01606 /** 01607 * @} 01608 */ 01609 01610 /** @addtogroup SAI_Private_Functions 01611 * @brief Private functions 01612 * @{ 01613 */ 01614 01615 /** 01616 * @brief Initialize the SAI I2S protocol according to the specified parameters 01617 * in the SAI_InitTypeDef and create the associated handle. 01618 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01619 * the configuration information for SAI module. 01620 * @param protocol one of the supported protocol. 01621 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize 01622 * the configuration information for SAI module. 01623 * @param nbslot number of slot minimum value is 2 and max is 16. 01624 * the value must be a multiple of 2. 01625 * @retval HAL status 01626 */ 01627 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot) 01628 { 01629 hsai->Init.Protocol = SAI_FREE_PROTOCOL; 01630 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB; 01631 /* Compute ClockStrobing according AudioMode */ 01632 if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) 01633 { /* Transmit */ 01634 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 01635 } 01636 else 01637 { /* Receive */ 01638 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 01639 } 01640 hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01641 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL; 01642 hsai->SlotInit.FirstBitOffset = 0U; 01643 hsai->SlotInit.SlotNumber = nbslot; 01644 01645 /* in IS2 the number of slot must be even */ 01646 if((nbslot & 0x1U) != 0U) 01647 { 01648 return HAL_ERROR; 01649 } 01650 01651 switch(protocol) 01652 { 01653 case SAI_I2S_STANDARD : 01654 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01655 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01656 break; 01657 case SAI_I2S_MSBJUSTIFIED : 01658 case SAI_I2S_LSBJUSTIFIED : 01659 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH; 01660 hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT; 01661 break; 01662 default : 01663 return HAL_ERROR; 01664 } 01665 01666 /* Frame definition */ 01667 switch(datasize) 01668 { 01669 case SAI_PROTOCOL_DATASIZE_16BIT: 01670 hsai->Init.DataSize = SAI_DATASIZE_16; 01671 hsai->FrameInit.FrameLength = 32U*(nbslot/2U); 01672 hsai->FrameInit.ActiveFrameLength = 16U*(nbslot/2U); 01673 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B; 01674 break; 01675 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED : 01676 hsai->Init.DataSize = SAI_DATASIZE_16; 01677 hsai->FrameInit.FrameLength = 64U*(nbslot/2U); 01678 hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U); 01679 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 01680 break; 01681 case SAI_PROTOCOL_DATASIZE_24BIT: 01682 hsai->Init.DataSize = SAI_DATASIZE_24; 01683 hsai->FrameInit.FrameLength = 64U*(nbslot/2U); 01684 hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U); 01685 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 01686 break; 01687 case SAI_PROTOCOL_DATASIZE_32BIT: 01688 hsai->Init.DataSize = SAI_DATASIZE_32; 01689 hsai->FrameInit.FrameLength = 64U*(nbslot/2U); 01690 hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U); 01691 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 01692 break; 01693 default : 01694 return HAL_ERROR; 01695 } 01696 if(protocol == SAI_I2S_LSBJUSTIFIED) 01697 { 01698 if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED) 01699 { 01700 hsai->SlotInit.FirstBitOffset = 16U; 01701 } 01702 if (datasize == SAI_PROTOCOL_DATASIZE_24BIT) 01703 { 01704 hsai->SlotInit.FirstBitOffset = 8U; 01705 } 01706 } 01707 return HAL_OK; 01708 } 01709 01710 /** 01711 * @brief Initialize the SAI PCM protocol according to the specified parameters 01712 * in the SAI_InitTypeDef and create the associated handle. 01713 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01714 * the configuration information for SAI module. 01715 * @param protocol one of the supported protocol 01716 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize 01717 * @param nbslot number of slot minimum value is 1 and the max is 16. 01718 * @retval HAL status 01719 */ 01720 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot) 01721 { 01722 hsai->Init.Protocol = SAI_FREE_PROTOCOL; 01723 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB; 01724 /* Compute ClockStrobing according AudioMode */ 01725 if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) 01726 { /* Transmit */ 01727 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 01728 } 01729 else 01730 { /* Receive */ 01731 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 01732 } 01733 hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME; 01734 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH; 01735 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01736 hsai->SlotInit.FirstBitOffset = 0U; 01737 hsai->SlotInit.SlotNumber = nbslot; 01738 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL; 01739 01740 switch(protocol) 01741 { 01742 case SAI_PCM_SHORT : 01743 hsai->FrameInit.ActiveFrameLength = 1U; 01744 break; 01745 case SAI_PCM_LONG : 01746 hsai->FrameInit.ActiveFrameLength = 13U; 01747 break; 01748 default : 01749 return HAL_ERROR; 01750 } 01751 01752 switch(datasize) 01753 { 01754 case SAI_PROTOCOL_DATASIZE_16BIT: 01755 hsai->Init.DataSize = SAI_DATASIZE_16; 01756 hsai->FrameInit.FrameLength = 16U * nbslot; 01757 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B; 01758 break; 01759 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED : 01760 hsai->Init.DataSize = SAI_DATASIZE_16; 01761 hsai->FrameInit.FrameLength = 32U * nbslot; 01762 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 01763 break; 01764 case SAI_PROTOCOL_DATASIZE_24BIT : 01765 hsai->Init.DataSize = SAI_DATASIZE_24; 01766 hsai->FrameInit.FrameLength = 32U * nbslot; 01767 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 01768 break; 01769 case SAI_PROTOCOL_DATASIZE_32BIT: 01770 hsai->Init.DataSize = SAI_DATASIZE_32; 01771 hsai->FrameInit.FrameLength = 32U * nbslot; 01772 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 01773 break; 01774 default : 01775 return HAL_ERROR; 01776 } 01777 01778 return HAL_OK; 01779 } 01780 01781 /** 01782 * @brief Fill the fifo. 01783 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01784 * the configuration information for SAI module. 01785 * @retval None 01786 */ 01787 static void SAI_FillFifo(SAI_HandleTypeDef *hsai) 01788 { 01789 /* fill the fifo with data before to enabled the SAI */ 01790 while(((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U)) 01791 { 01792 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) 01793 { 01794 hsai->Instance->DR = (*hsai->pBuffPtr++); 01795 } 01796 else if(hsai->Init.DataSize <= SAI_DATASIZE_16) 01797 { 01798 hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr); 01799 hsai->pBuffPtr+= 2U; 01800 } 01801 else 01802 { 01803 hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr); 01804 hsai->pBuffPtr+= 4U; 01805 } 01806 hsai->XferCount--; 01807 } 01808 } 01809 01810 /** 01811 * @brief Return the interrupt flag to set according the SAI setup. 01812 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01813 * the configuration information for SAI module. 01814 * @param mode SAI_MODE_DMA or SAI_MODE_IT 01815 * @retval the list of the IT flag to enable 01816 */ 01817 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode) 01818 { 01819 uint32_t tmpIT = SAI_IT_OVRUDR; 01820 01821 if(mode == SAI_MODE_IT) 01822 { 01823 tmpIT|= SAI_IT_FREQ; 01824 } 01825 01826 if((hsai->Init.Protocol == SAI_AC97_PROTOCOL) && 01827 ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX))) 01828 { 01829 tmpIT|= SAI_IT_CNRDY; 01830 } 01831 01832 if((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) 01833 { 01834 tmpIT|= SAI_IT_AFSDET | SAI_IT_LFSDET; 01835 } 01836 else 01837 { 01838 /* hsai has been configured in master mode */ 01839 tmpIT|= SAI_IT_WCKCFG; 01840 } 01841 return tmpIT; 01842 } 01843 01844 /** 01845 * @brief Disable the SAI and wait for the disabling. 01846 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01847 * the configuration information for SAI module. 01848 * @retval None 01849 */ 01850 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai) 01851 { 01852 register uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock /7U/1000U); 01853 HAL_StatusTypeDef status = HAL_OK; 01854 01855 /* Disable the SAI instance */ 01856 __HAL_SAI_DISABLE(hsai); 01857 01858 do 01859 { 01860 /* Check for the Timeout */ 01861 if (count-- == 0U) 01862 { 01863 /* Update error code */ 01864 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT; 01865 status = HAL_TIMEOUT; 01866 break; 01867 } 01868 } while((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != RESET); 01869 01870 return status; 01871 } 01872 01873 /** 01874 * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer. 01875 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01876 * the configuration information for SAI module. 01877 * @retval None 01878 */ 01879 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai) 01880 { 01881 if(hsai->XferCount == 0U) 01882 { 01883 /* Handle the end of the transmission */ 01884 /* Disable FREQ and OVRUDR interrupts */ 01885 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 01886 hsai->State = HAL_SAI_STATE_READY; 01887 HAL_SAI_TxCpltCallback(hsai); 01888 } 01889 else 01890 { 01891 /* Write data on DR register */ 01892 hsai->Instance->DR = (*hsai->pBuffPtr++); 01893 hsai->XferCount--; 01894 } 01895 } 01896 01897 /** 01898 * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer. 01899 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01900 * the configuration information for SAI module. 01901 * @retval None 01902 */ 01903 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai) 01904 { 01905 if(hsai->XferCount == 0U) 01906 { 01907 /* Handle the end of the transmission */ 01908 /* Disable FREQ and OVRUDR interrupts */ 01909 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 01910 hsai->State = HAL_SAI_STATE_READY; 01911 HAL_SAI_TxCpltCallback(hsai); 01912 } 01913 else 01914 { 01915 /* Write data on DR register */ 01916 hsai->Instance->DR = *(uint16_t *)hsai->pBuffPtr; 01917 hsai->pBuffPtr+=2U; 01918 hsai->XferCount--; 01919 } 01920 } 01921 01922 /** 01923 * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer. 01924 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01925 * the configuration information for SAI module. 01926 * @retval None 01927 */ 01928 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai) 01929 { 01930 if(hsai->XferCount == 0U) 01931 { 01932 /* Handle the end of the transmission */ 01933 /* Disable FREQ and OVRUDR interrupts */ 01934 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 01935 hsai->State = HAL_SAI_STATE_READY; 01936 HAL_SAI_TxCpltCallback(hsai); 01937 } 01938 else 01939 { 01940 /* Write data on DR register */ 01941 hsai->Instance->DR = *(uint32_t *)hsai->pBuffPtr; 01942 hsai->pBuffPtr+=4U; 01943 hsai->XferCount--; 01944 } 01945 } 01946 01947 /** 01948 * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer. 01949 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01950 * the configuration information for SAI module. 01951 * @retval None 01952 */ 01953 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai) 01954 { 01955 /* Receive data */ 01956 (*hsai->pBuffPtr++) = hsai->Instance->DR; 01957 hsai->XferCount--; 01958 01959 /* Check end of the transfer */ 01960 if(hsai->XferCount == 0U) 01961 { 01962 /* Disable TXE and OVRUDR interrupts */ 01963 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 01964 01965 /* Clear the SAI Overrun flag */ 01966 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); 01967 01968 hsai->State = HAL_SAI_STATE_READY; 01969 HAL_SAI_RxCpltCallback(hsai); 01970 } 01971 } 01972 01973 /** 01974 * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer. 01975 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01976 * the configuration information for SAI module. 01977 * @retval None 01978 */ 01979 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai) 01980 { 01981 /* Receive data */ 01982 *(uint16_t*)hsai->pBuffPtr = hsai->Instance->DR; 01983 hsai->pBuffPtr+=2U; 01984 hsai->XferCount--; 01985 01986 /* Check end of the transfer */ 01987 if(hsai->XferCount == 0U) 01988 { 01989 /* Disable TXE and OVRUDR interrupts */ 01990 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 01991 01992 /* Clear the SAI Overrun flag */ 01993 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); 01994 01995 hsai->State = HAL_SAI_STATE_READY; 01996 HAL_SAI_RxCpltCallback(hsai); 01997 } 01998 } 01999 02000 /** 02001 * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer. 02002 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02003 * the configuration information for SAI module. 02004 * @retval None 02005 */ 02006 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai) 02007 { 02008 /* Receive data */ 02009 *(uint32_t*)hsai->pBuffPtr = hsai->Instance->DR; 02010 hsai->pBuffPtr+=4U; 02011 hsai->XferCount--; 02012 02013 /* Check end of the transfer */ 02014 if(hsai->XferCount == 0U) 02015 { 02016 /* Disable TXE and OVRUDR interrupts */ 02017 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 02018 02019 /* Clear the SAI Overrun flag */ 02020 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); 02021 02022 hsai->State = HAL_SAI_STATE_READY; 02023 HAL_SAI_RxCpltCallback(hsai); 02024 } 02025 } 02026 02027 /** 02028 * @brief DMA SAI transmit process complete callback. 02029 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02030 * the configuration information for the specified DMA module. 02031 * @retval None 02032 */ 02033 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma) 02034 { 02035 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef* )hdma)->Parent; 02036 02037 if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U) 02038 { 02039 hsai->XferCount = 0U; 02040 02041 /* Disable SAI Tx DMA Request */ 02042 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN); 02043 02044 /* Stop the interrupts error handling */ 02045 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); 02046 02047 hsai->State= HAL_SAI_STATE_READY; 02048 } 02049 HAL_SAI_TxCpltCallback(hsai); 02050 } 02051 02052 /** 02053 * @brief DMA SAI transmit process half complete callback. 02054 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02055 * the configuration information for the specified DMA module. 02056 * @retval None 02057 */ 02058 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma) 02059 { 02060 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; 02061 02062 HAL_SAI_TxHalfCpltCallback(hsai); 02063 } 02064 02065 /** 02066 * @brief DMA SAI receive process complete callback. 02067 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02068 * the configuration information for the specified DMA module. 02069 * @retval None 02070 */ 02071 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma) 02072 { 02073 SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; 02074 if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U) 02075 { 02076 /* Disable Rx DMA Request */ 02077 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN); 02078 hsai->XferCount = 0U; 02079 02080 /* Stop the interrupts error handling */ 02081 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); 02082 02083 hsai->State = HAL_SAI_STATE_READY; 02084 } 02085 HAL_SAI_RxCpltCallback(hsai); 02086 } 02087 02088 /** 02089 * @brief DMA SAI receive process half complete callback 02090 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02091 * the configuration information for the specified DMA module. 02092 * @retval None 02093 */ 02094 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma) 02095 { 02096 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; 02097 02098 HAL_SAI_RxHalfCpltCallback(hsai); 02099 } 02100 02101 /** 02102 * @brief DMA SAI communication error callback. 02103 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02104 * the configuration information for the specified DMA module. 02105 * @retval None 02106 */ 02107 static void SAI_DMAError(DMA_HandleTypeDef *hdma) 02108 { 02109 SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; 02110 02111 /* Set SAI error code */ 02112 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 02113 02114 if((hsai->hdmatx->ErrorCode == HAL_DMA_ERROR_TE) || (hsai->hdmarx->ErrorCode == HAL_DMA_ERROR_TE)) 02115 { 02116 /* Disable the SAI DMA request */ 02117 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; 02118 02119 /* Disable SAI peripheral */ 02120 SAI_Disable(hsai); 02121 02122 /* Set the SAI state ready to be able to start again the process */ 02123 hsai->State = HAL_SAI_STATE_READY; 02124 02125 /* Initialize XferCount */ 02126 hsai->XferCount = 0U; 02127 } 02128 /* SAI error Callback */ 02129 HAL_SAI_ErrorCallback(hsai); 02130 } 02131 02132 /** 02133 * @brief DMA SAI Abort callback. 02134 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02135 * the configuration information for the specified DMA module. 02136 * @retval None 02137 */ 02138 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma) 02139 { 02140 SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; 02141 02142 /* Disable DMA request */ 02143 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; 02144 02145 /* Disable all interrupts and clear all flags */ 02146 hsai->Instance->IMR = 0U; 02147 hsai->Instance->CLRFR = 0xFFFFFFFFU; 02148 02149 if(hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG) 02150 { 02151 /* Disable SAI peripheral */ 02152 SAI_Disable(hsai); 02153 02154 /* Flush the fifo */ 02155 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 02156 } 02157 /* Set the SAI state to ready to be able to start again the process */ 02158 hsai->State = HAL_SAI_STATE_READY; 02159 02160 /* Initialize XferCount */ 02161 hsai->XferCount = 0U; 02162 02163 /* SAI error Callback */ 02164 HAL_SAI_ErrorCallback(hsai); 02165 } 02166 02167 /** 02168 * @} 02169 */ 02170 02171 #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */ 02172 #endif /* HAL_SAI_MODULE_ENABLED */ 02173 /** 02174 * @} 02175 */ 02176 02177 /** 02178 * @} 02179 */ 02180 02181 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/