/** * @brief DMA I2S communication error callback * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ static void I2SEx_TxRxDMAError(DMA_HandleTypeDef *hdma) { I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; /* Check if the SPI2S is disabled to edit CFG1 register */ if ((hi2s->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) { /* Disable Rx and Tx DMA Request */ CLEAR_BIT(hi2s->Instance->CFG1, (SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN)); } else { /* Disable SPI peripheral */ __HAL_I2S_DISABLE(hi2s); /* Disable Rx and Tx DMA Request */ CLEAR_BIT(hi2s->Instance->CFG1, (SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN)); /* Enable SPI peripheral */ __HAL_I2S_ENABLE(hi2s); } hi2s->TxXferCount = 0U; hi2s->RxXferCount = 0U; hi2s->State= HAL_I2S_STATE_READY; /* Set the error code and execute error callback*/ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA); HAL_I2S_ErrorCallback(hi2s); }
/** * @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 */ SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN); } else if(hi2s->State == HAL_I2S_STATE_BUSY_RX) { /* Enable the I2S DMA Rx request */ SET_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN); } /* 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 Receive an amount of data in non-blocking mode with Interrupt * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @param pData: 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). * @note It is recommended to use DMA for the I2S receiver to avoid de-synchronisation * between Master and Slave otherwise the I2S interrupt should be optimized. * @retval HAL status */ HAL_StatusTypeDef HAL_I2S_Receive_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size) { uint32_t tmp1 = 0, tmp2 = 0; if(hi2s->State == HAL_I2S_STATE_READY) { if((pData == NULL) || (Size == 0)) { return HAL_ERROR; } hi2s->pRxBuffPtr = pData; tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); tmp2 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); if((tmp1 == I2S_DATAFORMAT_24B)||\ (tmp2 == I2S_DATAFORMAT_32B)) { hi2s->RxXferSize = Size*2; hi2s->RxXferCount = Size*2; } else { hi2s->RxXferSize = Size; hi2s->RxXferCount = Size; } /* Process Locked */ __HAL_LOCK(hi2s); hi2s->State = HAL_I2S_STATE_BUSY_RX; hi2s->ErrorCode = HAL_I2S_ERROR_NONE; /* Enable TXE and ERR interrupt */ __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) { /* Enable I2S peripheral */ __HAL_I2S_ENABLE(hi2s); } /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { return HAL_BUSY; } }
/** * @brief Transmit an amount of data in non-blocking mode with Interrupt * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @param pData: a 16-bit pointer to 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_I2S_Transmit_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size) { if((pData == NULL) || (Size == 0)) { return HAL_ERROR; } /* Process Locked */ __HAL_LOCK(hi2s); if(hi2s->State == HAL_I2S_STATE_READY) { hi2s->pTxBuffPtr = pData; hi2s->State = HAL_I2S_STATE_BUSY_TX; hi2s->ErrorCode = HAL_I2S_ERROR_NONE; if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B)) { hi2s->TxXferSize = (Size << 1); hi2s->TxXferCount = (Size << 1); } else { hi2s->TxXferSize = Size; hi2s->TxXferCount = Size; } /* Enable TXE and ERR interrupt */ __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 I2S peripheral */ __HAL_I2S_ENABLE(hi2s); } /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_BUSY; } }
/** * @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 */ __weak 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; } else { /* Enable the I2S DMA Rx request */ hi2s->Instance->CR2 |= SPI_CR2_RXDMAEN; } } /* 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 DMA I2S transmit receive process complete callback * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ static void I2SEx_DMATxRxCplt(DMA_HandleTypeDef *hdma) { I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; if(((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & DMA_SxCR_CIRC) == 0U) { /* Check if the SPI2S is disabled to edit CFG1 register */ if ((hi2s->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) { /* Disable Tx/Rx DMA Request */ CLEAR_BIT(hi2s->Instance->CFG1, SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN); } else { /* Disable SPI peripheral */ __HAL_I2S_DISABLE(hi2s); /* Disable Rx DMA Request */ CLEAR_BIT(hi2s->Instance->CFG1, SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN); /* Enable SPI peripheral */ __HAL_I2S_ENABLE(hi2s); } hi2s->TxXferCount = 0U; hi2s->RxXferCount = 0U; hi2s->State = HAL_I2S_STATE_READY; if (hi2s->ErrorCode != HAL_I2S_ERROR_NONE) { HAL_I2S_ErrorCallback(hi2s); return; } } HAL_I2SEx_TxRxCpltCallback(hi2s); }
/** * @brief Transmit an amount of data in non-blocking mode with DMA * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @param pData: a 16-bit pointer to the Transmit 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_I2S_Transmit_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size) { uint32_t *tmp; uint32_t tmp1 = 0, tmp2 = 0; if((pData == NULL) || (Size == 0)) { return HAL_ERROR; } if(hi2s->State == HAL_I2S_STATE_READY) { hi2s->pTxBuffPtr = pData; tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); tmp2 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); if((tmp1 == I2S_DATAFORMAT_24B)|| \ (tmp2 == I2S_DATAFORMAT_32B)) { hi2s->TxXferSize = Size*2; hi2s->TxXferCount = Size*2; } else { hi2s->TxXferSize = Size; hi2s->TxXferCount = Size; } /* Process Locked */ __HAL_LOCK(hi2s); hi2s->State = HAL_I2S_STATE_BUSY_TX; hi2s->ErrorCode = HAL_I2S_ERROR_NONE; /* 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 DMA error callback */ hi2s->hdmatx->XferErrorCallback = I2S_DMAError; /* Enable the Tx DMA Stream */ tmp = (uint32_t*)&pData; HAL_DMA_Start_IT(hi2s->hdmatx, *(uint32_t*)tmp, (uint32_t)&hi2s->Instance->DR, hi2s->TxXferSize); /* Check if the I2S is already enabled */ if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) { /* Enable I2S peripheral */ __HAL_I2S_ENABLE(hi2s); } /* Check if the I2S Tx request is already enabled */ if((hi2s->Instance->CR2 & SPI_CR2_TXDMAEN) != SPI_CR2_TXDMAEN) { /* Enable Tx DMA Request */ hi2s->Instance->CR2 |= SPI_CR2_TXDMAEN; } /* 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 transfert complete callback */ hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt; /* Set the I2S Rx DMA transfert 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 transfert complete callback */ hi2s->hdmatx->XferHalfCpltCallback = I2S_DMATxHalfCplt; /* Set the I2S Tx DMA transfert 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 Receive an amount of data in blocking mode * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @param pData: a 16-bit pointer to 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). * @note In I2S Master Receiver mode, just after enabling the peripheral the clock will be generate * in continuous way and as the I2S is not disabled at the end of the I2S transaction. * @retval HAL status */ HAL_StatusTypeDef HAL_I2S_Receive(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout) { uint32_t tmp1 = 0, tmp2 = 0; if((pData == NULL ) || (Size == 0)) { return HAL_ERROR; } 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); if((tmp1 == I2S_DATAFORMAT_24B)|| \ (tmp2 == I2S_DATAFORMAT_32B)) { hi2s->RxXferSize = Size*2; hi2s->RxXferCount = Size*2; } else { hi2s->RxXferSize = Size; hi2s->RxXferCount = Size; } /* Process Locked */ __HAL_LOCK(hi2s); hi2s->State = HAL_I2S_STATE_BUSY_RX; /* Check if the I2S is already enabled */ if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) { /* Enable I2S peripheral */ __HAL_I2S_ENABLE(hi2s); } /* 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); } /* Receive data */ while(hi2s->RxXferCount > 0) { /* Wait until RXNE flag is set */ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, RESET, Timeout) != HAL_OK) { return HAL_TIMEOUT; } (*pData++) = hi2s->Instance->DR; hi2s->RxXferCount--; } hi2s->State = HAL_I2S_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { return HAL_BUSY; } }
/** * @brief Transmit an amount of data in blocking mode * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @param pData: a 16-bit pointer to 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_I2S_Transmit(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout) { uint32_t tmp1 = 0, tmp2 = 0; if((pData == NULL ) || (Size == 0)) { return HAL_ERROR; } 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); if((tmp1 == I2S_DATAFORMAT_24B)|| \ (tmp2 == I2S_DATAFORMAT_32B)) { hi2s->TxXferSize = Size*2; hi2s->TxXferCount = Size*2; } else { hi2s->TxXferSize = Size; hi2s->TxXferCount = Size; } /* Process Locked */ __HAL_LOCK(hi2s); hi2s->State = HAL_I2S_STATE_BUSY_TX; /* Check if the I2S is already enabled */ if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) { /* Enable I2S peripheral */ __HAL_I2S_ENABLE(hi2s); } while(hi2s->TxXferCount > 0) { hi2s->Instance->DR = (*pData++); hi2s->TxXferCount--; /* Wait until TXE flag is set */ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, RESET, Timeout) != HAL_OK) { return HAL_TIMEOUT; } } /* Wait until Busy flag is reset */ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, SET, Timeout) != HAL_OK) { return HAL_TIMEOUT; } hi2s->State = HAL_I2S_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { return HAL_BUSY; } }
/** * @brief Transmit an amount of data in blocking mode * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @param pData: a 16-bit pointer to 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_I2S_Transmit(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout) { if((pData == NULL ) || (Size == 0)) { return HAL_ERROR; } if(hi2s->State == HAL_I2S_STATE_READY) { if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B)) { hi2s->TxXferSize = (Size << 1); hi2s->TxXferCount = (Size << 1); } else { hi2s->TxXferSize = Size; hi2s->TxXferCount = Size; } /* Process Locked */ __HAL_LOCK(hi2s); hi2s->ErrorCode = HAL_I2S_ERROR_NONE; hi2s->State = HAL_I2S_STATE_BUSY_TX; /* Check if the I2S is already enabled */ if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) { /* Enable I2S peripheral */ __HAL_I2S_ENABLE(hi2s); } while(hi2s->TxXferCount > 0) { hi2s->Instance->DR = (*pData++); hi2s->TxXferCount--; /* Wait until TXE flag is set */ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, Timeout) != HAL_OK) { /* Set the error code and execute error callback*/ hi2s->ErrorCode |= HAL_I2S_ERROR_TIMEOUT; HAL_I2S_ErrorCallback(hi2s); return HAL_TIMEOUT; } /* Check if an underrun occurs */ if(__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_UDR) == SET) { /* Set the I2S State ready */ hi2s->State = HAL_I2S_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2s); /* Set the error code and execute error callback*/ hi2s->ErrorCode |= HAL_I2S_ERROR_UDR; HAL_I2S_ErrorCallback(hi2s); return HAL_ERROR; } } /* Wait until Busy flag is reset */ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, RESET, Timeout) != HAL_OK) { /* Set the error code and execute error callback*/ hi2s->ErrorCode |= HAL_I2S_ERROR_TIMEOUT; HAL_I2S_ErrorCallback(hi2s); return HAL_TIMEOUT; } hi2s->State = HAL_I2S_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { return HAL_BUSY; } }
/** * @brief Transmit and Receive an amount of data in non-blocking mode with 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 frames to be sent. * @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) { /* Check Mode parameter */ assert_param(IS_I2S_FD_MODE(hi2s->Init.Mode)); if((pTxData == NULL) || (Size == 0U)) { return HAL_ERROR; } /* Process Locked */ __HAL_LOCK(hi2s); if(hi2s->State == HAL_I2S_STATE_READY) { hi2s->pTxBuffPtr = pTxData; hi2s->pRxBuffPtr = pRxData; hi2s->State = HAL_I2S_STATE_BUSY_TX_RX; hi2s->ErrorCode = HAL_I2S_ERROR_NONE; if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B)) { hi2s->TxXferSize = (Size << 1U); hi2s->TxXferCount = (Size << 1U); hi2s->RxXferSize = (Size << 1U); hi2s->RxXferCount = (Size << 1U); } else { hi2s->TxXferSize = Size; hi2s->TxXferCount = Size; hi2s->RxXferSize = Size; hi2s->RxXferCount = Size; } /* Set the I2S Rx DMA Half transfert complete callback */ hi2s->hdmarx->XferHalfCpltCallback = I2SEx_DMATxRxHalfCplt; /* Set the I2S Rx DMA transfert complete callback */ hi2s->hdmarx->XferCpltCallback = I2SEx_DMATxRxCplt; /* Set the DMA error callback */ hi2s->hdmarx->XferErrorCallback = I2SEx_TxRxDMAError; /* Enable the Rx DMA Channel */ HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->RXDR, (uint32_t)hi2s->pRxBuffPtr, hi2s->RxXferSize); /* Check if the I2S Rx requests are already enabled */ if(HAL_IS_BIT_CLR(hi2s->Instance->CFG1, SPI_CFG1_RXDMAEN)) { /* Check if the SPI2S is disabled to edit CFG1 register */ if ((hi2s->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) { /* Enable Rx DMA Request */ SET_BIT(hi2s->Instance->CFG1, SPI_CFG1_RXDMAEN); } else { /* Disable SPI peripheral */ __HAL_I2S_DISABLE(hi2s); /* Enable Rx DMA Request */ SET_BIT(hi2s->Instance->CFG1, SPI_CFG1_RXDMAEN); /* Enable SPI peripheral */ __HAL_I2S_ENABLE(hi2s); } } /* Set the I2S Tx DMA transfer callbacks as NULL because the communication closing is performed in DMA reception callbacks */ hi2s->hdmatx->XferHalfCpltCallback = NULL; hi2s->hdmatx->XferCpltCallback = NULL; hi2s->hdmatx->XferErrorCallback = NULL; /* Enable the Tx DMA Channel */ HAL_DMA_Start_IT(hi2s->hdmatx, (uint32_t)hi2s->pTxBuffPtr, (uint32_t)&hi2s->Instance->TXDR, hi2s->TxXferSize); /* Check if the I2S Tx requests are already enabled */ if(HAL_IS_BIT_CLR(hi2s->Instance->CFG1, SPI_CFG1_TXDMAEN)) { /* Check if the SPI2S is disabled to edit CFG1 register */ if ((hi2s->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) { /* Enable Tx DMA Request */ SET_BIT(hi2s->Instance->CFG1, SPI_CFG1_TXDMAEN); } else { /* Disable SPI peripheral */ __HAL_I2S_DISABLE(hi2s); /* Enable Tx/Rx DMA Request */ SET_BIT(hi2s->Instance->CFG1, SPI_CFG1_TXDMAEN); /* Enable SPI peripheral */ __HAL_I2S_ENABLE(hi2s); } } /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { /* Process Unlocked */ __HAL_UNLOCK(hi2s); 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 Transmit and Receive an amount of data in non-blocking mode with 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). * @note This function can use an Audio Frequency up to 48KHz when I2S Clock Source is 32MHz * @retval HAL status */ HAL_StatusTypeDef HAL_I2SEx_TransmitReceive_IT(I2S_HandleTypeDef *hi2s, uint16_t *pTxData, uint16_t *pRxData, uint16_t Size) { /* Check Mode parameter */ assert_param(IS_I2S_FD_MODE(hi2s->Init.Mode)); /* Process Locked */ __HAL_LOCK(hi2s); if((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) { __HAL_UNLOCK(hi2s); return HAL_ERROR; } if (hi2s->State == HAL_I2S_STATE_READY) { __HAL_UNLOCK(hi2s); return HAL_BUSY; } /* Set the transaction information */ hi2s->State = HAL_I2S_STATE_BUSY_TX; hi2s->ErrorCode = HAL_I2S_ERROR_NONE; hi2s->pTxBuffPtr = pTxData; hi2s->TxXferSize = Size; hi2s->TxXferCount = Size; /* Init field not used in handle to zero */ hi2s->pRxBuffPtr = pRxData; hi2s->RxXferSize = Size; hi2s->RxXferCount = Size; /* Set the function for IT treatment */ if (hi2s->Init.DataFormat > I2S_DATAFORMAT_16B) { hi2s->RxISR = I2SEx_2linesRxISR_32BIT; hi2s->TxISR = I2SEx_2linesTxISR_32BIT; } else { hi2s->RxISR = I2SEx_2linesRxISR_16BIT; hi2s->TxISR = I2SEx_2linesTxISR_16BIT; } /* Check if the I2S is already enabled */ if ((hi2s->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) { /* Enable SPI peripheral */ __HAL_I2S_ENABLE(hi2s); } if (IS_I2S_MASTER(hi2s->Init.Mode)) { /* Master transfer start */ SET_BIT(hi2s->Instance->CR1, SPI_CR1_CSTART); } /* Enable TXE and ERR interrupt */ __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_RXNE | I2S_IT_ERR)); /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; }
/** * @brief Receive an amount of data in non-blocking mode with DMA * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @param pData: 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_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size) { uint32_t *tmp; uint32_t tmp1 = 0, tmp2 = 0; if((pData == NULL) || (Size == 0)) { return HAL_ERROR; } if(hi2s->State == HAL_I2S_STATE_READY) { hi2s->pRxBuffPtr = pData; tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); tmp2 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); if((tmp1 == I2S_DATAFORMAT_24B)|| \ (tmp2 == I2S_DATAFORMAT_32B)) { hi2s->RxXferSize = Size*2; hi2s->RxXferCount = Size*2; } else { hi2s->RxXferSize = Size; hi2s->RxXferCount = Size; } /* Process Locked */ __HAL_LOCK(hi2s); hi2s->State = HAL_I2S_STATE_BUSY_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 DMA error callback */ hi2s->hdmarx->XferErrorCallback = I2S_DMAError; /* 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 to the SPI_DR register followed by a read access to the SPI_SR register. */ __HAL_I2S_CLEAR_OVRFLAG(hi2s); } /* Enable the Rx DMA Stream */ tmp = (uint32_t*)&pData; HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->DR, *(uint32_t*)tmp, hi2s->RxXferSize); /* Check if the I2S is already enabled */ if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) { /* Enable I2S peripheral */ __HAL_I2S_ENABLE(hi2s); } /* Check if the I2S Rx request is already enabled */ if((hi2s->Instance->CR2 &SPI_CR2_RXDMAEN) != SPI_CR2_RXDMAEN) { /* Enable Rx DMA Request */ hi2s->Instance->CR2 |= SPI_CR2_RXDMAEN; } /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { return HAL_BUSY; } }
/** * @brief Receive an amount of data in blocking mode * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @param pData: a 16-bit pointer to 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). * @note In I2S Master Receiver mode, just after enabling the peripheral the clock will be generate * in continouse way and as the I2S is not disabled at the end of the I2S transaction. * @retval HAL status */ HAL_StatusTypeDef HAL_I2S_Receive(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout) { if((pData == NULL ) || (Size == 0)) { return HAL_ERROR; } if(hi2s->State == HAL_I2S_STATE_READY) { if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B)) { hi2s->RxXferSize = (Size << 1); hi2s->RxXferCount = (Size << 1); } else { hi2s->RxXferSize = Size; hi2s->RxXferCount = Size; } /* Process Locked */ __HAL_LOCK(hi2s); hi2s->ErrorCode = HAL_I2S_ERROR_NONE; hi2s->State = HAL_I2S_STATE_BUSY_RX; /* Check if the I2S is already enabled */ if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) { /* Enable I2S peripheral */ __HAL_I2S_ENABLE(hi2s); } /* 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); } /* Receive data */ while(hi2s->RxXferCount > 0) { /* Wait until RXNE flag is set */ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, SET, Timeout) != HAL_OK) { /* Set the error code and execute error callback*/ hi2s->ErrorCode |= HAL_I2S_ERROR_TIMEOUT; HAL_I2S_ErrorCallback(hi2s); return HAL_TIMEOUT; } /* Check if an overrun occurs */ if(__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_OVR) == SET) { /* Set the I2S State ready */ hi2s->State = HAL_I2S_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2s); /* Set the error code and execute error callback*/ hi2s->ErrorCode |= HAL_I2S_ERROR_OVR; HAL_I2S_ErrorCallback(hi2s); return HAL_ERROR; } (*pData++) = hi2s->Instance->DR; hi2s->RxXferCount--; } hi2s->State = HAL_I2S_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { return HAL_BUSY; } }
/** * @brief Receive an amount of data in blocking mode * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @param pData: a 16-bit pointer to 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). * @note In I2S Master Receiver mode, just after enabling the peripheral the clock will be generate * in continouse way and as the I2S is not disabled at the end of the I2S transaction. * @retval HAL status */ HAL_StatusTypeDef HAL_I2S_Receive(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout) { if((pData == NULL ) || (Size == 0)) { return HAL_ERROR; } /* Process Locked */ __HAL_LOCK(hi2s); if(hi2s->State == HAL_I2S_STATE_READY) { if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B)) { hi2s->RxXferSize = (Size << 1); hi2s->RxXferCount = (Size << 1); } else { hi2s->RxXferSize = Size; hi2s->RxXferCount = Size; } /* Set state and reset error code */ hi2s->ErrorCode = HAL_I2S_ERROR_NONE; hi2s->State = HAL_I2S_STATE_BUSY_RX; hi2s->pRxBuffPtr = pData; /* Check if the I2S is already enabled */ if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) { /* Enable I2S peripheral */ __HAL_I2S_ENABLE(hi2s); } /* Receive data */ while(hi2s->RxXferCount > 0) { /* Wait until RXNE flag is set */ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, RESET, Timeout) != HAL_OK) { return HAL_TIMEOUT; } (*hi2s->pRxBuffPtr++) = hi2s->Instance->DR; hi2s->RxXferCount--; } hi2s->State = HAL_I2S_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_BUSY; } }
/** * @brief Transmit an amount of data in blocking mode * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @param pData: a 16-bit pointer to 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_I2S_Transmit(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout) { if((pData == NULL ) || (Size == 0)) { return HAL_ERROR; } /* Process Locked */ __HAL_LOCK(hi2s); if(hi2s->State == HAL_I2S_STATE_READY) { if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B)) { hi2s->TxXferSize = (Size << 1); hi2s->TxXferCount = (Size << 1); } else { hi2s->TxXferSize = Size; hi2s->TxXferCount = Size; } /* Set state and reset error code */ hi2s->ErrorCode = HAL_I2S_ERROR_NONE; hi2s->State = HAL_I2S_STATE_BUSY_TX; hi2s->pTxBuffPtr = pData; /* Check if the I2S is already enabled */ if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) { /* Enable I2S 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 = (*hi2s->pTxBuffPtr++); hi2s->TxXferCount--; } /* Wait until TXE flag is set, to confirm the end of the transcation */ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, RESET, Timeout) != HAL_OK) { return HAL_TIMEOUT; } /* Check if Slave mode is selected */ if(((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX) || ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_RX)) { /* Wait until Busy flag is reset */ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, SET, Timeout) != HAL_OK) { return HAL_TIMEOUT; } } hi2s->State = HAL_I2S_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_BUSY; } }
/** * @brief Transmit an amount of data in non-blocking mode with DMA * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains * the configuration information for I2S module * @param pData: a 16-bit pointer to the Transmit 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_I2S_Transmit_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size) { if((pData == NULL) || (Size == 0)) { return HAL_ERROR; } /* Process Locked */ __HAL_LOCK(hi2s); if(hi2s->State == HAL_I2S_STATE_READY) { hi2s->pTxBuffPtr = pData; hi2s->State = HAL_I2S_STATE_BUSY_TX; hi2s->ErrorCode = HAL_I2S_ERROR_NONE; if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B)) { hi2s->TxXferSize = (Size << 1); hi2s->TxXferCount = (Size << 1); } else { hi2s->TxXferSize = Size; hi2s->TxXferCount = Size; } /* Set the I2S Tx DMA Half transfert complete callback */ hi2s->hdmatx->XferHalfCpltCallback = I2S_DMATxHalfCplt; /* Set the I2S Tx DMA transfert complete callback */ hi2s->hdmatx->XferCpltCallback = I2S_DMATxCplt; /* Set the DMA error callback */ hi2s->hdmatx->XferErrorCallback = I2S_DMAError; /* Enable the Tx DMA Channel */ HAL_DMA_Start_IT(hi2s->hdmatx, (uint32_t)hi2s->pTxBuffPtr, (uint32_t)&hi2s->Instance->DR, hi2s->TxXferSize); /* Check if the I2S is already enabled */ if(HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE)) { /* Enable I2S peripheral */ __HAL_I2S_ENABLE(hi2s); } /* Check if the I2S Tx request is already enabled */ if(HAL_IS_BIT_CLR(hi2s->Instance->CR2, SPI_CR2_TXDMAEN)) { /* Enable Tx DMA Request */ SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN); } /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_BUSY; } }
/** * @brief Transmit and Receive an amount of 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 frames to be sent * @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). * @note This function can use an Audio Frequency up to 48KHz when I2S Clock Source is 32MHz * @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 = 0U; uint32_t isDataFormat16B = 2U; /* Check Mode parameter */ assert_param(IS_I2S_FD_MODE(hi2s->Init.Mode)); if((pTxData == NULL ) || (Size == 0U)) { return HAL_ERROR; } /* Process Locked */ __HAL_LOCK(hi2s); /* Init tickstart for timeout management*/ tickstart = HAL_GetTick(); if(hi2s->State == HAL_I2S_STATE_READY) { /* Check the Data Format value */ if (((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B) || ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B)) { isDataFormat16B = 0U; } else { isDataFormat16B = 1U; } if(!isDataFormat16B) { hi2s->TxXferSize = (Size << 1U); hi2s->TxXferCount = (Size << 1U); hi2s->RxXferSize = (Size << 1U); hi2s->RxXferCount = (Size << 1U); } else { hi2s->TxXferSize = Size; hi2s->TxXferCount = Size; hi2s->RxXferSize = Size; hi2s->RxXferCount = Size; } /* Set state and reset error code */ hi2s->ErrorCode = HAL_I2S_ERROR_NONE; hi2s->State = HAL_I2S_STATE_BUSY_TX_RX; hi2s->pTxBuffPtr = pTxData; hi2s->pRxBuffPtr = pRxData; /* Check if the SPI2S is already enabled */ if((hi2s->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) { /* Enable I2S peripheral */ __HAL_I2S_ENABLE(hi2s); } if(IS_I2S_MASTER(hi2s->Init.Mode)) { hi2s->Instance->CR1 |= SPI_CR1_CSTART; } /* Transmit and Receive data in 32 Bit mode */ if (!isDataFormat16B) { while ((hi2s->TxXferCount > 0U) || (hi2s->RxXferCount > 0U)) { /* Check TXE flag */ if ((hi2s->TxXferCount > 0U) && (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_TXE))) { *((__IO uint32_t *)&hi2s->Instance->TXDR) = *((uint32_t *)hi2s->pTxBuffPtr); hi2s->pTxBuffPtr += sizeof(uint32_t); hi2s->TxXferCount --; } /* Check RXNE flag */ if ((hi2s->RxXferCount > 0U) && (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_RXNE))) { *((uint32_t *)hi2s->pRxBuffPtr) = *((__IO uint32_t *)&hi2s->Instance->RXDR); hi2s->pRxBuffPtr += sizeof(uint32_t); hi2s->RxXferCount --; } /* Timeout Management */ if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout)) { /* Set the error code and execute error callback*/ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); HAL_I2S_ErrorCallback(hi2s); /* Set the I2S State ready */ hi2s->State = HAL_I2S_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_ERROR; } } } /* Transmit and Receive data in 16 Bit mode */ else { while ((hi2s->TxXferCount > 0U) || (hi2s->RxXferCount > 0U)) { /* Check TXE flag */ if ((hi2s->TxXferCount > 0U) && (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_TXE))) { if ( (hi2s->TxXferCount > 1U) && (hi2s->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA)) { *((__IO uint32_t *)&hi2s->Instance->TXDR) = *((uint32_t *)hi2s->pTxBuffPtr); hi2s->pTxBuffPtr += sizeof(uint32_t); hi2s->TxXferCount-=2; } else { *((__IO uint16_t *)&hi2s->Instance->TXDR) = *((uint16_t *)hi2s->pTxBuffPtr); hi2s->pTxBuffPtr += sizeof(uint16_t); hi2s->TxXferCount--; } } /* Check RXNE flag */ if ((hi2s->RxXferCount > 0U) && (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_RXNE))) { if (hi2s->Instance->SR & I2S_FLAG_RXWNE) { *((uint32_t *)hi2s->pRxBuffPtr) = *((__IO uint32_t *)&hi2s->Instance->RXDR); hi2s->pRxBuffPtr += sizeof(uint32_t); hi2s->RxXferCount-=2; } else { *((uint16_t *)hi2s->pRxBuffPtr) = *((__IO uint16_t *)&hi2s->Instance->RXDR); hi2s->pRxBuffPtr += sizeof(uint16_t); hi2s->RxXferCount--; } } /* Timeout Management */ if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout)) { /* Set the error code and execute error callback*/ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); HAL_I2S_ErrorCallback(hi2s); /* Set the I2S State ready */ hi2s->State = HAL_I2S_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_ERROR; } } } /* Wait until TXE flag is set, to confirm the end of the transaction */ if (I2SEx_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, RESET, Timeout) != HAL_OK) { return HAL_TIMEOUT; } hi2s->State = HAL_I2S_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_OK; } else { /* Process Unlocked */ __HAL_UNLOCK(hi2s); return HAL_BUSY; } }
/** * @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; } }