cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 I2S DMA using HAL Firmware 1.5 Troubleshoot

eeyurdakul
Associate II

I try to operate very basic I2S DMA function in STM32H750 chip. This is a very simple function which successfully works on STM32F4 and F7 chips.

I have read the previous comments about I2S problems on H7 chip, and know

there are some problems with I2S in previous releases of HAL library, but with the release of v.1.50. this library was rewritten. 

Right know, polling mode and interrupt mode are successfully working.

For DMA problems on H7, the linker script is re-edited. I2C and SPI DMA functions are working successfully, but I2S function starts without any errors, finishes 1 cycle successfully, then halts. It does not work in neither normal nor circular mode. 

In debug mode, HAL_I2S_TxHalfCpltCallback is called after one cycle, then it halts. No error callbacks are called. Below tryouts were not successful either;

  • placing dma buffer on RAM_D2
  • using cache maintenance functions (SCB_CleanDCache)
  • using I2S2 or I2S3

Solving this problem is very crucial for my project. Project files are attached.Any help or suggestion would be apreciated.

main.c ---->

#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "i2s.h"
#include "tim.h"
#include "gpio.h"
 
#include "audio.h"
#include "CS43L22.h"
 
uint16_t counter = 0;
int16_t dataI2S[2];
 
void SystemClock_Config(void);
 
int main(void) {
 
  HAL_Init();
  SystemClock_Config();
 
  MX_GPIO_Init();
  MX_I2C3_Init();
  MX_I2S1_Init();
  MX_DMA_Init();
 
  HAL_GPIO_WritePin(I2S1_RESET_GPIO_Port, I2S1_RESET_Pin, GPIO_PIN_SET);
  CS43_Init(hi2c3, MODE_I2S);
  CS43_SetVolume(30);
  CS43_Enable_RightLeft(CS43_RIGHT_LEFT);
  CS43_Start();
 
  HAL_I2S_Transmit_DMA(&hi2s1, (uint16_t *)dataI2S, 2);
 
  while (1) {}
}
 
void SystemClock_Config(void) {}
 
void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s) {
}
 
void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) {
	  if (hi2s == &hi2s1) {
		  if (counter < 2205) {
			  dataI2S[0] = kAudioSample[counter] - 32767;
			  dataI2S[1] = kAudioSample[counter] - 32767;
			  counter += 1;
		  } else if (counter < 44100){
			  counter += 1;
		  } else {
			  counter = 0;
		  }
	  }
}
 
void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s) {
 
}
 
void Error_Handler(void) {}

i2s.c---->

void MX_I2S1_Init(void)
{
 
  hi2s1.Instance = SPI1;
  hi2s1.Init.Mode = I2S_MODE_MASTER_TX;
  hi2s1.Init.Standard = I2S_STANDARD_PHILIPS;
  hi2s1.Init.DataFormat = I2S_DATAFORMAT_16B;
  hi2s1.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
  hi2s1.Init.AudioFreq = I2S_AUDIOFREQ_44K;
  hi2s1.Init.CPOL = I2S_CPOL_LOW;
  hi2s1.Init.FirstBit = I2S_FIRSTBIT_MSB;
  hi2s1.Init.WSInversion = I2S_WS_INVERSION_DISABLE;
  hi2s1.Init.Data24BitAlignment = I2S_DATA_24BIT_ALIGNMENT_RIGHT;
  hi2s1.Init.MasterKeepIOState = I2S_MASTER_KEEP_IO_STATE_DISABLE;
  if (HAL_I2S_Init(&hi2s1) != HAL_OK)
  {
    Error_Handler();
  }
 
}
 
void HAL_I2S_MspInit(I2S_HandleTypeDef* i2sHandle)
{
 
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(i2sHandle->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */
 
  /* USER CODE END SPI1_MspInit 0 */
    /* I2S1 clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();
  
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**I2S1 GPIO Configuration    
    PA4     ------> I2S1_WS
    PA5     ------> I2S1_CK
    PA7     ------> I2S1_SDO
    PC4     ------> I2S1_MCK 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
    /* I2S1 DMA Init */
    /* SPI1_TX Init */
    hdma_spi1_tx.Instance = DMA1_Stream0;
    hdma_spi1_tx.Init.Request = DMA_REQUEST_SPI1_TX;
    hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_spi1_tx.Init.Mode = DMA_CIRCULAR;
    hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
    {
      Error_Handler();
    }
 
    __HAL_LINKDMA(i2sHandle,hdmatx,hdma_spi1_tx);
 
    /* I2S1 interrupt Init */
    HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SPI1_IRQn);
  }
}

linker script---->

.data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
 
    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM_D1 AT> FLASH
 
 
  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)
 
    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM_D1
 
  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM_D1

0690X00000ButtRQAR.png0690X00000ButtWQAR.png 

1 ACCEPTED SOLUTION

Accepted Solutions
eeyurdakul
Associate II
MX_GPIO_Init();
MX_I2C3_Init();
MX_I2S1_Init();
MX_DMA_Init();

STM32Cube automatically generates init functions, but the order is false, MX_DMA_Init() should be the first.

MX_DMA_Init();
MX_GPIO_Init();
MX_I2C3_Init();
MX_I2S1_Init();

This solves the problem, right now it works both in normal and circular mode.

View solution in original post

2 REPLIES 2
eeyurdakul
Associate II
MX_GPIO_Init();
MX_I2C3_Init();
MX_I2S1_Init();
MX_DMA_Init();

STM32Cube automatically generates init functions, but the order is false, MX_DMA_Init() should be the first.

MX_DMA_Init();
MX_GPIO_Init();
MX_I2C3_Init();
MX_I2S1_Init();

This solves the problem, right now it works both in normal and circular mode.