Release v1.2.9
diff --git a/Src/stm32f7xx_hal_i2s.c b/Src/stm32f7xx_hal_i2s.c
index aa955fc..a116d92 100644
--- a/Src/stm32f7xx_hal_i2s.c
+++ b/Src/stm32f7xx_hal_i2s.c
@@ -88,6 +88,10 @@
(+) Pause the DMA Transfer using HAL_I2S_DMAPause()
(+) Resume the DMA Transfer using HAL_I2S_DMAResume()
(+) Stop the DMA Transfer using HAL_I2S_DMAStop()
+ In Slave mode, if HAL_I2S_DMAStop is used to stop the communication, an error
+ HAL_I2S_ERROR_BUSY_LINE_RX is raised as the master continue to transmit data.
+ In this case __HAL_I2S_FLUSH_RX_DR macro must be used to flush the remaining data
+ inside DR register and avoid using DeInit/Init process for the next transfer.
*** I2S HAL driver macros list ***
===================================
@@ -99,6 +103,7 @@
(+) __HAL_I2S_ENABLE_IT : Enable the specified I2S interrupts
(+) __HAL_I2S_DISABLE_IT : Disable the specified I2S interrupts
(+) __HAL_I2S_GET_FLAG: Check whether the specified I2S flag is set or not
+ (+) __HAL_I2S_FLUSH_RX_DR: Read DR Register to Flush RX Data
[..]
(@) You can refer to the I2S HAL driver header file for more useful macros
@@ -113,13 +118,13 @@
Use Functions HAL_I2S_RegisterCallback() to register an interrupt callback.
Function HAL_I2S_RegisterCallback() allows to register following callbacks:
- (+) TxCpltCallback : I2S Tx Completed callback
- (+) RxCpltCallback : I2S Rx Completed callback
- (+) TxHalfCpltCallback : I2S Tx Half Completed callback
- (+) RxHalfCpltCallback : I2S Rx Half Completed callback
- (+) ErrorCallback : I2S Error callback
- (+) MspInitCallback : I2S Msp Init callback
- (+) MspDeInitCallback : I2S Msp DeInit callback
+ (++) TxCpltCallback : I2S Tx Completed callback
+ (++) RxCpltCallback : I2S Rx Completed callback
+ (++) TxHalfCpltCallback : I2S Tx Half Completed callback
+ (++) RxHalfCpltCallback : I2S Rx Half Completed callback
+ (++) ErrorCallback : I2S Error callback
+ (++) MspInitCallback : I2S Msp Init callback
+ (++) MspDeInitCallback : I2S Msp DeInit callback
This function takes as parameters the HAL peripheral handle, the Callback ID
and a pointer to the user callback function.
@@ -129,14 +134,15 @@
HAL_I2S_UnRegisterCallback takes as parameters the HAL peripheral handle,
and the Callback ID.
This function allows to reset following callbacks:
- (+) TxCpltCallback : I2S Tx Completed callback
- (+) RxCpltCallback : I2S Rx Completed callback
- (+) TxHalfCpltCallback : I2S Tx Half Completed callback
- (+) RxHalfCpltCallback : I2S Rx Half Completed callback
- (+) ErrorCallback : I2S Error callback
- (+) MspInitCallback : I2S Msp Init callback
- (+) MspDeInitCallback : I2S Msp DeInit callback
+ (++) TxCpltCallback : I2S Tx Completed callback
+ (++) RxCpltCallback : I2S Rx Completed callback
+ (++) TxHalfCpltCallback : I2S Tx Half Completed callback
+ (++) RxHalfCpltCallback : I2S Rx Half Completed callback
+ (++) ErrorCallback : I2S Error callback
+ (++) MspInitCallback : I2S Msp Init callback
+ (++) MspDeInitCallback : I2S Msp DeInit callback
+ [..]
By default, after the HAL_I2S_Init() and when the state is HAL_I2S_STATE_RESET
all callbacks are set to the corresponding weak functions:
examples HAL_I2S_MasterTxCpltCallback(), HAL_I2S_MasterRxCpltCallback().
@@ -146,6 +152,7 @@
If MspInit or MspDeInit are not null, the HAL_I2S_Init()/ HAL_I2S_DeInit()
keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+ [..]
Callbacks can be registered/unregistered in HAL_I2S_STATE_READY state only.
Exception done MspInit/MspDeInit functions that can be registered/unregistered
in HAL_I2S_STATE_READY or HAL_I2S_STATE_RESET state,
@@ -154,7 +161,8 @@
using HAL_I2S_RegisterCallback() before calling HAL_I2S_DeInit()
or HAL_I2S_Init() function.
- When The compilation define USE_HAL_I2S_REGISTER_CALLBACKS is set to 0 or
+ [..]
+ When the compilation define USE_HAL_I2S_REGISTER_CALLBACKS is set to 0 or
not defined, the callback registering feature is not available
and weak (surcharged) callbacks are used.
@@ -189,6 +197,7 @@
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
+#define I2S_TIMEOUT_FLAG 100U /*!< Timeout 100 ms */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
@@ -328,7 +337,7 @@
/* I2S standard */
if (hi2s->Init.Standard <= I2S_STANDARD_LSB)
{
- /* In I2S standard packet lenght is multiplied by 2 */
+ /* In I2S standard packet length is multiplied by 2 */
packetlength = packetlength * 2U;
}
@@ -412,7 +421,7 @@
/* Write to SPIx I2SCFGR */
SET_BIT(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_ASTRTEN);
}
-#endif
+#endif /* SPI_I2SCFGR_ASTRTEN */
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
hi2s->State = HAL_I2S_STATE_READY;
@@ -506,7 +515,8 @@
* @param pCallback pointer to the Callback function
* @retval HAL status
*/
-HAL_StatusTypeDef HAL_I2S_RegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID, pI2S_CallbackTypeDef pCallback)
+HAL_StatusTypeDef HAL_I2S_RegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID,
+ pI2S_CallbackTypeDef pCallback)
{
HAL_StatusTypeDef status = HAL_OK;
@@ -742,7 +752,7 @@
* @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.
+ * the Size parameter means the number of 24-bit or 32-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).
@@ -831,7 +841,8 @@
}
/* Check if Slave mode is selected */
- if (((tmpreg_cfgr & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX) || ((tmpreg_cfgr & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_RX))
+ if (((tmpreg_cfgr & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX)
+ || ((tmpreg_cfgr & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_RX))
{
/* Wait until Busy flag is reset */
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, RESET, Timeout) != HAL_OK)
@@ -858,7 +869,7 @@
* @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.
+ * the Size parameter means the number of 24-bit or 32-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).
@@ -959,7 +970,7 @@
* @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.
+ * the Size parameter means the number of 24-bit or 32-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
@@ -1023,7 +1034,7 @@
* @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.
+ * the Size parameter means the number of 24-bit or 32-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-synchronization
@@ -1089,7 +1100,7 @@
* @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.
+ * the Size parameter means the number of 24-bit or 32-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
@@ -1140,7 +1151,10 @@
hi2s->hdmatx->XferErrorCallback = I2S_DMAError;
/* Enable the Tx DMA Stream/Channel */
- if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmatx, (uint32_t)hi2s->pTxBuffPtr, (uint32_t)&hi2s->Instance->DR, hi2s->TxXferSize))
+ if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmatx,
+ (uint32_t)hi2s->pTxBuffPtr,
+ (uint32_t)&hi2s->Instance->DR,
+ hi2s->TxXferSize))
{
/* Update SPI error code */
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
@@ -1177,7 +1191,7 @@
* @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.
+ * the Size parameter means the number of 24-bit or 32-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
@@ -1236,7 +1250,8 @@
}
/* Enable the Rx DMA Stream/Channel */
- if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->DR, (uint32_t)hi2s->pRxBuffPtr, hi2s->RxXferSize))
+ if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->DR, (uint32_t)hi2s->pRxBuffPtr,
+ hi2s->RxXferSize))
{
/* Update SPI error code */
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
@@ -1350,35 +1365,86 @@
and the correspond call back is executed HAL_I2S_TxCpltCallback() or HAL_I2S_RxCpltCallback()
*/
- /* Disable the I2S Tx/Rx DMA requests */
- CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
- CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
-
- /* Abort the I2S DMA tx Stream/Channel */
- if (hi2s->hdmatx != NULL)
+ if ((hi2s->Init.Mode == I2S_MODE_MASTER_TX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_TX))
{
- /* Disable the I2S DMA tx Stream/Channel */
- if (HAL_OK != HAL_DMA_Abort(hi2s->hdmatx))
+ /* Abort the I2S DMA tx Stream/Channel */
+ if (hi2s->hdmatx != NULL)
{
- SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
- errorcode = HAL_ERROR;
+ /* Disable the I2S DMA tx Stream/Channel */
+ if (HAL_OK != HAL_DMA_Abort(hi2s->hdmatx))
+ {
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
+ errorcode = HAL_ERROR;
+ }
}
+
+ /* Wait until TXE flag is set */
+ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, I2S_TIMEOUT_FLAG) != HAL_OK)
+ {
+ /* Set the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
+ hi2s->State = HAL_I2S_STATE_READY;
+ errorcode = HAL_ERROR;
+ }
+
+ /* Wait until BSY flag is Reset */
+ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, RESET, I2S_TIMEOUT_FLAG) != HAL_OK)
+ {
+ /* Set the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
+ hi2s->State = HAL_I2S_STATE_READY;
+ errorcode = HAL_ERROR;
+ }
+
+ /* Disable I2S peripheral */
+ __HAL_I2S_DISABLE(hi2s);
+
+ /* Clear UDR flag */
+ __HAL_I2S_CLEAR_UDRFLAG(hi2s);
+
+ /* Disable the I2S Tx DMA requests */
+ CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
+
}
- /* Abort the I2S DMA rx Stream/Channel */
- if (hi2s->hdmarx != NULL)
+ else if ((hi2s->Init.Mode == I2S_MODE_MASTER_RX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_RX))
{
- /* Disable the I2S DMA rx Stream/Channel */
- if (HAL_OK != HAL_DMA_Abort(hi2s->hdmarx))
+ /* Abort the I2S DMA rx Stream/Channel */
+ if (hi2s->hdmarx != NULL)
{
- SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
+ /* Disable the I2S DMA rx Stream/Channel */
+ if (HAL_OK != HAL_DMA_Abort(hi2s->hdmarx))
+ {
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
+ errorcode = HAL_ERROR;
+ }
+ }
+
+ /* Disable I2S peripheral */
+ __HAL_I2S_DISABLE(hi2s);
+
+ /* Clear OVR flag */
+ __HAL_I2S_CLEAR_OVRFLAG(hi2s);
+
+ /* Disable the I2S Rx DMA request */
+ CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
+
+ if (hi2s->Init.Mode == I2S_MODE_SLAVE_RX)
+ {
+ /* Set the error code */
+ SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_BUSY_LINE_RX);
+
+ /* Set the I2S State ready */
+ hi2s->State = HAL_I2S_STATE_READY;
errorcode = HAL_ERROR;
}
+ else
+ {
+ /* Read DR to Flush RX Data */
+ READ_REG((hi2s->Instance)->DR);
+ }
}
- /* Disable I2S peripheral */
- __HAL_I2S_DISABLE(hi2s);
-
hi2s->State = HAL_I2S_STATE_READY;
return errorcode;
@@ -1814,7 +1880,8 @@
* @param Timeout Duration of the timeout
* @retval HAL status
*/
-static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag, FlagStatus State, uint32_t Timeout)
+static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag, FlagStatus State,
+ uint32_t Timeout)
{
uint32_t tickstart;