STM32F4xx HAL Driver master
STM32CubeF4 HAL / LL Drivers API Reference
Loading...
Searching...
No Matches
stm32f4xx_hal_sai.c
Go to the documentation of this file.
1
214
215/* Includes ------------------------------------------------------------------*/
216#include "stm32f4xx_hal.h"
217
221
226
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
236typedef enum
237{
238 SAI_MODE_DMA,
239 SAI_MODE_IT
240} SAI_ModeTypedef;
244
245/* Private define ------------------------------------------------------------*/
246
250#define SAI_DEFAULT_TIMEOUT 4U /* 4ms */
251#define SAI_LONG_TIMEOUT 1000U /* 1s */
255
256/* Private macro -------------------------------------------------------------*/
257/* Private variables ---------------------------------------------------------*/
258/* Private function prototypes -----------------------------------------------*/
262static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
263static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, uint32_t mode);
264static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
265static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
266
267static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
268static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
269static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
270static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
271static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
272static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
273static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
274
275static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
276static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
277static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
278static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
279static void SAI_DMAError(DMA_HandleTypeDef *hdma);
280static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
284
285/* Exported functions ---------------------------------------------------------*/
289
320
333HAL_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
372HAL_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 */
429 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
430 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
431 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
432 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
433 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
434
435 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
436 if (hsai->MspInitCallback == NULL)
437 {
438 hsai->MspInitCallback = HAL_SAI_MspInit;
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 -----------------------------------------*/
453 SAI_BlockSynchroConfig(hsai);
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
569HAL_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 {
593 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
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
618__weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
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
634__weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
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)
661HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef *hsai,
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 {
680 case HAL_SAI_RX_COMPLETE_CB_ID :
681 hsai->RxCpltCallback = pCallback;
682 break;
683 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
684 hsai->RxHalfCpltCallback = pCallback;
685 break;
686 case HAL_SAI_TX_COMPLETE_CB_ID :
687 hsai->TxCpltCallback = pCallback;
688 break;
689 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
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;
698 case HAL_SAI_MSPDEINIT_CB_ID :
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;
716 case HAL_SAI_MSPDEINIT_CB_ID :
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
753HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef *hsai,
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 {
762 case HAL_SAI_RX_COMPLETE_CB_ID :
763 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
764 break;
765 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
766 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
767 break;
768 case HAL_SAI_TX_COMPLETE_CB_ID :
769 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
770 break;
771 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
772 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
773 break;
774 case HAL_SAI_ERROR_CB_ID :
775 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
776 break;
777 case HAL_SAI_MSPINIT_CB_ID :
778 hsai->MspInitCallback = HAL_SAI_MspInit;
779 break;
780 case HAL_SAI_MSPDEINIT_CB_ID :
781 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
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 :
796 hsai->MspInitCallback = HAL_SAI_MspInit;
797 break;
798 case HAL_SAI_MSPDEINIT_CB_ID :
799 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
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
823
865
875HAL_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;
892 hsai->State = HAL_SAI_STATE_BUSY_TX;
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
975HAL_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;
992 hsai->State = HAL_SAI_STATE_BUSY_RX;
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
1072HAL_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
1134HAL_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
1192HAL_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
1212HAL_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
1239HAL_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
1298HAL_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
1367HAL_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
1454HAL_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
1522HAL_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
1541HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
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
1559HAL_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
1582HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
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
1601void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
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 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1667 {
1668 /* Update SAI error code */
1669 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1670
1671 /* Call SAI error callback */
1672#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1673 hsai->ErrorCallback(hsai);
1674#else
1675 HAL_SAI_ErrorCallback(hsai);
1676#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1677 }
1678 }
1679 else if (hsai->hdmarx != NULL)
1680 {
1681 /* Set the DMA Rx abort callback */
1682 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1683
1684 /* Abort DMA in IT mode */
1685 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1686 {
1687 /* Update SAI error code */
1688 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1689
1690 /* Call SAI error callback */
1691#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1692 hsai->ErrorCallback(hsai);
1693#else
1694 HAL_SAI_ErrorCallback(hsai);
1695#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1696 }
1697 }
1698 }
1699 else
1700 {
1701 /* Abort SAI */
1702 HAL_SAI_Abort(hsai);
1703
1704 /* Set error callback */
1705#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1706 hsai->ErrorCallback(hsai);
1707#else
1708 HAL_SAI_ErrorCallback(hsai);
1709#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1710 }
1711 }
1712 /* SAI LFSDET interrupt occurred ----------------------------------*/
1713 else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
1714 {
1715 /* Clear the SAI LFSDET flag */
1716 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_LFSDET);
1717
1718 /* Change the SAI error code */
1719 hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
1720
1721 /* Check SAI DMA is enabled or not */
1722 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1723 {
1724 /* Abort the SAI DMA Streams */
1725 if (hsai->hdmatx != NULL)
1726 {
1727 /* Set the DMA Tx abort callback */
1728 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1729
1730 /* Abort DMA in IT mode */
1731 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1732 {
1733 /* Update SAI error code */
1734 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1735
1736 /* Call SAI error callback */
1737#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1738 hsai->ErrorCallback(hsai);
1739#else
1740 HAL_SAI_ErrorCallback(hsai);
1741#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1742 }
1743 }
1744 else if (hsai->hdmarx != NULL)
1745 {
1746 /* Set the DMA Rx abort callback */
1747 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1748
1749 /* Abort DMA in IT mode */
1750 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1751 {
1752 /* Update SAI error code */
1753 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1754
1755 /* Call SAI error callback */
1756#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1757 hsai->ErrorCallback(hsai);
1758#else
1759 HAL_SAI_ErrorCallback(hsai);
1760#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1761 }
1762 }
1763 }
1764 else
1765 {
1766 /* Abort SAI */
1767 HAL_SAI_Abort(hsai);
1768
1769 /* Set error callback */
1770#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1771 hsai->ErrorCallback(hsai);
1772#else
1773 HAL_SAI_ErrorCallback(hsai);
1774#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1775 }
1776 }
1777 /* SAI WCKCFG interrupt occurred ----------------------------------*/
1778 else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
1779 {
1780 /* Clear the SAI WCKCFG flag */
1781 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_WCKCFG);
1782
1783 /* Change the SAI error code */
1784 hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
1785
1786 /* Check SAI DMA is enabled or not */
1787 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1788 {
1789 /* Abort the SAI DMA Streams */
1790 if (hsai->hdmatx != NULL)
1791 {
1792 /* Set the DMA Tx abort callback */
1793 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1794
1795 /* Abort DMA in IT mode */
1796 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1797 {
1798 /* Update SAI error code */
1799 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1800
1801 /* Call SAI error callback */
1802#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1803 hsai->ErrorCallback(hsai);
1804#else
1805 HAL_SAI_ErrorCallback(hsai);
1806#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1807 }
1808 }
1809 else if (hsai->hdmarx != NULL)
1810 {
1811 /* Set the DMA Rx abort callback */
1812 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1813
1814 /* Abort DMA in IT mode */
1815 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1816 {
1817 /* Update SAI error code */
1818 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1819
1820 /* Call SAI error callback */
1821#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1822 hsai->ErrorCallback(hsai);
1823#else
1824 HAL_SAI_ErrorCallback(hsai);
1825#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1826 }
1827 }
1828 }
1829 else
1830 {
1831 /* If WCKCFG occurs, SAI audio block is automatically disabled */
1832 /* Disable all interrupts and clear all flags */
1833 hsai->Instance->IMR = 0U;
1834 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1835
1836 /* Set the SAI state to ready to be able to start again the process */
1837 hsai->State = HAL_SAI_STATE_READY;
1838
1839 /* Initialize XferCount */
1840 hsai->XferCount = 0U;
1841
1842 /* SAI error Callback */
1843#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1844 hsai->ErrorCallback(hsai);
1845#else
1846 HAL_SAI_ErrorCallback(hsai);
1847#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1848 }
1849 }
1850 /* SAI CNRDY interrupt occurred ----------------------------------*/
1851 else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
1852 {
1853 /* Clear the SAI CNRDY flag */
1854 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
1855
1856 /* Change the SAI error code */
1857 hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
1858
1859 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1860#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1861 hsai->ErrorCallback(hsai);
1862#else
1863 HAL_SAI_ErrorCallback(hsai);
1864#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1865 }
1866 else
1867 {
1868 /* Nothing to do */
1869 }
1870 }
1871}
1872
1879__weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
1880{
1881 /* Prevent unused argument(s) compilation warning */
1882 UNUSED(hsai);
1883
1884 /* NOTE : This function should not be modified, when the callback is needed,
1885 the HAL_SAI_TxCpltCallback could be implemented in the user file
1886 */
1887}
1888
1895__weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1896{
1897 /* Prevent unused argument(s) compilation warning */
1898 UNUSED(hsai);
1899
1900 /* NOTE : This function should not be modified, when the callback is needed,
1901 the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
1902 */
1903}
1904
1911__weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
1912{
1913 /* Prevent unused argument(s) compilation warning */
1914 UNUSED(hsai);
1915
1916 /* NOTE : This function should not be modified, when the callback is needed,
1917 the HAL_SAI_RxCpltCallback could be implemented in the user file
1918 */
1919}
1920
1927__weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1928{
1929 /* Prevent unused argument(s) compilation warning */
1930 UNUSED(hsai);
1931
1932 /* NOTE : This function should not be modified, when the callback is needed,
1933 the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
1934 */
1935}
1936
1943__weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
1944{
1945 /* Prevent unused argument(s) compilation warning */
1946 UNUSED(hsai);
1947
1948 /* NOTE : This function should not be modified, when the callback is needed,
1949 the HAL_SAI_ErrorCallback could be implemented in the user file
1950 */
1951}
1952
1956
1971
1978HAL_SAI_StateTypeDef HAL_SAI_GetState(const SAI_HandleTypeDef *hsai)
1979{
1980 return hsai->State;
1981}
1982
1989uint32_t HAL_SAI_GetError(const SAI_HandleTypeDef *hsai)
1990{
1991 return hsai->ErrorCode;
1992}
1996
2000
2005
2018static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2019{
2020 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2021 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2022 /* Compute ClockStrobing according AudioMode */
2023 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2024 {
2025 /* Transmit */
2026 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2027 }
2028 else
2029 {
2030 /* Receive */
2031 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2032 }
2033 hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
2034 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2035 hsai->SlotInit.FirstBitOffset = 0U;
2036 hsai->SlotInit.SlotNumber = nbslot;
2037
2038 /* in IS2 the number of slot must be even */
2039 if ((nbslot & 0x1U) != 0U)
2040 {
2041 return HAL_ERROR;
2042 }
2043
2044 if (protocol == SAI_I2S_STANDARD)
2045 {
2046 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
2047 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2048 }
2049 else
2050 {
2051 /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
2052 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2053 hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT;
2054 }
2055
2056 /* Frame definition */
2057 switch (datasize)
2058 {
2059 case SAI_PROTOCOL_DATASIZE_16BIT:
2060 hsai->Init.DataSize = SAI_DATASIZE_16;
2061 hsai->FrameInit.FrameLength = 32U * (nbslot / 2U);
2062 hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U);
2063 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2064 break;
2065 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2066 hsai->Init.DataSize = SAI_DATASIZE_16;
2067 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2068 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2069 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2070 break;
2071 case SAI_PROTOCOL_DATASIZE_24BIT:
2072 hsai->Init.DataSize = SAI_DATASIZE_24;
2073 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2074 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2075 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2076 break;
2077 case SAI_PROTOCOL_DATASIZE_32BIT:
2078 hsai->Init.DataSize = SAI_DATASIZE_32;
2079 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2080 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2081 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2082 break;
2083 default :
2084 return HAL_ERROR;
2085 }
2086 if (protocol == SAI_I2S_LSBJUSTIFIED)
2087 {
2088 if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
2089 {
2090 hsai->SlotInit.FirstBitOffset = 16U;
2091 }
2092 if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
2093 {
2094 hsai->SlotInit.FirstBitOffset = 8U;
2095 }
2096 }
2097 return HAL_OK;
2098}
2099
2110static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2111{
2112 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2113 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2114 /* Compute ClockStrobing according AudioMode */
2115 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2116 {
2117 /* Transmit */
2118 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2119 }
2120 else
2121 {
2122 /* Receive */
2123 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2124 }
2125 hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME;
2126 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2127 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2128 hsai->SlotInit.FirstBitOffset = 0U;
2129 hsai->SlotInit.SlotNumber = nbslot;
2130 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2131
2132 if (protocol == SAI_PCM_SHORT)
2133 {
2134 hsai->FrameInit.ActiveFrameLength = 1;
2135 }
2136 else
2137 {
2138 /* SAI_PCM_LONG */
2139 hsai->FrameInit.ActiveFrameLength = 13;
2140 }
2141
2142 switch (datasize)
2143 {
2144 case SAI_PROTOCOL_DATASIZE_16BIT:
2145 hsai->Init.DataSize = SAI_DATASIZE_16;
2146 hsai->FrameInit.FrameLength = 16U * nbslot;
2147 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2148 break;
2149 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2150 hsai->Init.DataSize = SAI_DATASIZE_16;
2151 hsai->FrameInit.FrameLength = 32U * nbslot;
2152 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2153 break;
2154 case SAI_PROTOCOL_DATASIZE_24BIT :
2155 hsai->Init.DataSize = SAI_DATASIZE_24;
2156 hsai->FrameInit.FrameLength = 32U * nbslot;
2157 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2158 break;
2159 case SAI_PROTOCOL_DATASIZE_32BIT:
2160 hsai->Init.DataSize = SAI_DATASIZE_32;
2161 hsai->FrameInit.FrameLength = 32U * nbslot;
2162 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2163 break;
2164 default :
2165 return HAL_ERROR;
2166 }
2167
2168 return HAL_OK;
2169}
2170
2177static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
2178{
2179 /* fill the fifo with data before to enabled the SAI */
2180 while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
2181 {
2182 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
2183 {
2184 hsai->Instance->DR = (*hsai->pBuffPtr++);
2185 }
2186 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
2187 {
2188 hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
2189 hsai->pBuffPtr += 2U;
2190 }
2191 else
2192 {
2193 hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
2194 hsai->pBuffPtr += 4U;
2195 }
2196 hsai->XferCount--;
2197 }
2198}
2199
2207static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, uint32_t mode)
2208{
2209 uint32_t tmpIT = SAI_IT_OVRUDR;
2210
2211 if (mode == SAI_MODE_IT)
2212 {
2213 tmpIT |= SAI_IT_FREQ;
2214 }
2215
2216 if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
2217 ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
2218 {
2219 tmpIT |= SAI_IT_CNRDY;
2220 }
2221
2222 if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2223 {
2224 tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET;
2225 }
2226 else
2227 {
2228 /* hsai has been configured in master mode */
2229 tmpIT |= SAI_IT_WCKCFG;
2230 }
2231 return tmpIT;
2232}
2233
2240static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
2241{
2242 uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U);
2243 HAL_StatusTypeDef status = HAL_OK;
2244
2245 /* Disable the SAI instance */
2246 __HAL_SAI_DISABLE(hsai);
2247
2248 do
2249 {
2250 /* Check for the Timeout */
2251 if (count-- == 0U)
2252 {
2253 /* Update error code */
2254 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
2255 status = HAL_TIMEOUT;
2256 break;
2257 }
2258 }
2259 while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != RESET);
2260
2261 return status;
2262}
2263
2270static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
2271{
2272 if (hsai->XferCount == 0U)
2273 {
2274 /* Handle the end of the transmission */
2275 /* Disable FREQ and OVRUDR interrupts */
2276 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2277 hsai->State = HAL_SAI_STATE_READY;
2278#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2279 hsai->TxCpltCallback(hsai);
2280#else
2281 HAL_SAI_TxCpltCallback(hsai);
2282#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2283 }
2284 else
2285 {
2286 /* Write data on DR register */
2287 hsai->Instance->DR = (*hsai->pBuffPtr++);
2288 hsai->XferCount--;
2289 }
2290}
2291
2298static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
2299{
2300 if (hsai->XferCount == 0U)
2301 {
2302 /* Handle the end of the transmission */
2303 /* Disable FREQ and OVRUDR interrupts */
2304 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2305 hsai->State = HAL_SAI_STATE_READY;
2306#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2307 hsai->TxCpltCallback(hsai);
2308#else
2309 HAL_SAI_TxCpltCallback(hsai);
2310#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2311 }
2312 else
2313 {
2314 /* Write data on DR register */
2315 hsai->Instance->DR = *(uint16_t *)hsai->pBuffPtr;
2316 hsai->pBuffPtr += 2U;
2317 hsai->XferCount--;
2318 }
2319}
2320
2327static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
2328{
2329 if (hsai->XferCount == 0U)
2330 {
2331 /* Handle the end of the transmission */
2332 /* Disable FREQ and OVRUDR interrupts */
2333 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2334 hsai->State = HAL_SAI_STATE_READY;
2335#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2336 hsai->TxCpltCallback(hsai);
2337#else
2338 HAL_SAI_TxCpltCallback(hsai);
2339#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2340 }
2341 else
2342 {
2343 /* Write data on DR register */
2344 hsai->Instance->DR = *(uint32_t *)hsai->pBuffPtr;
2345 hsai->pBuffPtr += 4U;
2346 hsai->XferCount--;
2347 }
2348}
2349
2356static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
2357{
2358 /* Receive data */
2359 (*hsai->pBuffPtr++) = hsai->Instance->DR;
2360 hsai->XferCount--;
2361
2362 /* Check end of the transfer */
2363 if (hsai->XferCount == 0U)
2364 {
2365 /* Disable TXE and OVRUDR interrupts */
2366 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2367
2368 /* Clear the SAI Overrun flag */
2369 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2370
2371 hsai->State = HAL_SAI_STATE_READY;
2372#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2373 hsai->RxCpltCallback(hsai);
2374#else
2375 HAL_SAI_RxCpltCallback(hsai);
2376#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2377 }
2378}
2379
2386static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
2387{
2388 /* Receive data */
2389 *(uint16_t *)hsai->pBuffPtr = hsai->Instance->DR;
2390 hsai->pBuffPtr += 2U;
2391 hsai->XferCount--;
2392
2393 /* Check end of the transfer */
2394 if (hsai->XferCount == 0U)
2395 {
2396 /* Disable TXE and OVRUDR interrupts */
2397 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2398
2399 /* Clear the SAI Overrun flag */
2400 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2401
2402 hsai->State = HAL_SAI_STATE_READY;
2403#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2404 hsai->RxCpltCallback(hsai);
2405#else
2406 HAL_SAI_RxCpltCallback(hsai);
2407#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2408 }
2409}
2410
2417static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
2418{
2419 /* Receive data */
2420 *(uint32_t *)hsai->pBuffPtr = hsai->Instance->DR;
2421 hsai->pBuffPtr += 4U;
2422 hsai->XferCount--;
2423
2424 /* Check end of the transfer */
2425 if (hsai->XferCount == 0U)
2426 {
2427 /* Disable TXE and OVRUDR interrupts */
2428 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2429
2430 /* Clear the SAI Overrun flag */
2431 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2432
2433 hsai->State = HAL_SAI_STATE_READY;
2434#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2435 hsai->RxCpltCallback(hsai);
2436#else
2437 HAL_SAI_RxCpltCallback(hsai);
2438#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2439 }
2440}
2441
2448static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
2449{
2450 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2451
2452 if (hdma->Init.Mode != DMA_CIRCULAR)
2453 {
2454 hsai->XferCount = 0U;
2455
2456 /* Disable SAI Tx DMA Request */
2457 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2458
2459 /* Stop the interrupts error handling */
2460 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2461
2462 hsai->State = HAL_SAI_STATE_READY;
2463 }
2464#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2465 hsai->TxCpltCallback(hsai);
2466#else
2467 HAL_SAI_TxCpltCallback(hsai);
2468#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2469}
2470
2477static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
2478{
2479 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2480
2481#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2482 hsai->TxHalfCpltCallback(hsai);
2483#else
2484 HAL_SAI_TxHalfCpltCallback(hsai);
2485#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2486}
2487
2494static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
2495{
2496 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2497
2498 if (hdma->Init.Mode != DMA_CIRCULAR)
2499 {
2500 /* Disable Rx DMA Request */
2501 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2502 hsai->XferCount = 0U;
2503
2504 /* Stop the interrupts error handling */
2505 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2506
2507 hsai->State = HAL_SAI_STATE_READY;
2508 }
2509#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2510 hsai->RxCpltCallback(hsai);
2511#else
2512 HAL_SAI_RxCpltCallback(hsai);
2513#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2514}
2515
2522static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
2523{
2524 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2525
2526#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2527 hsai->RxHalfCpltCallback(hsai);
2528#else
2529 HAL_SAI_RxHalfCpltCallback(hsai);
2530#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2531}
2532
2539static void SAI_DMAError(DMA_HandleTypeDef *hdma)
2540{
2541 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2542
2543 /* Set SAI error code */
2544 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2545
2546 if ((hsai->hdmatx->ErrorCode == HAL_DMA_ERROR_TE) || (hsai->hdmarx->ErrorCode == HAL_DMA_ERROR_TE))
2547 {
2548 /* Disable the SAI DMA request */
2549 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2550
2551 /* Disable SAI peripheral */
2552 SAI_Disable(hsai);
2553
2554 /* Set the SAI state ready to be able to start again the process */
2555 hsai->State = HAL_SAI_STATE_READY;
2556
2557 /* Initialize XferCount */
2558 hsai->XferCount = 0U;
2559 }
2560 /* SAI error Callback */
2561#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2562 hsai->ErrorCallback(hsai);
2563#else
2564 HAL_SAI_ErrorCallback(hsai);
2565#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2566}
2567
2574static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
2575{
2576 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2577
2578 /* Disable DMA request */
2579 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2580
2581 /* Disable all interrupts and clear all flags */
2582 hsai->Instance->IMR = 0U;
2583 hsai->Instance->CLRFR = 0xFFFFFFFFU;
2584
2585 if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
2586 {
2587 /* Disable SAI peripheral */
2588 SAI_Disable(hsai);
2589
2590 /* Flush the fifo */
2591 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
2592 }
2593 /* Set the SAI state to ready to be able to start again the process */
2594 hsai->State = HAL_SAI_STATE_READY;
2595
2596 /* Initialize XferCount */
2597 hsai->XferCount = 0U;
2598
2599 /* SAI error Callback */
2600#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2601 hsai->ErrorCallback(hsai);
2602#else
2603 HAL_SAI_ErrorCallback(hsai);
2604#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2605}
2606
2610
2611#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */
2612#endif /* HAL_SAI_MODULE_ENABLED */
2616
2620
#define HAL_DMA_ERROR_TE
#define HAL_DMA_ERROR_NO_XFER
HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
struct __DMA_HandleTypeDef DMA_HandleTypeDef
DMA handle Structure definition.
#define DMA_CIRCULAR
uint32_t HAL_GetTick(void)
Provides a tick value in millisecond.
#define assert_param(expr)
This file contains all the functions prototypes for the HAL module driver.
HAL_StatusTypeDef
HAL Status structures definition.
@ HAL_TIMEOUT
@ HAL_ERROR
@ HAL_OK
@ HAL_BUSY
#define __HAL_UNLOCK(__HANDLE__)
#define HAL_MAX_DELAY
@ HAL_UNLOCKED
#define __HAL_LOCK(__HANDLE__)