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