STM32L443xx HAL User Manual
stm32l4xx_hal_sai.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_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   ******************************************************************************
00014   * @attention
00015   *
00016   * Copyright (c) 2017 STMicroelectronics.
00017   * All rights reserved.
00018   *
00019   * This software is licensed under terms that can be found in the LICENSE file
00020   * in the root directory of this software component.
00021   * If no LICENSE file comes with this software, it is provided AS-IS.
00022   *
00023   ******************************************************************************
00024   @verbatim
00025   ==============================================================================
00026                   ##### How to use this driver #####
00027   ==============================================================================
00028 
00029   [..]
00030     The SAI HAL driver can be used as follows:
00031 
00032     (#) Declare a SAI_HandleTypeDef handle structure (eg. SAI_HandleTypeDef hsai).
00033     (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API:
00034         (##) Enable the SAI interface clock.
00035         (##) SAI pins configuration:
00036             (+++) Enable the clock for the SAI GPIOs.
00037             (+++) Configure these SAI pins as alternate function pull-up.
00038         (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT()
00039              and HAL_SAI_Receive_IT() APIs):
00040             (+++) Configure the SAI interrupt priority.
00041             (+++) Enable the NVIC SAI IRQ handle.
00042 
00043         (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA()
00044              and HAL_SAI_Receive_DMA() APIs):
00045             (+++) Declare a DMA handle structure for the Tx/Rx stream.
00046             (+++) Enable the DMAx interface clock.
00047             (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
00048             (+++) Configure the DMA Tx/Rx Stream.
00049             (+++) Associate the initialized DMA handle to the SAI DMA Tx/Rx handle.
00050             (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
00051                 DMA Tx/Rx Stream.
00052 
00053     (#) The initialization can be done by two ways
00054         (##) Expert mode : Initialize the structures Init, FrameInit and SlotInit and call HAL_SAI_Init().
00055         (##) Simplified mode : Initialize the high part of Init Structure and call HAL_SAI_InitProtocol().
00056 
00057   [..]
00058     (@) The specific SAI interrupts (FIFO request and Overrun underrun interrupt)
00059         will be managed using the macros __HAL_SAI_ENABLE_IT() and __HAL_SAI_DISABLE_IT()
00060         inside the transmit and receive process.
00061   [..]
00062     (@) Make sure that either:
00063         (+@) PLLSAI1CLK output is configured or
00064         (+@) PLLSAI2CLK output is configured or
00065         (+@) PLLSAI3CLK output is configured or
00066         (+@) External clock source is configured after setting correctly
00067              the define constant EXTERNAL_SAI1_CLOCK_VALUE or EXTERNAL_SAI2_CLOCK_VALUE in the stm32l4xx_hal_conf.h file.
00068 
00069   [..]
00070     (@) In master Tx mode: enabling the audio block immediately generates the bit clock
00071         for the external slaves even if there is no data in the FIFO, However FS signal
00072         generation is conditioned by the presence of data in the FIFO.
00073 
00074   [..]
00075     (@) In master Rx mode: enabling the audio block immediately generates the bit clock
00076         and FS signal for the external slaves.
00077 
00078   [..]
00079     (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
00080         (+@) First bit Offset <= (SLOT size - Data size)
00081         (+@) Data size <= SLOT size
00082         (+@) Number of SLOT x SLOT size = Frame length
00083         (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
00084 
00085   [..]
00086     (@) For STM32L4Rx/STM32L4Sx devices, PDM interface can be activated through HAL_SAI_Init function.
00087         Please note that PDM interface is only available for SAI1 sub-block A.
00088         PDM microphone delays can be tuned with HAL_SAIEx_ConfigPdmMicDelay function.
00089 
00090   [..]
00091     Three operation modes are available within this driver :
00092 
00093     *** Polling mode IO operation ***
00094     =================================
00095     [..]
00096       (+) Send an amount of data in blocking mode using HAL_SAI_Transmit()
00097       (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
00098 
00099     *** Interrupt mode IO operation ***
00100     ===================================
00101     [..]
00102       (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT()
00103       (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
00104           add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
00105       (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT()
00106       (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
00107           add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
00108       (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
00109           add his own code by customization of function pointer HAL_SAI_ErrorCallback()
00110 
00111     *** DMA mode IO operation ***
00112     =============================
00113     [..]
00114       (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA()
00115       (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
00116           add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
00117       (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA()
00118       (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
00119           add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
00120       (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
00121           add his own code by customization of function pointer HAL_SAI_ErrorCallback()
00122       (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
00123       (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
00124       (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
00125 
00126     *** SAI HAL driver additional function list ***
00127     ===============================================
00128     [..]
00129       Below the list the others API available SAI HAL driver :
00130 
00131       (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode
00132       (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode
00133       (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode
00134       (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode
00135       (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo.
00136       (+) HAL_SAI_Abort(): Abort the current transfer
00137 
00138     *** SAI HAL driver macros list ***
00139     ==================================
00140     [..]
00141       Below the list of most used macros in SAI HAL driver :
00142 
00143       (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral
00144       (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral
00145       (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts
00146       (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts
00147       (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is
00148           enabled or disabled
00149       (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
00150 
00151     *** Callback registration ***
00152     =============================
00153     [..]
00154     The compilation define USE_HAL_SAI_REGISTER_CALLBACKS when set to 1
00155     allows the user to configure dynamically the driver callbacks.
00156     Use functions HAL_SAI_RegisterCallback() to register a user callback.
00157 
00158     [..]
00159     Function HAL_SAI_RegisterCallback() allows to register following callbacks:
00160       (+) RxCpltCallback     : SAI receive complete.
00161       (+) RxHalfCpltCallback : SAI receive half complete.
00162       (+) TxCpltCallback     : SAI transmit complete.
00163       (+) TxHalfCpltCallback : SAI transmit half complete.
00164       (+) ErrorCallback      : SAI error.
00165       (+) MspInitCallback    : SAI MspInit.
00166       (+) MspDeInitCallback  : SAI MspDeInit.
00167     [..]
00168     This function takes as parameters the HAL peripheral handle, the callback ID
00169     and a pointer to the user callback function.
00170 
00171     [..]
00172     Use function HAL_SAI_UnRegisterCallback() to reset a callback to the default
00173     weak (surcharged) function.
00174     HAL_SAI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
00175     and the callback ID.
00176     [..]
00177     This function allows to reset following callbacks:
00178       (+) RxCpltCallback     : SAI receive complete.
00179       (+) RxHalfCpltCallback : SAI receive half complete.
00180       (+) TxCpltCallback     : SAI transmit complete.
00181       (+) TxHalfCpltCallback : SAI transmit half complete.
00182       (+) ErrorCallback      : SAI error.
00183       (+) MspInitCallback    : SAI MspInit.
00184       (+) MspDeInitCallback  : SAI MspDeInit.
00185 
00186     [..]
00187     By default, after the HAL_SAI_Init and if the state is HAL_SAI_STATE_RESET
00188     all callbacks are reset to the corresponding legacy weak (surcharged) functions:
00189     examples HAL_SAI_RxCpltCallback(), HAL_SAI_ErrorCallback().
00190     Exception done for MspInit and MspDeInit callbacks that are respectively
00191     reset to the legacy weak (surcharged) functions in the HAL_SAI_Init
00192     and HAL_SAI_DeInit only when these callbacks are null (not registered beforehand).
00193     If not, MspInit or MspDeInit are not null, the HAL_SAI_Init and HAL_SAI_DeInit
00194     keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
00195 
00196     [..]
00197     Callbacks can be registered/unregistered in READY state only.
00198     Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
00199     in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
00200     during the Init/DeInit.
00201     In that case first register the MspInit/MspDeInit user callbacks
00202     using HAL_SAI_RegisterCallback before calling HAL_SAI_DeInit
00203     or HAL_SAI_Init function.
00204 
00205     [..]
00206     When the compilation define USE_HAL_SAI_REGISTER_CALLBACKS is set to 0 or
00207     not defined, the callback registering feature is not available
00208     and weak (surcharged) callbacks are used.
00209 
00210   @endverbatim
00211   */
00212 
00213 /* Includes ------------------------------------------------------------------*/
00214 #include "stm32l4xx_hal.h"
00215 
00216 /** @addtogroup STM32L4xx_HAL_Driver
00217   * @{
00218   */
00219 
00220 #ifdef HAL_SAI_MODULE_ENABLED
00221 #if !defined(STM32L412xx) && !defined(STM32L422xx)
00222 
00223 /** @defgroup SAI SAI
00224   * @brief SAI HAL module driver
00225   * @{
00226   */
00227 
00228 /* Private typedef -----------------------------------------------------------*/
00229 /** @defgroup SAI_Private_Typedefs  SAI Private Typedefs
00230   * @{
00231   */
00232 typedef enum
00233 {
00234   SAI_MODE_DMA,
00235   SAI_MODE_IT
00236 } SAI_ModeTypedef;
00237 /**
00238   * @}
00239   */
00240 
00241 /* Private define ------------------------------------------------------------*/
00242 /** @defgroup SAI_Private_Constants  SAI Private Constants
00243   * @{
00244   */
00245 #define SAI_DEFAULT_TIMEOUT      4U
00246 #define SAI_LONG_TIMEOUT         1000U
00247 /**
00248   * @}
00249   */
00250 
00251 /* Private macro -------------------------------------------------------------*/
00252 /* Private variables ---------------------------------------------------------*/
00253 /* Private function prototypes -----------------------------------------------*/
00254 /** @defgroup SAI_Private_Functions  SAI Private Functions
00255   * @{
00256   */
00257 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
00258 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode);
00259 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
00260 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
00261 
00262 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
00263 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
00264 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
00265 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
00266 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
00267 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
00268 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
00269 
00270 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
00271 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
00272 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
00273 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
00274 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
00275 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
00276 /**
00277   * @}
00278   */
00279 
00280 /* Exported functions ---------------------------------------------------------*/
00281 /** @defgroup SAI_Exported_Functions SAI Exported Functions
00282   * @{
00283   */
00284 
00285 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
00286   * @brief    Initialization and Configuration functions
00287   *
00288 @verbatim
00289  ===============================================================================
00290              ##### Initialization and de-initialization functions #####
00291  ===============================================================================
00292   [..]  This subsection provides a set of functions allowing to initialize and
00293         de-initialize the SAIx peripheral:
00294 
00295       (+) User must implement HAL_SAI_MspInit() function in which he configures
00296           all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
00297 
00298       (+) Call the function HAL_SAI_Init() to configure the selected device with
00299           the selected configuration:
00300         (++) Mode (Master/slave TX/RX)
00301         (++) Protocol
00302         (++) Data Size
00303         (++) MCLK Output
00304         (++) Audio frequency
00305         (++) FIFO Threshold
00306         (++) Frame Config
00307         (++) Slot Config
00308         (++) PDM Config (only for STM32L4Rx/STM32L4Sx devices)
00309 
00310       (+) Call the function HAL_SAI_DeInit() to restore the default configuration
00311           of the selected SAI peripheral.
00312 
00313 @endverbatim
00314   * @{
00315   */
00316 
00317 /**
00318   * @brief  Initialize the structure FrameInit, SlotInit and the low part of
00319   *         Init according to the specified parameters and call the function
00320   *         HAL_SAI_Init to initialize the SAI block.
00321   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00322   *              the configuration information for SAI module.
00323   * @param  protocol one of the supported protocol @ref SAI_Protocol
00324   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
00325   *                   the configuration information for SAI module.
00326   * @param  nbslot Number of slot.
00327   * @retval HAL status
00328   */
00329 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
00330 {
00331   HAL_StatusTypeDef status;
00332 
00333   /* Check the parameters */
00334   assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
00335   assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
00336 
00337   switch (protocol)
00338   {
00339     case SAI_I2S_STANDARD :
00340     case SAI_I2S_MSBJUSTIFIED :
00341     case SAI_I2S_LSBJUSTIFIED :
00342       status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
00343       break;
00344     case SAI_PCM_LONG :
00345     case SAI_PCM_SHORT :
00346       status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
00347       break;
00348     default :
00349       status = HAL_ERROR;
00350       break;
00351   }
00352 
00353   if (status == HAL_OK)
00354   {
00355     status = HAL_SAI_Init(hsai);
00356   }
00357 
00358   return status;
00359 }
00360 
00361 /**
00362   * @brief  Initialize the SAI according to the specified parameters.
00363   *         in the SAI_InitTypeDef structure and initialize the associated handle.
00364   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00365   *              the configuration information for SAI module.
00366   * @retval HAL status
00367   */
00368 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
00369 {
00370 #if defined(SAI2)
00371   uint32_t tmpregisterGCR;
00372 #endif /* SAI2 */
00373   uint32_t ckstr_bits;
00374   uint32_t syncen_bits;
00375 
00376   /* Check the SAI handle allocation */
00377   if (hsai == NULL)
00378   {
00379     return HAL_ERROR;
00380   }
00381 
00382   /* check the instance */
00383   assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
00384 
00385   /* Check the SAI Block parameters */
00386   assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
00387   assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
00388   assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
00389   assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
00390   assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
00391   assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
00392   assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
00393   assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
00394   assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
00395   assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
00396   assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
00397   assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
00398   assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
00399   assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
00400 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \
00401     defined(STM32L4P5xx) || defined(STM32L4Q5xx)
00402   assert_param(IS_SAI_BLOCK_MCK_OVERSAMPLING(hsai->Init.MckOverSampling));
00403 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx || */
00404   /* STM32L4P5xx || STM32L4Q5xx */
00405 
00406   /* Check the SAI Block Frame parameters */
00407   assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
00408   assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
00409   assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
00410   assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
00411   assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
00412 
00413   /* Check the SAI Block Slot parameters */
00414   assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
00415   assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
00416   assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
00417   assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
00418 
00419 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \
00420     defined(STM32L4P5xx) || defined(STM32L4Q5xx)
00421   /* Check the SAI PDM parameters */
00422   assert_param(IS_FUNCTIONAL_STATE(hsai->Init.PdmInit.Activation));
00423   if (hsai->Init.PdmInit.Activation == ENABLE)
00424   {
00425     assert_param(IS_SAI_PDM_MIC_PAIRS_NUMBER(hsai->Init.PdmInit.MicPairsNbr));
00426     assert_param(IS_SAI_PDM_CLOCK_ENABLE(hsai->Init.PdmInit.ClockEnable));
00427     /* Check that SAI sub-block is SAI1 sub-block A, in master RX mode with free protocol */
00428     if ((hsai->Instance != SAI1_Block_A) ||
00429         (hsai->Init.AudioMode != SAI_MODEMASTER_RX) ||
00430         (hsai->Init.Protocol != SAI_FREE_PROTOCOL))
00431     {
00432       return HAL_ERROR;
00433     }
00434   }
00435 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx || */
00436   /* STM32L4P5xx || STM32L4Q5xx */
00437 
00438   if (hsai->State == HAL_SAI_STATE_RESET)
00439   {
00440     /* Allocate lock resource and initialize it */
00441     hsai->Lock = HAL_UNLOCKED;
00442 
00443 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
00444     /* Reset callback pointers to the weak predefined callbacks */
00445     hsai->RxCpltCallback     = HAL_SAI_RxCpltCallback;
00446     hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
00447     hsai->TxCpltCallback     = HAL_SAI_TxCpltCallback;
00448     hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
00449     hsai->ErrorCallback      = HAL_SAI_ErrorCallback;
00450 
00451     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
00452     if (hsai->MspInitCallback == NULL)
00453     {
00454       hsai->MspInitCallback = HAL_SAI_MspInit;
00455     }
00456     hsai->MspInitCallback(hsai);
00457 #else
00458     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
00459     HAL_SAI_MspInit(hsai);
00460 #endif
00461   }
00462 
00463   /* Disable the selected SAI peripheral */
00464   if (SAI_Disable(hsai) != HAL_OK)
00465   {
00466     return HAL_ERROR;
00467   }
00468 
00469   hsai->State = HAL_SAI_STATE_BUSY;
00470 
00471   /* SAI Block Synchro Configuration -----------------------------------------*/
00472   /* This setting must be done with both audio block (A & B) disabled         */
00473 #if defined(SAI2)
00474   switch (hsai->Init.SynchroExt)
00475   {
00476     case SAI_SYNCEXT_DISABLE :
00477       tmpregisterGCR = 0;
00478       break;
00479     case SAI_SYNCEXT_OUTBLOCKA_ENABLE :
00480       tmpregisterGCR = SAI_GCR_SYNCOUT_0;
00481       break;
00482     case SAI_SYNCEXT_OUTBLOCKB_ENABLE :
00483       tmpregisterGCR = SAI_GCR_SYNCOUT_1;
00484       break;
00485     default :
00486       tmpregisterGCR = 0;
00487       break;
00488   }
00489 #endif /* SAI2 */
00490 
00491   switch (hsai->Init.Synchro)
00492   {
00493     case SAI_ASYNCHRONOUS :
00494       syncen_bits = 0;
00495       break;
00496     case SAI_SYNCHRONOUS :
00497       syncen_bits = SAI_xCR1_SYNCEN_0;
00498       break;
00499 #if defined(SAI2)
00500     case SAI_SYNCHRONOUS_EXT_SAI1 :
00501       syncen_bits = SAI_xCR1_SYNCEN_1;
00502       break;
00503     case SAI_SYNCHRONOUS_EXT_SAI2 :
00504       syncen_bits = SAI_xCR1_SYNCEN_1;
00505       tmpregisterGCR |= SAI_GCR_SYNCIN_0;
00506       break;
00507 #endif /* SAI2 */
00508     default :
00509       syncen_bits = 0;
00510       break;
00511   }
00512 
00513 #if defined(SAI2)
00514   if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
00515   {
00516     SAI1->GCR = tmpregisterGCR;
00517   }
00518   else
00519   {
00520     SAI2->GCR = tmpregisterGCR;
00521   }
00522 #else
00523   SAI1->GCR = 0;
00524 #endif /* SAI2 */
00525 
00526   if (hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
00527   {
00528     uint32_t freq;
00529     uint32_t tmpval;
00530 
00531     /* In this case, the MCKDIV value is calculated to get AudioFrequency */
00532 #if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \
00533     defined(STM32L496xx) || defined(STM32L4A6xx) || \
00534     defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \
00535     defined(STM32L4P5xx) || defined(STM32L4Q5xx)
00536 
00537     if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
00538     {
00539       freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1);
00540     }
00541     else
00542     {
00543       /* SAI2_Block_A or SAI2_Block_B */
00544       freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2);
00545     }
00546 
00547 #else
00548 
00549     freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1);
00550 
00551 #endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */
00552     /* STM32L496xx || STM32L4A6xx || */
00553     /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx || */
00554     /* STM32L4P5xx || STM32L4Q5xx */
00555 
00556 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \
00557     defined(STM32L4P5xx) || defined(STM32L4Q5xx)
00558     /* Configure Master Clock Divider using the following formula :
00559        - If NOMCK = 1 :
00560          MCKDIV[5:0] = SAI_CK_x / (FS * (FRL + 1))
00561        - If NOMCK = 0 :
00562          MCKDIV[5:0] = SAI_CK_x / (FS * (OSR + 1) * 256) */
00563     if (hsai->Init.NoDivider == SAI_MASTERDIVIDER_DISABLE)
00564     {
00565       /* NOMCK = 1 */
00566       uint32_t tmpframelength;
00567 
00568       if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
00569       {
00570         /* For SPDIF protocol, frame length is set by hardware to 64 */
00571         tmpframelength = 64U;
00572       }
00573       else if (hsai->Init.Protocol == SAI_AC97_PROTOCOL)
00574       {
00575         /* For AC97 protocol, frame length is set by hardware to 256 */
00576         tmpframelength = 256U;
00577       }
00578       else
00579       {
00580         /* For free protocol, frame length is set by user */
00581         tmpframelength = hsai->FrameInit.FrameLength;
00582       }
00583 
00584       /* (freq x 10) to keep Significant digits */
00585       tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmpframelength);
00586     }
00587     else
00588     {
00589       /* NOMCK = 0 */
00590       uint32_t tmposr;
00591       tmposr = (hsai->Init.MckOverSampling == SAI_MCK_OVERSAMPLING_ENABLE) ? 2U : 1U;
00592       /* (freq x 10) to keep Significant digits */
00593       tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmposr * 256U);
00594     }
00595     hsai->Init.Mckdiv = tmpval / 10U;
00596 
00597     /* Round result to the nearest integer */
00598     if ((tmpval % 10U) > 8U)
00599     {
00600       hsai->Init.Mckdiv += 1U;
00601     }
00602 #else
00603     /* Configure Master Clock using the following formula :
00604        MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS
00605        FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256
00606        MCKDIV[3:0] = SAI_CK_x / FS * 512 */
00607     /* (freq x 10) to keep Significant digits */
00608     tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * 2U * 256U);
00609     hsai->Init.Mckdiv = tmpval / 10U;
00610 
00611     /* Round result to the nearest integer */
00612     if ((tmpval % 10U) > 8U)
00613     {
00614       hsai->Init.Mckdiv += 1U;
00615     }
00616 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx || */
00617     /* STM32L4P5xx || STM32L4Q5xx */
00618 
00619     /* For SPDIF protocol, SAI shall provide a bit clock twice faster the symbol-rate */
00620     if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
00621     {
00622       hsai->Init.Mckdiv = hsai->Init.Mckdiv >> 1;
00623     }
00624   }
00625   /* Check the SAI Block master clock divider parameter */
00626   assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(hsai->Init.Mckdiv));
00627 
00628   /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */
00629   if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
00630   {
00631     /* Transmit */
00632     ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR;
00633   }
00634   else
00635   {
00636     /* Receive */
00637     ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U;
00638   }
00639 
00640   /* SAI Block Configuration -------------------------------------------------*/
00641   /* SAI CR1 Configuration */
00642 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \
00643     defined(STM32L4P5xx) || defined(STM32L4Q5xx)
00644   hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG |  SAI_xCR1_DS |      \
00645                            SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
00646                            SAI_xCR1_MONO | SAI_xCR1_OUTDRIV  | SAI_xCR1_DMAEN |  \
00647                            SAI_xCR1_NOMCK | SAI_xCR1_MCKDIV | SAI_xCR1_OSR);
00648 
00649   hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol |           \
00650                           hsai->Init.DataSize | hsai->Init.FirstBit  |           \
00651                           ckstr_bits | syncen_bits |                             \
00652                           hsai->Init.MonoStereoMode | hsai->Init.OutputDrive |   \
00653                           hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) |     \
00654                           hsai->Init.MckOverSampling);
00655 #else
00656   hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG |  SAI_xCR1_DS |      \
00657                            SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
00658                            SAI_xCR1_MONO | SAI_xCR1_OUTDRIV  | SAI_xCR1_DMAEN |  \
00659                            SAI_xCR1_NODIV | SAI_xCR1_MCKDIV);
00660 
00661   hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol |           \
00662                           hsai->Init.DataSize | hsai->Init.FirstBit  |           \
00663                           ckstr_bits | syncen_bits |                             \
00664                           hsai->Init.MonoStereoMode | hsai->Init.OutputDrive |   \
00665                           hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20));
00666 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx || */
00667   /* STM32L4P5xx || STM32L4Q5xx */
00668 
00669   /* SAI CR2 Configuration */
00670   hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
00671   hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
00672 
00673   /* SAI Frame Configuration -----------------------------------------*/
00674   hsai->Instance->FRCR &= (~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
00675                              SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
00676   hsai->Instance->FRCR |= ((hsai->FrameInit.FrameLength - 1U) |
00677                            hsai->FrameInit.FSOffset |
00678                            hsai->FrameInit.FSDefinition |
00679                            hsai->FrameInit.FSPolarity   |
00680                            ((hsai->FrameInit.ActiveFrameLength - 1U) << 8));
00681 
00682   /* SAI Block_x SLOT Configuration ------------------------------------------*/
00683   /* This register has no meaning in AC 97 and SPDIF audio protocol */
00684   hsai->Instance->SLOTR &= (~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ |  \
00685                               SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN));
00686 
00687   hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \
00688                            (hsai->SlotInit.SlotActive << 16) | ((hsai->SlotInit.SlotNumber - 1U) <<  8);
00689 
00690 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \
00691     defined(STM32L4P5xx) || defined(STM32L4Q5xx)
00692   /* SAI PDM Configuration ---------------------------------------------------*/
00693   if (hsai->Instance == SAI1_Block_A)
00694   {
00695     /* Disable PDM interface */
00696     SAI1->PDMCR &= ~(SAI_PDMCR_PDMEN);
00697     if (hsai->Init.PdmInit.Activation == ENABLE)
00698     {
00699       /* Configure and enable PDM interface */
00700       SAI1->PDMCR = (hsai->Init.PdmInit.ClockEnable |
00701                      ((hsai->Init.PdmInit.MicPairsNbr - 1U) << SAI_PDMCR_MICNBR_Pos));
00702       SAI1->PDMCR |= SAI_PDMCR_PDMEN;
00703     }
00704   }
00705 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx || */
00706   /* STM32L4P5xx || STM32L4Q5xx */
00707 
00708   /* Initialize the error code */
00709   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00710 
00711   /* Initialize the SAI state */
00712   hsai->State = HAL_SAI_STATE_READY;
00713 
00714   /* Release Lock */
00715   __HAL_UNLOCK(hsai);
00716 
00717   return HAL_OK;
00718 }
00719 
00720 /**
00721   * @brief  DeInitialize the SAI peripheral.
00722   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00723   *              the configuration information for SAI module.
00724   * @retval HAL status
00725   */
00726 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
00727 {
00728   /* Check the SAI handle allocation */
00729   if (hsai == NULL)
00730   {
00731     return HAL_ERROR;
00732   }
00733 
00734   hsai->State = HAL_SAI_STATE_BUSY;
00735 
00736   /* Disabled All interrupt and clear all the flag */
00737   hsai->Instance->IMR = 0;
00738   hsai->Instance->CLRFR = 0xFFFFFFFFU;
00739 
00740   /* Disable the SAI */
00741   if (SAI_Disable(hsai) != HAL_OK)
00742   {
00743     /* Reset SAI state to ready */
00744     hsai->State = HAL_SAI_STATE_READY;
00745 
00746     /* Release Lock */
00747     __HAL_UNLOCK(hsai);
00748 
00749     return HAL_ERROR;
00750   }
00751 
00752   /* Flush the fifo */
00753   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
00754 
00755 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) || \
00756     defined(STM32L4P5xx) || defined(STM32L4Q5xx)
00757   /* Disable SAI PDM interface */
00758   if (hsai->Instance == SAI1_Block_A)
00759   {
00760     /* Reset PDM delays */
00761     SAI1->PDMDLY = 0U;
00762 
00763     /* Disable PDM interface */
00764     SAI1->PDMCR &= ~(SAI_PDMCR_PDMEN);
00765   }
00766 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx || */
00767   /* STM32L4P5xx || STM32L4Q5xx */
00768 
00769   /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
00770 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
00771   if (hsai->MspDeInitCallback == NULL)
00772   {
00773     hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
00774   }
00775   hsai->MspDeInitCallback(hsai);
00776 #else
00777   HAL_SAI_MspDeInit(hsai);
00778 #endif
00779 
00780   /* Initialize the error code */
00781   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00782 
00783   /* Initialize the SAI state */
00784   hsai->State = HAL_SAI_STATE_RESET;
00785 
00786   /* Release Lock */
00787   __HAL_UNLOCK(hsai);
00788 
00789   return HAL_OK;
00790 }
00791 
00792 /**
00793   * @brief Initialize the SAI MSP.
00794   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00795   *              the configuration information for SAI module.
00796   * @retval None
00797   */
00798 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
00799 {
00800   /* Prevent unused argument(s) compilation warning */
00801   UNUSED(hsai);
00802 
00803   /* NOTE : This function should not be modified, when the callback is needed,
00804             the HAL_SAI_MspInit could be implemented in the user file
00805    */
00806 }
00807 
00808 /**
00809   * @brief DeInitialize the SAI MSP.
00810   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00811   *              the configuration information for SAI module.
00812   * @retval None
00813   */
00814 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
00815 {
00816   /* Prevent unused argument(s) compilation warning */
00817   UNUSED(hsai);
00818 
00819   /* NOTE : This function should not be modified, when the callback is needed,
00820             the HAL_SAI_MspDeInit could be implemented in the user file
00821    */
00822 }
00823 
00824 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
00825 /**
00826   * @brief  Register a user SAI callback
00827   *         to be used instead of the weak predefined callback.
00828   * @param  hsai SAI handle.
00829   * @param  CallbackID ID of the callback to be registered.
00830   *         This parameter can be one of the following values:
00831   *           @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
00832   *           @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
00833   *           @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
00834   *           @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
00835   *           @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
00836   *           @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
00837   *           @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
00838   * @param  pCallback pointer to the callback function.
00839   * @retval HAL status.
00840   */
00841 HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef        *hsai,
00842                                            HAL_SAI_CallbackIDTypeDef CallbackID,
00843                                            pSAI_CallbackTypeDef      pCallback)
00844 {
00845   HAL_StatusTypeDef status = HAL_OK;
00846 
00847   if (pCallback == NULL)
00848   {
00849     /* update the error code */
00850     hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00851     /* update return status */
00852     status = HAL_ERROR;
00853   }
00854   else
00855   {
00856     if (HAL_SAI_STATE_READY == hsai->State)
00857     {
00858       switch (CallbackID)
00859       {
00860         case HAL_SAI_RX_COMPLETE_CB_ID :
00861           hsai->RxCpltCallback = pCallback;
00862           break;
00863         case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
00864           hsai->RxHalfCpltCallback = pCallback;
00865           break;
00866         case HAL_SAI_TX_COMPLETE_CB_ID :
00867           hsai->TxCpltCallback = pCallback;
00868           break;
00869         case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
00870           hsai->TxHalfCpltCallback = pCallback;
00871           break;
00872         case HAL_SAI_ERROR_CB_ID :
00873           hsai->ErrorCallback = pCallback;
00874           break;
00875         case HAL_SAI_MSPINIT_CB_ID :
00876           hsai->MspInitCallback = pCallback;
00877           break;
00878         case HAL_SAI_MSPDEINIT_CB_ID :
00879           hsai->MspDeInitCallback = pCallback;
00880           break;
00881         default :
00882           /* update the error code */
00883           hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00884           /* update return status */
00885           status = HAL_ERROR;
00886           break;
00887       }
00888     }
00889     else if (HAL_SAI_STATE_RESET == hsai->State)
00890     {
00891       switch (CallbackID)
00892       {
00893         case HAL_SAI_MSPINIT_CB_ID :
00894           hsai->MspInitCallback = pCallback;
00895           break;
00896         case HAL_SAI_MSPDEINIT_CB_ID :
00897           hsai->MspDeInitCallback = pCallback;
00898           break;
00899         default :
00900           /* update the error code */
00901           hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00902           /* update return status */
00903           status = HAL_ERROR;
00904           break;
00905       }
00906     }
00907     else
00908     {
00909       /* update the error code */
00910       hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00911       /* update return status */
00912       status = HAL_ERROR;
00913     }
00914   }
00915   return status;
00916 }
00917 
00918 /**
00919   * @brief  Unregister a user SAI callback.
00920   *         SAI callback is redirected to the weak predefined callback.
00921   * @param  hsai SAI handle.
00922   * @param  CallbackID ID of the callback to be unregistered.
00923   *         This parameter can be one of the following values:
00924   *           @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
00925   *           @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
00926   *           @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
00927   *           @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
00928   *           @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
00929   *           @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
00930   *           @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
00931   * @retval HAL status.
00932   */
00933 HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef        *hsai,
00934                                              HAL_SAI_CallbackIDTypeDef CallbackID)
00935 {
00936   HAL_StatusTypeDef status = HAL_OK;
00937 
00938   if (HAL_SAI_STATE_READY == hsai->State)
00939   {
00940     switch (CallbackID)
00941     {
00942       case HAL_SAI_RX_COMPLETE_CB_ID :
00943         hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
00944         break;
00945       case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
00946         hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
00947         break;
00948       case HAL_SAI_TX_COMPLETE_CB_ID :
00949         hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
00950         break;
00951       case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
00952         hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
00953         break;
00954       case HAL_SAI_ERROR_CB_ID :
00955         hsai->ErrorCallback = HAL_SAI_ErrorCallback;
00956         break;
00957       case HAL_SAI_MSPINIT_CB_ID :
00958         hsai->MspInitCallback = HAL_SAI_MspInit;
00959         break;
00960       case HAL_SAI_MSPDEINIT_CB_ID :
00961         hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
00962         break;
00963       default :
00964         /* update the error code */
00965         hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00966         /* update return status */
00967         status = HAL_ERROR;
00968         break;
00969     }
00970   }
00971   else if (HAL_SAI_STATE_RESET == hsai->State)
00972   {
00973     switch (CallbackID)
00974     {
00975       case HAL_SAI_MSPINIT_CB_ID :
00976         hsai->MspInitCallback = HAL_SAI_MspInit;
00977         break;
00978       case HAL_SAI_MSPDEINIT_CB_ID :
00979         hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
00980         break;
00981       default :
00982         /* update the error code */
00983         hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00984         /* update return status */
00985         status = HAL_ERROR;
00986         break;
00987     }
00988   }
00989   else
00990   {
00991     /* update the error code */
00992     hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00993     /* update return status */
00994     status = HAL_ERROR;
00995   }
00996   return status;
00997 }
00998 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
00999 
01000 /**
01001   * @}
01002   */
01003 
01004 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
01005   * @brief    Data transfers functions
01006   *
01007 @verbatim
01008   ==============================================================================
01009                       ##### IO operation functions #####
01010   ==============================================================================
01011   [..]
01012     This subsection provides a set of functions allowing to manage the SAI data
01013     transfers.
01014 
01015     (+) There are two modes of transfer:
01016       (++) Blocking mode : The communication is performed in the polling mode.
01017            The status of all data processing is returned by the same function
01018            after finishing transfer.
01019       (++) No-Blocking mode : The communication is performed using Interrupts
01020            or DMA. These functions return the status of the transfer startup.
01021            The end of the data processing will be indicated through the
01022            dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
01023            using DMA mode.
01024 
01025     (+) Blocking mode functions are :
01026       (++) HAL_SAI_Transmit()
01027       (++) HAL_SAI_Receive()
01028 
01029     (+) Non Blocking mode functions with Interrupt are :
01030       (++) HAL_SAI_Transmit_IT()
01031       (++) HAL_SAI_Receive_IT()
01032 
01033     (+) Non Blocking mode functions with DMA are :
01034       (++) HAL_SAI_Transmit_DMA()
01035       (++) HAL_SAI_Receive_DMA()
01036 
01037     (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
01038       (++) HAL_SAI_TxCpltCallback()
01039       (++) HAL_SAI_RxCpltCallback()
01040       (++) HAL_SAI_ErrorCallback()
01041 
01042 @endverbatim
01043   * @{
01044   */
01045 
01046 /**
01047   * @brief  Transmit an amount of data in blocking mode.
01048   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01049   *              the configuration information for SAI module.
01050   * @param  pData Pointer to data buffer
01051   * @param  Size Amount of data to be sent
01052   * @param  Timeout Timeout duration
01053   * @retval HAL status
01054   */
01055 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
01056 {
01057   uint32_t tickstart = HAL_GetTick();
01058   uint32_t temp;
01059 
01060   if ((pData == NULL) || (Size == 0U))
01061   {
01062     return  HAL_ERROR;
01063   }
01064 
01065   if (hsai->State == HAL_SAI_STATE_READY)
01066   {
01067     /* Process Locked */
01068     __HAL_LOCK(hsai);
01069 
01070     hsai->XferSize = Size;
01071     hsai->XferCount = Size;
01072     hsai->pBuffPtr = pData;
01073     hsai->State = HAL_SAI_STATE_BUSY_TX;
01074     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01075 
01076     /* Check if the SAI is already enabled */
01077     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
01078     {
01079       /* fill the fifo with data before to enabled the SAI */
01080       SAI_FillFifo(hsai);
01081       /* Enable SAI peripheral */
01082       __HAL_SAI_ENABLE(hsai);
01083     }
01084 
01085     while (hsai->XferCount > 0U)
01086     {
01087       /* Write data if the FIFO is not full */
01088       if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
01089       {
01090         if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
01091         {
01092           hsai->Instance->DR = *hsai->pBuffPtr;
01093           hsai->pBuffPtr++;
01094         }
01095         else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
01096         {
01097           temp = (uint32_t)(*hsai->pBuffPtr);
01098           hsai->pBuffPtr++;
01099           temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
01100           hsai->pBuffPtr++;
01101           hsai->Instance->DR = temp;
01102         }
01103         else
01104         {
01105           temp = (uint32_t)(*hsai->pBuffPtr);
01106           hsai->pBuffPtr++;
01107           temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
01108           hsai->pBuffPtr++;
01109           temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
01110           hsai->pBuffPtr++;
01111           temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
01112           hsai->pBuffPtr++;
01113           hsai->Instance->DR = temp;
01114         }
01115         hsai->XferCount--;
01116       }
01117       else
01118       {
01119         /* Check for the Timeout */
01120         if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
01121         {
01122           /* Update error code */
01123           hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
01124 
01125           /* Clear all the flags */
01126           hsai->Instance->CLRFR = 0xFFFFFFFFU;
01127 
01128           /* Disable SAI peripheral */
01129           /* No need to check return value because state update, unlock and error return will be performed later */
01130           (void) SAI_Disable(hsai);
01131 
01132           /* Flush the fifo */
01133           SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
01134 
01135           /* Change the SAI state */
01136           hsai->State = HAL_SAI_STATE_READY;
01137 
01138           /* Process Unlocked */
01139           __HAL_UNLOCK(hsai);
01140 
01141           return HAL_ERROR;
01142         }
01143       }
01144     }
01145 
01146     hsai->State = HAL_SAI_STATE_READY;
01147 
01148     /* Process Unlocked */
01149     __HAL_UNLOCK(hsai);
01150 
01151     return HAL_OK;
01152   }
01153   else
01154   {
01155     return HAL_BUSY;
01156   }
01157 }
01158 
01159 /**
01160   * @brief  Receive an amount of data in blocking mode.
01161   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01162   *              the configuration information for SAI module.
01163   * @param  pData Pointer to data buffer
01164   * @param  Size Amount of data to be received
01165   * @param  Timeout Timeout duration
01166   * @retval HAL status
01167   */
01168 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
01169 {
01170   uint32_t tickstart = HAL_GetTick();
01171   uint32_t temp;
01172 
01173   if ((pData == NULL) || (Size == 0U))
01174   {
01175     return  HAL_ERROR;
01176   }
01177 
01178   if (hsai->State == HAL_SAI_STATE_READY)
01179   {
01180     /* Process Locked */
01181     __HAL_LOCK(hsai);
01182 
01183     hsai->pBuffPtr = pData;
01184     hsai->XferSize = Size;
01185     hsai->XferCount = Size;
01186     hsai->State = HAL_SAI_STATE_BUSY_RX;
01187     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01188 
01189     /* Check if the SAI is already enabled */
01190     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
01191     {
01192       /* Enable SAI peripheral */
01193       __HAL_SAI_ENABLE(hsai);
01194     }
01195 
01196     /* Receive data */
01197     while (hsai->XferCount > 0U)
01198     {
01199       if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
01200       {
01201         if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
01202         {
01203           *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
01204           hsai->pBuffPtr++;
01205         }
01206         else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
01207         {
01208           temp = hsai->Instance->DR;
01209           *hsai->pBuffPtr = (uint8_t)temp;
01210           hsai->pBuffPtr++;
01211           *hsai->pBuffPtr = (uint8_t)(temp >> 8);
01212           hsai->pBuffPtr++;
01213         }
01214         else
01215         {
01216           temp = hsai->Instance->DR;
01217           *hsai->pBuffPtr = (uint8_t)temp;
01218           hsai->pBuffPtr++;
01219           *hsai->pBuffPtr = (uint8_t)(temp >> 8);
01220           hsai->pBuffPtr++;
01221           *hsai->pBuffPtr = (uint8_t)(temp >> 16);
01222           hsai->pBuffPtr++;
01223           *hsai->pBuffPtr = (uint8_t)(temp >> 24);
01224           hsai->pBuffPtr++;
01225         }
01226         hsai->XferCount--;
01227       }
01228       else
01229       {
01230         /* Check for the Timeout */
01231         if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
01232         {
01233           /* Update error code */
01234           hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
01235 
01236           /* Clear all the flags */
01237           hsai->Instance->CLRFR = 0xFFFFFFFFU;
01238 
01239           /* Disable SAI peripheral */
01240           /* No need to check return value because state update, unlock and error return will be performed later */
01241           (void) SAI_Disable(hsai);
01242 
01243           /* Flush the fifo */
01244           SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
01245 
01246           /* Change the SAI state */
01247           hsai->State = HAL_SAI_STATE_READY;
01248 
01249           /* Process Unlocked */
01250           __HAL_UNLOCK(hsai);
01251 
01252           return HAL_ERROR;
01253         }
01254       }
01255     }
01256 
01257     hsai->State = HAL_SAI_STATE_READY;
01258 
01259     /* Process Unlocked */
01260     __HAL_UNLOCK(hsai);
01261 
01262     return HAL_OK;
01263   }
01264   else
01265   {
01266     return HAL_BUSY;
01267   }
01268 }
01269 
01270 /**
01271   * @brief  Transmit an amount of data in non-blocking mode with Interrupt.
01272   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01273   *              the configuration information for SAI module.
01274   * @param  pData Pointer to data buffer
01275   * @param  Size Amount of data to be sent
01276   * @retval HAL status
01277   */
01278 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01279 {
01280   if ((pData == NULL) || (Size == 0U))
01281   {
01282     return  HAL_ERROR;
01283   }
01284 
01285   if (hsai->State == HAL_SAI_STATE_READY)
01286   {
01287     /* Process Locked */
01288     __HAL_LOCK(hsai);
01289 
01290     hsai->pBuffPtr = pData;
01291     hsai->XferSize = Size;
01292     hsai->XferCount = Size;
01293     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01294     hsai->State = HAL_SAI_STATE_BUSY_TX;
01295 
01296     if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
01297     {
01298       hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
01299     }
01300     else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
01301     {
01302       hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
01303     }
01304     else
01305     {
01306       hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
01307     }
01308 
01309     /* Fill the fifo before starting the communication */
01310     SAI_FillFifo(hsai);
01311 
01312     /* Enable FRQ and OVRUDR interrupts */
01313     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01314 
01315     /* Check if the SAI is already enabled */
01316     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
01317     {
01318       /* Enable SAI peripheral */
01319       __HAL_SAI_ENABLE(hsai);
01320     }
01321     /* Process Unlocked */
01322     __HAL_UNLOCK(hsai);
01323 
01324     return HAL_OK;
01325   }
01326   else
01327   {
01328     return HAL_BUSY;
01329   }
01330 }
01331 
01332 /**
01333   * @brief  Receive an amount of data in non-blocking mode with Interrupt.
01334   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01335   *              the configuration information for SAI module.
01336   * @param  pData Pointer to data buffer
01337   * @param  Size Amount of data to be received
01338   * @retval HAL status
01339   */
01340 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01341 {
01342   if ((pData == NULL) || (Size == 0U))
01343   {
01344     return  HAL_ERROR;
01345   }
01346 
01347   if (hsai->State == HAL_SAI_STATE_READY)
01348   {
01349     /* Process Locked */
01350     __HAL_LOCK(hsai);
01351 
01352     hsai->pBuffPtr = pData;
01353     hsai->XferSize = Size;
01354     hsai->XferCount = Size;
01355     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01356     hsai->State = HAL_SAI_STATE_BUSY_RX;
01357 
01358     if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
01359     {
01360       hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
01361     }
01362     else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
01363     {
01364       hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
01365     }
01366     else
01367     {
01368       hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
01369     }
01370 
01371     /* Enable TXE and OVRUDR interrupts */
01372     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01373 
01374     /* Check if the SAI is already enabled */
01375     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
01376     {
01377       /* Enable SAI peripheral */
01378       __HAL_SAI_ENABLE(hsai);
01379     }
01380 
01381     /* Process Unlocked */
01382     __HAL_UNLOCK(hsai);
01383 
01384     return HAL_OK;
01385   }
01386   else
01387   {
01388     return HAL_BUSY;
01389   }
01390 }
01391 
01392 /**
01393   * @brief Pause the audio stream playing from the Media.
01394   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01395   *              the configuration information for SAI module.
01396   * @retval HAL status
01397   */
01398 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
01399 {
01400   /* Process Locked */
01401   __HAL_LOCK(hsai);
01402 
01403   /* Pause the audio file playing by disabling the SAI DMA requests */
01404   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
01405 
01406   /* Process Unlocked */
01407   __HAL_UNLOCK(hsai);
01408 
01409   return HAL_OK;
01410 }
01411 
01412 /**
01413   * @brief Resume the audio stream playing from the Media.
01414   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01415   *              the configuration information for SAI module.
01416   * @retval HAL status
01417   */
01418 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
01419 {
01420   /* Process Locked */
01421   __HAL_LOCK(hsai);
01422 
01423   /* Enable the SAI DMA requests */
01424   hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
01425 
01426   /* If the SAI peripheral is still not enabled, enable it */
01427   if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
01428   {
01429     /* Enable SAI peripheral */
01430     __HAL_SAI_ENABLE(hsai);
01431   }
01432 
01433   /* Process Unlocked */
01434   __HAL_UNLOCK(hsai);
01435 
01436   return HAL_OK;
01437 }
01438 
01439 /**
01440   * @brief Stop the audio stream playing from the Media.
01441   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01442   *              the configuration information for SAI module.
01443   * @retval HAL status
01444   */
01445 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
01446 {
01447   HAL_StatusTypeDef status = HAL_OK;
01448 
01449   /* Process Locked */
01450   __HAL_LOCK(hsai);
01451 
01452   /* Disable the SAI DMA request */
01453   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
01454 
01455   /* Abort the SAI Tx DMA Stream */
01456   if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL))
01457   {
01458     /* No need to check the returned value of HAL_DMA_Abort. */
01459     /* Only HAL_DMA_ERROR_NO_XFER can be returned in case of error and it's not an error for SAI. */
01460     (void) HAL_DMA_Abort(hsai->hdmatx);
01461   }
01462 
01463   /* Abort the SAI Rx DMA Stream */
01464   if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
01465   {
01466     /* No need to check the returned value of HAL_DMA_Abort. */
01467     /* Only HAL_DMA_ERROR_NO_XFER can be returned in case of error and it's not an error for SAI. */
01468     (void) HAL_DMA_Abort(hsai->hdmarx);
01469   }
01470 
01471   /* Disable SAI peripheral */
01472   if (SAI_Disable(hsai) != HAL_OK)
01473   {
01474     status = HAL_ERROR;
01475   }
01476 
01477   /* Flush the fifo */
01478   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
01479 
01480   /* Set hsai state to ready */
01481   hsai->State = HAL_SAI_STATE_READY;
01482 
01483   /* Process Unlocked */
01484   __HAL_UNLOCK(hsai);
01485 
01486   return status;
01487 }
01488 
01489 /**
01490   * @brief Abort the current transfer and disable the SAI.
01491   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01492   *              the configuration information for SAI module.
01493   * @retval HAL status
01494   */
01495 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
01496 {
01497   HAL_StatusTypeDef status = HAL_OK;
01498 
01499   /* Process Locked */
01500   __HAL_LOCK(hsai);
01501 
01502   /* Check SAI DMA is enabled or not */
01503   if ((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01504   {
01505     /* Disable the SAI DMA request */
01506     hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
01507 
01508     /* Abort the SAI Tx DMA Stream */
01509     if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL))
01510     {
01511       /* No need to check the returned value of HAL_DMA_Abort. */
01512       /* Only HAL_DMA_ERROR_NO_XFER can be returned in case of error and it's not an error for SAI. */
01513       (void) HAL_DMA_Abort(hsai->hdmatx);
01514     }
01515 
01516     /* Abort the SAI Rx DMA Stream */
01517     if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
01518     {
01519       /* No need to check the returned value of HAL_DMA_Abort. */
01520       /* Only HAL_DMA_ERROR_NO_XFER can be returned in case of error and it's not an error for SAI. */
01521       (void) HAL_DMA_Abort(hsai->hdmarx);
01522     }
01523   }
01524 
01525   /* Disabled All interrupt and clear all the flag */
01526   hsai->Instance->IMR = 0;
01527   hsai->Instance->CLRFR = 0xFFFFFFFFU;
01528 
01529   /* Disable SAI peripheral */
01530   if (SAI_Disable(hsai) != HAL_OK)
01531   {
01532     status = HAL_ERROR;
01533   }
01534 
01535   /* Flush the fifo */
01536   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
01537 
01538   /* Set hsai state to ready */
01539   hsai->State = HAL_SAI_STATE_READY;
01540 
01541   /* Process Unlocked */
01542   __HAL_UNLOCK(hsai);
01543 
01544   return status;
01545 }
01546 
01547 /**
01548   * @brief  Transmit an amount of data in non-blocking mode with DMA.
01549   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01550   *              the configuration information for SAI module.
01551   * @param  pData Pointer to data buffer
01552   * @param  Size Amount of data to be sent
01553   * @retval HAL status
01554   */
01555 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01556 {
01557   uint32_t tickstart = HAL_GetTick();
01558 
01559   if ((pData == NULL) || (Size == 0U))
01560   {
01561     return  HAL_ERROR;
01562   }
01563 
01564   if (hsai->State == HAL_SAI_STATE_READY)
01565   {
01566     /* Process Locked */
01567     __HAL_LOCK(hsai);
01568 
01569     hsai->pBuffPtr = pData;
01570     hsai->XferSize = Size;
01571     hsai->XferCount = Size;
01572     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01573     hsai->State = HAL_SAI_STATE_BUSY_TX;
01574 
01575     /* Set the SAI Tx DMA Half transfer complete callback */
01576     hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
01577 
01578     /* Set the SAI TxDMA transfer complete callback */
01579     hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
01580 
01581     /* Set the DMA error callback */
01582     hsai->hdmatx->XferErrorCallback = SAI_DMAError;
01583 
01584     /* Set the DMA Tx abort callback */
01585     hsai->hdmatx->XferAbortCallback = NULL;
01586 
01587     /* Enable the Tx DMA Stream */
01588     if (HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
01589     {
01590       __HAL_UNLOCK(hsai);
01591       return  HAL_ERROR;
01592     }
01593 
01594     /* Enable the interrupts for error handling */
01595     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
01596 
01597     /* Enable SAI Tx DMA Request */
01598     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
01599 
01600     /* Wait untill FIFO is not empty */
01601     while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY)
01602     {
01603       /* Check for the Timeout */
01604       if ((HAL_GetTick() - tickstart) > SAI_LONG_TIMEOUT)
01605       {
01606         /* Update error code */
01607         hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
01608 
01609         /* Process Unlocked */
01610         __HAL_UNLOCK(hsai);
01611 
01612         return HAL_TIMEOUT;
01613       }
01614     }
01615 
01616     /* Check if the SAI is already enabled */
01617     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
01618     {
01619       /* Enable SAI peripheral */
01620       __HAL_SAI_ENABLE(hsai);
01621     }
01622 
01623     /* Process Unlocked */
01624     __HAL_UNLOCK(hsai);
01625 
01626     return HAL_OK;
01627   }
01628   else
01629   {
01630     return HAL_BUSY;
01631   }
01632 }
01633 
01634 /**
01635   * @brief  Receive an amount of data in non-blocking mode with DMA.
01636   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01637   *              the configuration information for SAI module.
01638   * @param  pData Pointer to data buffer
01639   * @param  Size Amount of data to be received
01640   * @retval HAL status
01641   */
01642 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01643 {
01644 
01645   if ((pData == NULL) || (Size == 0U))
01646   {
01647     return  HAL_ERROR;
01648   }
01649 
01650   if (hsai->State == HAL_SAI_STATE_READY)
01651   {
01652     /* Process Locked */
01653     __HAL_LOCK(hsai);
01654 
01655     hsai->pBuffPtr = pData;
01656     hsai->XferSize = Size;
01657     hsai->XferCount = Size;
01658     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01659     hsai->State = HAL_SAI_STATE_BUSY_RX;
01660 
01661     /* Set the SAI Rx DMA Half transfer complete callback */
01662     hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
01663 
01664     /* Set the SAI Rx DMA transfer complete callback */
01665     hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
01666 
01667     /* Set the DMA error callback */
01668     hsai->hdmarx->XferErrorCallback = SAI_DMAError;
01669 
01670     /* Set the DMA Rx abort callback */
01671     hsai->hdmarx->XferAbortCallback = NULL;
01672 
01673     /* Enable the Rx DMA Stream */
01674     if (HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
01675     {
01676       __HAL_UNLOCK(hsai);
01677       return  HAL_ERROR;
01678     }
01679 
01680     /* Enable the interrupts for error handling */
01681     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
01682 
01683     /* Enable SAI Rx DMA Request */
01684     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
01685 
01686     /* Check if the SAI is already enabled */
01687     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
01688     {
01689       /* Enable SAI peripheral */
01690       __HAL_SAI_ENABLE(hsai);
01691     }
01692 
01693     /* Process Unlocked */
01694     __HAL_UNLOCK(hsai);
01695 
01696     return HAL_OK;
01697   }
01698   else
01699   {
01700     return HAL_BUSY;
01701   }
01702 }
01703 
01704 /**
01705   * @brief  Enable the Tx mute mode.
01706   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01707   *              the configuration information for SAI module.
01708   * @param  val  value sent during the mute @ref SAI_Block_Mute_Value
01709   * @retval HAL status
01710   */
01711 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
01712 {
01713   assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
01714 
01715   if (hsai->State != HAL_SAI_STATE_RESET)
01716   {
01717     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
01718     SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | (uint32_t)val);
01719     return HAL_OK;
01720   }
01721   return HAL_ERROR;
01722 }
01723 
01724 /**
01725   * @brief  Disable the Tx mute mode.
01726   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01727   *              the configuration information for SAI module.
01728   * @retval HAL status
01729   */
01730 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
01731 {
01732   if (hsai->State != HAL_SAI_STATE_RESET)
01733   {
01734     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
01735     return HAL_OK;
01736   }
01737   return HAL_ERROR;
01738 }
01739 
01740 /**
01741   * @brief  Enable the Rx mute detection.
01742   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01743   *              the configuration information for SAI module.
01744   * @param  callback function called when the mute is detected.
01745   * @param  counter number a data before mute detection max 63.
01746   * @retval HAL status
01747   */
01748 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
01749 {
01750   assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
01751 
01752   if (hsai->State != HAL_SAI_STATE_RESET)
01753   {
01754     /* set the mute counter */
01755     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
01756     SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
01757     hsai->mutecallback = callback;
01758     /* enable the IT interrupt */
01759     __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
01760     return HAL_OK;
01761   }
01762   return HAL_ERROR;
01763 }
01764 
01765 /**
01766   * @brief  Disable the Rx mute detection.
01767   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01768   *              the configuration information for SAI module.
01769   * @retval HAL status
01770   */
01771 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
01772 {
01773   if (hsai->State != HAL_SAI_STATE_RESET)
01774   {
01775     /* set the mutecallback to NULL */
01776     hsai->mutecallback = NULL;
01777     /* enable the IT interrupt */
01778     __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
01779     return HAL_OK;
01780   }
01781   return HAL_ERROR;
01782 }
01783 
01784 /**
01785   * @brief  Handle SAI interrupt request.
01786   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01787   *              the configuration information for SAI module.
01788   * @retval None
01789   */
01790 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
01791 {
01792   if (hsai->State != HAL_SAI_STATE_RESET)
01793   {
01794     uint32_t itflags = hsai->Instance->SR;
01795     uint32_t itsources = hsai->Instance->IMR;
01796     uint32_t cr1config = hsai->Instance->CR1;
01797     uint32_t tmperror;
01798 
01799     /* SAI Fifo request interrupt occurred -----------------------------------*/
01800     if (((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
01801     {
01802       hsai->InterruptServiceRoutine(hsai);
01803     }
01804     /* SAI Overrun error interrupt occurred ----------------------------------*/
01805     else if (((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
01806     {
01807       /* Clear the SAI Overrun flag */
01808       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
01809       /* Get the SAI error code */
01810       tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
01811       /* Change the SAI error code */
01812       hsai->ErrorCode |= tmperror;
01813       /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
01814 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01815       hsai->ErrorCallback(hsai);
01816 #else
01817       HAL_SAI_ErrorCallback(hsai);
01818 #endif
01819     }
01820     /* SAI mutedet interrupt occurred ----------------------------------*/
01821     else if (((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
01822     {
01823       /* Clear the SAI mutedet flag */
01824       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
01825       /* call the call back function */
01826       if (hsai->mutecallback != NULL)
01827       {
01828         /* inform the user that an RX mute event has been detected */
01829         hsai->mutecallback();
01830       }
01831     }
01832     /* SAI AFSDET interrupt occurred ----------------------------------*/
01833     else if (((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
01834     {
01835       /* Clear the SAI AFSDET flag */
01836       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_AFSDET);
01837 
01838       /* Change the SAI error code */
01839       hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
01840 
01841       /* Check SAI DMA is enabled or not */
01842       if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01843       {
01844         /* Abort the SAI DMA Streams */
01845         if (hsai->hdmatx != NULL)
01846         {
01847           /* Set the DMA Tx abort callback */
01848           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
01849 
01850           /* Abort DMA in IT mode */
01851           if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
01852           {
01853             /* Update SAI error code */
01854             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
01855 
01856             /* Call SAI error callback */
01857 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01858             hsai->ErrorCallback(hsai);
01859 #else
01860             HAL_SAI_ErrorCallback(hsai);
01861 #endif
01862           }
01863         }
01864         if (hsai->hdmarx != NULL)
01865         {
01866           /* Set the DMA Rx abort callback */
01867           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
01868 
01869           /* Abort DMA in IT mode */
01870           if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
01871           {
01872             /* Update SAI error code */
01873             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
01874 
01875             /* Call SAI error callback */
01876 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01877             hsai->ErrorCallback(hsai);
01878 #else
01879             HAL_SAI_ErrorCallback(hsai);
01880 #endif
01881           }
01882         }
01883       }
01884       else
01885       {
01886         /* Abort SAI */
01887         /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
01888         (void) HAL_SAI_Abort(hsai);
01889 
01890         /* Set error callback */
01891 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01892         hsai->ErrorCallback(hsai);
01893 #else
01894         HAL_SAI_ErrorCallback(hsai);
01895 #endif
01896       }
01897     }
01898     /* SAI LFSDET interrupt occurred ----------------------------------*/
01899     else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
01900     {
01901       /* Clear the SAI LFSDET flag */
01902       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_LFSDET);
01903 
01904       /* Change the SAI error code */
01905       hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
01906 
01907       /* Check SAI DMA is enabled or not */
01908       if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01909       {
01910         /* Abort the SAI DMA Streams */
01911         if (hsai->hdmatx != NULL)
01912         {
01913           /* Set the DMA Tx abort callback */
01914           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
01915 
01916           /* Abort DMA in IT mode */
01917           if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
01918           {
01919             /* Update SAI error code */
01920             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
01921 
01922             /* Call SAI error callback */
01923 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01924             hsai->ErrorCallback(hsai);
01925 #else
01926             HAL_SAI_ErrorCallback(hsai);
01927 #endif
01928           }
01929         }
01930         if (hsai->hdmarx != NULL)
01931         {
01932           /* Set the DMA Rx abort callback */
01933           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
01934 
01935           /* Abort DMA in IT mode */
01936           if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
01937           {
01938             /* Update SAI error code */
01939             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
01940 
01941             /* Call SAI error callback */
01942 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01943             hsai->ErrorCallback(hsai);
01944 #else
01945             HAL_SAI_ErrorCallback(hsai);
01946 #endif
01947           }
01948         }
01949       }
01950       else
01951       {
01952         /* Abort SAI */
01953         /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
01954         (void) HAL_SAI_Abort(hsai);
01955 
01956         /* Set error callback */
01957 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01958         hsai->ErrorCallback(hsai);
01959 #else
01960         HAL_SAI_ErrorCallback(hsai);
01961 #endif
01962       }
01963     }
01964     /* SAI WCKCFG interrupt occurred ----------------------------------*/
01965     else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
01966     {
01967       /* Clear the SAI WCKCFG flag */
01968       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_WCKCFG);
01969 
01970       /* Change the SAI error code */
01971       hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
01972 
01973       /* Check SAI DMA is enabled or not */
01974       if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01975       {
01976         /* Abort the SAI DMA Streams */
01977         if (hsai->hdmatx != NULL)
01978         {
01979           /* Set the DMA Tx abort callback */
01980           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
01981 
01982           /* Abort DMA in IT mode */
01983           if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
01984           {
01985             /* Update SAI error code */
01986             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
01987 
01988             /* Call SAI error callback */
01989 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01990             hsai->ErrorCallback(hsai);
01991 #else
01992             HAL_SAI_ErrorCallback(hsai);
01993 #endif
01994           }
01995         }
01996         if (hsai->hdmarx != NULL)
01997         {
01998           /* Set the DMA Rx abort callback */
01999           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
02000 
02001           /* Abort DMA in IT mode */
02002           if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
02003           {
02004             /* Update SAI error code */
02005             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
02006 
02007             /* Call SAI error callback */
02008 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02009             hsai->ErrorCallback(hsai);
02010 #else
02011             HAL_SAI_ErrorCallback(hsai);
02012 #endif
02013           }
02014         }
02015       }
02016       else
02017       {
02018         /* If WCKCFG occurs, SAI audio block is automatically disabled */
02019         /* Disable all interrupts and clear all flags */
02020         hsai->Instance->IMR = 0U;
02021         hsai->Instance->CLRFR = 0xFFFFFFFFU;
02022         /* Set the SAI state to ready to be able to start again the process */
02023         hsai->State = HAL_SAI_STATE_READY;
02024 
02025         /* Initialize XferCount */
02026         hsai->XferCount = 0U;
02027 
02028         /* SAI error Callback */
02029 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02030         hsai->ErrorCallback(hsai);
02031 #else
02032         HAL_SAI_ErrorCallback(hsai);
02033 #endif
02034       }
02035     }
02036     /* SAI CNRDY interrupt occurred ----------------------------------*/
02037     else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
02038     {
02039       /* Clear the SAI CNRDY flag */
02040       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
02041       /* Change the SAI error code */
02042       hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
02043       /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
02044 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02045       hsai->ErrorCallback(hsai);
02046 #else
02047       HAL_SAI_ErrorCallback(hsai);
02048 #endif
02049     }
02050     else
02051     {
02052       /* Nothing to do */
02053     }
02054   }
02055 }
02056 
02057 /**
02058   * @brief Tx Transfer completed callback.
02059   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02060   *              the configuration information for SAI module.
02061   * @retval None
02062   */
02063 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
02064 {
02065   /* Prevent unused argument(s) compilation warning */
02066   UNUSED(hsai);
02067 
02068   /* NOTE : This function should not be modified, when the callback is needed,
02069             the HAL_SAI_TxCpltCallback could be implemented in the user file
02070    */
02071 }
02072 
02073 /**
02074   * @brief Tx Transfer Half completed callback.
02075   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02076   *              the configuration information for SAI module.
02077   * @retval None
02078   */
02079 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
02080 {
02081   /* Prevent unused argument(s) compilation warning */
02082   UNUSED(hsai);
02083 
02084   /* NOTE : This function should not be modified, when the callback is needed,
02085             the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
02086    */
02087 }
02088 
02089 /**
02090   * @brief Rx Transfer completed callback.
02091   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02092   *              the configuration information for SAI module.
02093   * @retval None
02094   */
02095 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
02096 {
02097   /* Prevent unused argument(s) compilation warning */
02098   UNUSED(hsai);
02099 
02100   /* NOTE : This function should not be modified, when the callback is needed,
02101             the HAL_SAI_RxCpltCallback could be implemented in the user file
02102    */
02103 }
02104 
02105 /**
02106   * @brief Rx Transfer half completed callback.
02107   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02108   *              the configuration information for SAI module.
02109   * @retval None
02110   */
02111 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
02112 {
02113   /* Prevent unused argument(s) compilation warning */
02114   UNUSED(hsai);
02115 
02116   /* NOTE : This function should not be modified, when the callback is needed,
02117             the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
02118    */
02119 }
02120 
02121 /**
02122   * @brief SAI error callback.
02123   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02124   *              the configuration information for SAI module.
02125   * @retval None
02126   */
02127 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
02128 {
02129   /* Prevent unused argument(s) compilation warning */
02130   UNUSED(hsai);
02131 
02132   /* NOTE : This function should not be modified, when the callback is needed,
02133             the HAL_SAI_ErrorCallback could be implemented in the user file
02134    */
02135 }
02136 
02137 /**
02138   * @}
02139   */
02140 
02141 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
02142   * @brief    Peripheral State functions
02143   *
02144 @verbatim
02145   ===============================================================================
02146                 ##### Peripheral State and Errors functions #####
02147   ===============================================================================
02148   [..]
02149     This subsection permits to get in run-time the status of the peripheral
02150     and the data flow.
02151 
02152 @endverbatim
02153   * @{
02154   */
02155 
02156 /**
02157   * @brief  Return the SAI handle state.
02158   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02159   *              the configuration information for SAI module.
02160   * @retval HAL state
02161   */
02162 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
02163 {
02164   return hsai->State;
02165 }
02166 
02167 /**
02168   * @brief  Return the SAI error code.
02169   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02170   *              the configuration information for the specified SAI Block.
02171   * @retval SAI Error Code
02172   */
02173 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
02174 {
02175   return hsai->ErrorCode;
02176 }
02177 
02178 /**
02179   * @}
02180   */
02181 
02182 /**
02183   * @}
02184   */
02185 
02186 /** @addtogroup SAI_Private_Functions
02187   * @brief      Private functions
02188   * @{
02189   */
02190 
02191 /**
02192   * @brief  Initialize the SAI I2S protocol according to the specified parameters
02193   *         in the SAI_InitTypeDef and create the associated handle.
02194   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02195   *              the configuration information for SAI module.
02196   * @param  protocol one of the supported protocol.
02197   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize.
02198   * @param  nbslot number of slot minimum value is 2 and max is 16.
02199   *         the value must be a multiple of 2.
02200   * @retval HAL status
02201   */
02202 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
02203 {
02204   HAL_StatusTypeDef status = HAL_OK;
02205 
02206   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
02207   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
02208   /* Compute ClockStrobing according AudioMode */
02209   if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
02210   {
02211     /* Transmit */
02212     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_FALLINGEDGE;
02213   }
02214   else
02215   {
02216     /* Receive */
02217     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_RISINGEDGE;
02218   }
02219   hsai->FrameInit.FSDefinition   = SAI_FS_CHANNEL_IDENTIFICATION;
02220   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
02221   hsai->SlotInit.FirstBitOffset  = 0;
02222   hsai->SlotInit.SlotNumber      = nbslot;
02223 
02224   /* in IS2 the number of slot must be even */
02225   if ((nbslot & 0x1U) != 0U)
02226   {
02227     return HAL_ERROR;
02228   }
02229 
02230   if (protocol == SAI_I2S_STANDARD)
02231   {
02232     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
02233     hsai->FrameInit.FSOffset   = SAI_FS_BEFOREFIRSTBIT;
02234   }
02235   else
02236   {
02237      /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
02238     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
02239     hsai->FrameInit.FSOffset   = SAI_FS_FIRSTBIT;
02240   }
02241 
02242   /* Frame definition */
02243   switch (datasize)
02244   {
02245     case SAI_PROTOCOL_DATASIZE_16BIT:
02246       hsai->Init.DataSize = SAI_DATASIZE_16;
02247       hsai->FrameInit.FrameLength = 32U * (nbslot / 2U);
02248       hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U);
02249       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
02250       break;
02251     case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
02252       hsai->Init.DataSize = SAI_DATASIZE_16;
02253       hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
02254       hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
02255       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02256       break;
02257     case SAI_PROTOCOL_DATASIZE_24BIT:
02258       hsai->Init.DataSize = SAI_DATASIZE_24;
02259       hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
02260       hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
02261       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02262       break;
02263     case SAI_PROTOCOL_DATASIZE_32BIT:
02264       hsai->Init.DataSize = SAI_DATASIZE_32;
02265       hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
02266       hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
02267       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02268       break;
02269     default :
02270       status = HAL_ERROR;
02271       break;
02272   }
02273   if (protocol == SAI_I2S_LSBJUSTIFIED)
02274   {
02275     if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
02276     {
02277       hsai->SlotInit.FirstBitOffset = 16;
02278     }
02279     if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
02280     {
02281       hsai->SlotInit.FirstBitOffset = 8;
02282     }
02283   }
02284   return status;
02285 }
02286 
02287 /**
02288   * @brief  Initialize the SAI PCM protocol according to the specified parameters
02289   *         in the SAI_InitTypeDef and create the associated handle.
02290   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02291   *              the configuration information for SAI module.
02292   * @param  protocol one of the supported protocol
02293   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
02294   * @param  nbslot number of slot minimum value is 1 and the max is 16.
02295   * @retval HAL status
02296   */
02297 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
02298 {
02299   HAL_StatusTypeDef status = HAL_OK;
02300 
02301   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
02302   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
02303   /* Compute ClockStrobing according AudioMode */
02304   if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
02305   {
02306     /* Transmit */
02307     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_RISINGEDGE;
02308   }
02309   else
02310   {
02311     /* Receive */
02312     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_FALLINGEDGE;
02313   }
02314   hsai->FrameInit.FSDefinition   = SAI_FS_STARTFRAME;
02315   hsai->FrameInit.FSPolarity     = SAI_FS_ACTIVE_HIGH;
02316   hsai->FrameInit.FSOffset       = SAI_FS_BEFOREFIRSTBIT;
02317   hsai->SlotInit.FirstBitOffset  = 0;
02318   hsai->SlotInit.SlotNumber      = nbslot;
02319   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
02320 
02321   if (protocol == SAI_PCM_SHORT)
02322   {
02323     hsai->FrameInit.ActiveFrameLength = 1;
02324   }
02325   else
02326   {
02327     /* SAI_PCM_LONG */
02328     hsai->FrameInit.ActiveFrameLength = 13;
02329   }
02330 
02331   switch (datasize)
02332   {
02333     case SAI_PROTOCOL_DATASIZE_16BIT:
02334       hsai->Init.DataSize = SAI_DATASIZE_16;
02335       hsai->FrameInit.FrameLength = 16U * nbslot;
02336       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
02337       break;
02338     case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
02339       hsai->Init.DataSize = SAI_DATASIZE_16;
02340       hsai->FrameInit.FrameLength = 32U * nbslot;
02341       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02342       break;
02343     case SAI_PROTOCOL_DATASIZE_24BIT :
02344       hsai->Init.DataSize = SAI_DATASIZE_24;
02345       hsai->FrameInit.FrameLength = 32U * nbslot;
02346       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02347       break;
02348     case SAI_PROTOCOL_DATASIZE_32BIT:
02349       hsai->Init.DataSize = SAI_DATASIZE_32;
02350       hsai->FrameInit.FrameLength = 32U * nbslot;
02351       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02352       break;
02353     default :
02354       status = HAL_ERROR;
02355       break;
02356   }
02357 
02358   return status;
02359 }
02360 
02361 /**
02362   * @brief  Fill the fifo.
02363   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02364   *              the configuration information for SAI module.
02365   * @retval None
02366   */
02367 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
02368 {
02369   uint32_t temp;
02370 
02371   /* fill the fifo with data before to enabled the SAI */
02372   while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
02373   {
02374     if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
02375     {
02376       hsai->Instance->DR = *hsai->pBuffPtr;
02377       hsai->pBuffPtr++;
02378     }
02379     else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
02380     {
02381       temp = (uint32_t)(*hsai->pBuffPtr);
02382       hsai->pBuffPtr++;
02383       temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
02384       hsai->pBuffPtr++;
02385       hsai->Instance->DR = temp;
02386     }
02387     else
02388     {
02389       temp = (uint32_t)(*hsai->pBuffPtr);
02390       hsai->pBuffPtr++;
02391       temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
02392       hsai->pBuffPtr++;
02393       temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
02394       hsai->pBuffPtr++;
02395       temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
02396       hsai->pBuffPtr++;
02397       hsai->Instance->DR = temp;
02398     }
02399     hsai->XferCount--;
02400   }
02401 }
02402 
02403 /**
02404   * @brief  Return the interrupt flag to set according the SAI setup.
02405   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02406   *              the configuration information for SAI module.
02407   * @param  mode SAI_MODE_DMA or SAI_MODE_IT
02408   * @retval the list of the IT flag to enable
02409   */
02410 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode)
02411 {
02412   uint32_t tmpIT = SAI_IT_OVRUDR;
02413 
02414   if (mode == SAI_MODE_IT)
02415   {
02416     tmpIT |= SAI_IT_FREQ;
02417   }
02418 
02419   if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
02420       ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
02421   {
02422     tmpIT |= SAI_IT_CNRDY;
02423   }
02424 
02425   if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
02426   {
02427     tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET;
02428   }
02429   else
02430   {
02431     /* hsai has been configured in master mode */
02432     tmpIT |= SAI_IT_WCKCFG;
02433   }
02434   return tmpIT;
02435 }
02436 
02437 /**
02438   * @brief  Disable the SAI and wait for the disabling.
02439   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02440   *              the configuration information for SAI module.
02441   * @retval None
02442   */
02443 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
02444 {
02445   uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U);
02446   HAL_StatusTypeDef status = HAL_OK;
02447 
02448   /* Disable the SAI instance */
02449   __HAL_SAI_DISABLE(hsai);
02450 
02451   do
02452   {
02453     /* Check for the Timeout */
02454     if (count == 0U)
02455     {
02456       /* Update error code */
02457       hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
02458       status = HAL_TIMEOUT;
02459       break;
02460     }
02461     count--;
02462   }
02463   while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != 0U);
02464 
02465   return status;
02466 }
02467 
02468 /**
02469   * @brief  Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
02470   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02471   *              the configuration information for SAI module.
02472   * @retval None
02473   */
02474 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
02475 {
02476   if (hsai->XferCount == 0U)
02477   {
02478     /* Handle the end of the transmission */
02479     /* Disable FREQ and OVRUDR interrupts */
02480     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02481     hsai->State = HAL_SAI_STATE_READY;
02482 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02483     hsai->TxCpltCallback(hsai);
02484 #else
02485     HAL_SAI_TxCpltCallback(hsai);
02486 #endif
02487   }
02488   else
02489   {
02490     /* Write data on DR register */
02491     hsai->Instance->DR = *hsai->pBuffPtr;
02492     hsai->pBuffPtr++;
02493     hsai->XferCount--;
02494   }
02495 }
02496 
02497 /**
02498   * @brief  Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
02499   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02500   *              the configuration information for SAI module.
02501   * @retval None
02502   */
02503 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
02504 {
02505   if (hsai->XferCount == 0U)
02506   {
02507     /* Handle the end of the transmission */
02508     /* Disable FREQ and OVRUDR interrupts */
02509     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02510     hsai->State = HAL_SAI_STATE_READY;
02511 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02512     hsai->TxCpltCallback(hsai);
02513 #else
02514     HAL_SAI_TxCpltCallback(hsai);
02515 #endif
02516   }
02517   else
02518   {
02519     /* Write data on DR register */
02520     uint32_t temp;
02521     temp = (uint32_t)(*hsai->pBuffPtr);
02522     hsai->pBuffPtr++;
02523     temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
02524     hsai->pBuffPtr++;
02525     hsai->Instance->DR = temp;
02526     hsai->XferCount--;
02527   }
02528 }
02529 
02530 /**
02531   * @brief  Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
02532   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02533   *              the configuration information for SAI module.
02534   * @retval None
02535   */
02536 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
02537 {
02538   if (hsai->XferCount == 0U)
02539   {
02540     /* Handle the end of the transmission */
02541     /* Disable FREQ and OVRUDR interrupts */
02542     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02543     hsai->State = HAL_SAI_STATE_READY;
02544 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02545     hsai->TxCpltCallback(hsai);
02546 #else
02547     HAL_SAI_TxCpltCallback(hsai);
02548 #endif
02549   }
02550   else
02551   {
02552     /* Write data on DR register */
02553     uint32_t temp;
02554     temp = (uint32_t)(*hsai->pBuffPtr);
02555     hsai->pBuffPtr++;
02556     temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
02557     hsai->pBuffPtr++;
02558     temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
02559     hsai->pBuffPtr++;
02560     temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
02561     hsai->pBuffPtr++;
02562     hsai->Instance->DR = temp;
02563     hsai->XferCount--;
02564   }
02565 }
02566 
02567 /**
02568   * @brief  Rx Handler for Receive in Interrupt mode 8-Bit transfer.
02569   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02570   *              the configuration information for SAI module.
02571   * @retval None
02572   */
02573 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
02574 {
02575   /* Receive data */
02576   *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
02577   hsai->pBuffPtr++;
02578   hsai->XferCount--;
02579 
02580   /* Check end of the transfer */
02581   if (hsai->XferCount == 0U)
02582   {
02583     /* Disable TXE and OVRUDR interrupts */
02584     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02585 
02586     /* Clear the SAI Overrun flag */
02587     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
02588 
02589     hsai->State = HAL_SAI_STATE_READY;
02590 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02591     hsai->RxCpltCallback(hsai);
02592 #else
02593     HAL_SAI_RxCpltCallback(hsai);
02594 #endif
02595   }
02596 }
02597 
02598 /**
02599   * @brief  Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
02600   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02601   *              the configuration information for SAI module.
02602   * @retval None
02603   */
02604 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
02605 {
02606   uint32_t temp;
02607 
02608   /* Receive data */
02609   temp = hsai->Instance->DR;
02610   *hsai->pBuffPtr = (uint8_t)temp;
02611   hsai->pBuffPtr++;
02612   *hsai->pBuffPtr = (uint8_t)(temp >> 8);
02613   hsai->pBuffPtr++;
02614   hsai->XferCount--;
02615 
02616   /* Check end of the transfer */
02617   if (hsai->XferCount == 0U)
02618   {
02619     /* Disable TXE and OVRUDR interrupts */
02620     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02621 
02622     /* Clear the SAI Overrun flag */
02623     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
02624 
02625     hsai->State = HAL_SAI_STATE_READY;
02626 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02627     hsai->RxCpltCallback(hsai);
02628 #else
02629     HAL_SAI_RxCpltCallback(hsai);
02630 #endif
02631   }
02632 }
02633 
02634 /**
02635   * @brief  Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
02636   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02637   *              the configuration information for SAI module.
02638   * @retval None
02639   */
02640 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
02641 {
02642   uint32_t temp;
02643 
02644   /* Receive data */
02645   temp = hsai->Instance->DR;
02646   *hsai->pBuffPtr = (uint8_t)temp;
02647   hsai->pBuffPtr++;
02648   *hsai->pBuffPtr = (uint8_t)(temp >> 8);
02649   hsai->pBuffPtr++;
02650   *hsai->pBuffPtr = (uint8_t)(temp >> 16);
02651   hsai->pBuffPtr++;
02652   *hsai->pBuffPtr = (uint8_t)(temp >> 24);
02653   hsai->pBuffPtr++;
02654   hsai->XferCount--;
02655 
02656   /* Check end of the transfer */
02657   if (hsai->XferCount == 0U)
02658   {
02659     /* Disable TXE and OVRUDR interrupts */
02660     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02661 
02662     /* Clear the SAI Overrun flag */
02663     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
02664 
02665     hsai->State = HAL_SAI_STATE_READY;
02666 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02667     hsai->RxCpltCallback(hsai);
02668 #else
02669     HAL_SAI_RxCpltCallback(hsai);
02670 #endif
02671   }
02672 }
02673 
02674 /**
02675   * @brief  DMA SAI transmit process complete callback.
02676   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02677   *              the configuration information for the specified DMA module.
02678   * @retval None
02679   */
02680 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
02681 {
02682   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02683 
02684   if (hdma->Init.Mode != DMA_CIRCULAR)
02685   {
02686     hsai->XferCount = 0;
02687 
02688     /* Disable SAI Tx DMA Request */
02689     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
02690 
02691     /* Stop the interrupts error handling */
02692     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
02693 
02694     hsai->State = HAL_SAI_STATE_READY;
02695   }
02696 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02697   hsai->TxCpltCallback(hsai);
02698 #else
02699   HAL_SAI_TxCpltCallback(hsai);
02700 #endif
02701 }
02702 
02703 /**
02704   * @brief  DMA SAI transmit process half complete callback.
02705   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02706   *              the configuration information for the specified DMA module.
02707   * @retval None
02708   */
02709 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
02710 {
02711   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02712 
02713 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02714   hsai->TxHalfCpltCallback(hsai);
02715 #else
02716   HAL_SAI_TxHalfCpltCallback(hsai);
02717 #endif
02718 }
02719 
02720 /**
02721   * @brief  DMA SAI receive process complete callback.
02722   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02723   *              the configuration information for the specified DMA module.
02724   * @retval None
02725   */
02726 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
02727 {
02728   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02729 
02730   if (hdma->Init.Mode != DMA_CIRCULAR)
02731   {
02732     /* Disable Rx DMA Request */
02733     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
02734     hsai->XferCount = 0;
02735 
02736     /* Stop the interrupts error handling */
02737     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
02738 
02739     hsai->State = HAL_SAI_STATE_READY;
02740   }
02741 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02742   hsai->RxCpltCallback(hsai);
02743 #else
02744   HAL_SAI_RxCpltCallback(hsai);
02745 #endif
02746 }
02747 
02748 /**
02749   * @brief  DMA SAI receive process half complete callback
02750   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02751   *              the configuration information for the specified DMA module.
02752   * @retval None
02753   */
02754 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
02755 {
02756   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02757 
02758 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02759   hsai->RxHalfCpltCallback(hsai);
02760 #else
02761   HAL_SAI_RxHalfCpltCallback(hsai);
02762 #endif
02763 }
02764 
02765 /**
02766   * @brief  DMA SAI communication error callback.
02767   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02768   *              the configuration information for the specified DMA module.
02769   * @retval None
02770   */
02771 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
02772 {
02773   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02774 
02775   /* Set SAI error code */
02776   hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
02777 
02778   /* Disable the SAI DMA request */
02779   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
02780 
02781   /* Disable SAI peripheral */
02782   /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
02783   (void) SAI_Disable(hsai);
02784 
02785   /* Set the SAI state ready to be able to start again the process */
02786   hsai->State = HAL_SAI_STATE_READY;
02787 
02788   /* Initialize XferCount */
02789   hsai->XferCount = 0U;
02790 
02791   /* SAI error Callback */
02792 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02793   hsai->ErrorCallback(hsai);
02794 #else
02795   HAL_SAI_ErrorCallback(hsai);
02796 #endif
02797 }
02798 
02799 /**
02800   * @brief  DMA SAI Abort callback.
02801   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02802   *              the configuration information for the specified DMA module.
02803   * @retval None
02804   */
02805 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
02806 {
02807   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02808 
02809   /* Disable DMA request */
02810   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
02811 
02812   /* Disable all interrupts and clear all flags */
02813   hsai->Instance->IMR = 0U;
02814   hsai->Instance->CLRFR = 0xFFFFFFFFU;
02815 
02816   if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
02817   {
02818     /* Disable SAI peripheral */
02819     /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
02820     (void) SAI_Disable(hsai);
02821 
02822     /* Flush the fifo */
02823     SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
02824   }
02825   /* Set the SAI state to ready to be able to start again the process */
02826   hsai->State = HAL_SAI_STATE_READY;
02827 
02828   /* Initialize XferCount */
02829   hsai->XferCount = 0U;
02830 
02831   /* SAI error Callback */
02832 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02833   hsai->ErrorCallback(hsai);
02834 #else
02835   HAL_SAI_ErrorCallback(hsai);
02836 #endif
02837 }
02838 
02839 /**
02840   * @}
02841   */
02842 
02843 /**
02844   * @}
02845   */
02846 
02847 #endif /* !STM32L412xx && !STM32L422xx */
02848 #endif /* HAL_SAI_MODULE_ENABLED */
02849 
02850 /**
02851   * @}
02852   */
02853