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