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-09-26 08:44 PM
Hi uprogc,
I'm very glad to hear that, Could you please describe how you solved it. Many thanks for your help
2019-09-27 12:20 AM
It seems DMA interrupt issues..
2019-12-22 09:37 AM
Any solution so far with HAL v1.5? I can do polling and interrupt mode successfully, but stops with dma mode? It is very critical for my project. I would be pleased, if you have any solution or suggestion for this issue?
2021-05-01 06:30 PM
I had a very similar issue.
First call to HAL_I2S_Transmit_DMA worked. If i called it again in the completion handler also ok.
Every now and then due to other things going on i did not process the interrupt in time so I had some recovery code that re-initiated the transmit by calling HAL_I2S_Transmit_DMA again ... but although it returned ok the completion handler was never called.
Rather than change the HAL (because who knows what new versions will do) I added the following 2 lines just before I call HAL_I2S_Transmit_DMA.
CLEAR_BIT(hi2sWav.Instance->CFG1, SPI_CFG1_TXDMAEN);
__HAL_I2S_DISABLE(&hi2sWav);
These seem to be ok because HAL_I2S_Transmit_DMA checks if these are in the right state and if not sets them again.
With this change it seems to be working.