Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:09

0001 /**
0002   ******************************************************************************
0003   * @file    stm32h7xx_hal_sai.c
0004   * @author  MCD Application Team
0005   * @brief   SAI HAL module driver.
0006   *          This file provides firmware functions to manage the following
0007   *          functionalities of the Serial Audio Interface (SAI) peripheral:
0008   *           + Initialization/de-initialization functions
0009   *           + I/O operation functions
0010   *           + Peripheral Control functions
0011   *           + Peripheral State functions
0012   *
0013   ******************************************************************************
0014   * @attention
0015   *
0016   * Copyright (c) 2017 STMicroelectronics.
0017   * All rights reserved.
0018   *
0019   * This software is licensed under terms that can be found in the LICENSE file
0020   * in the root directory of this software component.
0021   * If no LICENSE file comes with this software, it is provided AS-IS.
0022   *
0023   ******************************************************************************
0024   @verbatim
0025   ==============================================================================
0026                   ##### How to use this driver #####
0027   ==============================================================================
0028 
0029   [..]
0030     The SAI HAL driver can be used as follows:
0031 
0032     (#) Declare a SAI_HandleTypeDef handle structure (eg. SAI_HandleTypeDef hsai).
0033     (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API:
0034         (##) Enable the SAI interface clock.
0035         (##) SAI pins configuration:
0036             (+++) Enable the clock for the SAI GPIOs.
0037             (+++) Configure these SAI pins as alternate function pull-up.
0038         (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT()
0039              and HAL_SAI_Receive_IT() APIs):
0040             (+++) Configure the SAI interrupt priority.
0041             (+++) Enable the NVIC SAI IRQ handle.
0042 
0043         (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA()
0044              and HAL_SAI_Receive_DMA() APIs):
0045             (+++) Declare a DMA handle structure for the Tx/Rx stream.
0046             (+++) Enable the DMAx interface clock.
0047             (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
0048             (+++) Configure the DMA Tx/Rx Stream.
0049             (+++) Associate the initialized DMA handle to the SAI DMA Tx/Rx handle.
0050             (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
0051                 DMA Tx/Rx Stream.
0052 
0053     (#) The initialization can be done by two ways
0054         (##) Expert mode : Initialize the structures Init, FrameInit and SlotInit and call HAL_SAI_Init().
0055         (##) Simplified mode : Initialize the high part of Init Structure and call HAL_SAI_InitProtocol().
0056 
0057   [..]
0058     (@) The specific SAI interrupts (FIFO request and Overrun underrun interrupt)
0059         will be managed using the macros __HAL_SAI_ENABLE_IT() and __HAL_SAI_DISABLE_IT()
0060         inside the transmit and receive process.
0061   [..]
0062     (@) Make sure that either:
0063         (+@) PLLSAI1CLK output is configured or
0064         (+@) PLLSAI2CLK output is configured or
0065         (+@) PLLSAI3CLK output is configured or
0066         (+@) PLLSAI4ACLK output is configured or
0067         (+@) PLLSAI4BCLK output is configured or
0068         (+@) External clock source is configured after setting correctly
0069              the define constant EXTERNAL_CLOCK_VALUE in the stm32h7xx_hal_conf.h file.
0070 
0071   [..]
0072     (@) In master Tx mode: enabling the audio block immediately generates the bit clock
0073         for the external slaves even if there is no data in the FIFO, However FS signal
0074         generation is conditioned by the presence of data in the FIFO.
0075 
0076   [..]
0077     (@) In master Rx mode: enabling the audio block immediately generates the bit clock
0078         and FS signal for the external slaves.
0079 
0080   [..]
0081     (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
0082         (+@) First bit Offset <= (SLOT size - Data size)
0083         (+@) Data size <= SLOT size
0084         (+@) Number of SLOT x SLOT size = Frame length
0085         (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
0086 
0087   [..]
0088     (@) PDM interface can be activated through HAL_SAI_Init function.
0089         Please note that PDM interface is only available for SAI1 or SAI4 sub-block A.
0090         PDM microphone delays can be tuned with HAL_SAIEx_ConfigPdmMicDelay function.
0091 
0092   [..]
0093     Three operation modes are available within this driver :
0094 
0095     *** Polling mode IO operation ***
0096     =================================
0097     [..]
0098       (+) Send an amount of data in blocking mode using HAL_SAI_Transmit()
0099       (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
0100 
0101     *** Interrupt mode IO operation ***
0102     ===================================
0103     [..]
0104       (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT()
0105       (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
0106           add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
0107       (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT()
0108       (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
0109           add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
0110       (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
0111           add his own code by customization of function pointer HAL_SAI_ErrorCallback()
0112 
0113     *** DMA mode IO operation ***
0114     =============================
0115     [..]
0116       (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA()
0117       (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
0118           add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
0119       (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA()
0120       (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
0121           add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
0122       (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
0123           add his own code by customization of function pointer HAL_SAI_ErrorCallback()
0124       (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
0125       (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
0126       (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
0127 
0128     *** SAI HAL driver additional function list ***
0129     ===============================================
0130     [..]
0131       Below the list the others API available SAI HAL driver :
0132 
0133       (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode
0134       (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode
0135       (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode
0136       (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode
0137       (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo.
0138       (+) HAL_SAI_Abort(): Abort the current transfer
0139 
0140     *** SAI HAL driver macros list ***
0141     ==================================
0142     [..]
0143       Below the list of most used macros in SAI HAL driver :
0144 
0145       (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral
0146       (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral
0147       (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts
0148       (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts
0149       (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is
0150           enabled or disabled
0151       (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
0152 
0153     *** Callback registration ***
0154     =============================
0155     [..]
0156     The compilation define USE_HAL_SAI_REGISTER_CALLBACKS when set to 1
0157     allows the user to configure dynamically the driver callbacks.
0158     Use functions HAL_SAI_RegisterCallback() to register a user callback.
0159 
0160     [..]
0161     Function HAL_SAI_RegisterCallback() allows to register following callbacks:
0162       (+) RxCpltCallback     : SAI receive complete.
0163       (+) RxHalfCpltCallback : SAI receive half complete.
0164       (+) TxCpltCallback     : SAI transmit complete.
0165       (+) TxHalfCpltCallback : SAI transmit half complete.
0166       (+) ErrorCallback      : SAI error.
0167       (+) MspInitCallback    : SAI MspInit.
0168       (+) MspDeInitCallback  : SAI MspDeInit.
0169     [..]
0170     This function takes as parameters the HAL peripheral handle, the callback ID
0171     and a pointer to the user callback function.
0172 
0173     [..]
0174     Use function HAL_SAI_UnRegisterCallback() to reset a callback to the default
0175     weak function.
0176     HAL_SAI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
0177     and the callback ID.
0178     [..]
0179     This function allows to reset following callbacks:
0180       (+) RxCpltCallback     : SAI receive complete.
0181       (+) RxHalfCpltCallback : SAI receive half complete.
0182       (+) TxCpltCallback     : SAI transmit complete.
0183       (+) TxHalfCpltCallback : SAI transmit half complete.
0184       (+) ErrorCallback      : SAI error.
0185       (+) MspInitCallback    : SAI MspInit.
0186       (+) MspDeInitCallback  : SAI MspDeInit.
0187 
0188     [..]
0189     By default, after the HAL_SAI_Init and if the state is HAL_SAI_STATE_RESET
0190     all callbacks are reset to the corresponding legacy weak functions:
0191     examples HAL_SAI_RxCpltCallback(), HAL_SAI_ErrorCallback().
0192     Exception done for MspInit and MspDeInit callbacks that are respectively
0193     reset to the legacy weak functions in the HAL_SAI_Init
0194     and HAL_SAI_DeInit only when these callbacks are null (not registered beforehand).
0195     If not, MspInit or MspDeInit are not null, the HAL_SAI_Init and HAL_SAI_DeInit
0196     keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
0197 
0198     [..]
0199     Callbacks can be registered/unregistered in READY state only.
0200     Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
0201     in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
0202     during the Init/DeInit.
0203     In that case first register the MspInit/MspDeInit user callbacks
0204     using HAL_SAI_RegisterCallback before calling HAL_SAI_DeInit
0205     or HAL_SAI_Init function.
0206 
0207     [..]
0208     When the compilation define USE_HAL_SAI_REGISTER_CALLBACKS is set to 0 or
0209     not defined, the callback registering feature is not available
0210     and weak callbacks are used.
0211 
0212   @endverbatim
0213   */
0214 
0215 /* Includes ------------------------------------------------------------------*/
0216 #include "stm32h7xx_hal.h"
0217 
0218 /** @addtogroup STM32H7xx_HAL_Driver
0219   * @{
0220   */
0221 
0222 /** @defgroup SAI SAI
0223   * @ingroup RTEMSBSPsARMSTM32H7
0224   * @brief SAI HAL module driver
0225   * @{
0226   */
0227 
0228 #ifdef HAL_SAI_MODULE_ENABLED
0229 
0230 /* Private typedef -----------------------------------------------------------*/
0231 /** @defgroup SAI_Private_Typedefs  SAI Private Typedefs
0232   * @ingroup RTEMSBSPsARMSTM32H7
0233   * @{
0234   */
0235 typedef enum
0236 {
0237   SAI_MODE_DMA,
0238   SAI_MODE_IT
0239 } SAI_ModeTypedef;
0240 /**
0241   * @}
0242   */
0243 
0244 /* Private define ------------------------------------------------------------*/
0245 /** @defgroup SAI_Private_Constants  SAI Private Constants
0246   * @ingroup RTEMSBSPsARMSTM32H7
0247   * @{
0248   */
0249 #define SAI_DEFAULT_TIMEOUT      4U
0250 #define SAI_LONG_TIMEOUT         1000U
0251 #define SAI_SPDIF_FRAME_LENGTH   64U
0252 #define SAI_AC97_FRAME_LENGTH    256U
0253 /**
0254   * @}
0255   */
0256 
0257 /* Private macro -------------------------------------------------------------*/
0258 /* Private variables ---------------------------------------------------------*/
0259 /* Private function prototypes -----------------------------------------------*/
0260 /** @defgroup SAI_Private_Functions  SAI Private Functions
0261   * @ingroup RTEMSBSPsARMSTM32H7
0262   * @{
0263   */
0264 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
0265 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode);
0266 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
0267 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
0268 
0269 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
0270 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
0271 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
0272 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
0273 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
0274 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
0275 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
0276 
0277 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
0278 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
0279 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
0280 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
0281 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
0282 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
0283 /**
0284   * @}
0285   */
0286 
0287 /* Exported functions ---------------------------------------------------------*/
0288 /** @defgroup SAI_Exported_Functions SAI Exported Functions
0289   * @ingroup RTEMSBSPsARMSTM32H7
0290   * @{
0291   */
0292 
0293 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
0294   * @ingroup RTEMSBSPsARMSTM32H7
0295   * @brief    Initialization and Configuration functions
0296   *
0297 @verbatim
0298  ===============================================================================
0299              ##### Initialization and de-initialization functions #####
0300  ===============================================================================
0301   [..]  This subsection provides a set of functions allowing to initialize and
0302         de-initialize the SAIx peripheral:
0303 
0304       (+) User must implement HAL_SAI_MspInit() function in which he configures
0305           all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
0306 
0307       (+) Call the function HAL_SAI_Init() to configure the selected device with
0308           the selected configuration:
0309         (++) Mode (Master/slave TX/RX)
0310         (++) Protocol
0311         (++) Data Size
0312         (++) MCLK Output
0313         (++) Audio frequency
0314         (++) FIFO Threshold
0315         (++) Frame Config
0316         (++) Slot Config
0317         (++) PDM Config
0318 
0319       (+) Call the function HAL_SAI_DeInit() to restore the default configuration
0320           of the selected SAI peripheral.
0321 
0322 @endverbatim
0323   * @{
0324   */
0325 
0326 /**
0327   * @brief  Initialize the structure FrameInit, SlotInit and the low part of
0328   *         Init according to the specified parameters and call the function
0329   *         HAL_SAI_Init to initialize the SAI block.
0330   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
0331   *              the configuration information for SAI module.
0332   * @param  protocol one of the supported protocol @ref SAI_Protocol
0333   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
0334   *                   the configuration information for SAI module.
0335   * @param  nbslot Number of slot.
0336   * @retval HAL status
0337   */
0338 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
0339 {
0340   HAL_StatusTypeDef status;
0341 
0342   /* Check the parameters */
0343   assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
0344   assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
0345 
0346   switch (protocol)
0347   {
0348     case SAI_I2S_STANDARD :
0349     case SAI_I2S_MSBJUSTIFIED :
0350     case SAI_I2S_LSBJUSTIFIED :
0351       status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
0352       break;
0353     case SAI_PCM_LONG :
0354     case SAI_PCM_SHORT :
0355       status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
0356       break;
0357     default :
0358       status = HAL_ERROR;
0359       break;
0360   }
0361 
0362   if (status == HAL_OK)
0363   {
0364     status = HAL_SAI_Init(hsai);
0365   }
0366 
0367   return status;
0368 }
0369 
0370 /**
0371   * @brief  Initialize the SAI according to the specified parameters.
0372   *         in the SAI_InitTypeDef structure and initialize the associated handle.
0373   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
0374   *              the configuration information for SAI module.
0375   * @retval HAL status
0376   */
0377 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
0378 {
0379   uint32_t tmpregisterGCR;
0380   uint32_t ckstr_bits;
0381   uint32_t syncen_bits;
0382   SAI_TypeDef *SaiBaseAddress;
0383 
0384   /* Check the SAI handle allocation */
0385   if (hsai == NULL)
0386   {
0387     return HAL_ERROR;
0388   }
0389 
0390   /* check the instance */
0391   assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
0392 
0393   /* Check the SAI Block parameters */
0394   assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
0395   assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
0396   assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
0397   assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
0398   assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
0399   assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
0400   assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
0401 #if defined(SAI_VER_V2_X)
0402   /* SAI Peripheral version depends on STM32H7 device revision ID */
0403   if (HAL_GetREVID() >= REV_ID_B) /* STM32H7xx Rev.B and above */
0404   {
0405     assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai->Init.MckOutput));
0406   }
0407 #else /* SAI_VER_V2_1 */
0408   assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai->Init.MckOutput));
0409 #endif /* SAI_VER_V2_X */
0410   assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
0411   assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
0412   assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
0413   assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
0414   assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
0415   assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
0416   assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
0417   assert_param(IS_SAI_BLOCK_MCK_OVERSAMPLING(hsai->Init.MckOverSampling));
0418 
0419   /* Check the SAI Block Frame parameters */
0420   assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
0421   assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
0422   assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
0423   assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
0424   assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
0425 
0426   /* Check the SAI Block Slot parameters */
0427   assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
0428   assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
0429   assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
0430   assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
0431 
0432   /* Check the SAI PDM parameters */
0433   assert_param(IS_FUNCTIONAL_STATE(hsai->Init.PdmInit.Activation));
0434   if (hsai->Init.PdmInit.Activation == ENABLE)
0435   {
0436     assert_param(IS_SAI_PDM_MIC_PAIRS_NUMBER(hsai->Init.PdmInit.MicPairsNbr));
0437     assert_param(IS_SAI_PDM_CLOCK_ENABLE(hsai->Init.PdmInit.ClockEnable));
0438     /* Check that SAI sub-block is SAI1 or SAI4 sub-block A, in master RX mode with free protocol */
0439 #if defined(SAI4)
0440     if (((hsai->Instance != SAI1_Block_A) && (hsai->Instance != SAI4_Block_A)) ||
0441          (hsai->Init.AudioMode != SAI_MODEMASTER_RX) ||
0442          (hsai->Init.Protocol != SAI_FREE_PROTOCOL))
0443     {
0444       return HAL_ERROR;
0445     }
0446 #else
0447     if ((hsai->Instance != SAI1_Block_A) ||
0448         (hsai->Init.AudioMode != SAI_MODEMASTER_RX) ||
0449         (hsai->Init.Protocol != SAI_FREE_PROTOCOL))
0450     {
0451       return HAL_ERROR;
0452     }
0453 #endif /* SAI4 */
0454   }
0455 
0456   /* Get the SAI base address according to the SAI handle */
0457   if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
0458   {
0459     SaiBaseAddress = SAI1;
0460   }
0461 #if defined(SAI2)
0462   else if ((hsai->Instance == SAI2_Block_A) || (hsai->Instance == SAI2_Block_B))
0463   {
0464     SaiBaseAddress = SAI2;
0465   }
0466 #endif /* SAI2 */
0467 #if defined(SAI3)
0468   else if ((hsai->Instance == SAI3_Block_A) || (hsai->Instance == SAI3_Block_B))
0469   {
0470     SaiBaseAddress = SAI3;
0471   }
0472 #endif /* SAI3 */
0473 #if defined(SAI4)
0474   else if ((hsai->Instance == SAI4_Block_A) || (hsai->Instance == SAI4_Block_B))
0475   {
0476     SaiBaseAddress = SAI4;
0477   }
0478 #endif /* SAI4 */
0479   else
0480   {
0481     return HAL_ERROR;
0482   }
0483 
0484   if (hsai->State == HAL_SAI_STATE_RESET)
0485   {
0486     /* Allocate lock resource and initialize it */
0487     hsai->Lock = HAL_UNLOCKED;
0488 
0489 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
0490     /* Reset callback pointers to the weak predefined callbacks */
0491     hsai->RxCpltCallback     = HAL_SAI_RxCpltCallback;
0492     hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
0493     hsai->TxCpltCallback     = HAL_SAI_TxCpltCallback;
0494     hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
0495     hsai->ErrorCallback      = HAL_SAI_ErrorCallback;
0496 
0497     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
0498     if (hsai->MspInitCallback == NULL)
0499     {
0500       hsai->MspInitCallback = HAL_SAI_MspInit;
0501     }
0502     hsai->MspInitCallback(hsai);
0503 #else
0504     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
0505     HAL_SAI_MspInit(hsai);
0506 #endif
0507   }
0508 
0509   /* Disable the selected SAI peripheral */
0510   if(SAI_Disable(hsai) != HAL_OK)
0511   {
0512     return HAL_ERROR;
0513   }
0514 
0515   hsai->State = HAL_SAI_STATE_BUSY;
0516 
0517   /* SAI Block Synchro Configuration -----------------------------------------*/
0518   /* This setting must be done with both audio block (A & B) disabled         */
0519   switch (hsai->Init.SynchroExt)
0520   {
0521     case SAI_SYNCEXT_DISABLE :
0522       tmpregisterGCR = 0;
0523       break;
0524     case SAI_SYNCEXT_OUTBLOCKA_ENABLE :
0525       tmpregisterGCR = SAI_GCR_SYNCOUT_0;
0526       break;
0527     case SAI_SYNCEXT_OUTBLOCKB_ENABLE :
0528       tmpregisterGCR = SAI_GCR_SYNCOUT_1;
0529       break;
0530     default:
0531       tmpregisterGCR = 0;
0532       break;
0533   }
0534 
0535   switch (hsai->Init.Synchro)
0536   {
0537     case SAI_ASYNCHRONOUS :
0538       syncen_bits = 0;
0539       break;
0540     case SAI_SYNCHRONOUS :
0541       syncen_bits = SAI_xCR1_SYNCEN_0;
0542       break;
0543     case SAI_SYNCHRONOUS_EXT_SAI1 :
0544       syncen_bits = SAI_xCR1_SYNCEN_1;
0545       break;
0546 #if defined(SAI2)
0547     case SAI_SYNCHRONOUS_EXT_SAI2 :
0548       syncen_bits = SAI_xCR1_SYNCEN_1;
0549       tmpregisterGCR |= SAI_GCR_SYNCIN_0;
0550       break;
0551 #endif /* SAI2 */
0552 #if defined(SAI3)
0553     case SAI_SYNCHRONOUS_EXT_SAI3 :
0554       syncen_bits = SAI_xCR1_SYNCEN_1;
0555       tmpregisterGCR |= SAI_GCR_SYNCIN_1;
0556       break;
0557 #endif /* SAI3 */
0558 #if defined(SAI4)
0559     case SAI_SYNCHRONOUS_EXT_SAI4 :
0560       syncen_bits = SAI_xCR1_SYNCEN_1;
0561       tmpregisterGCR |= (SAI_GCR_SYNCIN_1 | SAI_GCR_SYNCIN_0);
0562       break;
0563 #endif /* SAI4 */
0564     default:
0565       syncen_bits = 0;
0566       break;
0567   }
0568 
0569   /* Set the SAI Block Synchro Configuration */
0570   SaiBaseAddress->GCR = tmpregisterGCR;
0571 
0572   if (hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
0573   {
0574     uint32_t freq = 0;
0575     uint32_t tmpval;
0576 
0577     /* In this case, the MCKDIV value is calculated to get AudioFrequency */
0578     if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
0579     {
0580       freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1);
0581     }
0582 
0583 #if defined(SAI2)
0584 #if defined(RCC_PERIPHCLK_SAI2)
0585     if ((hsai->Instance == SAI2_Block_A) || (hsai->Instance == SAI2_Block_B))
0586     {
0587       freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2);
0588     }
0589 #else
0590     if (hsai->Instance == SAI2_Block_A)
0591     {
0592       freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2A);
0593     }
0594     if (hsai->Instance == SAI2_Block_B)
0595     {
0596       freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2B);
0597     }
0598 #endif /* RCC_PERIPHCLK_SAI2 */
0599 #endif /* SAI2 */
0600 
0601 #if defined(SAI3)
0602     if ((hsai->Instance == SAI3_Block_A) || (hsai->Instance == SAI3_Block_B))
0603     {
0604       freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI3);
0605     }
0606 #endif /* SAI3 */
0607 #if defined(SAI4)
0608     if (hsai->Instance == SAI4_Block_A)
0609     {
0610       freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4A);
0611     }
0612     if (hsai->Instance == SAI4_Block_B)
0613     {
0614       freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4B);
0615     }
0616 #endif /* SAI4 */
0617 
0618     /* Configure Master Clock Divider using the following formula :
0619        - If NODIV = 1 :
0620          MCKDIV[5:0] = SAI_CK_x / (FS * (FRL + 1))
0621        - If NODIV = 0 :
0622          MCKDIV[5:0] = SAI_CK_x / (FS * (OSR + 1) * 256) */
0623     if (hsai->Init.NoDivider == SAI_MASTERDIVIDER_DISABLE)
0624     {
0625       /* NODIV = 1 */
0626       uint32_t tmpframelength;
0627 
0628       if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
0629       {
0630         /* For SPDIF protocol, frame length is set by hardware to 64 */
0631         tmpframelength = SAI_SPDIF_FRAME_LENGTH;
0632       }
0633       else if (hsai->Init.Protocol == SAI_AC97_PROTOCOL)
0634       {
0635         /* For AC97 protocol, frame length is set by hardware to 256 */
0636         tmpframelength = SAI_AC97_FRAME_LENGTH;
0637       }
0638       else
0639       {
0640         /* For free protocol, frame length is set by user */
0641         tmpframelength = hsai->FrameInit.FrameLength;
0642       }
0643 
0644       /* (freq x 10) to keep Significant digits */
0645       tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmpframelength);
0646     }
0647     else
0648     {
0649       /* NODIV = 0 */
0650       uint32_t tmposr;
0651       tmposr = (hsai->Init.MckOverSampling == SAI_MCK_OVERSAMPLING_ENABLE) ? 2U : 1U;
0652       /* (freq x 10) to keep Significant digits */
0653       tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmposr * 256U);
0654     }
0655     hsai->Init.Mckdiv = tmpval / 10U;
0656 
0657     /* Round result to the nearest integer */
0658     if ((tmpval % 10U) > 8U)
0659     {
0660       hsai->Init.Mckdiv += 1U;
0661     }
0662 
0663     /* For SPDIF protocol, SAI shall provide a bit clock twice faster the symbol-rate */
0664     if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
0665     {
0666       hsai->Init.Mckdiv = hsai->Init.Mckdiv >> 1;
0667     }
0668   }
0669 
0670   /* Check the SAI Block master clock divider parameter */
0671   assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(hsai->Init.Mckdiv));
0672 
0673   /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */
0674   if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
0675   {
0676     /* Transmit */
0677     ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR;
0678   }
0679   else
0680   {
0681     /* Receive */
0682     ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U;
0683   }
0684 
0685   /* SAI Block Configuration -------------------------------------------------*/
0686   /* SAI CR1 Configuration */
0687 #if defined(SAI_VER_V2_X) /* SAI Peripheral version depends on STM32H7 device revision ID */
0688 
0689   if (HAL_GetREVID() >= REV_ID_B) /* STM32H7xx Rev.B and above */
0690   {
0691     hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG |  SAI_xCR1_DS |      \
0692                              SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
0693                              SAI_xCR1_MONO | SAI_xCR1_OUTDRIV  | SAI_xCR1_DMAEN |  \
0694                              SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR |     \
0695                              SAI_xCR1_MCKEN);
0696 
0697     hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol |           \
0698                             hsai->Init.DataSize | hsai->Init.FirstBit  |           \
0699                             ckstr_bits | syncen_bits |                             \
0700                             hsai->Init.MonoStereoMode | hsai->Init.OutputDrive |   \
0701                             hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) |     \
0702                             hsai->Init.MckOverSampling | hsai->Init.MckOutput);
0703   }
0704   else /* STM32H7xx Rev.Y */
0705   {
0706     hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG |  SAI_xCR1_DS |      \
0707                              SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
0708                              SAI_xCR1_MONO | SAI_xCR1_OUTDRIV  | SAI_xCR1_DMAEN |  \
0709                              SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR);
0710 
0711     hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol |           \
0712                             hsai->Init.DataSize | hsai->Init.FirstBit  |           \
0713                             ckstr_bits | syncen_bits |                             \
0714                             hsai->Init.MonoStereoMode | hsai->Init.OutputDrive |   \
0715                             hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) |     \
0716                             hsai->Init.MckOverSampling);
0717   }
0718 #else /* SAI_VER_V2_1*/
0719   hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG |  SAI_xCR1_DS |      \
0720                            SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
0721                            SAI_xCR1_MONO | SAI_xCR1_OUTDRIV  | SAI_xCR1_DMAEN |  \
0722                            SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR |     \
0723                            SAI_xCR1_MCKEN);
0724 
0725   hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol |           \
0726                           hsai->Init.DataSize | hsai->Init.FirstBit  |           \
0727                           ckstr_bits | syncen_bits |                             \
0728                           hsai->Init.MonoStereoMode | hsai->Init.OutputDrive |   \
0729                           hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) |     \
0730                           hsai->Init.MckOverSampling | hsai->Init.MckOutput);
0731 #endif /* SAI_VER_V2_X */
0732 
0733   /* SAI CR2 Configuration */
0734   hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
0735   hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
0736 
0737   /* SAI Frame Configuration -----------------------------------------*/
0738   hsai->Instance->FRCR &= (~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
0739                              SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
0740   hsai->Instance->FRCR |= ((hsai->FrameInit.FrameLength - 1U) |
0741                            hsai->FrameInit.FSOffset |
0742                            hsai->FrameInit.FSDefinition |
0743                            hsai->FrameInit.FSPolarity   |
0744                            ((hsai->FrameInit.ActiveFrameLength - 1U) << 8));
0745 
0746   /* SAI Block_x SLOT Configuration ------------------------------------------*/
0747   /* This register has no meaning in AC 97 and SPDIF audio protocol */
0748   hsai->Instance->SLOTR &= (~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ |  \
0749                               SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN));
0750 
0751   hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \
0752                            (hsai->SlotInit.SlotActive << 16) | ((hsai->SlotInit.SlotNumber - 1U) <<  8);
0753 
0754   /* SAI PDM Configuration ---------------------------------------------------*/
0755 #if defined(SAI4)
0756   if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI4_Block_A))
0757 #else
0758   if (hsai->Instance == SAI1_Block_A)
0759 #endif /* SAI4 */
0760   {
0761     /* Disable PDM interface */
0762     SaiBaseAddress->PDMCR &= ~(SAI_PDMCR_PDMEN);
0763     if (hsai->Init.PdmInit.Activation == ENABLE)
0764     {
0765       /* Configure and enable PDM interface */
0766       SaiBaseAddress->PDMCR = (hsai->Init.PdmInit.ClockEnable |
0767                                ((hsai->Init.PdmInit.MicPairsNbr - 1U) << SAI_PDMCR_MICNBR_Pos));
0768       SaiBaseAddress->PDMCR |= SAI_PDMCR_PDMEN;
0769     }
0770   }
0771 
0772   /* Initialize the error code */
0773   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
0774 
0775   /* Initialize the SAI state */
0776   hsai->State = HAL_SAI_STATE_READY;
0777 
0778   /* Release Lock */
0779   __HAL_UNLOCK(hsai);
0780 
0781   return HAL_OK;
0782 }
0783 
0784 /**
0785   * @brief  DeInitialize the SAI peripheral.
0786   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
0787   *              the configuration information for SAI module.
0788   * @retval HAL status
0789   */
0790 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
0791 {
0792   SAI_TypeDef *SaiBaseAddress;
0793 
0794   /* Check the SAI handle allocation */
0795   if (hsai == NULL)
0796   {
0797     return HAL_ERROR;
0798   }
0799 
0800   hsai->State = HAL_SAI_STATE_BUSY;
0801 
0802   /* Disabled All interrupt and clear all the flag */
0803   hsai->Instance->IMR = 0;
0804   hsai->Instance->CLRFR = 0xFFFFFFFFU;
0805 
0806   /* Disable the SAI */
0807   if (SAI_Disable(hsai) != HAL_OK)
0808   {
0809     /* Reset SAI state to ready */
0810     hsai->State = HAL_SAI_STATE_READY;
0811 
0812     /* Release Lock */
0813     __HAL_UNLOCK(hsai);
0814 
0815     return HAL_ERROR;
0816   }
0817 
0818   /* Flush the fifo */
0819   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
0820 
0821   /* Disable SAI PDM interface */
0822 #if defined(SAI4)
0823   if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI4_Block_A))
0824 #else
0825   if (hsai->Instance == SAI1_Block_A)
0826 #endif /* SAI4 */
0827   {
0828     /* Get the SAI base address according to the SAI handle */
0829 #if defined(SAI4)
0830     SaiBaseAddress = (hsai->Instance == SAI1_Block_A) ? SAI1 : SAI4;
0831 #else
0832     SaiBaseAddress = SAI1;
0833 #endif /* SAI4 */
0834 
0835     /* Reset PDM delays */
0836     SaiBaseAddress->PDMDLY = 0U;
0837 
0838     /* Disable PDM interface */
0839     SaiBaseAddress->PDMCR &= ~(SAI_PDMCR_PDMEN);
0840   }
0841 
0842   /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
0843 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
0844   if (hsai->MspDeInitCallback == NULL)
0845   {
0846     hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
0847   }
0848   hsai->MspDeInitCallback(hsai);
0849 #else
0850   HAL_SAI_MspDeInit(hsai);
0851 #endif
0852 
0853   /* Initialize the error code */
0854   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
0855 
0856   /* Initialize the SAI state */
0857   hsai->State = HAL_SAI_STATE_RESET;
0858 
0859   /* Release Lock */
0860   __HAL_UNLOCK(hsai);
0861 
0862   return HAL_OK;
0863 }
0864 
0865 /**
0866   * @brief Initialize the SAI MSP.
0867   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
0868   *              the configuration information for SAI module.
0869   * @retval None
0870   */
0871 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
0872 {
0873   /* Prevent unused argument(s) compilation warning */
0874   UNUSED(hsai);
0875 
0876   /* NOTE : This function should not be modified, when the callback is needed,
0877             the HAL_SAI_MspInit could be implemented in the user file
0878    */
0879 }
0880 
0881 /**
0882   * @brief DeInitialize the SAI MSP.
0883   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
0884   *              the configuration information for SAI module.
0885   * @retval None
0886   */
0887 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
0888 {
0889   /* Prevent unused argument(s) compilation warning */
0890   UNUSED(hsai);
0891 
0892   /* NOTE : This function should not be modified, when the callback is needed,
0893             the HAL_SAI_MspDeInit could be implemented in the user file
0894    */
0895 }
0896 
0897 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
0898 /**
0899   * @brief  Register a user SAI callback
0900   *         to be used instead of the weak predefined callback.
0901   * @param  hsai SAI handle.
0902   * @param  CallbackID ID of the callback to be registered.
0903   *         This parameter can be one of the following values:
0904   *           @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
0905   *           @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
0906   *           @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
0907   *           @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
0908   *           @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
0909   *           @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
0910   *           @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
0911   * @param  pCallback pointer to the callback function.
0912   * @retval HAL status.
0913   */
0914 HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef        *hsai,
0915                                            HAL_SAI_CallbackIDTypeDef CallbackID,
0916                                            pSAI_CallbackTypeDef      pCallback)
0917 {
0918   HAL_StatusTypeDef status = HAL_OK;
0919 
0920   if (pCallback == NULL)
0921   {
0922     /* update the error code */
0923     hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
0924     /* update return status */
0925     status = HAL_ERROR;
0926   }
0927   else
0928   {
0929     if (HAL_SAI_STATE_READY == hsai->State)
0930     {
0931       switch (CallbackID)
0932       {
0933         case HAL_SAI_RX_COMPLETE_CB_ID :
0934           hsai->RxCpltCallback = pCallback;
0935           break;
0936         case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
0937           hsai->RxHalfCpltCallback = pCallback;
0938           break;
0939         case HAL_SAI_TX_COMPLETE_CB_ID :
0940           hsai->TxCpltCallback = pCallback;
0941           break;
0942         case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
0943           hsai->TxHalfCpltCallback = pCallback;
0944           break;
0945         case HAL_SAI_ERROR_CB_ID :
0946           hsai->ErrorCallback = pCallback;
0947           break;
0948         case HAL_SAI_MSPINIT_CB_ID :
0949           hsai->MspInitCallback = pCallback;
0950           break;
0951         case HAL_SAI_MSPDEINIT_CB_ID :
0952           hsai->MspDeInitCallback = pCallback;
0953           break;
0954         default :
0955           /* update the error code */
0956           hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
0957           /* update return status */
0958           status = HAL_ERROR;
0959           break;
0960       }
0961     }
0962     else if (HAL_SAI_STATE_RESET == hsai->State)
0963     {
0964       switch (CallbackID)
0965       {
0966         case HAL_SAI_MSPINIT_CB_ID :
0967           hsai->MspInitCallback = pCallback;
0968           break;
0969         case HAL_SAI_MSPDEINIT_CB_ID :
0970           hsai->MspDeInitCallback = pCallback;
0971           break;
0972         default :
0973           /* update the error code */
0974           hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
0975           /* update return status */
0976           status = HAL_ERROR;
0977           break;
0978       }
0979     }
0980     else
0981     {
0982       /* update the error code */
0983       hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
0984       /* update return status */
0985       status = HAL_ERROR;
0986     }
0987   }
0988   return status;
0989 }
0990 
0991 /**
0992   * @brief  Unregister a user SAI callback.
0993   *         SAI callback is redirected to the weak predefined callback.
0994   * @param  hsai SAI handle.
0995   * @param  CallbackID ID of the callback to be unregistered.
0996   *         This parameter can be one of the following values:
0997   *           @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
0998   *           @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
0999   *           @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
1000   *           @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
1001   *           @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
1002   *           @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
1003   *           @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
1004   * @retval HAL status.
1005   */
1006 HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef        *hsai,
1007                                              HAL_SAI_CallbackIDTypeDef CallbackID)
1008 {
1009   HAL_StatusTypeDef status = HAL_OK;
1010 
1011   if (HAL_SAI_STATE_READY == hsai->State)
1012   {
1013     switch (CallbackID)
1014     {
1015       case HAL_SAI_RX_COMPLETE_CB_ID :
1016         hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
1017         break;
1018       case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
1019         hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
1020         break;
1021       case HAL_SAI_TX_COMPLETE_CB_ID :
1022         hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
1023         break;
1024       case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
1025         hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
1026         break;
1027       case HAL_SAI_ERROR_CB_ID :
1028         hsai->ErrorCallback = HAL_SAI_ErrorCallback;
1029         break;
1030       case HAL_SAI_MSPINIT_CB_ID :
1031         hsai->MspInitCallback = HAL_SAI_MspInit;
1032         break;
1033       case HAL_SAI_MSPDEINIT_CB_ID :
1034         hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
1035         break;
1036       default :
1037         /* update the error code */
1038         hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
1039         /* update return status */
1040         status = HAL_ERROR;
1041         break;
1042     }
1043   }
1044   else if (HAL_SAI_STATE_RESET == hsai->State)
1045   {
1046     switch (CallbackID)
1047     {
1048       case HAL_SAI_MSPINIT_CB_ID :
1049         hsai->MspInitCallback = HAL_SAI_MspInit;
1050         break;
1051       case HAL_SAI_MSPDEINIT_CB_ID :
1052         hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
1053         break;
1054       default :
1055         /* update the error code */
1056         hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
1057         /* update return status */
1058         status = HAL_ERROR;
1059         break;
1060     }
1061   }
1062   else
1063   {
1064     /* update the error code */
1065     hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
1066     /* update return status */
1067     status = HAL_ERROR;
1068   }
1069   return status;
1070 }
1071 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1072 
1073 /**
1074   * @}
1075   */
1076 
1077 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
1078   * @ingroup RTEMSBSPsARMSTM32H7
1079   * @brief    Data transfers functions
1080   *
1081 @verbatim
1082   ==============================================================================
1083                       ##### IO operation functions #####
1084   ==============================================================================
1085   [..]
1086     This subsection provides a set of functions allowing to manage the SAI data
1087     transfers.
1088 
1089     (+) There are two modes of transfer:
1090       (++) Blocking mode : The communication is performed in the polling mode.
1091            The status of all data processing is returned by the same function
1092            after finishing transfer.
1093       (++) No-Blocking mode : The communication is performed using Interrupts
1094            or DMA. These functions return the status of the transfer startup.
1095            The end of the data processing will be indicated through the
1096            dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
1097            using DMA mode.
1098 
1099     (+) Blocking mode functions are :
1100       (++) HAL_SAI_Transmit()
1101       (++) HAL_SAI_Receive()
1102 
1103     (+) Non Blocking mode functions with Interrupt are :
1104       (++) HAL_SAI_Transmit_IT()
1105       (++) HAL_SAI_Receive_IT()
1106 
1107     (+) Non Blocking mode functions with DMA are :
1108       (++) HAL_SAI_Transmit_DMA()
1109       (++) HAL_SAI_Receive_DMA()
1110 
1111     (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
1112       (++) HAL_SAI_TxCpltCallback()
1113       (++) HAL_SAI_RxCpltCallback()
1114       (++) HAL_SAI_ErrorCallback()
1115 
1116 @endverbatim
1117   * @{
1118   */
1119 
1120 /**
1121   * @brief  Transmit an amount of data in blocking mode.
1122   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1123   *              the configuration information for SAI module.
1124   * @param  pData Pointer to data buffer
1125   * @param  Size Amount of data to be sent
1126   * @param  Timeout Timeout duration
1127   * @retval HAL status
1128   */
1129 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
1130 {
1131   uint32_t tickstart = HAL_GetTick();
1132   uint32_t temp;
1133 
1134   if ((pData == NULL) || (Size == 0U))
1135   {
1136     return  HAL_ERROR;
1137   }
1138 
1139   if (hsai->State == HAL_SAI_STATE_READY)
1140   {
1141     /* Process Locked */
1142     __HAL_LOCK(hsai);
1143 
1144     hsai->XferSize = Size;
1145     hsai->XferCount = Size;
1146     hsai->pBuffPtr = pData;
1147     hsai->State = HAL_SAI_STATE_BUSY_TX;
1148     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1149 
1150     /* Check if the SAI is already enabled */
1151     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1152     {
1153       /* fill the fifo with data before to enabled the SAI */
1154       SAI_FillFifo(hsai);
1155       /* Enable SAI peripheral */
1156       __HAL_SAI_ENABLE(hsai);
1157     }
1158 
1159     while (hsai->XferCount > 0U)
1160     {
1161       /* Write data if the FIFO is not full */
1162       if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
1163       {
1164         if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1165         {
1166           hsai->Instance->DR = *hsai->pBuffPtr;
1167           hsai->pBuffPtr++;
1168         }
1169         else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1170         {
1171           temp = (uint32_t)(*hsai->pBuffPtr);
1172           hsai->pBuffPtr++;
1173           temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
1174           hsai->pBuffPtr++;
1175           hsai->Instance->DR = temp;
1176         }
1177         else
1178         {
1179           temp = (uint32_t)(*hsai->pBuffPtr);
1180           hsai->pBuffPtr++;
1181           temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
1182           hsai->pBuffPtr++;
1183           temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
1184           hsai->pBuffPtr++;
1185           temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
1186           hsai->pBuffPtr++;
1187           hsai->Instance->DR = temp;
1188         }
1189         hsai->XferCount--;
1190       }
1191       else
1192       {
1193         /* Check for the Timeout */
1194         if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
1195         {
1196           /* Update error code */
1197           hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1198 
1199           /* Clear all the flags */
1200           hsai->Instance->CLRFR = 0xFFFFFFFFU;
1201 
1202           /* Disable SAI peripheral */
1203           /* No need to check return value because state update, unlock and error return will be performed later */
1204           (void) SAI_Disable(hsai);
1205 
1206           /* Flush the fifo */
1207           SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1208 
1209           /* Change the SAI state */
1210           hsai->State = HAL_SAI_STATE_READY;
1211 
1212           /* Process Unlocked */
1213           __HAL_UNLOCK(hsai);
1214 
1215           return HAL_ERROR;
1216         }
1217       }
1218     }
1219 
1220     hsai->State = HAL_SAI_STATE_READY;
1221 
1222     /* Process Unlocked */
1223     __HAL_UNLOCK(hsai);
1224 
1225     return HAL_OK;
1226   }
1227   else
1228   {
1229     return HAL_BUSY;
1230   }
1231 }
1232 
1233 /**
1234   * @brief  Receive an amount of data in blocking mode.
1235   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1236   *              the configuration information for SAI module.
1237   * @param  pData Pointer to data buffer
1238   * @param  Size Amount of data to be received
1239   * @param  Timeout Timeout duration
1240   * @retval HAL status
1241   */
1242 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
1243 {
1244   uint32_t tickstart = HAL_GetTick();
1245   uint32_t temp;
1246 
1247   if ((pData == NULL) || (Size == 0U))
1248   {
1249     return  HAL_ERROR;
1250   }
1251 
1252   if (hsai->State == HAL_SAI_STATE_READY)
1253   {
1254     /* Process Locked */
1255     __HAL_LOCK(hsai);
1256 
1257     hsai->pBuffPtr = pData;
1258     hsai->XferSize = Size;
1259     hsai->XferCount = Size;
1260     hsai->State = HAL_SAI_STATE_BUSY_RX;
1261     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1262 
1263     /* Check if the SAI is already enabled */
1264     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1265     {
1266       /* Enable SAI peripheral */
1267       __HAL_SAI_ENABLE(hsai);
1268     }
1269 
1270     /* Receive data */
1271     while (hsai->XferCount > 0U)
1272     {
1273       if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
1274       {
1275         if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1276         {
1277           *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
1278           hsai->pBuffPtr++;
1279         }
1280         else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1281         {
1282           temp = hsai->Instance->DR;
1283           *hsai->pBuffPtr = (uint8_t)temp;
1284           hsai->pBuffPtr++;
1285           *hsai->pBuffPtr = (uint8_t)(temp >> 8);
1286           hsai->pBuffPtr++;
1287         }
1288         else
1289         {
1290           temp = hsai->Instance->DR;
1291           *hsai->pBuffPtr = (uint8_t)temp;
1292           hsai->pBuffPtr++;
1293           *hsai->pBuffPtr = (uint8_t)(temp >> 8);
1294           hsai->pBuffPtr++;
1295           *hsai->pBuffPtr = (uint8_t)(temp >> 16);
1296           hsai->pBuffPtr++;
1297           *hsai->pBuffPtr = (uint8_t)(temp >> 24);
1298           hsai->pBuffPtr++;
1299         }
1300         hsai->XferCount--;
1301       }
1302       else
1303       {
1304         /* Check for the Timeout */
1305         if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
1306         {
1307           /* Update error code */
1308           hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1309 
1310           /* Clear all the flags */
1311           hsai->Instance->CLRFR = 0xFFFFFFFFU;
1312 
1313           /* Disable SAI peripheral */
1314           /* No need to check return value because state update, unlock and error return will be performed later */
1315           (void) SAI_Disable(hsai);
1316 
1317           /* Flush the fifo */
1318           SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1319 
1320           /* Change the SAI state */
1321           hsai->State = HAL_SAI_STATE_READY;
1322 
1323           /* Process Unlocked */
1324           __HAL_UNLOCK(hsai);
1325 
1326           return HAL_ERROR;
1327         }
1328       }
1329     }
1330 
1331     hsai->State = HAL_SAI_STATE_READY;
1332 
1333     /* Process Unlocked */
1334     __HAL_UNLOCK(hsai);
1335 
1336     return HAL_OK;
1337   }
1338   else
1339   {
1340     return HAL_BUSY;
1341   }
1342 }
1343 
1344 /**
1345   * @brief  Transmit an amount of data in non-blocking mode with Interrupt.
1346   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1347   *              the configuration information for SAI module.
1348   * @param  pData Pointer to data buffer
1349   * @param  Size Amount of data to be sent
1350   * @retval HAL status
1351   */
1352 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1353 {
1354   if ((pData == NULL) || (Size == 0U))
1355   {
1356     return  HAL_ERROR;
1357   }
1358 
1359   if (hsai->State == HAL_SAI_STATE_READY)
1360   {
1361     /* Process Locked */
1362     __HAL_LOCK(hsai);
1363 
1364     hsai->pBuffPtr = pData;
1365     hsai->XferSize = Size;
1366     hsai->XferCount = Size;
1367     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1368     hsai->State = HAL_SAI_STATE_BUSY_TX;
1369 
1370     if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1371     {
1372       hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
1373     }
1374     else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1375     {
1376       hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
1377     }
1378     else
1379     {
1380       hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
1381     }
1382 
1383     /* Fill the fifo before starting the communication */
1384     SAI_FillFifo(hsai);
1385 
1386     /* Enable FRQ and OVRUDR interrupts */
1387     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1388 
1389     /* Check if the SAI is already enabled */
1390     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1391     {
1392       /* Enable SAI peripheral */
1393       __HAL_SAI_ENABLE(hsai);
1394     }
1395     /* Process Unlocked */
1396     __HAL_UNLOCK(hsai);
1397 
1398     return HAL_OK;
1399   }
1400   else
1401   {
1402     return HAL_BUSY;
1403   }
1404 }
1405 
1406 /**
1407   * @brief  Receive an amount of data in non-blocking mode with Interrupt.
1408   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1409   *              the configuration information for SAI module.
1410   * @param  pData Pointer to data buffer
1411   * @param  Size Amount of data to be received
1412   * @retval HAL status
1413   */
1414 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1415 {
1416   if ((pData == NULL) || (Size == 0U))
1417   {
1418     return  HAL_ERROR;
1419   }
1420 
1421   if (hsai->State == HAL_SAI_STATE_READY)
1422   {
1423     /* Process Locked */
1424     __HAL_LOCK(hsai);
1425 
1426     hsai->pBuffPtr = pData;
1427     hsai->XferSize = Size;
1428     hsai->XferCount = Size;
1429     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1430     hsai->State = HAL_SAI_STATE_BUSY_RX;
1431 
1432     if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1433     {
1434       hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
1435     }
1436     else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1437     {
1438       hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
1439     }
1440     else
1441     {
1442       hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
1443     }
1444 
1445     /* Enable TXE and OVRUDR interrupts */
1446     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1447 
1448     /* Check if the SAI is already enabled */
1449     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1450     {
1451       /* Enable SAI peripheral */
1452       __HAL_SAI_ENABLE(hsai);
1453     }
1454 
1455     /* Process Unlocked */
1456     __HAL_UNLOCK(hsai);
1457 
1458     return HAL_OK;
1459   }
1460   else
1461   {
1462     return HAL_BUSY;
1463   }
1464 }
1465 
1466 /**
1467   * @brief Pause the audio stream playing from the Media.
1468   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1469   *              the configuration information for SAI module.
1470   * @retval HAL status
1471   */
1472 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
1473 {
1474   /* Process Locked */
1475   __HAL_LOCK(hsai);
1476 
1477   /* Pause the audio file playing by disabling the SAI DMA requests */
1478   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1479 
1480   /* Process Unlocked */
1481   __HAL_UNLOCK(hsai);
1482 
1483   return HAL_OK;
1484 }
1485 
1486 /**
1487   * @brief Resume the audio stream playing from the Media.
1488   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1489   *              the configuration information for SAI module.
1490   * @retval HAL status
1491   */
1492 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
1493 {
1494   /* Process Locked */
1495   __HAL_LOCK(hsai);
1496 
1497   /* Enable the SAI DMA requests */
1498   hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1499 
1500   /* If the SAI peripheral is still not enabled, enable it */
1501   if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1502   {
1503     /* Enable SAI peripheral */
1504     __HAL_SAI_ENABLE(hsai);
1505   }
1506 
1507   /* Process Unlocked */
1508   __HAL_UNLOCK(hsai);
1509 
1510   return HAL_OK;
1511 }
1512 
1513 /**
1514   * @brief Stop the audio stream playing from the Media.
1515   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1516   *              the configuration information for SAI module.
1517   * @retval HAL status
1518   */
1519 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
1520 {
1521   HAL_StatusTypeDef status = HAL_OK;
1522 
1523   /* Process Locked */
1524   __HAL_LOCK(hsai);
1525 
1526   /* Disable SAI peripheral */
1527   if (SAI_Disable(hsai) != HAL_OK)
1528   {
1529     status = HAL_ERROR;
1530   }
1531 
1532   /* Disable the SAI DMA request */
1533   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1534 
1535   /* Abort the SAI Tx DMA Stream */
1536   if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL))
1537   {
1538     if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1539     {
1540       /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1541       if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1542       {
1543         status = HAL_ERROR;
1544         hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1545       }
1546     }
1547   }
1548 
1549   /* Abort the SAI Rx DMA Stream */
1550   if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
1551   {
1552     if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1553     {
1554       /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1555       if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1556       {
1557         status = HAL_ERROR;
1558         hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1559       }
1560     }
1561   }
1562 
1563   /* Flush the fifo */
1564   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1565 
1566   /* Set hsai state to ready */
1567   hsai->State = HAL_SAI_STATE_READY;
1568 
1569   /* Process Unlocked */
1570   __HAL_UNLOCK(hsai);
1571 
1572   return status;
1573 }
1574 
1575 /**
1576   * @brief Abort the current transfer and disable the SAI.
1577   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1578   *              the configuration information for SAI module.
1579   * @retval HAL status
1580   */
1581 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
1582 {
1583   HAL_StatusTypeDef status = HAL_OK;
1584 
1585   /* Process Locked */
1586   __HAL_LOCK(hsai);
1587 
1588   /* Disable SAI peripheral */
1589   if (SAI_Disable(hsai) != HAL_OK)
1590   {
1591     status = HAL_ERROR;
1592   }
1593 
1594   /* Check SAI DMA is enabled or not */
1595   if ((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1596   {
1597     /* Disable the SAI DMA request */
1598     hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1599 
1600     /* Abort the SAI Tx DMA Stream */
1601     if ((hsai->State == HAL_SAI_STATE_BUSY_TX)&& (hsai->hdmatx != NULL))
1602     {
1603       if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1604       {
1605         /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1606         if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1607         {
1608           status = HAL_ERROR;
1609           hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1610         }
1611       }
1612     }
1613 
1614     /* Abort the SAI Rx DMA Stream */
1615     if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
1616     {
1617       if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1618       {
1619         /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1620         if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1621         {
1622           status = HAL_ERROR;
1623           hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1624         }
1625       }
1626     }
1627   }
1628 
1629   /* Disabled All interrupt and clear all the flag */
1630   hsai->Instance->IMR = 0;
1631   hsai->Instance->CLRFR = 0xFFFFFFFFU;
1632 
1633   /* Flush the fifo */
1634   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1635 
1636   /* Set hsai state to ready */
1637   hsai->State = HAL_SAI_STATE_READY;
1638 
1639   /* Process Unlocked */
1640   __HAL_UNLOCK(hsai);
1641 
1642   return status;
1643 }
1644 
1645 /**
1646   * @brief  Transmit an amount of data in non-blocking mode with DMA.
1647   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1648   *              the configuration information for SAI module.
1649   * @param  pData Pointer to data buffer
1650   * @param  Size Amount of data to be sent
1651   * @retval HAL status
1652   */
1653 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1654 {
1655   uint32_t tickstart = HAL_GetTick();
1656 
1657   if ((pData == NULL) || (Size == 0U))
1658   {
1659     return  HAL_ERROR;
1660   }
1661 
1662   if (hsai->State == HAL_SAI_STATE_READY)
1663   {
1664     /* Process Locked */
1665     __HAL_LOCK(hsai);
1666 
1667     hsai->pBuffPtr = pData;
1668     hsai->XferSize = Size;
1669     hsai->XferCount = Size;
1670     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1671     hsai->State = HAL_SAI_STATE_BUSY_TX;
1672 
1673     /* Set the SAI Tx DMA Half transfer complete callback */
1674     hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
1675 
1676     /* Set the SAI TxDMA transfer complete callback */
1677     hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
1678 
1679     /* Set the DMA error callback */
1680     hsai->hdmatx->XferErrorCallback = SAI_DMAError;
1681 
1682     /* Set the DMA Tx abort callback */
1683     hsai->hdmatx->XferAbortCallback = NULL;
1684 
1685     /* Enable the Tx DMA Stream */
1686     if (HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
1687     {
1688       __HAL_UNLOCK(hsai);
1689       return  HAL_ERROR;
1690     }
1691 
1692     /* Enable the interrupts for error handling */
1693     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1694 
1695     /* Enable SAI Tx DMA Request */
1696     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1697 
1698     /* Wait until FIFO is not empty */
1699     while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY)
1700     {
1701       /* Check for the Timeout */
1702       if ((HAL_GetTick() - tickstart) > SAI_LONG_TIMEOUT)
1703       {
1704         /* Update error code */
1705         hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1706 
1707         /* Process Unlocked */
1708         __HAL_UNLOCK(hsai);
1709 
1710         return HAL_TIMEOUT;
1711       }
1712     }
1713 
1714     /* Check if the SAI is already enabled */
1715     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1716     {
1717       /* Enable SAI peripheral */
1718       __HAL_SAI_ENABLE(hsai);
1719     }
1720 
1721     /* Process Unlocked */
1722     __HAL_UNLOCK(hsai);
1723 
1724     return HAL_OK;
1725   }
1726   else
1727   {
1728     return HAL_BUSY;
1729   }
1730 }
1731 
1732 /**
1733   * @brief  Receive an amount of data in non-blocking mode with DMA.
1734   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1735   *              the configuration information for SAI module.
1736   * @param  pData Pointer to data buffer
1737   * @param  Size Amount of data to be received
1738   * @retval HAL status
1739   */
1740 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1741 {
1742 
1743   if ((pData == NULL) || (Size == 0U))
1744   {
1745     return  HAL_ERROR;
1746   }
1747 
1748   if (hsai->State == HAL_SAI_STATE_READY)
1749   {
1750     /* Process Locked */
1751     __HAL_LOCK(hsai);
1752 
1753     hsai->pBuffPtr = pData;
1754     hsai->XferSize = Size;
1755     hsai->XferCount = Size;
1756     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1757     hsai->State = HAL_SAI_STATE_BUSY_RX;
1758 
1759     /* Set the SAI Rx DMA Half transfer complete callback */
1760     hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
1761 
1762     /* Set the SAI Rx DMA transfer complete callback */
1763     hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
1764 
1765     /* Set the DMA error callback */
1766     hsai->hdmarx->XferErrorCallback = SAI_DMAError;
1767 
1768     /* Set the DMA Rx abort callback */
1769     hsai->hdmarx->XferAbortCallback = NULL;
1770 
1771     /* Enable the Rx DMA Stream */
1772     if (HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
1773     {
1774       __HAL_UNLOCK(hsai);
1775       return  HAL_ERROR;
1776     }
1777 
1778     /* Enable the interrupts for error handling */
1779     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1780 
1781     /* Enable SAI Rx DMA Request */
1782     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1783 
1784     /* Check if the SAI is already enabled */
1785     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1786     {
1787       /* Enable SAI peripheral */
1788       __HAL_SAI_ENABLE(hsai);
1789     }
1790 
1791     /* Process Unlocked */
1792     __HAL_UNLOCK(hsai);
1793 
1794     return HAL_OK;
1795   }
1796   else
1797   {
1798     return HAL_BUSY;
1799   }
1800 }
1801 
1802 /**
1803   * @brief  Enable the Tx mute mode.
1804   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1805   *              the configuration information for SAI module.
1806   * @param  val  value sent during the mute @ref SAI_Block_Mute_Value
1807   * @retval HAL status
1808   */
1809 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
1810 {
1811   assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
1812 
1813   if (hsai->State != HAL_SAI_STATE_RESET)
1814   {
1815     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1816     SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | (uint32_t)val);
1817     return HAL_OK;
1818   }
1819   return HAL_ERROR;
1820 }
1821 
1822 /**
1823   * @brief  Disable the Tx mute mode.
1824   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1825   *              the configuration information for SAI module.
1826   * @retval HAL status
1827   */
1828 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
1829 {
1830   if (hsai->State != HAL_SAI_STATE_RESET)
1831   {
1832     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1833     return HAL_OK;
1834   }
1835   return HAL_ERROR;
1836 }
1837 
1838 /**
1839   * @brief  Enable the Rx mute detection.
1840   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1841   *              the configuration information for SAI module.
1842   * @param  callback function called when the mute is detected.
1843   * @param  counter number a data before mute detection max 63.
1844   * @retval HAL status
1845   */
1846 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
1847 {
1848   assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
1849 
1850   if (hsai->State != HAL_SAI_STATE_RESET)
1851   {
1852     /* set the mute counter */
1853     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
1854     SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
1855     hsai->mutecallback = callback;
1856     /* enable the IT interrupt */
1857     __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
1858     return HAL_OK;
1859   }
1860   return HAL_ERROR;
1861 }
1862 
1863 /**
1864   * @brief  Disable the Rx mute detection.
1865   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1866   *              the configuration information for SAI module.
1867   * @retval HAL status
1868   */
1869 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
1870 {
1871   if (hsai->State != HAL_SAI_STATE_RESET)
1872   {
1873     /* set the mutecallback to NULL */
1874     hsai->mutecallback = NULL;
1875     /* enable the IT interrupt */
1876     __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
1877     return HAL_OK;
1878   }
1879   return HAL_ERROR;
1880 }
1881 
1882 /**
1883   * @brief  Handle SAI interrupt request.
1884   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1885   *              the configuration information for SAI module.
1886   * @retval None
1887   */
1888 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
1889 {
1890   if (hsai->State != HAL_SAI_STATE_RESET)
1891   {
1892     uint32_t itflags = hsai->Instance->SR;
1893     uint32_t itsources = hsai->Instance->IMR;
1894     uint32_t cr1config = hsai->Instance->CR1;
1895     uint32_t tmperror;
1896 
1897     /* SAI Fifo request interrupt occurred ------------------------------------*/
1898     if (((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
1899     {
1900       hsai->InterruptServiceRoutine(hsai);
1901     }
1902     /* SAI Overrun error interrupt occurred ----------------------------------*/
1903     else if (((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
1904     {
1905       /* Clear the SAI Overrun flag */
1906       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1907       /* Get the SAI error code */
1908       tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
1909       /* Change the SAI error code */
1910       hsai->ErrorCode |= tmperror;
1911       /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1912 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1913       hsai->ErrorCallback(hsai);
1914 #else
1915       HAL_SAI_ErrorCallback(hsai);
1916 #endif
1917     }
1918     /* SAI mutedet interrupt occurred ----------------------------------*/
1919     else if (((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
1920     {
1921       /* Clear the SAI mutedet flag */
1922       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
1923       /* call the call back function */
1924       if (hsai->mutecallback != NULL)
1925       {
1926         /* inform the user that an RX mute event has been detected */
1927         hsai->mutecallback();
1928       }
1929     }
1930     /* SAI AFSDET interrupt occurred ----------------------------------*/
1931     else if (((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
1932     {
1933       /* Clear the SAI AFSDET flag */
1934       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_AFSDET);
1935 
1936       /* Change the SAI error code */
1937       hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
1938 
1939       /* Check SAI DMA is enabled or not */
1940       if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1941       {
1942         /* Abort the SAI DMA Streams */
1943         if (hsai->hdmatx != NULL)
1944         {
1945           /* Set the DMA Tx abort callback */
1946           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1947 
1948           /* Abort DMA in IT mode */
1949           if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1950           {
1951             /* Update SAI error code */
1952             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1953 
1954             /* Call SAI error callback */
1955 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1956             hsai->ErrorCallback(hsai);
1957 #else
1958             HAL_SAI_ErrorCallback(hsai);
1959 #endif
1960           }
1961         }
1962         if (hsai->hdmarx != NULL)
1963         {
1964           /* Set the DMA Rx abort callback */
1965           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1966 
1967           /* Abort DMA in IT mode */
1968           if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1969           {
1970             /* Update SAI error code */
1971             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1972 
1973             /* Call SAI error callback */
1974 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1975             hsai->ErrorCallback(hsai);
1976 #else
1977             HAL_SAI_ErrorCallback(hsai);
1978 #endif
1979           }
1980         }
1981       }
1982       else
1983       {
1984         /* Abort SAI */
1985         /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
1986         (void) HAL_SAI_Abort(hsai);
1987 
1988         /* Set error callback */
1989 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1990         hsai->ErrorCallback(hsai);
1991 #else
1992         HAL_SAI_ErrorCallback(hsai);
1993 #endif
1994       }
1995     }
1996     /* SAI LFSDET interrupt occurred ----------------------------------*/
1997     else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
1998     {
1999       /* Clear the SAI LFSDET flag */
2000       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_LFSDET);
2001 
2002       /* Change the SAI error code */
2003       hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
2004 
2005       /* Check SAI DMA is enabled or not */
2006       if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
2007       {
2008         /* Abort the SAI DMA Streams */
2009         if (hsai->hdmatx != NULL)
2010         {
2011           /* Set the DMA Tx abort callback */
2012           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
2013 
2014           /* Abort DMA in IT mode */
2015           if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
2016           {
2017             /* Update SAI error code */
2018             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2019 
2020             /* Call SAI error callback */
2021 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2022             hsai->ErrorCallback(hsai);
2023 #else
2024             HAL_SAI_ErrorCallback(hsai);
2025 #endif
2026           }
2027         }
2028         if (hsai->hdmarx != NULL)
2029         {
2030           /* Set the DMA Rx abort callback */
2031           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
2032 
2033           /* Abort DMA in IT mode */
2034           if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
2035           {
2036             /* Update SAI error code */
2037             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2038 
2039             /* Call SAI error callback */
2040 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2041             hsai->ErrorCallback(hsai);
2042 #else
2043             HAL_SAI_ErrorCallback(hsai);
2044 #endif
2045           }
2046         }
2047       }
2048       else
2049       {
2050         /* Abort SAI */
2051         /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
2052         (void) HAL_SAI_Abort(hsai);
2053 
2054         /* Set error callback */
2055 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2056         hsai->ErrorCallback(hsai);
2057 #else
2058         HAL_SAI_ErrorCallback(hsai);
2059 #endif
2060       }
2061     }
2062     /* SAI WCKCFG interrupt occurred ----------------------------------*/
2063     else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
2064     {
2065       /* Clear the SAI WCKCFG flag */
2066       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_WCKCFG);
2067 
2068       /* Change the SAI error code */
2069       hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
2070 
2071       /* Check SAI DMA is enabled or not */
2072       if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
2073       {
2074         /* Abort the SAI DMA Streams */
2075         if (hsai->hdmatx != NULL)
2076         {
2077           /* Set the DMA Tx abort callback */
2078           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
2079 
2080           /* Abort DMA in IT mode */
2081           if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
2082           {
2083             /* Update SAI error code */
2084             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2085 
2086             /* Call SAI error callback */
2087 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2088             hsai->ErrorCallback(hsai);
2089 #else
2090             HAL_SAI_ErrorCallback(hsai);
2091 #endif
2092           }
2093         }
2094         if (hsai->hdmarx != NULL)
2095         {
2096           /* Set the DMA Rx abort callback */
2097           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
2098 
2099           /* Abort DMA in IT mode */
2100           if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
2101           {
2102             /* Update SAI error code */
2103             hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2104 
2105             /* Call SAI error callback */
2106 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2107             hsai->ErrorCallback(hsai);
2108 #else
2109             HAL_SAI_ErrorCallback(hsai);
2110 #endif
2111           }
2112         }
2113       }
2114       else
2115       {
2116         /* If WCKCFG occurs, SAI audio block is automatically disabled */
2117         /* Disable all interrupts and clear all flags */
2118         hsai->Instance->IMR = 0U;
2119         hsai->Instance->CLRFR = 0xFFFFFFFFU;
2120         /* Set the SAI state to ready to be able to start again the process */
2121         hsai->State = HAL_SAI_STATE_READY;
2122 
2123         /* Initialize XferCount */
2124         hsai->XferCount = 0U;
2125 
2126         /* SAI error Callback */
2127 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2128         hsai->ErrorCallback(hsai);
2129 #else
2130         HAL_SAI_ErrorCallback(hsai);
2131 #endif
2132       }
2133     }
2134     /* SAI CNRDY interrupt occurred ----------------------------------*/
2135     else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
2136     {
2137       /* Clear the SAI CNRDY flag */
2138       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
2139       /* Change the SAI error code */
2140       hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
2141       /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
2142 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2143       hsai->ErrorCallback(hsai);
2144 #else
2145       HAL_SAI_ErrorCallback(hsai);
2146 #endif
2147     }
2148     else
2149     {
2150       /* Nothing to do */
2151     }
2152   }
2153 }
2154 
2155 /**
2156   * @brief Tx Transfer completed callback.
2157   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2158   *              the configuration information for SAI module.
2159   * @retval None
2160   */
2161 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
2162 {
2163   /* Prevent unused argument(s) compilation warning */
2164   UNUSED(hsai);
2165 
2166   /* NOTE : This function should not be modified, when the callback is needed,
2167             the HAL_SAI_TxCpltCallback could be implemented in the user file
2168    */
2169 }
2170 
2171 /**
2172   * @brief Tx Transfer Half completed callback.
2173   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2174   *              the configuration information for SAI module.
2175   * @retval None
2176   */
2177 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
2178 {
2179   /* Prevent unused argument(s) compilation warning */
2180   UNUSED(hsai);
2181 
2182   /* NOTE : This function should not be modified, when the callback is needed,
2183             the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
2184    */
2185 }
2186 
2187 /**
2188   * @brief Rx Transfer completed callback.
2189   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2190   *              the configuration information for SAI module.
2191   * @retval None
2192   */
2193 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
2194 {
2195   /* Prevent unused argument(s) compilation warning */
2196   UNUSED(hsai);
2197 
2198   /* NOTE : This function should not be modified, when the callback is needed,
2199             the HAL_SAI_RxCpltCallback could be implemented in the user file
2200    */
2201 }
2202 
2203 /**
2204   * @brief Rx Transfer half completed callback.
2205   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2206   *              the configuration information for SAI module.
2207   * @retval None
2208   */
2209 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
2210 {
2211   /* Prevent unused argument(s) compilation warning */
2212   UNUSED(hsai);
2213 
2214   /* NOTE : This function should not be modified, when the callback is needed,
2215             the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
2216    */
2217 }
2218 
2219 /**
2220   * @brief SAI error callback.
2221   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2222   *              the configuration information for SAI module.
2223   * @retval None
2224   */
2225 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
2226 {
2227   /* Prevent unused argument(s) compilation warning */
2228   UNUSED(hsai);
2229 
2230   /* NOTE : This function should not be modified, when the callback is needed,
2231             the HAL_SAI_ErrorCallback could be implemented in the user file
2232    */
2233 }
2234 
2235 /**
2236   * @}
2237   */
2238 
2239 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
2240   * @ingroup RTEMSBSPsARMSTM32H7
2241   * @brief    Peripheral State functions
2242   *
2243 @verbatim
2244   ===============================================================================
2245                 ##### Peripheral State and Errors functions #####
2246   ===============================================================================
2247   [..]
2248     This subsection permits to get in run-time the status of the peripheral
2249     and the data flow.
2250 
2251 @endverbatim
2252   * @{
2253   */
2254 
2255 /**
2256   * @brief  Return the SAI handle state.
2257   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2258   *              the configuration information for SAI module.
2259   * @retval HAL state
2260   */
2261 HAL_SAI_StateTypeDef HAL_SAI_GetState(const SAI_HandleTypeDef *hsai)
2262 {
2263   return hsai->State;
2264 }
2265 
2266 /**
2267   * @brief  Return the SAI error code.
2268   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2269   *              the configuration information for the specified SAI Block.
2270   * @retval SAI Error Code
2271   */
2272 uint32_t HAL_SAI_GetError(const SAI_HandleTypeDef *hsai)
2273 {
2274   return hsai->ErrorCode;
2275 }
2276 
2277 /**
2278   * @}
2279   */
2280 
2281 /**
2282   * @}
2283   */
2284 
2285 /** @addtogroup SAI_Private_Functions
2286   * @brief      Private functions
2287   * @{
2288   */
2289 
2290 /**
2291   * @brief  Initialize the SAI I2S protocol according to the specified parameters
2292   *         in the SAI_InitTypeDef and create the associated handle.
2293   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2294   *              the configuration information for SAI module.
2295   * @param  protocol one of the supported protocol.
2296   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize.
2297   * @param  nbslot number of slot minimum value is 2 and max is 16.
2298   *         the value must be a multiple of 2.
2299   * @retval HAL status
2300   */
2301 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2302 {
2303   HAL_StatusTypeDef status = HAL_OK;
2304 
2305   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
2306   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
2307   /* Compute ClockStrobing according AudioMode */
2308   if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2309   {
2310     /* Transmit */
2311     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_FALLINGEDGE;
2312   }
2313   else
2314   {
2315     /* Receive */
2316     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_RISINGEDGE;
2317   }
2318   hsai->FrameInit.FSDefinition   = SAI_FS_CHANNEL_IDENTIFICATION;
2319   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
2320   hsai->SlotInit.FirstBitOffset  = 0;
2321   hsai->SlotInit.SlotNumber      = nbslot;
2322 
2323   /* in IS2 the number of slot must be even */
2324   if ((nbslot & 0x1U) != 0U)
2325   {
2326     return HAL_ERROR;
2327   }
2328 
2329   if (protocol == SAI_I2S_STANDARD)
2330   {
2331       hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
2332       hsai->FrameInit.FSOffset   = SAI_FS_BEFOREFIRSTBIT;
2333   }
2334   else
2335   {
2336      /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
2337       hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2338       hsai->FrameInit.FSOffset   = SAI_FS_FIRSTBIT;
2339   }
2340 
2341   /* Frame definition */
2342   switch (datasize)
2343   {
2344     case SAI_PROTOCOL_DATASIZE_16BIT:
2345       hsai->Init.DataSize = SAI_DATASIZE_16;
2346       hsai->FrameInit.FrameLength = 32U * (nbslot / 2U);
2347       hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U);
2348       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2349       break;
2350     case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2351       hsai->Init.DataSize = SAI_DATASIZE_16;
2352       hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2353       hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2354       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2355       break;
2356     case SAI_PROTOCOL_DATASIZE_24BIT:
2357       hsai->Init.DataSize = SAI_DATASIZE_24;
2358       hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2359       hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2360       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2361       break;
2362     case SAI_PROTOCOL_DATASIZE_32BIT:
2363       hsai->Init.DataSize = SAI_DATASIZE_32;
2364       hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2365       hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2366       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2367       break;
2368     default :
2369       status = HAL_ERROR;
2370       break;
2371   }
2372   if (protocol == SAI_I2S_LSBJUSTIFIED)
2373   {
2374     if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
2375     {
2376       hsai->SlotInit.FirstBitOffset = 16;
2377     }
2378     if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
2379     {
2380       hsai->SlotInit.FirstBitOffset = 8;
2381     }
2382   }
2383   return status;
2384 }
2385 
2386 /**
2387   * @brief  Initialize the SAI PCM protocol according to the specified parameters
2388   *         in the SAI_InitTypeDef and create the associated handle.
2389   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2390   *              the configuration information for SAI module.
2391   * @param  protocol one of the supported protocol
2392   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
2393   * @param  nbslot number of slot minimum value is 1 and the max is 16.
2394   * @retval HAL status
2395   */
2396 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2397 {
2398   HAL_StatusTypeDef status = HAL_OK;
2399 
2400   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
2401   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
2402   /* Compute ClockStrobing according AudioMode */
2403   if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2404   {
2405     /* Transmit */
2406     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_RISINGEDGE;
2407   }
2408   else
2409   {
2410     /* Receive */
2411     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_FALLINGEDGE;
2412   }
2413   hsai->FrameInit.FSDefinition   = SAI_FS_STARTFRAME;
2414   hsai->FrameInit.FSPolarity     = SAI_FS_ACTIVE_HIGH;
2415   hsai->FrameInit.FSOffset       = SAI_FS_BEFOREFIRSTBIT;
2416   hsai->SlotInit.FirstBitOffset  = 0;
2417   hsai->SlotInit.SlotNumber      = nbslot;
2418   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
2419 
2420   if (protocol == SAI_PCM_SHORT)
2421   {
2422       hsai->FrameInit.ActiveFrameLength = 1;
2423   }
2424   else
2425   {
2426     /* SAI_PCM_LONG */
2427       hsai->FrameInit.ActiveFrameLength = 13;
2428   }
2429 
2430   switch (datasize)
2431   {
2432     case SAI_PROTOCOL_DATASIZE_16BIT:
2433       hsai->Init.DataSize = SAI_DATASIZE_16;
2434       hsai->FrameInit.FrameLength = 16U * nbslot;
2435       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2436       break;
2437     case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2438       hsai->Init.DataSize = SAI_DATASIZE_16;
2439       hsai->FrameInit.FrameLength = 32U * nbslot;
2440       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2441       break;
2442     case SAI_PROTOCOL_DATASIZE_24BIT :
2443       hsai->Init.DataSize = SAI_DATASIZE_24;
2444       hsai->FrameInit.FrameLength = 32U * nbslot;
2445       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2446       break;
2447     case SAI_PROTOCOL_DATASIZE_32BIT:
2448       hsai->Init.DataSize = SAI_DATASIZE_32;
2449       hsai->FrameInit.FrameLength = 32U * nbslot;
2450       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2451       break;
2452     default :
2453       status = HAL_ERROR;
2454       break;
2455   }
2456 
2457   return status;
2458 }
2459 
2460 /**
2461   * @brief  Fill the fifo.
2462   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2463   *              the configuration information for SAI module.
2464   * @retval None
2465   */
2466 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
2467 {
2468   uint32_t temp;
2469 
2470   /* fill the fifo with data before to enabled the SAI */
2471   while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
2472   {
2473     if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
2474     {
2475       hsai->Instance->DR = *hsai->pBuffPtr;
2476       hsai->pBuffPtr++;
2477     }
2478     else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
2479     {
2480       temp = (uint32_t)(*hsai->pBuffPtr);
2481       hsai->pBuffPtr++;
2482       temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2483       hsai->pBuffPtr++;
2484       hsai->Instance->DR = temp;
2485     }
2486     else
2487     {
2488       temp = (uint32_t)(*hsai->pBuffPtr);
2489       hsai->pBuffPtr++;
2490       temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2491       hsai->pBuffPtr++;
2492       temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
2493       hsai->pBuffPtr++;
2494       temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
2495       hsai->pBuffPtr++;
2496       hsai->Instance->DR = temp;
2497     }
2498     hsai->XferCount--;
2499   }
2500 }
2501 
2502 /**
2503   * @brief  Return the interrupt flag to set according the SAI setup.
2504   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2505   *              the configuration information for SAI module.
2506   * @param  mode SAI_MODE_DMA or SAI_MODE_IT
2507   * @retval the list of the IT flag to enable
2508   */
2509 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode)
2510 {
2511   uint32_t tmpIT = SAI_IT_OVRUDR;
2512 
2513   if (mode == SAI_MODE_IT)
2514   {
2515     tmpIT |= SAI_IT_FREQ;
2516   }
2517 
2518   if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
2519       ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
2520   {
2521     tmpIT |= SAI_IT_CNRDY;
2522   }
2523 
2524   if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2525   {
2526     tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET;
2527   }
2528   else
2529   {
2530     /* hsai has been configured in master mode */
2531     tmpIT |= SAI_IT_WCKCFG;
2532   }
2533   return tmpIT;
2534 }
2535 
2536 /**
2537   * @brief  Disable the SAI and wait for the disabling.
2538   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2539   *              the configuration information for SAI module.
2540   * @retval None
2541   */
2542 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
2543 {
2544   uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U);
2545   HAL_StatusTypeDef status = HAL_OK;
2546 
2547   /* Disable the SAI instance */
2548   __HAL_SAI_DISABLE(hsai);
2549 
2550   do
2551   {
2552     /* Check for the Timeout */
2553     if (count == 0U)
2554     {
2555       /* Update error code */
2556       hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
2557       status = HAL_TIMEOUT;
2558       break;
2559     }
2560     count--;
2561   }
2562   while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != 0U);
2563 
2564   return status;
2565 }
2566 
2567 /**
2568   * @brief  Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
2569   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2570   *              the configuration information for SAI module.
2571   * @retval None
2572   */
2573 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
2574 {
2575   if (hsai->XferCount == 0U)
2576   {
2577     /* Handle the end of the transmission */
2578     /* Disable FREQ and OVRUDR interrupts */
2579     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2580     hsai->State = HAL_SAI_STATE_READY;
2581 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2582     hsai->TxCpltCallback(hsai);
2583 #else
2584     HAL_SAI_TxCpltCallback(hsai);
2585 #endif
2586   }
2587   else
2588   {
2589     /* Write data on DR register */
2590     hsai->Instance->DR = *hsai->pBuffPtr;
2591     hsai->pBuffPtr++;
2592     hsai->XferCount--;
2593   }
2594 }
2595 
2596 /**
2597   * @brief  Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
2598   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2599   *              the configuration information for SAI module.
2600   * @retval None
2601   */
2602 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
2603 {
2604   if (hsai->XferCount == 0U)
2605   {
2606     /* Handle the end of the transmission */
2607     /* Disable FREQ and OVRUDR interrupts */
2608     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2609     hsai->State = HAL_SAI_STATE_READY;
2610 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2611     hsai->TxCpltCallback(hsai);
2612 #else
2613     HAL_SAI_TxCpltCallback(hsai);
2614 #endif
2615   }
2616   else
2617   {
2618     /* Write data on DR register */
2619     uint32_t temp;
2620     temp = (uint32_t)(*hsai->pBuffPtr);
2621     hsai->pBuffPtr++;
2622     temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2623     hsai->pBuffPtr++;
2624     hsai->Instance->DR = temp;
2625     hsai->XferCount--;
2626   }
2627 }
2628 
2629 /**
2630   * @brief  Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
2631   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2632   *              the configuration information for SAI module.
2633   * @retval None
2634   */
2635 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
2636 {
2637   if (hsai->XferCount == 0U)
2638   {
2639     /* Handle the end of the transmission */
2640     /* Disable FREQ and OVRUDR interrupts */
2641     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2642     hsai->State = HAL_SAI_STATE_READY;
2643 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2644     hsai->TxCpltCallback(hsai);
2645 #else
2646     HAL_SAI_TxCpltCallback(hsai);
2647 #endif
2648   }
2649   else
2650   {
2651     /* Write data on DR register */
2652     uint32_t temp;
2653     temp = (uint32_t)(*hsai->pBuffPtr);
2654     hsai->pBuffPtr++;
2655     temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2656     hsai->pBuffPtr++;
2657     temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
2658     hsai->pBuffPtr++;
2659     temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
2660     hsai->pBuffPtr++;
2661     hsai->Instance->DR = temp;
2662     hsai->XferCount--;
2663   }
2664 }
2665 
2666 /**
2667   * @brief  Rx Handler for Receive in Interrupt mode 8-Bit transfer.
2668   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2669   *              the configuration information for SAI module.
2670   * @retval None
2671   */
2672 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
2673 {
2674   /* Receive data */
2675   *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
2676   hsai->pBuffPtr++;
2677   hsai->XferCount--;
2678 
2679   /* Check end of the transfer */
2680   if (hsai->XferCount == 0U)
2681   {
2682     /* Disable TXE and OVRUDR interrupts */
2683     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2684 
2685     /* Clear the SAI Overrun flag */
2686     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2687 
2688     hsai->State = HAL_SAI_STATE_READY;
2689 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2690     hsai->RxCpltCallback(hsai);
2691 #else
2692     HAL_SAI_RxCpltCallback(hsai);
2693 #endif
2694   }
2695 }
2696 
2697 /**
2698   * @brief  Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
2699   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2700   *              the configuration information for SAI module.
2701   * @retval None
2702   */
2703 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
2704 {
2705   uint32_t temp;
2706 
2707   /* Receive data */
2708   temp = hsai->Instance->DR;
2709   *hsai->pBuffPtr = (uint8_t)temp;
2710   hsai->pBuffPtr++;
2711   *hsai->pBuffPtr = (uint8_t)(temp >> 8);
2712   hsai->pBuffPtr++;
2713   hsai->XferCount--;
2714 
2715   /* Check end of the transfer */
2716   if (hsai->XferCount == 0U)
2717   {
2718     /* Disable TXE and OVRUDR interrupts */
2719     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2720 
2721     /* Clear the SAI Overrun flag */
2722     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2723 
2724     hsai->State = HAL_SAI_STATE_READY;
2725 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2726     hsai->RxCpltCallback(hsai);
2727 #else
2728     HAL_SAI_RxCpltCallback(hsai);
2729 #endif
2730   }
2731 }
2732 
2733 /**
2734   * @brief  Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
2735   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2736   *              the configuration information for SAI module.
2737   * @retval None
2738   */
2739 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
2740 {
2741   uint32_t temp;
2742 
2743   /* Receive data */
2744   temp = hsai->Instance->DR;
2745   *hsai->pBuffPtr = (uint8_t)temp;
2746   hsai->pBuffPtr++;
2747   *hsai->pBuffPtr = (uint8_t)(temp >> 8);
2748   hsai->pBuffPtr++;
2749   *hsai->pBuffPtr = (uint8_t)(temp >> 16);
2750   hsai->pBuffPtr++;
2751   *hsai->pBuffPtr = (uint8_t)(temp >> 24);
2752   hsai->pBuffPtr++;
2753   hsai->XferCount--;
2754 
2755   /* Check end of the transfer */
2756   if (hsai->XferCount == 0U)
2757   {
2758     /* Disable TXE and OVRUDR interrupts */
2759     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2760 
2761     /* Clear the SAI Overrun flag */
2762     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2763 
2764     hsai->State = HAL_SAI_STATE_READY;
2765 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2766     hsai->RxCpltCallback(hsai);
2767 #else
2768     HAL_SAI_RxCpltCallback(hsai);
2769 #endif
2770   }
2771 }
2772 
2773 /**
2774   * @brief  DMA SAI transmit process complete callback.
2775   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2776   *              the configuration information for the specified DMA module.
2777   * @retval None
2778   */
2779 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
2780 {
2781   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2782 
2783   if (hdma->Init.Mode != DMA_CIRCULAR)
2784   {
2785     hsai->XferCount = 0;
2786 
2787     /* Disable SAI Tx DMA Request */
2788     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2789 
2790     /* Stop the interrupts error handling */
2791     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2792 
2793     hsai->State = HAL_SAI_STATE_READY;
2794   }
2795 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2796   hsai->TxCpltCallback(hsai);
2797 #else
2798   HAL_SAI_TxCpltCallback(hsai);
2799 #endif
2800 }
2801 
2802 /**
2803   * @brief  DMA SAI transmit process half complete callback.
2804   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2805   *              the configuration information for the specified DMA module.
2806   * @retval None
2807   */
2808 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
2809 {
2810   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2811 
2812 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2813   hsai->TxHalfCpltCallback(hsai);
2814 #else
2815   HAL_SAI_TxHalfCpltCallback(hsai);
2816 #endif
2817 }
2818 
2819 /**
2820   * @brief  DMA SAI receive process complete callback.
2821   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2822   *              the configuration information for the specified DMA module.
2823   * @retval None
2824   */
2825 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
2826 {
2827   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2828 
2829   if (hdma->Init.Mode != DMA_CIRCULAR)
2830   {
2831     /* Disable Rx DMA Request */
2832     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2833     hsai->XferCount = 0;
2834 
2835     /* Stop the interrupts error handling */
2836     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2837 
2838     hsai->State = HAL_SAI_STATE_READY;
2839   }
2840 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2841   hsai->RxCpltCallback(hsai);
2842 #else
2843   HAL_SAI_RxCpltCallback(hsai);
2844 #endif
2845 }
2846 
2847 /**
2848   * @brief  DMA SAI receive process half complete callback
2849   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2850   *              the configuration information for the specified DMA module.
2851   * @retval None
2852   */
2853 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
2854 {
2855   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2856 
2857 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2858   hsai->RxHalfCpltCallback(hsai);
2859 #else
2860   HAL_SAI_RxHalfCpltCallback(hsai);
2861 #endif
2862 }
2863 
2864 /**
2865   * @brief  DMA SAI communication error callback.
2866   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2867   *              the configuration information for the specified DMA module.
2868   * @retval None
2869   */
2870 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
2871 {
2872   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2873 
2874   /* Ignore DMA FIFO error */
2875   if (HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE)
2876   {
2877     /* Set SAI error code */
2878     hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2879 
2880     /* Disable the SAI DMA request */
2881     hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2882 
2883     /* Disable SAI peripheral */
2884     /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2885     (void) SAI_Disable(hsai);
2886 
2887     /* Set the SAI state ready to be able to start again the process */
2888     hsai->State = HAL_SAI_STATE_READY;
2889 
2890     /* Initialize XferCount */
2891     hsai->XferCount = 0U;
2892 
2893     /* SAI error Callback */
2894 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2895     hsai->ErrorCallback(hsai);
2896 #else
2897     HAL_SAI_ErrorCallback(hsai);
2898 #endif
2899   }
2900 }
2901 
2902 /**
2903   * @brief  DMA SAI Abort callback.
2904   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2905   *              the configuration information for the specified DMA module.
2906   * @retval None
2907   */
2908 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
2909 {
2910   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2911 
2912   /* Disable DMA request */
2913   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2914 
2915   /* Disable all interrupts and clear all flags */
2916   hsai->Instance->IMR = 0U;
2917   hsai->Instance->CLRFR = 0xFFFFFFFFU;
2918 
2919   if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
2920   {
2921     /* Disable SAI peripheral */
2922     /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2923     (void) SAI_Disable(hsai);
2924 
2925     /* Flush the fifo */
2926     SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
2927   }
2928   /* Set the SAI state to ready to be able to start again the process */
2929   hsai->State = HAL_SAI_STATE_READY;
2930 
2931   /* Initialize XferCount */
2932   hsai->XferCount = 0U;
2933 
2934   /* SAI error Callback */
2935 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2936   hsai->ErrorCallback(hsai);
2937 #else
2938   HAL_SAI_ErrorCallback(hsai);
2939 #endif
2940 }
2941 
2942 /**
2943   * @}
2944   */
2945 
2946 #endif /* HAL_SAI_MODULE_ENABLED */
2947 /**
2948   * @}
2949   */
2950 
2951 /**
2952   * @}
2953   */
2954