2019-01-17 08:18 AM
Hello STM32 Community!
My I2S dma transfer worked perfectly on stm32f7x in the past, but due to time critical calculations i just started to continue the development on the advanced stm32h7 system.
I use the same code, same initialization procedure and same HAL function calls (as i did on stm32f7) but the H7 stops executing the code after the HAL_I2S_Transmit_DMA function call.
I am aware that the peripheral bus can't access ITCM and DTCM, therefore i placed all memory to D1 domain, as it is written here (https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices, e.g., IRAM2 0x24000000 0x80000)
Did anyone successfully use the I2S peripheral with DMA on H7 system?
Here is the code for the clock setup i use:
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3|RCC_PERIPHCLK_USART1
|RCC_PERIPHCLK_SPI3;
PeriphClkInitStruct.PLL2.PLL2M = 8;
PeriphClkInitStruct.PLL2.PLL2N = 192;
PeriphClkInitStruct.PLL2.PLL2P = 2;
PeriphClkInitStruct.PLL2.PLL2Q = 2;
PeriphClkInitStruct.PLL2.PLL2R = 2;
PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_1;
PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL2;
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO2SOURCE_PLL2PCLK, RCC_MCODIV_5);
The following is the code for the I2S3 initialization:
static void MX_I2S3_Init(void)
{
/* USER CODE BEGIN I2S3_Init 0 */
/* USER CODE END I2S3_Init 0 */
/* USER CODE BEGIN I2S3_Init 1 */
/* USER CODE END I2S3_Init 1 */
hi2s3.Instance = SPI3;
hi2s3.Init.Mode = I2S_MODE_MASTER_TX;
hi2s3.Init.Standard = I2S_STANDARD_PHILIPS;
hi2s3.Init.DataFormat = I2S_DATAFORMAT_32B;
hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;
hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_48K;
hi2s3.Init.CPOL = I2S_CPOL_LOW;
hi2s3.Init.FirstBit = I2S_FIRSTBIT_MSB;
hi2s3.Init.WSInversion = I2S_WS_INVERSION_DISABLE;
hi2s3.Init.IOSwap = I2S_IO_SWAP_DISABLE;
hi2s3.Init.Data24BitAlignment = I2S_DATA_24BIT_ALIGNMENT_RIGHT;
hi2s3.Init.FifoThreshold = I2S_FIFO_THRESHOLD_01DATA;
hi2s3.Init.MasterKeepIOState = I2S_MASTER_KEEP_IO_STATE_DISABLE;
hi2s3.Init.SlaveExtendFREDetection = I2S_SLAVE_EXTEND_FRE_DETECTION_DISABLE;
if (HAL_I2S_Init(&hi2s3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2S3_Init 2 */
/* USER CODE END I2S3_Init 2 */
}
And this is the MSP initialization:
if(hi2s->Instance==SPI3)
{
/* USER CODE BEGIN SPI3_MspInit 0 */
/* USER CODE END SPI3_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**I2S3 GPIO Configuration
PA15 (JTDI) ------> I2S3_WS
PC10 ------> I2S3_CK
PC12 ------> I2S3_SDO
*/
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* I2S3 DMA Init */
/* SPI3_TX Init */
hdma_spi3_tx.Instance = DMA1_Stream5;
hdma_spi3_tx.Init.Request = DMA_REQUEST_SPI3_TX;
hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi3_tx.Init.Mode = DMA_CIRCULAR;
hdma_spi3_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi3_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hi2s,hdmatx,hdma_spi3_tx);
/* I2S3 interrupt Init */
HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI3_IRQn);
/* USER CODE BEGIN SPI3_MspInit 1 */
/* USER CODE END SPI3_MspInit 1 */
}
Everything works until i call the transmit function
HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t*) signalTable, (uint16_t) SIGNAL_TABLE_SIZE/2);
I generated the initialization code with the latest CubeMX and STM32Cube_FW_H7_V1.3.0.
Thank you for the reply in advance
2019-01-28 02:27 AM
I'm having the same issue... did you solved the problem?
2019-01-28 02:42 AM
no, unfortunately i did not.
i should have dig myself into the debugging of the hal api for which i did not have time.
i am waiting for the STM32Cube_FW_H7 1.4.....
2019-02-04 06:28 AM
Hi, same issue here... Found any solution ?
Thanks!
2019-04-16 02:47 AM
Fix HAL Lib.
In stm32h7_hal_i2s.c replace function "HAL_I2S_Transmit_DMA(...)" by below.
Today, i had the same issue. And I solved it. STM32H7xx_HAL_... maybe update lib to fix this issue.
I hope useful to anyone got this issue.
HAL_StatusTypeDef HAL_I2S_Transmit_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
{
/* Check Mode parameter */
assert_param(IS_I2S_TX_MODE(hi2s->Init.Mode));
if((pData == NULL) || (Size == 0U))
{
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 << 1U);
hi2s->TxXferCount = (Size << 1U);
}
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;
/* Clear TXDMAEN bit*/
CLEAR_BIT(hi2s->Instance->CFG1, SPI_CFG1_TXDMAEN);
/* Enable the Tx DMA Channel */
HAL_DMA_Start_IT(hi2s->hdmatx, (uint32_t)hi2s->pTxBuffPtr, (uint32_t)&hi2s->Instance->TXDR, hi2s->TxXferSize);
/* Set the number if data at current transfer */
if (hi2s->hdmatx->Init.Mode == DMA_CIRCULAR)
{
MODIFY_REG(hi2s->Instance->CR2, SPI_CR2_TSIZE, 0);
}
else
{
MODIFY_REG(hi2s->Instance->CR2, SPI_CR2_TSIZE, Size);
}
/* Check if the I2S Tx request is 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);
/* Enable SPI peripheral */
__HAL_I2S_ENABLE(hi2s);
}
else
{
/* Disable SPI peripheral */
__HAL_I2S_DISABLE(hi2s);
/* Enable Tx DMA Request */
SET_BIT(hi2s->Instance->CFG1, SPI_CFG1_TXDMAEN);
/* Enable SPI peripheral */
__HAL_I2S_ENABLE(hi2s);
}
}
/* Master transfer start */
SET_BIT(hi2s->Instance->CR1, SPI_CR1_CSTART);
/* Process Unlocked */
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
else
{
/* Process Unlocked */
__HAL_UNLOCK(hi2s);
return HAL_BUSY;
}
}
2019-04-29 01:43 AM
Hi,
I have the "same" problem, but with RX. I'm using the I2S3 in master RX mode.
I modified the CubeMX generated HAL_I2S_Receive_DMA ( ) function (see below), because the SPE bit in CR1 register was 0 , but still not working
I'm looking with oscilloscope on I2S clock and ws pins but no signal.
HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
{
/* Check Mode parameter */
assert_param(IS_I2S_RX_MODE(hi2s->Init.Mode));
if((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(hi2s);
if(hi2s->State == HAL_I2S_STATE_READY)
{
hi2s->pRxBuffPtr = pData;
hi2s->State = HAL_I2S_STATE_BUSY_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->RxXferSize = (Size << 1U);
hi2s->RxXferCount = (Size << 1U);
}
else
{
hi2s->RxXferSize = Size;
hi2s->RxXferCount = Size;
}
/* 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 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 Channel */
HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->RXDR, (uint32_t)hi2s->pRxBuffPtr, hi2s->RxXferSize);
/* Set the number if data at current transfer */
if (hi2s->hdmatx->Init.Mode == DMA_CIRCULAR)
{
MODIFY_REG(hi2s->Instance->CR2, SPI_CR2_TSIZE, 0);
}
else
{
MODIFY_REG(hi2s->Instance->CR2, SPI_CR2_TSIZE, Size);
}
/* Check if the I2S Rx request is 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);
/* Enable SPI peripheral */
__HAL_I2S_ENABLE(hi2s);
}
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);
}
}
/* Master transfer start */
SET_BIT(hi2s->Instance->CR1, SPI_CR1_CSTART);
/* Process Unlocked */
__HAL_UNLOCK(hi2s);
return HAL_OK;
}
else
{
/* Process Unlocked */
__HAL_UNLOCK(hi2s);
return HAL_BUSY;
}
}
Regards,
uprog
2019-09-05 08:22 PM
deleted!
2019-09-24 01:13 AM
Hi, I'm having the same issue... did you solved the problem?
2019-09-24 01:17 AM
Hi , I follow your suggestion to modify HAL_I2S_Transmit_DMA function. But it seems still not working. Has anyone actually been successful with this ?
2019-09-24 03:33 AM
Hi, I have solved the I2S DMA RX/TX for double buffer.