STM32F4xx_HAL_Driver  1.8.3
stm32f4xx_hal_sai.c
Go to the documentation of this file.
1 
215 /* Includes ------------------------------------------------------------------*/
216 #include "stm32f4xx_hal.h"
217 
227 #ifdef HAL_SAI_MODULE_ENABLED
228 
229 #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\
230  defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) ||\
231  defined(STM32F423xx)
232 
236 typedef enum
237 {
238  SAI_MODE_DMA,
239  SAI_MODE_IT
240 } SAI_ModeTypedef;
245 /* Private define ------------------------------------------------------------*/
246 
250 #define SAI_DEFAULT_TIMEOUT 4U /* 4ms */
251 #define SAI_LONG_TIMEOUT 1000U /* 1s */
256 /* Private macro -------------------------------------------------------------*/
257 /* Private variables ---------------------------------------------------------*/
258 /* Private function prototypes -----------------------------------------------*/
262 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
263 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, uint32_t mode);
264 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
265 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
266 
267 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
268 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
269 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
270 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
271 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
272 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
273 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
274 
275 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
276 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
277 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
278 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
279 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
280 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
285 /* Exported functions ---------------------------------------------------------*/
333 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
334 {
335  HAL_StatusTypeDef status = HAL_OK;
336 
337  /* Check the parameters */
338  assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
339  assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
340 
341  switch (protocol)
342  {
343  case SAI_I2S_STANDARD :
344  case SAI_I2S_MSBJUSTIFIED :
345  case SAI_I2S_LSBJUSTIFIED :
346  status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
347  break;
348  case SAI_PCM_LONG :
349  case SAI_PCM_SHORT :
350  status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
351  break;
352  default :
353  status = HAL_ERROR;
354  break;
355  }
356 
357  if (status == HAL_OK)
358  {
359  status = HAL_SAI_Init(hsai);
360  }
361 
362  return status;
363 }
364 
372 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
373 {
374  uint32_t tmpregisterGCR = 0U;
375 
376  /* This variable used to store the SAI_CK_x (value in Hz) */
377  uint32_t freq = 0U;
378 
379  /* This variable is used to compute CKSTR bits of SAI CR1 according to
380  ClockStrobing and AudioMode fields */
381  uint32_t ckstr_bits = 0U;
382  uint32_t syncen_bits = 0U;
383 
384  /* Check the SAI handle allocation */
385  if (hsai == NULL)
386  {
387  return HAL_ERROR;
388  }
389 
390  /* check the instance */
391  assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
392 
393  /* Check the SAI Block parameters */
394  assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
395  assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
396  assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
397  assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
398  assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
399  assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
400  assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
401  assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
402  assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
403  assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
404  assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
405  assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
406  assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
407  assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
408 
409  /* Check the SAI Block Frame parameters */
410  assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
411  assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
412  assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
413  assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
414  assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
415 
416  /* Check the SAI Block Slot parameters */
417  assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
418  assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
419  assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
420  assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
421 
422  if (hsai->State == HAL_SAI_STATE_RESET)
423  {
424  /* Allocate lock resource and initialize it */
425  hsai->Lock = HAL_UNLOCKED;
426 
427 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
428  /* Reset callback pointers to the weak predefined callbacks */
434 
435  /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
436  if (hsai->MspInitCallback == NULL)
437  {
439  }
440  hsai->MspInitCallback(hsai);
441 #else
442  /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
443  HAL_SAI_MspInit(hsai);
444 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
445  }
446 
447  hsai->State = HAL_SAI_STATE_BUSY;
448 
449  /* Disable the selected SAI peripheral */
450  SAI_Disable(hsai);
451 
452  /* SAI Block Synchro Configuration -----------------------------------------*/
454 
455  /* Configure Master Clock using the following formula :
456  MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS
457  FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256
458  MCKDIV[3:0] = SAI_CK_x / FS * 512 */
459  if (hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
460  {
461  /* Get SAI clock source based on Source clock selection from RCC */
462  freq = SAI_GetInputClock(hsai);
463 
464  /* (saiclocksource x 10) to keep Significant digits */
465  tmpregisterGCR = (((freq * 10U) / ((hsai->Init.AudioFrequency) * 512U)));
466 
467  hsai->Init.Mckdiv = tmpregisterGCR / 10U;
468 
469  /* Round result to the nearest integer */
470  if ((tmpregisterGCR % 10U) > 8U)
471  {
472  hsai->Init.Mckdiv += 1U;
473  }
474 
475  /* For SPDIF protocol, SAI shall provide a bit clock twice faster the symbol-rate */
476  if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
477  {
478  hsai->Init.Mckdiv = hsai->Init.Mckdiv >> 1;
479  }
480  }
481 
482  /* Check the SAI Block master clock divider parameter */
483  assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(hsai->Init.Mckdiv));
484 
485  /* Compute CKSTR bits of SAI CR1 according to ClockStrobing and AudioMode */
486  if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
487  {
488  ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR;
489  }
490  else
491  {
492  ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U;
493  }
494 
495  /* SAI Block Configuration -------------------------------------------------*/
496  switch (hsai->Init.Synchro)
497  {
498  case SAI_ASYNCHRONOUS :
499  {
500  syncen_bits = 0U;
501  }
502  break;
503  case SAI_SYNCHRONOUS :
504  {
505  syncen_bits = SAI_xCR1_SYNCEN_0;
506  }
507  break;
508  case SAI_SYNCHRONOUS_EXT_SAI1 :
509  case SAI_SYNCHRONOUS_EXT_SAI2 :
510  {
511  syncen_bits = SAI_xCR1_SYNCEN_1;
512  }
513  break;
514  default:
515  break;
516  }
517 
518  /* SAI CR1 Configuration */
519  hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
520  SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
521  SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
522  SAI_xCR1_NODIV | SAI_xCR1_MCKDIV);
523 
524  hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
525  hsai->Init.DataSize | hsai->Init.FirstBit | \
526  ckstr_bits | syncen_bits | \
527  hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
528  hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20U));
529 
530  /* SAI CR2 Configuration */
531  hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
532  hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
533 
534  /* SAI Frame Configuration -----------------------------------------*/
535  hsai->Instance->FRCR &= (~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
536  SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
537  hsai->Instance->FRCR |= ((hsai->FrameInit.FrameLength - 1U) |
538  hsai->FrameInit.FSOffset |
539  hsai->FrameInit.FSDefinition |
540  hsai->FrameInit.FSPolarity |
541  ((hsai->FrameInit.ActiveFrameLength - 1U) << 8U));
542 
543  /* SAI Block_x SLOT Configuration ------------------------------------------*/
544  /* This register has no meaning in AC 97 and SPDIF audio protocol */
545  hsai->Instance->SLOTR &= ~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \
546  SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN);
547 
548  hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \
549  (hsai->SlotInit.SlotActive << 16U) | ((hsai->SlotInit.SlotNumber - 1U) << 8U);
550 
551  /* Initialize the error code */
552  hsai->ErrorCode = HAL_SAI_ERROR_NONE;
553 
554  /* Initialize the SAI state */
555  hsai->State = HAL_SAI_STATE_READY;
556 
557  /* Release Lock */
558  __HAL_UNLOCK(hsai);
559 
560  return HAL_OK;
561 }
562 
569 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
570 {
571  /* Check the SAI handle allocation */
572  if (hsai == NULL)
573  {
574  return HAL_ERROR;
575  }
576 
577  hsai->State = HAL_SAI_STATE_BUSY;
578 
579  /* Disabled All interrupt and clear all the flag */
580  hsai->Instance->IMR = 0U;
581  hsai->Instance->CLRFR = 0xFFFFFFFFU;
582 
583  /* Disable the SAI */
584  SAI_Disable(hsai);
585 
586  /* Flush the fifo */
587  SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
588 
589  /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
590 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
591  if (hsai->MspDeInitCallback == NULL)
592  {
594  }
595  hsai->MspDeInitCallback(hsai);
596 #else
597  HAL_SAI_MspDeInit(hsai);
598 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
599 
600  /* Initialize the error code */
601  hsai->ErrorCode = HAL_SAI_ERROR_NONE;
602 
603  /* Initialize the SAI state */
604  hsai->State = HAL_SAI_STATE_RESET;
605 
606  /* Release Lock */
607  __HAL_UNLOCK(hsai);
608 
609  return HAL_OK;
610 }
611 
619 {
620  /* Prevent unused argument(s) compilation warning */
621  UNUSED(hsai);
622 
623  /* NOTE : This function should not be modified, when the callback is needed,
624  the HAL_SAI_MspInit could be implemented in the user file
625  */
626 }
627 
635 {
636  /* Prevent unused argument(s) compilation warning */
637  UNUSED(hsai);
638 
639  /* NOTE : This function should not be modified, when the callback is needed,
640  the HAL_SAI_MspDeInit could be implemented in the user file
641  */
642 }
643 
644 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
662  HAL_SAI_CallbackIDTypeDef CallbackID,
663  pSAI_CallbackTypeDef pCallback)
664 {
665  HAL_StatusTypeDef status = HAL_OK;
666 
667  if (pCallback == NULL)
668  {
669  /* update the error code */
670  hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
671  /* update return status */
672  status = HAL_ERROR;
673  }
674  else
675  {
676  if (HAL_SAI_STATE_READY == hsai->State)
677  {
678  switch (CallbackID)
679  {
681  hsai->RxCpltCallback = pCallback;
682  break;
684  hsai->RxHalfCpltCallback = pCallback;
685  break;
687  hsai->TxCpltCallback = pCallback;
688  break;
690  hsai->TxHalfCpltCallback = pCallback;
691  break;
692  case HAL_SAI_ERROR_CB_ID :
693  hsai->ErrorCallback = pCallback;
694  break;
695  case HAL_SAI_MSPINIT_CB_ID :
696  hsai->MspInitCallback = pCallback;
697  break;
699  hsai->MspDeInitCallback = pCallback;
700  break;
701  default :
702  /* update the error code */
703  hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
704  /* update return status */
705  status = HAL_ERROR;
706  break;
707  }
708  }
709  else if (HAL_SAI_STATE_RESET == hsai->State)
710  {
711  switch (CallbackID)
712  {
713  case HAL_SAI_MSPINIT_CB_ID :
714  hsai->MspInitCallback = pCallback;
715  break;
717  hsai->MspDeInitCallback = pCallback;
718  break;
719  default :
720  /* update the error code */
721  hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
722  /* update return status */
723  status = HAL_ERROR;
724  break;
725  }
726  }
727  else
728  {
729  /* update the error code */
730  hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
731  /* update return status */
732  status = HAL_ERROR;
733  }
734  }
735  return status;
736 }
737 
754  HAL_SAI_CallbackIDTypeDef CallbackID)
755 {
756  HAL_StatusTypeDef status = HAL_OK;
757 
758  if (HAL_SAI_STATE_READY == hsai->State)
759  {
760  switch (CallbackID)
761  {
764  break;
767  break;
770  break;
773  break;
774  case HAL_SAI_ERROR_CB_ID :
776  break;
777  case HAL_SAI_MSPINIT_CB_ID :
779  break;
782  break;
783  default :
784  /* update the error code */
785  hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
786  /* update return status */
787  status = HAL_ERROR;
788  break;
789  }
790  }
791  else if (HAL_SAI_STATE_RESET == hsai->State)
792  {
793  switch (CallbackID)
794  {
795  case HAL_SAI_MSPINIT_CB_ID :
797  break;
800  break;
801  default :
802  /* update the error code */
803  hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
804  /* update return status */
805  status = HAL_ERROR;
806  break;
807  }
808  }
809  else
810  {
811  /* update the error code */
812  hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
813  /* update return status */
814  status = HAL_ERROR;
815  }
816  return status;
817 }
818 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
819 
875 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
876 {
877  uint32_t tickstart = HAL_GetTick();
878 
879  if ((pData == NULL) || (Size == 0))
880  {
881  return HAL_ERROR;
882  }
883 
884  if (hsai->State == HAL_SAI_STATE_READY)
885  {
886  /* Process Locked */
887  __HAL_LOCK(hsai);
888 
889  hsai->XferSize = Size;
890  hsai->XferCount = Size;
891  hsai->pBuffPtr = pData;
893  hsai->ErrorCode = HAL_SAI_ERROR_NONE;
894 
895  /* Check if the SAI is already enabled */
896  if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
897  {
898  /* fill the fifo with data before to enabled the SAI */
899  SAI_FillFifo(hsai);
900  /* Enable SAI peripheral */
901  __HAL_SAI_ENABLE(hsai);
902  }
903 
904  while (hsai->XferCount > 0U)
905  {
906  /* Write data if the FIFO is not full */
907  if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
908  {
909  if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
910  {
911  hsai->Instance->DR = (*hsai->pBuffPtr++);
912  }
913  else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
914  {
915  hsai->Instance->DR = *((uint16_t *)hsai->pBuffPtr);
916  hsai->pBuffPtr += 2U;
917  }
918  else
919  {
920  hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
921  hsai->pBuffPtr += 4U;
922  }
923  hsai->XferCount--;
924  }
925  else
926  {
927  /* Check for the Timeout */
928  if ((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)))
929  {
930  /* Update error code */
931  hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
932 
933  /* Clear all the flags */
934  hsai->Instance->CLRFR = 0xFFFFFFFFU;
935 
936  /* Disable SAI peripheral */
937  SAI_Disable(hsai);
938 
939  /* Flush the fifo */
940  SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
941 
942  /* Change the SAI state */
943  hsai->State = HAL_SAI_STATE_READY;
944 
945  /* Process Unlocked */
946  __HAL_UNLOCK(hsai);
947 
948  return HAL_ERROR;
949  }
950  }
951  }
952 
953  hsai->State = HAL_SAI_STATE_READY;
954 
955  /* Process Unlocked */
956  __HAL_UNLOCK(hsai);
957 
958  return HAL_OK;
959  }
960  else
961  {
962  return HAL_BUSY;
963  }
964 }
965 
975 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
976 {
977  uint32_t tickstart = HAL_GetTick();
978 
979  if ((pData == NULL) || (Size == 0))
980  {
981  return HAL_ERROR;
982  }
983 
984  if (hsai->State == HAL_SAI_STATE_READY)
985  {
986  /* Process Locked */
987  __HAL_LOCK(hsai);
988 
989  hsai->pBuffPtr = pData;
990  hsai->XferSize = Size;
991  hsai->XferCount = Size;
993  hsai->ErrorCode = HAL_SAI_ERROR_NONE;
994 
995  /* Check if the SAI is already enabled */
996  if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
997  {
998  /* Enable SAI peripheral */
999  __HAL_SAI_ENABLE(hsai);
1000  }
1001 
1002  /* Receive data */
1003  while (hsai->XferCount > 0U)
1004  {
1005  if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
1006  {
1007  if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1008  {
1009  (*hsai->pBuffPtr++) = hsai->Instance->DR;
1010  }
1011  else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1012  {
1013  *((uint16_t *)hsai->pBuffPtr) = hsai->Instance->DR;
1014  hsai->pBuffPtr += 2U;
1015  }
1016  else
1017  {
1018  *((uint32_t *)hsai->pBuffPtr) = hsai->Instance->DR;
1019  hsai->pBuffPtr += 4U;
1020  }
1021  hsai->XferCount--;
1022  }
1023  else
1024  {
1025  /* Check for the Timeout */
1026  if ((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)))
1027  {
1028  /* Update error code */
1029  hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1030 
1031  /* Clear all the flags */
1032  hsai->Instance->CLRFR = 0xFFFFFFFFU;
1033 
1034  /* Disable SAI peripheral */
1035  SAI_Disable(hsai);
1036 
1037  /* Flush the fifo */
1038  SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1039 
1040  /* Change the SAI state */
1041  hsai->State = HAL_SAI_STATE_READY;
1042 
1043  /* Process Unlocked */
1044  __HAL_UNLOCK(hsai);
1045 
1046  return HAL_ERROR;
1047  }
1048  }
1049  }
1050 
1051  hsai->State = HAL_SAI_STATE_READY;
1052 
1053  /* Process Unlocked */
1054  __HAL_UNLOCK(hsai);
1055 
1056  return HAL_OK;
1057  }
1058  else
1059  {
1060  return HAL_BUSY;
1061  }
1062 }
1063 
1072 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1073 {
1074  if ((pData == NULL) || (Size == 0))
1075  {
1076  return HAL_ERROR;
1077  }
1078 
1079  if (hsai->State == HAL_SAI_STATE_READY)
1080  {
1081  /* Process Locked */
1082  __HAL_LOCK(hsai);
1083 
1084  hsai->pBuffPtr = pData;
1085  hsai->XferSize = Size;
1086  hsai->XferCount = Size;
1087  hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1088  hsai->State = HAL_SAI_STATE_BUSY_TX;
1089 
1090  if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1091  {
1092  hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
1093  }
1094  else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1095  {
1096  hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
1097  }
1098  else
1099  {
1100  hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
1101  }
1102 
1103  /* Fill the fifo before starting the communication */
1104  SAI_FillFifo(hsai);
1105 
1106  /* Enable FRQ and OVRUDR interrupts */
1107  __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1108 
1109  /* Check if the SAI is already enabled */
1110  if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1111  {
1112  /* Enable SAI peripheral */
1113  __HAL_SAI_ENABLE(hsai);
1114  }
1115  /* Process Unlocked */
1116  __HAL_UNLOCK(hsai);
1117 
1118  return HAL_OK;
1119  }
1120  else
1121  {
1122  return HAL_BUSY;
1123  }
1124 }
1125 
1134 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1135 {
1136  if ((pData == NULL) || (Size == 0))
1137  {
1138  return HAL_ERROR;
1139  }
1140 
1141  if (hsai->State == HAL_SAI_STATE_READY)
1142  {
1143  /* Process Locked */
1144  __HAL_LOCK(hsai);
1145 
1146  hsai->pBuffPtr = pData;
1147  hsai->XferSize = Size;
1148  hsai->XferCount = Size;
1149  hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1150  hsai->State = HAL_SAI_STATE_BUSY_RX;
1151 
1152  if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1153  {
1154  hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
1155  }
1156  else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1157  {
1158  hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
1159  }
1160  else
1161  {
1162  hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
1163  }
1164 
1165  /* Enable TXE and OVRUDR interrupts */
1166  __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1167 
1168  /* Check if the SAI is already enabled */
1169  if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1170  {
1171  /* Enable SAI peripheral */
1172  __HAL_SAI_ENABLE(hsai);
1173  }
1174 
1175  /* Process Unlocked */
1176  __HAL_UNLOCK(hsai);
1177 
1178  return HAL_OK;
1179  }
1180  else
1181  {
1182  return HAL_BUSY;
1183  }
1184 }
1185 
1192 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
1193 {
1194  /* Process Locked */
1195  __HAL_LOCK(hsai);
1196 
1197  /* Pause the audio file playing by disabling the SAI DMA requests */
1198  hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1199 
1200  /* Process Unlocked */
1201  __HAL_UNLOCK(hsai);
1202 
1203  return HAL_OK;
1204 }
1205 
1212 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
1213 {
1214  /* Process Locked */
1215  __HAL_LOCK(hsai);
1216 
1217  /* Enable the SAI DMA requests */
1218  hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1219 
1220  /* If the SAI peripheral is still not enabled, enable it */
1221  if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1222  {
1223  /* Enable SAI peripheral */
1224  __HAL_SAI_ENABLE(hsai);
1225  }
1226 
1227  /* Process Unlocked */
1228  __HAL_UNLOCK(hsai);
1229 
1230  return HAL_OK;
1231 }
1232 
1239 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
1240 {
1241  HAL_StatusTypeDef status = HAL_OK;
1242 
1243  /* Process Locked */
1244  __HAL_LOCK(hsai);
1245 
1246  /* Disable SAI peripheral */
1247  SAI_Disable(hsai);
1248 
1249  /* Disable the SAI DMA request */
1250  hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1251 
1252  /* Abort the SAI Tx DMA Stream */
1253  if ((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX))
1254  {
1255  if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1256  {
1257  /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1258  if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1259  {
1260  status = HAL_ERROR;
1261  hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1262  }
1263  }
1264  }
1265 
1266  /* Abort the SAI Rx DMA Stream */
1267  if ((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX))
1268  {
1269  if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1270  {
1271  /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1272  if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1273  {
1274  status = HAL_ERROR;
1275  hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1276  }
1277  }
1278  }
1279 
1280  /* Flush the fifo */
1281  SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1282 
1283  /* Set hsai state to ready */
1284  hsai->State = HAL_SAI_STATE_READY;
1285 
1286  /* Process Unlocked */
1287  __HAL_UNLOCK(hsai);
1288 
1289  return status;
1290 }
1291 
1298 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
1299 {
1300  HAL_StatusTypeDef status = HAL_OK;
1301 
1302  /* Process Locked */
1303  __HAL_LOCK(hsai);
1304 
1305  /* Disable SAI peripheral */
1306  SAI_Disable(hsai);
1307 
1308  /* Check SAI DMA is enabled or not */
1309  if ((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1310  {
1311  /* Disable the SAI DMA request */
1312  hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1313 
1314  /* Abort the SAI Tx DMA Stream */
1315  if ((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX))
1316  {
1317  if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1318  {
1319  /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1320  if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1321  {
1322  status = HAL_ERROR;
1323  hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1324  }
1325  }
1326  }
1327 
1328  /* Abort the SAI Rx DMA Stream */
1329  if ((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX))
1330  {
1331  if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1332  {
1333  /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1334  if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1335  {
1336  status = HAL_ERROR;
1337  hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1338  }
1339  }
1340  }
1341  }
1342 
1343  /* Disabled All interrupt and clear all the flag */
1344  hsai->Instance->IMR = 0U;
1345  hsai->Instance->CLRFR = 0xFFFFFFFFU;
1346 
1347  /* Flush the fifo */
1348  SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1349 
1350  /* Set hsai state to ready */
1351  hsai->State = HAL_SAI_STATE_READY;
1352 
1353  /* Process Unlocked */
1354  __HAL_UNLOCK(hsai);
1355 
1356  return status;
1357 }
1358 
1367 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1368 {
1369  uint32_t tickstart = HAL_GetTick();
1370 
1371  if ((pData == NULL) || (Size == 0))
1372  {
1373  return HAL_ERROR;
1374  }
1375 
1376  if (hsai->State == HAL_SAI_STATE_READY)
1377  {
1378  /* Process Locked */
1379  __HAL_LOCK(hsai);
1380 
1381  hsai->pBuffPtr = pData;
1382  hsai->XferSize = Size;
1383  hsai->XferCount = Size;
1384  hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1385  hsai->State = HAL_SAI_STATE_BUSY_TX;
1386 
1387  /* Set the SAI Tx DMA Half transfer complete callback */
1388  hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
1389 
1390  /* Set the SAI TxDMA transfer complete callback */
1391  hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
1392 
1393  /* Set the DMA error callback */
1394  hsai->hdmatx->XferErrorCallback = SAI_DMAError;
1395 
1396  /* Set the DMA Tx abort callback */
1397  hsai->hdmatx->XferAbortCallback = NULL;
1398 
1399  /* Enable the Tx DMA Stream */
1400  if (HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
1401  {
1402  __HAL_UNLOCK(hsai);
1403  return HAL_ERROR;
1404  }
1405 
1406  /* Enable the interrupts for error handling */
1407  __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1408 
1409  /* Enable SAI Tx DMA Request */
1410  hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1411 
1412  /* Wait until FIFO is not empty */
1413  while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY)
1414  {
1415  /* Check for the Timeout */
1416  if ((HAL_GetTick() - tickstart) > SAI_LONG_TIMEOUT)
1417  {
1418  /* Update error code */
1419  hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1420 
1421  /* Process Unlocked */
1422  __HAL_UNLOCK(hsai);
1423 
1424  return HAL_TIMEOUT;
1425  }
1426  }
1427 
1428  /* Check if the SAI is already enabled */
1429  if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1430  {
1431  /* Enable SAI peripheral */
1432  __HAL_SAI_ENABLE(hsai);
1433  }
1434 
1435  /* Process Unlocked */
1436  __HAL_UNLOCK(hsai);
1437 
1438  return HAL_OK;
1439  }
1440  else
1441  {
1442  return HAL_BUSY;
1443  }
1444 }
1445 
1454 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1455 {
1456  if ((pData == NULL) || (Size == 0))
1457  {
1458  return HAL_ERROR;
1459  }
1460 
1461  if (hsai->State == HAL_SAI_STATE_READY)
1462  {
1463  /* Process Locked */
1464  __HAL_LOCK(hsai);
1465 
1466  hsai->pBuffPtr = pData;
1467  hsai->XferSize = Size;
1468  hsai->XferCount = Size;
1469  hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1470  hsai->State = HAL_SAI_STATE_BUSY_RX;
1471 
1472  /* Set the SAI Rx DMA Half transfer complete callback */
1473  hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
1474 
1475  /* Set the SAI Rx DMA transfer complete callback */
1476  hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
1477 
1478  /* Set the DMA error callback */
1479  hsai->hdmarx->XferErrorCallback = SAI_DMAError;
1480 
1481  /* Set the DMA Rx abort callback */
1482  hsai->hdmarx->XferAbortCallback = NULL;
1483 
1484  /* Enable the Rx DMA Stream */
1485  if (HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
1486  {
1487  __HAL_UNLOCK(hsai);
1488  return HAL_ERROR;
1489  }
1490 
1491  /* Enable the interrupts for error handling */
1492  __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1493 
1494  /* Enable SAI Rx DMA Request */
1495  hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1496 
1497  /* Check if the SAI is already enabled */
1498  if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1499  {
1500  /* Enable SAI peripheral */
1501  __HAL_SAI_ENABLE(hsai);
1502  }
1503 
1504  /* Process Unlocked */
1505  __HAL_UNLOCK(hsai);
1506 
1507  return HAL_OK;
1508  }
1509  else
1510  {
1511  return HAL_BUSY;
1512  }
1513 }
1514 
1522 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
1523 {
1524  assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
1525 
1526  if (hsai->State != HAL_SAI_STATE_RESET)
1527  {
1528  CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1529  SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | val);
1530  return HAL_OK;
1531  }
1532  return HAL_ERROR;
1533 }
1534 
1542 {
1543  if (hsai->State != HAL_SAI_STATE_RESET)
1544  {
1545  CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1546  return HAL_OK;
1547  }
1548  return HAL_ERROR;
1549 }
1550 
1559 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
1560 {
1561  assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
1562 
1563  if (hsai->State != HAL_SAI_STATE_RESET)
1564  {
1565  /* set the mute counter */
1566  CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
1567  SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
1568  hsai->mutecallback = callback;
1569  /* enable the IT interrupt */
1570  __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
1571  return HAL_OK;
1572  }
1573  return HAL_ERROR;
1574 }
1575 
1583 {
1584  if (hsai->State != HAL_SAI_STATE_RESET)
1585  {
1586  /* set the mutecallback to NULL */
1587  hsai->mutecallback = (SAIcallback)NULL;
1588  /* enable the IT interrupt */
1589  __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
1590  return HAL_OK;
1591  }
1592  return HAL_ERROR;
1593 }
1594 
1602 {
1603  if (hsai->State != HAL_SAI_STATE_RESET)
1604  {
1605  uint32_t itflags = hsai->Instance->SR;
1606  uint32_t itsources = hsai->Instance->IMR;
1607  uint32_t cr1config = hsai->Instance->CR1;
1608  uint32_t tmperror;
1609 
1610  /* SAI Fifo request interrupt occurred ------------------------------------*/
1611  if (((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
1612  {
1613  hsai->InterruptServiceRoutine(hsai);
1614  }
1615  /* SAI Overrun error interrupt occurred ----------------------------------*/
1616  else if (((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
1617  {
1618  /* Clear the SAI Overrun flag */
1619  __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1620 
1621  /* Get the SAI error code */
1622  tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
1623 
1624  /* Change the SAI error code */
1625  hsai->ErrorCode |= tmperror;
1626 
1627  /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1628 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1629  hsai->ErrorCallback(hsai);
1630 #else
1631  HAL_SAI_ErrorCallback(hsai);
1632 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1633  }
1634  /* SAI mutedet interrupt occurred ----------------------------------*/
1635  else if (((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
1636  {
1637  /* Clear the SAI mutedet flag */
1638  __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
1639 
1640  /* call the call back function */
1641  if (hsai->mutecallback != (SAIcallback)NULL)
1642  {
1643  /* inform the user that an RX mute event has been detected */
1644  hsai->mutecallback();
1645  }
1646  }
1647  /* SAI AFSDET interrupt occurred ----------------------------------*/
1648  else if (((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
1649  {
1650  /* Clear the SAI AFSDET flag */
1651  __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_AFSDET);
1652 
1653  /* Change the SAI error code */
1654  hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
1655 
1656  /* Check SAI DMA is enabled or not */
1657  if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1658  {
1659  /* Abort the SAI DMA Streams */
1660  if (hsai->hdmatx != NULL)
1661  {
1662  /* Set the DMA Tx abort callback */
1663  hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1664 
1665  /* Abort DMA in IT mode */
1666  HAL_DMA_Abort_IT(hsai->hdmatx);
1667  }
1668  else if (hsai->hdmarx != NULL)
1669  {
1670  /* Set the DMA Rx abort callback */
1671  hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1672 
1673  /* Abort DMA in IT mode */
1674  HAL_DMA_Abort_IT(hsai->hdmarx);
1675  }
1676  }
1677  else
1678  {
1679  /* Abort SAI */
1680  HAL_SAI_Abort(hsai);
1681 
1682  /* Set error callback */
1683 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1684  hsai->ErrorCallback(hsai);
1685 #else
1686  HAL_SAI_ErrorCallback(hsai);
1687 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1688  }
1689  }
1690  /* SAI LFSDET interrupt occurred ----------------------------------*/
1691  else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
1692  {
1693  /* Clear the SAI LFSDET flag */
1694  __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_LFSDET);
1695 
1696  /* Change the SAI error code */
1697  hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
1698 
1699  /* Check SAI DMA is enabled or not */
1700  if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1701  {
1702  /* Abort the SAI DMA Streams */
1703  if (hsai->hdmatx != NULL)
1704  {
1705  /* Set the DMA Tx abort callback */
1706  hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1707 
1708  /* Abort DMA in IT mode */
1709  HAL_DMA_Abort_IT(hsai->hdmatx);
1710  }
1711  else if (hsai->hdmarx != NULL)
1712  {
1713  /* Set the DMA Rx abort callback */
1714  hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1715 
1716  /* Abort DMA in IT mode */
1717  HAL_DMA_Abort_IT(hsai->hdmarx);
1718  }
1719  }
1720  else
1721  {
1722  /* Abort SAI */
1723  HAL_SAI_Abort(hsai);
1724 
1725  /* Set error callback */
1726 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1727  hsai->ErrorCallback(hsai);
1728 #else
1729  HAL_SAI_ErrorCallback(hsai);
1730 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1731  }
1732  }
1733  /* SAI WCKCFG interrupt occurred ----------------------------------*/
1734  else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
1735  {
1736  /* Clear the SAI WCKCFG flag */
1737  __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_WCKCFG);
1738 
1739  /* Change the SAI error code */
1740  hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
1741 
1742  /* Check SAI DMA is enabled or not */
1743  if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1744  {
1745  /* Abort the SAI DMA Streams */
1746  if (hsai->hdmatx != NULL)
1747  {
1748  /* Set the DMA Tx abort callback */
1749  hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1750 
1751  /* Abort DMA in IT mode */
1752  HAL_DMA_Abort_IT(hsai->hdmatx);
1753  }
1754  else if (hsai->hdmarx != NULL)
1755  {
1756  /* Set the DMA Rx abort callback */
1757  hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1758 
1759  /* Abort DMA in IT mode */
1760  HAL_DMA_Abort_IT(hsai->hdmarx);
1761  }
1762  }
1763  else
1764  {
1765  /* If WCKCFG occurs, SAI audio block is automatically disabled */
1766  /* Disable all interrupts and clear all flags */
1767  hsai->Instance->IMR = 0U;
1768  hsai->Instance->CLRFR = 0xFFFFFFFFU;
1769 
1770  /* Set the SAI state to ready to be able to start again the process */
1771  hsai->State = HAL_SAI_STATE_READY;
1772 
1773  /* Initialize XferCount */
1774  hsai->XferCount = 0U;
1775 
1776  /* SAI error Callback */
1777 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1778  hsai->ErrorCallback(hsai);
1779 #else
1780  HAL_SAI_ErrorCallback(hsai);
1781 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1782  }
1783  }
1784  /* SAI CNRDY interrupt occurred ----------------------------------*/
1785  else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
1786  {
1787  /* Clear the SAI CNRDY flag */
1788  __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
1789 
1790  /* Change the SAI error code */
1791  hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
1792 
1793  /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1794 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1795  hsai->ErrorCallback(hsai);
1796 #else
1797  HAL_SAI_ErrorCallback(hsai);
1798 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1799  }
1800  else
1801  {
1802  /* Nothing to do */
1803  }
1804  }
1805 }
1806 
1814 {
1815  /* Prevent unused argument(s) compilation warning */
1816  UNUSED(hsai);
1817 
1818  /* NOTE : This function should not be modified, when the callback is needed,
1819  the HAL_SAI_TxCpltCallback could be implemented in the user file
1820  */
1821 }
1822 
1830 {
1831  /* Prevent unused argument(s) compilation warning */
1832  UNUSED(hsai);
1833 
1834  /* NOTE : This function should not be modified, when the callback is needed,
1835  the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
1836  */
1837 }
1838 
1846 {
1847  /* Prevent unused argument(s) compilation warning */
1848  UNUSED(hsai);
1849 
1850  /* NOTE : This function should not be modified, when the callback is needed,
1851  the HAL_SAI_RxCpltCallback could be implemented in the user file
1852  */
1853 }
1854 
1862 {
1863  /* Prevent unused argument(s) compilation warning */
1864  UNUSED(hsai);
1865 
1866  /* NOTE : This function should not be modified, when the callback is needed,
1867  the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
1868  */
1869 }
1870 
1878 {
1879  /* Prevent unused argument(s) compilation warning */
1880  UNUSED(hsai);
1881 
1882  /* NOTE : This function should not be modified, when the callback is needed,
1883  the HAL_SAI_ErrorCallback could be implemented in the user file
1884  */
1885 }
1886 
1913 {
1914  return hsai->State;
1915 }
1916 
1924 {
1925  return hsai->ErrorCode;
1926 }
1952 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
1953 {
1954  hsai->Init.Protocol = SAI_FREE_PROTOCOL;
1955  hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
1956  /* Compute ClockStrobing according AudioMode */
1957  if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
1958  {
1959  /* Transmit */
1960  hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
1961  }
1962  else
1963  {
1964  /* Receive */
1965  hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
1966  }
1967  hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
1968  hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
1969  hsai->SlotInit.FirstBitOffset = 0U;
1970  hsai->SlotInit.SlotNumber = nbslot;
1971 
1972  /* in IS2 the number of slot must be even */
1973  if ((nbslot & 0x1U) != 0U)
1974  {
1975  return HAL_ERROR;
1976  }
1977 
1978  if (protocol == SAI_I2S_STANDARD)
1979  {
1980  hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
1981  hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
1982  }
1983  else
1984  {
1985  /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
1986  hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
1987  hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT;
1988  }
1989 
1990  /* Frame definition */
1991  switch (datasize)
1992  {
1993  case SAI_PROTOCOL_DATASIZE_16BIT:
1994  hsai->Init.DataSize = SAI_DATASIZE_16;
1995  hsai->FrameInit.FrameLength = 32U * (nbslot / 2U);
1996  hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U);
1997  hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
1998  break;
1999  case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2000  hsai->Init.DataSize = SAI_DATASIZE_16;
2001  hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2002  hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2003  hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2004  break;
2005  case SAI_PROTOCOL_DATASIZE_24BIT:
2006  hsai->Init.DataSize = SAI_DATASIZE_24;
2007  hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2008  hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2009  hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2010  break;
2011  case SAI_PROTOCOL_DATASIZE_32BIT:
2012  hsai->Init.DataSize = SAI_DATASIZE_32;
2013  hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2014  hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2015  hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2016  break;
2017  default :
2018  return HAL_ERROR;
2019  }
2020  if (protocol == SAI_I2S_LSBJUSTIFIED)
2021  {
2022  if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
2023  {
2024  hsai->SlotInit.FirstBitOffset = 16U;
2025  }
2026  if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
2027  {
2028  hsai->SlotInit.FirstBitOffset = 8U;
2029  }
2030  }
2031  return HAL_OK;
2032 }
2033 
2044 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2045 {
2046  hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2047  hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2048  /* Compute ClockStrobing according AudioMode */
2049  if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2050  {
2051  /* Transmit */
2052  hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2053  }
2054  else
2055  {
2056  /* Receive */
2057  hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2058  }
2059  hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME;
2060  hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2061  hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2062  hsai->SlotInit.FirstBitOffset = 0U;
2063  hsai->SlotInit.SlotNumber = nbslot;
2064  hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2065 
2066  if (protocol == SAI_PCM_SHORT)
2067  {
2068  hsai->FrameInit.ActiveFrameLength = 1;
2069  }
2070  else
2071  {
2072  /* SAI_PCM_LONG */
2073  hsai->FrameInit.ActiveFrameLength = 13;
2074  }
2075 
2076  switch (datasize)
2077  {
2078  case SAI_PROTOCOL_DATASIZE_16BIT:
2079  hsai->Init.DataSize = SAI_DATASIZE_16;
2080  hsai->FrameInit.FrameLength = 16U * nbslot;
2081  hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2082  break;
2083  case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2084  hsai->Init.DataSize = SAI_DATASIZE_16;
2085  hsai->FrameInit.FrameLength = 32U * nbslot;
2086  hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2087  break;
2088  case SAI_PROTOCOL_DATASIZE_24BIT :
2089  hsai->Init.DataSize = SAI_DATASIZE_24;
2090  hsai->FrameInit.FrameLength = 32U * nbslot;
2091  hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2092  break;
2093  case SAI_PROTOCOL_DATASIZE_32BIT:
2094  hsai->Init.DataSize = SAI_DATASIZE_32;
2095  hsai->FrameInit.FrameLength = 32U * nbslot;
2096  hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2097  break;
2098  default :
2099  return HAL_ERROR;
2100  }
2101 
2102  return HAL_OK;
2103 }
2104 
2111 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
2112 {
2113  /* fill the fifo with data before to enabled the SAI */
2114  while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
2115  {
2116  if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
2117  {
2118  hsai->Instance->DR = (*hsai->pBuffPtr++);
2119  }
2120  else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
2121  {
2122  hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
2123  hsai->pBuffPtr += 2U;
2124  }
2125  else
2126  {
2127  hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
2128  hsai->pBuffPtr += 4U;
2129  }
2130  hsai->XferCount--;
2131  }
2132 }
2133 
2141 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, uint32_t mode)
2142 {
2143  uint32_t tmpIT = SAI_IT_OVRUDR;
2144 
2145  if (mode == SAI_MODE_IT)
2146  {
2147  tmpIT |= SAI_IT_FREQ;
2148  }
2149 
2150  if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
2151  ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
2152  {
2153  tmpIT |= SAI_IT_CNRDY;
2154  }
2155 
2156  if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2157  {
2158  tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET;
2159  }
2160  else
2161  {
2162  /* hsai has been configured in master mode */
2163  tmpIT |= SAI_IT_WCKCFG;
2164  }
2165  return tmpIT;
2166 }
2167 
2174 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
2175 {
2176  uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U);
2177  HAL_StatusTypeDef status = HAL_OK;
2178 
2179  /* Disable the SAI instance */
2180  __HAL_SAI_DISABLE(hsai);
2181 
2182  do
2183  {
2184  /* Check for the Timeout */
2185  if (count-- == 0U)
2186  {
2187  /* Update error code */
2188  hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
2189  status = HAL_TIMEOUT;
2190  break;
2191  }
2192  }
2193  while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != RESET);
2194 
2195  return status;
2196 }
2197 
2204 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
2205 {
2206  if (hsai->XferCount == 0U)
2207  {
2208  /* Handle the end of the transmission */
2209  /* Disable FREQ and OVRUDR interrupts */
2210  __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2211  hsai->State = HAL_SAI_STATE_READY;
2212 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2213  hsai->TxCpltCallback(hsai);
2214 #else
2215  HAL_SAI_TxCpltCallback(hsai);
2216 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2217  }
2218  else
2219  {
2220  /* Write data on DR register */
2221  hsai->Instance->DR = (*hsai->pBuffPtr++);
2222  hsai->XferCount--;
2223  }
2224 }
2225 
2232 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
2233 {
2234  if (hsai->XferCount == 0U)
2235  {
2236  /* Handle the end of the transmission */
2237  /* Disable FREQ and OVRUDR interrupts */
2238  __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2239  hsai->State = HAL_SAI_STATE_READY;
2240 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2241  hsai->TxCpltCallback(hsai);
2242 #else
2243  HAL_SAI_TxCpltCallback(hsai);
2244 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2245  }
2246  else
2247  {
2248  /* Write data on DR register */
2249  hsai->Instance->DR = *(uint16_t *)hsai->pBuffPtr;
2250  hsai->pBuffPtr += 2U;
2251  hsai->XferCount--;
2252  }
2253 }
2254 
2261 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
2262 {
2263  if (hsai->XferCount == 0U)
2264  {
2265  /* Handle the end of the transmission */
2266  /* Disable FREQ and OVRUDR interrupts */
2267  __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2268  hsai->State = HAL_SAI_STATE_READY;
2269 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2270  hsai->TxCpltCallback(hsai);
2271 #else
2272  HAL_SAI_TxCpltCallback(hsai);
2273 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2274  }
2275  else
2276  {
2277  /* Write data on DR register */
2278  hsai->Instance->DR = *(uint32_t *)hsai->pBuffPtr;
2279  hsai->pBuffPtr += 4U;
2280  hsai->XferCount--;
2281  }
2282 }
2283 
2290 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
2291 {
2292  /* Receive data */
2293  (*hsai->pBuffPtr++) = hsai->Instance->DR;
2294  hsai->XferCount--;
2295 
2296  /* Check end of the transfer */
2297  if (hsai->XferCount == 0U)
2298  {
2299  /* Disable TXE and OVRUDR interrupts */
2300  __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2301 
2302  /* Clear the SAI Overrun flag */
2303  __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2304 
2305  hsai->State = HAL_SAI_STATE_READY;
2306 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2307  hsai->RxCpltCallback(hsai);
2308 #else
2309  HAL_SAI_RxCpltCallback(hsai);
2310 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2311  }
2312 }
2313 
2320 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
2321 {
2322  /* Receive data */
2323  *(uint16_t *)hsai->pBuffPtr = hsai->Instance->DR;
2324  hsai->pBuffPtr += 2U;
2325  hsai->XferCount--;
2326 
2327  /* Check end of the transfer */
2328  if (hsai->XferCount == 0U)
2329  {
2330  /* Disable TXE and OVRUDR interrupts */
2331  __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2332 
2333  /* Clear the SAI Overrun flag */
2334  __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2335 
2336  hsai->State = HAL_SAI_STATE_READY;
2337 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2338  hsai->RxCpltCallback(hsai);
2339 #else
2340  HAL_SAI_RxCpltCallback(hsai);
2341 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2342  }
2343 }
2344 
2351 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
2352 {
2353  /* Receive data */
2354  *(uint32_t *)hsai->pBuffPtr = hsai->Instance->DR;
2355  hsai->pBuffPtr += 4U;
2356  hsai->XferCount--;
2357 
2358  /* Check end of the transfer */
2359  if (hsai->XferCount == 0U)
2360  {
2361  /* Disable TXE and OVRUDR interrupts */
2362  __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2363 
2364  /* Clear the SAI Overrun flag */
2365  __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2366 
2367  hsai->State = HAL_SAI_STATE_READY;
2368 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2369  hsai->RxCpltCallback(hsai);
2370 #else
2371  HAL_SAI_RxCpltCallback(hsai);
2372 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2373  }
2374 }
2375 
2382 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
2383 {
2384  SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2385 
2386  if (hdma->Init.Mode != DMA_CIRCULAR)
2387  {
2388  hsai->XferCount = 0U;
2389 
2390  /* Disable SAI Tx DMA Request */
2391  hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2392 
2393  /* Stop the interrupts error handling */
2394  __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2395 
2396  hsai->State = HAL_SAI_STATE_READY;
2397  }
2398 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2399  hsai->TxCpltCallback(hsai);
2400 #else
2401  HAL_SAI_TxCpltCallback(hsai);
2402 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2403 }
2404 
2411 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
2412 {
2413  SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2414 
2415 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2416  hsai->TxHalfCpltCallback(hsai);
2417 #else
2419 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2420 }
2421 
2428 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
2429 {
2430  SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2431 
2432  if (hdma->Init.Mode != DMA_CIRCULAR)
2433  {
2434  /* Disable Rx DMA Request */
2435  hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2436  hsai->XferCount = 0U;
2437 
2438  /* Stop the interrupts error handling */
2439  __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2440 
2441  hsai->State = HAL_SAI_STATE_READY;
2442  }
2443 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2444  hsai->RxCpltCallback(hsai);
2445 #else
2446  HAL_SAI_RxCpltCallback(hsai);
2447 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2448 }
2449 
2456 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
2457 {
2458  SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2459 
2460 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2461  hsai->RxHalfCpltCallback(hsai);
2462 #else
2464 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2465 }
2466 
2473 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
2474 {
2475  SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2476 
2477  /* Set SAI error code */
2478  hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2479 
2480  if ((hsai->hdmatx->ErrorCode == HAL_DMA_ERROR_TE) || (hsai->hdmarx->ErrorCode == HAL_DMA_ERROR_TE))
2481  {
2482  /* Disable the SAI DMA request */
2483  hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2484 
2485  /* Disable SAI peripheral */
2486  SAI_Disable(hsai);
2487 
2488  /* Set the SAI state ready to be able to start again the process */
2489  hsai->State = HAL_SAI_STATE_READY;
2490 
2491  /* Initialize XferCount */
2492  hsai->XferCount = 0U;
2493  }
2494  /* SAI error Callback */
2495 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2496  hsai->ErrorCallback(hsai);
2497 #else
2498  HAL_SAI_ErrorCallback(hsai);
2499 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2500 }
2501 
2508 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
2509 {
2510  SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2511 
2512  /* Disable DMA request */
2513  hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2514 
2515  /* Disable all interrupts and clear all flags */
2516  hsai->Instance->IMR = 0U;
2517  hsai->Instance->CLRFR = 0xFFFFFFFFU;
2518 
2519  if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
2520  {
2521  /* Disable SAI peripheral */
2522  SAI_Disable(hsai);
2523 
2524  /* Flush the fifo */
2525  SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
2526  }
2527  /* Set the SAI state to ready to be able to start again the process */
2528  hsai->State = HAL_SAI_STATE_READY;
2529 
2530  /* Initialize XferCount */
2531  hsai->XferCount = 0U;
2532 
2533  /* SAI error Callback */
2534 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2535  hsai->ErrorCallback(hsai);
2536 #else
2537  HAL_SAI_ErrorCallback(hsai);
2538 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2539 }
2540 
2545 #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */
2546 #endif /* HAL_SAI_MODULE_ENABLED */
HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
Aborts the DMA Transfer.
HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
Aborts the DMA Transfer in Interrupt mode.
HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
Start the DMA Transfer with interrupt enabled.
uint32_t HAL_GetTick(void)
Provides a tick value in millisecond.
void SAI_BlockSynchroConfig(const SAI_HandleTypeDef *hsai)
Configure SAI Block synchronization mode.
uint32_t SAI_GetInputClock(const SAI_HandleTypeDef *hsai)
Get SAI Input Clock based on SAI source clock selection.
HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
Initialize the structure FrameInit, SlotInit and the low part of Init according to the specified para...
HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef *hsai, HAL_SAI_CallbackIDTypeDef CallbackID, pSAI_CallbackTypeDef pCallback)
Register a user SAI callback to be used instead of the weak predefined callback.
void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
Initialize the SAI MSP.
HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef *hsai, HAL_SAI_CallbackIDTypeDef CallbackID)
Unregister a user SAI callback. SAI callback is redirected to the weak predefined callback.
void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
DeInitialize the SAI MSP.
HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
Initialize the SAI according to the specified parameters. in the SAI_InitTypeDef structure and initia...
HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
DeInitialize the SAI peripheral.
HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
Abort the current transfer and disable the SAI.
HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
Receive an amount of data in non-blocking mode with DMA.
void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
Tx Transfer completed callback.
HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
Receive an amount of data in blocking mode.
HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
Transmit an amount of data in non-blocking mode with Interrupt.
HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
Resume the audio stream playing from the Media.
HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
Receive an amount of data in non-blocking mode with Interrupt.
HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
Disable the Rx mute detection.
HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
Enable the Rx mute detection.
HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
Stop the audio stream playing from the Media.
void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
Handle SAI interrupt request.
HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
Transmit an amount of data in blocking mode.
HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
Pause the audio stream playing from the Media.
void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
SAI error callback.
void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
Rx Transfer half completed callback.
HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
Transmit an amount of data in non-blocking mode with DMA.
void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
Tx Transfer Half completed callback.
HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
Disable the Tx mute mode.
HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
Enable the Tx mute mode.
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
Rx Transfer completed callback.
uint32_t HAL_SAI_GetError(const SAI_HandleTypeDef *hsai)
Return the SAI error code.
HAL_SAI_StateTypeDef HAL_SAI_GetState(const SAI_HandleTypeDef *hsai)
Return the SAI handle state.
void(* pSAI_CallbackTypeDef)(SAI_HandleTypeDef *hsai)
SAI callback pointer definition.
void(* SAIcallback)(void)
SAI Callback prototype.
HAL_SAI_CallbackIDTypeDef
SAI callback ID enumeration definition.
HAL_SAI_StateTypeDef
HAL State structures definition.
@ HAL_SAI_MSPDEINIT_CB_ID
@ HAL_SAI_RX_HALFCOMPLETE_CB_ID
@ HAL_SAI_TX_HALFCOMPLETE_CB_ID
@ HAL_SAI_TX_COMPLETE_CB_ID
@ HAL_SAI_ERROR_CB_ID
@ HAL_SAI_MSPINIT_CB_ID
@ HAL_SAI_RX_COMPLETE_CB_ID
@ HAL_SAI_STATE_RESET
@ HAL_SAI_STATE_BUSY_RX
@ HAL_SAI_STATE_READY
@ HAL_SAI_STATE_BUSY
@ HAL_SAI_STATE_BUSY_TX
HAL_LockTypeDef Lock
SAI_InitTypeDef Init
void(* TxHalfCpltCallback)(struct __SAI_HandleTypeDef *hsai)
DMA_HandleTypeDef * hdmatx
SAI_FrameInitTypeDef FrameInit
SAI_SlotInitTypeDef SlotInit
void(* RxCpltCallback)(struct __SAI_HandleTypeDef *hsai)
void(* RxHalfCpltCallback)(struct __SAI_HandleTypeDef *hsai)
void(* MspInitCallback)(struct __SAI_HandleTypeDef *hsai)
__IO HAL_SAI_StateTypeDef State
SAI_Block_TypeDef * Instance
void(* ErrorCallback)(struct __SAI_HandleTypeDef *hsai)
void(* TxCpltCallback)(struct __SAI_HandleTypeDef *hsai)
DMA_HandleTypeDef * hdmarx
void(* MspDeInitCallback)(struct __SAI_HandleTypeDef *hsai)
This file contains all the functions prototypes for the HAL module driver.
DMA handle Structure definition.
void(* XferAbortCallback)(struct __DMA_HandleTypeDef *hdma)
DMA_InitTypeDef Init
void(* XferCpltCallback)(struct __DMA_HandleTypeDef *hdma)
void(* XferErrorCallback)(struct __DMA_HandleTypeDef *hdma)
void(* XferHalfCpltCallback)(struct __DMA_HandleTypeDef *hdma)