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