cancel
Showing results for 
Search instead for 
Did you mean: 

stm32h7 i2s dma transfer issue

akosodry
Associate II

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

13 REPLIES 13

Hi uprogc,

I'm very glad to hear that, Could you please describe how you solved it. Many thanks for your help

It seems DMA interrupt issues..

eeyurdakul
Associate II

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?

KWest.1
Associate II

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.