From 4a38cf6f44d1c013cbe794093ea6c5b50337431a Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Thu, 14 Apr 2016 18:50:38 -0400 Subject: import mbed rtos library --- .../Src/stm32f4xx_hal_i2s_ex.c | 1479 -------------------- 1 file changed, 1479 deletions(-) delete mode 100644 Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c (limited to 'Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c') diff --git a/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c b/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c deleted file mode 100644 index 3296c13..0000000 --- a/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c +++ /dev/null @@ -1,1479 +0,0 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_i2s_ex.c - * @author MCD Application Team - * @version V1.3.2 - * @date 26-June-2015 - * @brief I2S HAL module driver. - * This file provides firmware functions to manage the following - * functionalities of I2S extension peripheral: - * + Extension features Functions - * - @verbatim - ============================================================================== - ##### I2S Extension features ##### - ============================================================================== - [..] - (#) In I2S full duplex mode, each SPI peripheral is able to manage sending and receiving - data simultaneously using two data lines. Each SPI peripheral has an extended block - called I2Sxext (i.e I2S2ext for SPI2 and I2S3ext for SPI3). - (#) The extension block is not a full SPI IP, it is used only as I2S slave to - implement full duplex mode. The extension block uses the same clock sources - as its master. - - (#) Both I2Sx and I2Sx_ext can be configured as transmitters or receivers. - - [..] - (@) Only I2Sx can deliver SCK and WS to I2Sx_ext in full duplex mode, where - I2Sx can be I2S2 or I2S3. - - ##### How to use this driver ##### - =============================================================================== - [..] - Three operation modes are available within this driver : - - *** Polling mode IO operation *** - ================================= - [..] - (+) Send and receive in the same time an amount of data in blocking mode using HAL_I2S_TransmitReceive() - - *** Interrupt mode IO operation *** - =================================== - [..] - (+) Send and receive in the same time an amount of data in non blocking mode using HAL_I2S_TransmitReceive_IT() - (+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback - (+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2S_TxCpltCallback - (+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback - (+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2S_RxCpltCallback - (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can - add his own code by customization of function pointer HAL_I2S_ErrorCallback - - *** DMA mode IO operation *** - ============================== - [..] - (+) Send and receive an amount of data in non blocking mode (DMA) using HAL_I2S_TransmitReceive_DMA() - (+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback - (+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2S_TxCpltCallback - (+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback - (+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can - add his own code by customization of function pointer HAL_I2S_RxCpltCallback - (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can - add his own code by customization of function pointer HAL_I2S_ErrorCallback - (+) Pause the DMA Transfer using HAL_I2S_DMAPause() - (+) Resume the DMA Transfer using HAL_I2S_DMAResume() - (+) Stop the DMA Transfer using HAL_I2S_DMAStop() - - @endverbatim - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2015 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "stm32f4xx_hal.h" - -/** @addtogroup STM32F4xx_HAL_Driver - * @{ - */ - -/** @defgroup I2SEx I2SEx - * @brief I2S HAL module driver - * @{ - */ - -#ifdef HAL_I2S_MODULE_ENABLED - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ - defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) ||\ - defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ -/** @addtogroup I2SEx_Private_Functions - * @{ - */ -/** - * @} - */ - -/* Exported functions --------------------------------------------------------*/ -/** @defgroup I2SEx_Exported_Functions I2S Exported Functions - * @{ - */ - -/** @defgroup I2SEx_Group1 Extension features functions - * @brief Extension features functions - * -@verbatim - =============================================================================== - ##### Extension features Functions ##### - =============================================================================== - [..] - This subsection provides a set of functions allowing to manage the I2S data - transfers. - - (#) There are two modes of transfer: - (++) Blocking mode : The communication is performed in the polling mode. - The status of all data processing is returned by the same function - after finishing transfer. - (++) No-Blocking mode : The communication is performed using Interrupts - or DMA. These functions return the status of the transfer startup. - The end of the data processing will be indicated through the - dedicated I2S IRQ when using Interrupt mode or the DMA IRQ when - using DMA mode. - - (#) Blocking mode functions are : - (++) HAL_I2S_TransmitReceive() - - (#) No-Blocking mode functions with Interrupt are : - (++) HAL_I2S_TransmitReceive_IT() - - (#) No-Blocking mode functions with DMA are : - (++) HAL_I2S_TransmitReceive_DMA() - - (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: - (++) HAL_I2S_TxCpltCallback() - (++) HAL_I2S_RxCpltCallback() - (++) HAL_I2S_ErrorCallback() - -@endverbatim - * @{ - */ -/** - * @brief Initializes the I2S according to the specified parameters - * in the I2S_InitTypeDef and create the associated handle. - * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains - * the configuration information for I2S module - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2S_Init(I2S_HandleTypeDef *hi2s) -{ - uint32_t tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1; - uint32_t tmp = 0, i2sclk = 0; - - /* Check the I2S handle allocation */ - if(hi2s == NULL) - { - return HAL_ERROR; - } - - /* Check the I2S parameters */ - assert_param(IS_I2S_MODE(hi2s->Init.Mode)); - assert_param(IS_I2S_STANDARD(hi2s->Init.Standard)); - assert_param(IS_I2S_DATA_FORMAT(hi2s->Init.DataFormat)); - assert_param(IS_I2S_MCLK_OUTPUT(hi2s->Init.MCLKOutput)); - assert_param(IS_I2S_AUDIO_FREQ(hi2s->Init.AudioFreq)); - assert_param(IS_I2S_CPOL(hi2s->Init.CPOL)); - assert_param(IS_I2S_CLOCKSOURCE(hi2s->Init.ClockSource)); - - if(hi2s->State == HAL_I2S_STATE_RESET) - { - /* Allocate lock resource and initialize it */ - hi2s->Lock = HAL_UNLOCKED; - /* Init the low level hardware : GPIO, CLOCK, CORTEX */ - HAL_I2S_MspInit(hi2s); - } - - hi2s->State = HAL_I2S_STATE_BUSY; - - /*----------------------- SPIx I2SCFGR & I2SPR Configuration ---------------*/ - /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */ - hi2s->Instance->I2SCFGR &= ~(SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CKPOL | \ - SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC | SPI_I2SCFGR_I2SCFG | \ - SPI_I2SCFGR_I2SE | SPI_I2SCFGR_I2SMOD); - hi2s->Instance->I2SPR = 0x0002; - - /* Get the I2SCFGR register value */ - tmpreg = hi2s->Instance->I2SCFGR; - - /* If the default frequency value has to be written, reinitialize i2sdiv and i2sodd */ - /* If the requested audio frequency is not the default, compute the prescaler */ - if(hi2s->Init.AudioFreq != I2S_AUDIOFREQ_DEFAULT) - { - /* Check the frame length (For the Prescaler computing) *******************/ - if(hi2s->Init.DataFormat != I2S_DATAFORMAT_16B) - { - /* Packet length is 32 bits */ - packetlength = 2; - } - - /* Get I2S source Clock frequency ****************************************/ - i2sclk = I2S_GetInputClock(hi2s); - - /* Compute the Real divider depending on the MCLK output state, with a floating point */ - if(hi2s->Init.MCLKOutput == I2S_MCLKOUTPUT_ENABLE) - { - /* MCLK output is enabled */ - tmp = (uint32_t)(((((i2sclk / 256) * 10) / hi2s->Init.AudioFreq)) + 5); - } - else - { - /* MCLK output is disabled */ - tmp = (uint32_t)(((((i2sclk / (32 * packetlength)) *10 ) / hi2s->Init.AudioFreq)) + 5); - } - - /* Remove the flatting point */ - tmp = tmp / 10; - - /* Check the parity of the divider */ - i2sodd = (uint32_t)(tmp & (uint32_t)1); - - /* Compute the i2sdiv prescaler */ - i2sdiv = (uint32_t)((tmp - i2sodd) / 2); - - /* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */ - i2sodd = (uint32_t) (i2sodd << 8); - } - - /* Test if the divider is 1 or 0 or greater than 0xFF */ - if((i2sdiv < 2) || (i2sdiv > 0xFF)) - { - /* Set the default values */ - i2sdiv = 2; - i2sodd = 0; - } - - /* Write to SPIx I2SPR register the computed value */ - hi2s->Instance->I2SPR = (uint32_t)((uint32_t)i2sdiv | (uint32_t)(i2sodd | (uint32_t)hi2s->Init.MCLKOutput)); - - /* Configure the I2S with the I2S_InitStruct values */ - tmpreg |= (uint32_t)(SPI_I2SCFGR_I2SMOD | hi2s->Init.Mode | hi2s->Init.Standard | hi2s->Init.DataFormat | hi2s->Init.CPOL); - -#if defined(SPI_I2SCFGR_ASTRTEN) - if (hi2s->Init.Standard == I2S_STANDARD_PCM_SHORT) - { - /* Write to SPIx I2SCFGR */ - hi2s->Instance->I2SCFGR = tmpreg | SPI_I2SCFGR_ASTRTEN; - } - else - { - /* Write to SPIx I2SCFGR */ - hi2s->Instance->I2SCFGR = tmpreg; - } -#else - /* Write to SPIx I2SCFGR */ - hi2s->Instance->I2SCFGR = tmpreg; -#endif - - /* Configure the I2S extended if the full duplex mode is enabled */ - assert_param(IS_I2S_FULLDUPLEX_MODE(hi2s->Init.FullDuplexMode)); - if(hi2s->Init.FullDuplexMode == I2S_FULLDUPLEXMODE_ENABLE) - { - /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */ - I2SxEXT(hi2s->Instance)->I2SCFGR &= ~(SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CKPOL | \ - SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC | SPI_I2SCFGR_I2SCFG | \ - SPI_I2SCFGR_I2SE | SPI_I2SCFGR_I2SMOD); - I2SxEXT(hi2s->Instance)->I2SPR = 2; - - /* Get the I2SCFGR register value */ - tmpreg = I2SxEXT(hi2s->Instance)->I2SCFGR; - - /* Get the mode to be configured for the extended I2S */ - if((hi2s->Init.Mode == I2S_MODE_MASTER_TX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_TX)) - { - tmp = I2S_MODE_SLAVE_RX; - } - else - { - if((hi2s->Init.Mode == I2S_MODE_MASTER_RX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_RX)) - { - tmp = I2S_MODE_SLAVE_TX; - } - } - - /* Configure the I2S Slave with the I2S Master parameter values */ - tmpreg |= (uint32_t)(SPI_I2SCFGR_I2SMOD | tmp | hi2s->Init.Standard | hi2s->Init.DataFormat | hi2s->Init.CPOL); - - /* Write to SPIx I2SCFGR */ - I2SxEXT(hi2s->Instance)->I2SCFGR = tmpreg; - } - - hi2s->ErrorCode = HAL_I2S_ERROR_NONE; - hi2s->State= HAL_I2S_STATE_READY; - - return HAL_OK; -} - -/** - * @brief Full-Duplex Transmit/Receive data in blocking mode. - * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains - * the configuration information for I2S module - * @param pTxData: a 16-bit pointer to the Transmit data buffer. - * @param pRxData: a 16-bit pointer to the Receive data buffer. - * @param Size: number of data sample to be sent: - * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S - * configuration phase, the Size parameter means the number of 16-bit data length - * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected - * the Size parameter means the number of 16-bit data length. - * @param Timeout: Timeout duration - * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization - * between Master and Slave(example: audio streaming). - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2SEx_TransmitReceive(I2S_HandleTypeDef *hi2s, uint16_t *pTxData, uint16_t *pRxData, uint16_t Size, uint32_t Timeout) -{ - uint32_t tickstart = 0; - uint32_t tmp1 = 0, tmp2 = 0; - - if((pTxData == NULL ) || (pRxData == NULL ) || (Size == 0)) - { - return HAL_ERROR; - } - - /* Check the I2S State */ - if(hi2s->State == HAL_I2S_STATE_READY) - { - tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); - tmp2 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); - /* Check the Data format: When a 16-bit data frame or a 16-bit data frame extended - is selected during the I2S configuration phase, the Size parameter means the number - of 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit data - frame is selected the Size parameter means the number of 16-bit data length. */ - if((tmp1 == I2S_DATAFORMAT_24B)|| \ - (tmp2 == I2S_DATAFORMAT_32B)) - { - hi2s->TxXferSize = Size*2; - hi2s->TxXferCount = Size*2; - hi2s->RxXferSize = Size*2; - hi2s->RxXferCount = Size*2; - } - else - { - hi2s->TxXferSize = Size; - hi2s->TxXferCount = Size; - hi2s->RxXferSize = Size; - hi2s->RxXferCount = Size; - } - - /* Process Locked */ - __HAL_LOCK(hi2s); - - /* Set the I2S State busy TX/RX */ - hi2s->State = HAL_I2S_STATE_BUSY_TX_RX; - - tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ - if((tmp1 == I2S_MODE_MASTER_TX) || (tmp2 == I2S_MODE_SLAVE_TX)) - { - /* Check if the I2S is already enabled: The I2S is kept enabled at the end of transaction - to avoid the clock de-synchronization between Master and Slave. */ - if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) - { - /* Enable I2Sext(receiver) before enabling I2Sx peripheral */ - I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; - - /* Enable I2Sx peripheral */ - __HAL_I2S_ENABLE(hi2s); - } - - while(hi2s->TxXferCount > 0) - { - /* Wait until TXE flag is set */ - if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, RESET, Timeout) != HAL_OK) - { - return HAL_TIMEOUT; - } - hi2s->Instance->DR = (*pTxData++); - - /* Get tick */ - tickstart = HAL_GetTick(); - - /* Wait until RXNE flag is set */ - while((I2SxEXT(hi2s->Instance)->SR & SPI_SR_RXNE) != SPI_SR_RXNE) - { - if(Timeout != HAL_MAX_DELAY) - { - if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) - { - /* Process Unlocked */ - __HAL_UNLOCK(hi2s); - - return HAL_TIMEOUT; - } - } - } - (*pRxData++) = I2SxEXT(hi2s->Instance)->DR; - - hi2s->TxXferCount--; - hi2s->RxXferCount--; - } - } - /* The I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX Mode is selected */ - else - { - /* Check if the I2S is already enabled */ - if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) - { - /* Enable I2S peripheral before the I2Sext*/ - __HAL_I2S_ENABLE(hi2s); - - /* Enable I2Sext(transmitter) after enabling I2Sx peripheral */ - I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; - } - else - { - /* Check if Master Receiver mode is selected */ - if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX) - { - /* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a read - access to the SPI_SR register. */ - __HAL_I2S_CLEAR_OVRFLAG(hi2s); - } - } - while(hi2s->TxXferCount > 0) - { - /* Get tick */ - tickstart = HAL_GetTick(); - - /* Wait until TXE flag is set */ - while((I2SxEXT(hi2s->Instance)->SR & SPI_SR_TXE) != SPI_SR_TXE) - { - if(Timeout != HAL_MAX_DELAY) - { - if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) - { - /* Process Unlocked */ - __HAL_UNLOCK(hi2s); - - return HAL_TIMEOUT; - } - } - } - I2SxEXT(hi2s->Instance)->DR = (*pTxData++); - - /* Wait until RXNE flag is set */ - if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, RESET, Timeout) != HAL_OK) - { - return HAL_TIMEOUT; - } - (*pRxData++) = hi2s->Instance->DR; - - hi2s->TxXferCount--; - hi2s->RxXferCount--; - } - } - - /* Set the I2S State ready */ - hi2s->State = HAL_I2S_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2s); - - return HAL_OK; - } - else - { - return HAL_BUSY; - } -} - -/** - * @brief Full-Duplex Transmit/Receive data in non-blocking mode using Interrupt - * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains - * the configuration information for I2S module - * @param pTxData: a 16-bit pointer to the Transmit data buffer. - * @param pRxData: a 16-bit pointer to the Receive data buffer. - * @param Size: number of data sample to be sent: - * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S - * configuration phase, the Size parameter means the number of 16-bit data length - * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected - * the Size parameter means the number of 16-bit data length. - * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization - * between Master and Slave(example: audio streaming). - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2SEx_TransmitReceive_IT(I2S_HandleTypeDef *hi2s, uint16_t *pTxData, uint16_t *pRxData, uint16_t Size) -{ - uint32_t tmp1 = 0, tmp2 = 0; - - if(hi2s->State == HAL_I2S_STATE_READY) - { - if((pTxData == NULL ) || (pRxData == NULL ) || (Size == 0)) - { - return HAL_ERROR; - } - - hi2s->pTxBuffPtr = pTxData; - hi2s->pRxBuffPtr = pRxData; - - tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); - tmp2 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); - /* Check the Data format: When a 16-bit data frame or a 16-bit data frame extended - is selected during the I2S configuration phase, the Size parameter means the number - of 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit data - frame is selected the Size parameter means the number of 16-bit data length. */ - if((tmp1 == I2S_DATAFORMAT_24B)||\ - (tmp2 == I2S_DATAFORMAT_32B)) - { - hi2s->TxXferSize = Size*2; - hi2s->TxXferCount = Size*2; - hi2s->RxXferSize = Size*2; - hi2s->RxXferCount = Size*2; - } - else - { - hi2s->TxXferSize = Size; - hi2s->TxXferCount = Size; - hi2s->RxXferSize = Size; - hi2s->RxXferCount = Size; - } - - /* Process Locked */ - __HAL_LOCK(hi2s); - - hi2s->State = HAL_I2S_STATE_BUSY_TX_RX; - hi2s->ErrorCode = HAL_I2S_ERROR_NONE; - - tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ - if((tmp1 == I2S_MODE_MASTER_TX) || (tmp2 == I2S_MODE_SLAVE_TX)) - { - /* Enable I2Sext RXNE and ERR interrupts */ - I2SxEXT(hi2s->Instance)->CR2 |= (I2S_IT_RXNE | I2S_IT_ERR); - - /* Enable I2Sx TXE and ERR interrupts */ - __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); - - /* Check if the I2S is already enabled */ - if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) - { - /* Enable I2Sext(receiver) before enabling I2Sx peripheral */ - I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; - - /* Enable I2Sx peripheral */ - __HAL_I2S_ENABLE(hi2s); - } - } - /* The I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX Mode is selected */ - else - { - /* Enable I2Sext TXE and ERR interrupts */ - I2SxEXT(hi2s->Instance)->CR2 |= (I2S_IT_TXE |I2S_IT_ERR); - - /* Enable I2Sext RXNE and ERR interrupts */ - __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); - - /* Check if the I2S is already enabled */ - if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) - { - /* Check if the I2S_MODE_MASTER_RX is selected */ - if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX) - { - /* Prepare the First Data before enabling the I2S */ - if(hi2s->TxXferCount != 0) - { - /* Transmit First data */ - I2SxEXT(hi2s->Instance)->DR = (*hi2s->pTxBuffPtr++); - hi2s->TxXferCount--; - - if(hi2s->TxXferCount == 0) - { - /* Disable I2Sext TXE interrupt */ - I2SxEXT(hi2s->Instance)->CR2 &= ~I2S_IT_TXE; - } - } - } - /* Enable I2S peripheral */ - __HAL_I2S_ENABLE(hi2s); - - /* Enable I2Sext(transmitter) after enabling I2Sx peripheral */ - I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; - } - } - /* Process Unlocked */ - __HAL_UNLOCK(hi2s); - - return HAL_OK; - } - else - { - return HAL_BUSY; - } -} - -/** - * @brief Full-Duplex Transmit/Receive data in non-blocking mode using DMA - * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains - * the configuration information for I2S module - * @param pTxData: a 16-bit pointer to the Transmit data buffer. - * @param pRxData: a 16-bit pointer to the Receive data buffer. - * @param Size: number of data sample to be sent: - * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S - * configuration phase, the Size parameter means the number of 16-bit data length - * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected - * the Size parameter means the number of 16-bit data length. - * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization - * between Master and Slave(example: audio streaming). - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2SEx_TransmitReceive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pTxData, uint16_t *pRxData, uint16_t Size) -{ - uint32_t *tmp; - uint32_t tmp1 = 0, tmp2 = 0; - - if((pTxData == NULL ) || (pRxData == NULL ) || (Size == 0)) - { - return HAL_ERROR; - } - - if(hi2s->State == HAL_I2S_STATE_READY) - { - hi2s->pTxBuffPtr = pTxData; - hi2s->pRxBuffPtr = pRxData; - - tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); - tmp2 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); - /* Check the Data format: When a 16-bit data frame or a 16-bit data frame extended - is selected during the I2S configuration phase, the Size parameter means the number - of 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit data - frame is selected the Size parameter means the number of 16-bit data length. */ - if((tmp1 == I2S_DATAFORMAT_24B)||\ - (tmp2 == I2S_DATAFORMAT_32B)) - { - hi2s->TxXferSize = Size*2; - hi2s->TxXferCount = Size*2; - hi2s->RxXferSize = Size*2; - hi2s->RxXferCount = Size*2; - } - else - { - hi2s->TxXferSize = Size; - hi2s->TxXferCount = Size; - hi2s->RxXferSize = Size; - hi2s->RxXferCount = Size; - } - - /* Process Locked */ - __HAL_LOCK(hi2s); - - hi2s->State = HAL_I2S_STATE_BUSY_TX_RX; - hi2s->ErrorCode = HAL_I2S_ERROR_NONE; - - /* Set the I2S Rx DMA Half transfer complete callback */ - hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt; - - /* Set the I2S Rx DMA transfer complete callback */ - hi2s->hdmarx->XferCpltCallback = I2S_DMARxCplt; - - /* Set the I2S Rx DMA error callback */ - hi2s->hdmarx->XferErrorCallback = I2S_DMAError; - - /* Set the I2S Tx DMA Half transfer complete callback */ - hi2s->hdmatx->XferHalfCpltCallback = I2S_DMATxHalfCplt; - - /* Set the I2S Tx DMA transfer complete callback */ - hi2s->hdmatx->XferCpltCallback = I2S_DMATxCplt; - - /* Set the I2S Tx DMA error callback */ - hi2s->hdmatx->XferErrorCallback = I2S_DMAError; - - tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ - if((tmp1 == I2S_MODE_MASTER_TX) || (tmp2 == I2S_MODE_SLAVE_TX)) - { - /* Enable the Rx DMA Stream */ - tmp = (uint32_t*)&pRxData; - HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&I2SxEXT(hi2s->Instance)->DR, *(uint32_t*)tmp, hi2s->RxXferSize); - - /* Enable Rx DMA Request */ - I2SxEXT(hi2s->Instance)->CR2 |= SPI_CR2_RXDMAEN; - - /* Enable the Tx DMA Stream */ - tmp = (uint32_t*)&pTxData; - HAL_DMA_Start_IT(hi2s->hdmatx, *(uint32_t*)tmp, (uint32_t)&hi2s->Instance->DR, hi2s->TxXferSize); - - /* Enable Tx DMA Request */ - hi2s->Instance->CR2 |= SPI_CR2_TXDMAEN; - - /* Check if the I2S is already enabled */ - if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) - { - /* Enable I2Sext(receiver) before enabling I2Sx peripheral */ - I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; - - /* Enable I2S peripheral after the I2Sext */ - __HAL_I2S_ENABLE(hi2s); - } - } - else - { - /* Enable the Tx DMA Stream */ - tmp = (uint32_t*)&pTxData; - HAL_DMA_Start_IT(hi2s->hdmatx, *(uint32_t*)tmp, (uint32_t)&I2SxEXT(hi2s->Instance)->DR, hi2s->TxXferSize); - - /* Enable Tx DMA Request */ - I2SxEXT(hi2s->Instance)->CR2 |= SPI_CR2_TXDMAEN; - - /* Enable the Rx DMA Stream */ - tmp = (uint32_t*)&pRxData; - HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->DR, *(uint32_t*)tmp, hi2s->RxXferSize); - - /* Enable Rx DMA Request */ - hi2s->Instance->CR2 |= SPI_CR2_RXDMAEN; - - /* Check if the I2S is already enabled */ - if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) - { - /* Enable I2S peripheral before the I2Sext */ - __HAL_I2S_ENABLE(hi2s); - - /* Enable I2Sext(transmitter) after enabling I2Sx peripheral */ - I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; - } - else - { - /* Check if Master Receiver mode is selected */ - if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX) - { - /* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a read - access to the SPI_SR register. */ - __HAL_I2S_CLEAR_OVRFLAG(hi2s); - } - } - } - - /* Process Unlocked */ - __HAL_UNLOCK(hi2s); - - return HAL_OK; - } - else - { - return HAL_BUSY; - } -} - -/** - * @brief Pauses the audio stream playing from the Media. - * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains - * the configuration information for I2S module - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2S_DMAPause(I2S_HandleTypeDef *hi2s) -{ - /* Process Locked */ - __HAL_LOCK(hi2s); - - if(hi2s->State == HAL_I2S_STATE_BUSY_TX) - { - /* Disable the I2S DMA Tx request */ - hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN); - } - else if(hi2s->State == HAL_I2S_STATE_BUSY_RX) - { - /* Disable the I2S DMA Rx request */ - hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN); - } - else if(hi2s->State == HAL_I2S_STATE_BUSY_TX_RX) - { - if((hi2s->Init.Mode == I2S_MODE_SLAVE_TX)||(hi2s->Init.Mode == I2S_MODE_MASTER_TX)) - { - /* Disable the I2S DMA Tx request */ - hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN); - /* Disable the I2SEx Rx DMA Request */ - I2SxEXT(hi2s->Instance)->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN); - } - else - { - /* Disable the I2S DMA Rx request */ - hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN); - /* Disable the I2SEx Tx DMA Request */ - I2SxEXT(hi2s->Instance)->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN); - } - } - - /* Process Unlocked */ - __HAL_UNLOCK(hi2s); - - return HAL_OK; -} - -/** - * @brief Resumes the audio stream playing from the Media. - * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains - * the configuration information for I2S module - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2S_DMAResume(I2S_HandleTypeDef *hi2s) -{ - /* Process Locked */ - __HAL_LOCK(hi2s); - - if(hi2s->State == HAL_I2S_STATE_BUSY_TX) - { - /* Enable the I2S DMA Tx request */ - hi2s->Instance->CR2 |= SPI_CR2_TXDMAEN; - } - else if(hi2s->State == HAL_I2S_STATE_BUSY_RX) - { - /* Enable the I2S DMA Rx request */ - hi2s->Instance->CR2 |= SPI_CR2_RXDMAEN; - } - else if(hi2s->State == HAL_I2S_STATE_BUSY_TX_RX) - { - if((hi2s->Init.Mode == I2S_MODE_SLAVE_TX)||(hi2s->Init.Mode == I2S_MODE_MASTER_TX)) - { - /* Enable the I2S DMA Tx request */ - hi2s->Instance->CR2 |= SPI_CR2_TXDMAEN; - /* Disable the I2SEx Rx DMA Request */ - I2SxEXT(hi2s->Instance)->CR2 |= SPI_CR2_RXDMAEN; - } - else - { - /* Enable the I2S DMA Rx request */ - hi2s->Instance->CR2 |= SPI_CR2_RXDMAEN; - /* Enable the I2SEx Tx DMA Request */ - I2SxEXT(hi2s->Instance)->CR2 |= SPI_CR2_TXDMAEN; - } - } - - /* If the I2S peripheral is still not enabled, enable it */ - if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) == 0) - { - /* Enable I2S peripheral */ - __HAL_I2S_ENABLE(hi2s); - } - - /* Process Unlocked */ - __HAL_UNLOCK(hi2s); - - return HAL_OK; -} - -/** - * @brief Resumes the audio stream playing from the Media. - * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains - * the configuration information for I2S module - * @retval HAL status - */ -HAL_StatusTypeDef HAL_I2S_DMAStop(I2S_HandleTypeDef *hi2s) -{ - /* Process Locked */ - __HAL_LOCK(hi2s); - - /* Disable the I2S Tx/Rx DMA requests */ - hi2s->Instance->CR2 &= ~SPI_CR2_TXDMAEN; - hi2s->Instance->CR2 &= ~SPI_CR2_RXDMAEN; - - if(hi2s->Init.FullDuplexMode == I2S_FULLDUPLEXMODE_ENABLE) - { - /* Disable the I2S extended Tx/Rx DMA requests */ - I2SxEXT(hi2s->Instance)->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN); - I2SxEXT(hi2s->Instance)->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN); - } - - /* Abort the I2S DMA Stream tx */ - if(hi2s->hdmatx != NULL) - { - HAL_DMA_Abort(hi2s->hdmatx); - } - /* Abort the I2S DMA Stream rx */ - if(hi2s->hdmarx != NULL) - { - HAL_DMA_Abort(hi2s->hdmarx); - } - - /* Disable I2S peripheral */ - __HAL_I2S_DISABLE(hi2s); - - if(hi2s->Init.FullDuplexMode == I2S_FULLDUPLEXMODE_ENABLE) - { - /* Disable the I2Sext peripheral */ - I2SxEXT(hi2s->Instance)->I2SCFGR &= ~SPI_I2SCFGR_I2SE; - } - hi2s->State = HAL_I2S_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(hi2s); - - return HAL_OK; -} - -/** - * @brief This function handles I2S interrupt request. - * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains - * the configuration information for I2S module - * @retval None - */ -void HAL_I2S_IRQHandler(I2S_HandleTypeDef *hi2s) -{ - uint32_t tmp1 = 0, tmp2 = 0; - __IO uint32_t tmpreg1 = 0; - if(hi2s->Init.FullDuplexMode != I2S_FULLDUPLEXMODE_ENABLE) - { - if(hi2s->State == HAL_I2S_STATE_BUSY_RX) - { - tmp1 = __HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_RXNE); - tmp2 = __HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_RXNE); - /* I2S in mode Receiver ------------------------------------------------*/ - if((tmp1 != RESET) && (tmp2 != RESET)) - { - I2S_Receive_IT(hi2s); - } - - tmp1 = __HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_OVR); - tmp2 = __HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_ERR); - /* I2S Overrun error interrupt occurred ---------------------------------*/ - if((tmp1 != RESET) && (tmp2 != RESET)) - { - __HAL_I2S_CLEAR_OVRFLAG(hi2s); - hi2s->ErrorCode |= HAL_I2S_ERROR_OVR; - } - } - - if(hi2s->State == HAL_I2S_STATE_BUSY_TX) - { - tmp1 = __HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_TXE); - tmp2 = __HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_TXE); - /* I2S in mode Tramitter -----------------------------------------------*/ - if((tmp1 != RESET) && (tmp2 != RESET)) - { - I2S_Transmit_IT(hi2s); - } - - tmp1 = __HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_UDR); - tmp2 = __HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_ERR); - /* I2S Underrun error interrupt occurred --------------------------------*/ - if((tmp1 != RESET) && (tmp2 != RESET)) - { - __HAL_I2S_CLEAR_UDRFLAG(hi2s); - hi2s->ErrorCode |= HAL_I2S_ERROR_UDR; - } - } - } - else - { - tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ - if((tmp1 == I2S_MODE_MASTER_TX) || (tmp2 == I2S_MODE_SLAVE_TX)) - { - tmp1 = I2SxEXT(hi2s->Instance)->SR & SPI_SR_RXNE; - tmp2 = I2SxEXT(hi2s->Instance)->CR2 & I2S_IT_RXNE; - /* I2Sext in mode Receiver ---------------------------------------------*/ - if((tmp1 == SPI_SR_RXNE) && (tmp2 == I2S_IT_RXNE)) - { - tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - /* When the I2S mode is configured as I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX, - the I2Sext RXNE interrupt will be generated to manage the full-duplex receive phase. */ - if((tmp1 == I2S_MODE_MASTER_TX) || (tmp2 == I2S_MODE_SLAVE_TX)) - { - I2SEx_TransmitReceive_IT(hi2s); - } - } - - tmp1 = I2SxEXT(hi2s->Instance)->SR & SPI_SR_OVR; - tmp2 = I2SxEXT(hi2s->Instance)->CR2 & I2S_IT_ERR; - /* I2Sext Overrun error interrupt occurred ------------------------------*/ - if((tmp1 == SPI_SR_OVR) && (tmp2 == I2S_IT_ERR)) - { - /* Clear I2Sext OVR Flag */ - tmpreg1 = I2SxEXT(hi2s->Instance)->DR; - tmpreg1 = I2SxEXT(hi2s->Instance)->SR; - hi2s->ErrorCode |= HAL_I2SEX_ERROR_OVR; - UNUSED(tmpreg1); - } - - tmp1 = __HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_TXE); - tmp2 = __HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_TXE); - /* I2S in mode Tramitter -----------------------------------------------*/ - if((tmp1 != RESET) && (tmp2 != RESET)) - { - tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - /* When the I2S mode is configured as I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX, - the I2S TXE interrupt will be generated to manage the full-duplex transmit phase. */ - if((tmp1 == I2S_MODE_MASTER_TX) || (tmp2 == I2S_MODE_SLAVE_TX)) - { - I2SEx_TransmitReceive_IT(hi2s); - } - } - - tmp1 = __HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_UDR); - tmp2 = __HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_ERR); - /* I2S Underrun error interrupt occurred --------------------------------*/ - if((tmp1 != RESET) && (tmp2 != RESET)) - { - __HAL_I2S_CLEAR_UDRFLAG(hi2s); - hi2s->ErrorCode |= HAL_I2S_ERROR_UDR; - } - } - /* The I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX Mode is selected */ - else - { - tmp1 = __HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_RXNE); - tmp2 = __HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_RXNE); - /* I2S in mode Receiver ------------------------------------------------*/ - if((tmp1 != RESET) && (tmp2 != RESET)) - { - tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - /* When the I2S mode is configured as I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX, - the I2S RXNE interrupt will be generated to manage the full-duplex receive phase. */ - if((tmp1 == I2S_MODE_MASTER_RX) || (tmp2 == I2S_MODE_SLAVE_RX)) - { - I2SEx_TransmitReceive_IT(hi2s); - } - } - - tmp1 = __HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_OVR); - tmp2 = __HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_ERR); - /* I2S Overrun error interrupt occurred ---------------------------------*/ - if((tmp1 != RESET) && (tmp2 != RESET)) - { - __HAL_I2S_CLEAR_OVRFLAG(hi2s); - hi2s->ErrorCode |= HAL_I2S_ERROR_OVR; - } - - tmp1 = I2SxEXT(hi2s->Instance)->SR & SPI_SR_TXE; - tmp2 = I2SxEXT(hi2s->Instance)->CR2 & I2S_IT_TXE; - /* I2Sext in mode Tramitter --------------------------------------------*/ - if((tmp1 == SPI_SR_TXE) && (tmp2 == I2S_IT_TXE)) - { - tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - /* When the I2S mode is configured as I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX, - the I2Sext TXE interrupt will be generated to manage the full-duplex transmit phase. */ - if((tmp1 == I2S_MODE_MASTER_RX) || (tmp2 == I2S_MODE_SLAVE_RX)) - { - I2SEx_TransmitReceive_IT(hi2s); - } - } - - tmp1 = I2SxEXT(hi2s->Instance)->SR & SPI_SR_UDR; - tmp2 = I2SxEXT(hi2s->Instance)->CR2 & I2S_IT_ERR; - /* I2Sext Underrun error interrupt occurred -----------------------------*/ - if((tmp1 == SPI_SR_UDR) && (tmp2 == I2S_IT_ERR)) - { - /* Clear I2Sext UDR Flag */ - tmpreg1 = I2SxEXT(hi2s->Instance)->SR; - hi2s->ErrorCode |= HAL_I2SEX_ERROR_UDR; - UNUSED(tmpreg1); - } - } - } - - /* Call the Error call Back in case of Errors */ - if(hi2s->ErrorCode != HAL_I2S_ERROR_NONE) - { - /* Set the I2S state ready to be able to start again the process */ - hi2s->State= HAL_I2S_STATE_READY; - HAL_I2S_ErrorCallback(hi2s); - } -} - -/** - * @} - */ - - -/** - * @brief Full-Duplex Transmit/Receive data in non-blocking mode using Interrupt - * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains - * the configuration information for I2S module - * @retval HAL status - */ -HAL_StatusTypeDef I2SEx_TransmitReceive_IT(I2S_HandleTypeDef *hi2s) -{ - uint32_t tmp1 = 0, tmp2 = 0; - - if(hi2s->State == HAL_I2S_STATE_BUSY_TX_RX) - { - /* Process Locked */ - __HAL_LOCK(hi2s); - - tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; - /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ - if((tmp1 == I2S_MODE_MASTER_TX) || (tmp2 == I2S_MODE_SLAVE_TX)) - { - if(hi2s->TxXferCount != 0) - { - if(__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_TXE) != RESET) - { - /* Transmit data */ - hi2s->Instance->DR = (*hi2s->pTxBuffPtr++); - hi2s->TxXferCount--; - - if(hi2s->TxXferCount == 0) - { - /* Disable TXE interrupt */ - __HAL_I2S_DISABLE_IT(hi2s, I2S_IT_TXE); - } - } - } - - if(hi2s->RxXferCount != 0) - { - if((I2SxEXT(hi2s->Instance)->SR & SPI_SR_RXNE) == SPI_SR_RXNE) - { - /* Receive data */ - (*hi2s->pRxBuffPtr++) = I2SxEXT(hi2s->Instance)->DR; - hi2s->RxXferCount--; - - if(hi2s->RxXferCount == 0) - { - /* Disable I2Sext RXNE interrupt */ - I2SxEXT(hi2s->Instance)->CR2 &= ~I2S_IT_RXNE; - } - } - } - } - /* The I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX Mode is selected */ - else - { - if(hi2s->TxXferCount != 0) - { - if((I2SxEXT(hi2s->Instance)->SR & SPI_SR_TXE) == SPI_SR_TXE) - { - /* Transmit data */ - I2SxEXT(hi2s->Instance)->DR = (*hi2s->pTxBuffPtr++); - hi2s->TxXferCount--; - - if(hi2s->TxXferCount == 0) - { - /* Disable I2Sext TXE interrupt */ - I2SxEXT(hi2s->Instance)->CR2 &= ~I2S_IT_TXE; - - HAL_I2S_TxCpltCallback(hi2s); - } - } - } - if(hi2s->RxXferCount != 0) - { - if(__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_RXNE) != RESET) - { - /* Receive data */ - (*hi2s->pRxBuffPtr++) = hi2s->Instance->DR; - hi2s->RxXferCount--; - - if(hi2s->RxXferCount == 0) - { - /* Disable RXNE interrupt */ - __HAL_I2S_DISABLE_IT(hi2s, I2S_IT_RXNE); - - HAL_I2S_RxCpltCallback(hi2s); - } - } - } - } - - tmp1 = hi2s->RxXferCount; - tmp2 = hi2s->TxXferCount; - if((tmp1 == 0) && (tmp2 == 0)) - { - /* Disable I2Sx ERR interrupt */ - __HAL_I2S_DISABLE_IT(hi2s, I2S_IT_ERR); - /* Disable I2Sext ERR interrupt */ - I2SxEXT(hi2s->Instance)->CR2 &= ~I2S_IT_ERR; - - hi2s->State = HAL_I2S_STATE_READY; - } - - /* Process Unlocked */ - __HAL_UNLOCK(hi2s); - - return HAL_OK; - } - else - { - return HAL_BUSY; - } -} -#endif /* STM32F40xxx/ STM32F41xxx/ STM32F42xxx/ STM32F43xxx/ STM32F401xx/ STM32F411xx */ -/** - * @brief DMA I2S transmit process complete callback - * @param hdma: pointer to a DMA_HandleTypeDef structure that contains - * the configuration information for the specified DMA module. - * @retval None - */ -void I2S_DMATxCplt(DMA_HandleTypeDef *hdma) -{ - I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; - - if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0) - { - hi2s->TxXferCount = 0; - - /* Disable Tx DMA Request */ - hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN); -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ - defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) ||\ - defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) - if(hi2s->Init.FullDuplexMode == I2S_FULLDUPLEXMODE_ENABLE) - { - /* Disable Rx DMA Request for the slave*/ - I2SxEXT(hi2s->Instance)->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN); - } -#endif /* STM32F40xxx/ STM32F41xxx/ STM32F42xxx/ STM32F43xxx/ STM32F401xx/ STM32F411xx */ - if(hi2s->State == HAL_I2S_STATE_BUSY_TX_RX) - { - if(hi2s->RxXferCount == 0) - { - hi2s->State = HAL_I2S_STATE_READY; - } - } - else - { - hi2s->State = HAL_I2S_STATE_READY; - } - } - HAL_I2S_TxCpltCallback(hi2s); -} - -/** - * @brief DMA I2S receive process complete callback - * @param hdma: pointer to a DMA_HandleTypeDef structure that contains - * the configuration information for the specified DMA module. - * @retval None - */ -void I2S_DMARxCplt(DMA_HandleTypeDef *hdma) -{ - I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; - - if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0) - { - /* Disable Rx DMA Request */ - hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN); -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ - defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) ||\ - defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) - if(hi2s->Init.FullDuplexMode == I2S_FULLDUPLEXMODE_ENABLE) - { - /* Disable Tx DMA Request for the slave*/ - I2SxEXT(hi2s->Instance)->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN); - } -#endif /* STM32F40xxx/ STM32F41xxx/ STM32F42xxx/ STM32F43xxx/ STM32F401xx/ STM32F411xx */ - hi2s->RxXferCount = 0; - if(hi2s->State == HAL_I2S_STATE_BUSY_TX_RX) - { - if(hi2s->TxXferCount == 0) - { - hi2s->State = HAL_I2S_STATE_READY; - } - } - else - { - hi2s->State = HAL_I2S_STATE_READY; - } - } - HAL_I2S_RxCpltCallback(hi2s); -} - -/** - * @brief Get I2S clock Input based on Source clock selection in RCC - * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains - * the configuration information for I2S module - * @retval I2S Clock Input - */ -uint32_t I2S_GetInputClock(I2S_HandleTypeDef *hi2s) -{ - /* This variable used to store the VCO Input (value in Hz) */ - uint32_t vcoinput = 0; - /* This variable used to store the VCO Output (value in Hz) */ - uint32_t vcooutput = 0; - /* This variable used to store the I2S_CK_x (value in Hz) */ - uint32_t i2ssourceclock = 0; - - /* Configure SAI Clock based on SAI source clock selection */ -#if defined(STM32F446xx) - switch(hi2s->Init.ClockSource) - { - case I2S_CLOCK_EXTERNAL : - { - /* Set the I2S clock to the external clock value */ - i2ssourceclock = EXTERNAL_CLOCK_VALUE; - break; - } - case I2S_CLOCK_PLL : - { - /* Configure the PLLI2S division factor */ - /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */ - if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) - { - /* Get the I2S source clock value */ - vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); - } - else - { - /* Get the I2S source clock value */ - vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); - } - - /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ - vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6) & (RCC_PLLI2SCFGR_PLLI2SN >> 6))); - /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */ - i2ssourceclock = (uint32_t)(vcooutput /(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28) & (RCC_PLLI2SCFGR_PLLI2SR >> 28))); - break; - } - case I2S_CLOCK_PLLR : - { - /* Configure the PLLI2S division factor */ - /* PLL_VCO Input = PLL_SOURCE/PLLM */ - if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) - { - /* Get the I2S source clock value */ - vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); - } - else - { - /* Get the I2S source clock value */ - vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); - } - - /* PLL_VCO Output = PLL_VCO Input * PLLN */ - vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6) & (RCC_PLLCFGR_PLLN >> 6))); - /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */ - i2ssourceclock = (uint32_t)(vcooutput /(((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28) & (RCC_PLLCFGR_PLLR >> 28))); - break; - } - case I2S_CLOCK_PLLSRC : - { - /* Configure the PLLI2S division factor */ - /* PLL_VCO Input = PLL_SOURCE/PLLM */ - if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) - { - /* Get the I2S source clock value */ - i2ssourceclock = (uint32_t)(HSE_VALUE); - } - else - { - /* Get the I2S source clock value */ - i2ssourceclock = (uint32_t)(HSI_VALUE); - } - break; - } - default : - { - break; - } - } -#endif /* STM32F446xx */ -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) ||\ - defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ - defined(STM32F401xC) || defined(STM32F401xE) - - /* If an external I2S clock has to be used, the specific define should be set - in the project configuration or in the stm32f4xx_conf.h file */ - if(hi2s->Init.ClockSource == I2S_CLOCK_EXTERNAL) - { - /* Enable the External Clock selection */ - __HAL_RCC_I2S_CONFIG(RCC_I2SCLKSOURCE_EXT); - - /* Set the I2S clock to the external clock value */ - i2ssourceclock = EXTERNAL_CLOCK_VALUE; - } - else - { - /* Configure the PLLI2S division factor */ - /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */ - if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) - { - /* Get the I2S source clock value */ - vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); - } - else - { - /* Get the I2S source clock value */ - vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); - } - - /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ - vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6) & (RCC_PLLI2SCFGR_PLLI2SN >> 6))); - /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */ - i2ssourceclock = (uint32_t)(vcooutput /(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28) & (RCC_PLLI2SCFGR_PLLI2SR >> 28))); - } -#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx */ - -#if defined(STM32F411xE) - - /* If an external I2S clock has to be used, the specific define should be set - in the project configuration or in the stm32f4xx_conf.h file */ - if(hi2s->Init.ClockSource == I2S_CLOCK_EXTERNAL) - { - /* Enable the External Clock selection */ - __HAL_RCC_I2S_CONFIG(RCC_I2SCLKSOURCE_EXT); - - /* Set the I2S clock to the external clock value */ - i2ssourceclock = EXTERNAL_CLOCK_VALUE; - } - else - { - /* Configure the PLLI2S division factor */ - /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */ - if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) - { - /* Get the I2S source clock value */ - vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); - } - else - { - /* Get the I2S source clock value */ - vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)); - } - - /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ - vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6) & (RCC_PLLI2SCFGR_PLLI2SN >> 6))); - /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */ - i2ssourceclock = (uint32_t)(vcooutput /(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28) & (RCC_PLLI2SCFGR_PLLI2SR >> 28))); - } -#endif /* STM32F411xE */ - - /* the return result is the value of SAI clock */ - return i2ssourceclock; - -} -/** - * @} - */ - -#endif /* HAL_I2S_MODULE_ENABLED */ -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ -- cgit v1.2.3