cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H732 I2S Unstable Clocks (Stutter)

Gkatsos
Associate III

I have set up a project in STM32CubeMX.

I have setup both I2S1 for Receiving and I2S2 for Transmiting with DMA.

After the normal initalization i start receiving from the DMA:

 

 

 

if (HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*)&output_buffer, 1) != HAL_OK)
{
    Error_Handler();
}

 

 

 

And the setup of the I2S are as following:

 

 

 

void MX_I2S1_Init(void)
{
  hi2s1.Instance = SPI1;
  hi2s1.Init.Mode = I2S_MODE_MASTER_RX;
  hi2s1.Init.Standard = I2S_STANDARD_PHILIPS;
  hi2s1.Init.DataFormat = I2S_DATAFORMAT_32B;
  hi2s1.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
  hi2s1.Init.AudioFreq = I2S_AUDIOFREQ_48K;
  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_LEFT;
  hi2s1.Init.MasterKeepIOState = I2S_MASTER_KEEP_IO_STATE_ENABLE;
  if (HAL_I2S_Init(&hi2s1) != HAL_OK)
  {
    Error_Handler();
  }
}

void MX_I2S2_Init(void)
{
  hi2s2.Instance = SPI2;
  hi2s2.Init.Mode = I2S_MODE_MASTER_TX;
  hi2s2.Init.Standard = I2S_STANDARD_PHILIPS;
  hi2s2.Init.DataFormat = I2S_DATAFORMAT_32B;
  hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
  hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_48K;
  hi2s2.Init.CPOL = I2S_CPOL_LOW;
  hi2s2.Init.FirstBit = I2S_FIRSTBIT_MSB;
  hi2s2.Init.WSInversion = I2S_WS_INVERSION_DISABLE;
  hi2s2.Init.Data24BitAlignment = I2S_DATA_24BIT_ALIGNMENT_LEFT;
  hi2s2.Init.MasterKeepIOState = I2S_MASTER_KEEP_IO_STATE_DISABLE;
  if (HAL_I2S_Init(&hi2s2) != HAL_OK)
  {
    Error_Handler();
  }
}

 

 

 

The HAL_I2S_RxCpltCallback doesn't do anything right now and the I2S2 is not started with the DMA.

I am only using the MCLK, BCLK, and LRCLK, and have conneted the peripherals ADC and DAC to these and their DIN and DOUT are connected, so if MCLK, BCLK, and LRCLK I should have a clean connection, but the audio is choppy. I can see when measuring MCLK, BCLK, and LRCLK, their frequency sporadically go up, cutting the correct transfer, to then go back. The stuttering happens a few times per second.

I have spent a lot of time trying to fix this, but i have no idea how to fix it.

1 ACCEPTED SOLUTION

Accepted Solutions
Gkatsos
Associate III

So I have finally fixed the problem, my reluctancy to acknowledged using the HSI could be the problem has been my downfall.

I have tried adding 24.576 MHz to is2_ckin, and now everything is stable...

A lot of thanks to every one who has applied to the thread.

View solution in original post

13 REPLIES 13
MasterT
Lead

Verify where main uCPU clock is coming from.  To have low jitter use crystal HSE. For nucleo boards ST-Link

Gkatsos
Associate III

So here are my newest measurements, LRCLK (BLUE) and BCLK (YELLOW). The problem isn't jitter, but that LRCLK changes more often than every 32 BCLK, but only a few times per second.

measurement.jpg

I am using the HSI, but as i have just added, it isn't jitter.

What is the dma mode? Is it possible that 

HAL_I2S_Transmit_DMA

restarts happened?

Better to post all your code.

Gkatsos
Associate III

The DMA mode is circular, so i don't expect any restarts, here is the rest of the I2S.c:

void HAL_I2S_MspInit(I2S_HandleTypeDef* i2sHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(i2sHandle->Instance==SPI1)
  {
    /* I2S1 clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**I2S1 GPIO Configuration
    PA5     ------> I2S1_CK
    PA6     ------> I2S1_SDI
    PC4     ------> I2S1_MCK
    PA15(JTDI)     ------> I2S1_WS
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_15;
    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_RX Init */
    hdma_spi1_rx.Instance = DMA1_Stream0;
    hdma_spi1_rx.Init.Request = DMA_REQUEST_SPI1_RX;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_spi1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(i2sHandle,hdmarx,hdma_spi1_rx);

    /* I2S1 interrupt Init */
    HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SPI1_IRQn);
  }
  else if(i2sHandle->Instance==SPI2)
  {
    /* I2S2 clock enable */
    __HAL_RCC_SPI2_CLK_ENABLE();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**I2S2 GPIO Configuration
    PC1     ------> I2S2_SDO
    PB10     ------> I2S2_CK
    PB12     ------> I2S2_WS
    PC6     ------> I2S2_MCK
    */
    GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOC, &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_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* I2S2 DMA Init */
    /* SPI2_TX Init */
    hdma_spi2_tx.Instance = DMA1_Stream1;
    hdma_spi2_tx.Init.Request = DMA_REQUEST_SPI2_TX;
    hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_spi2_tx.Init.Mode = DMA_CIRCULAR;
    hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(i2sHandle,hdmatx,hdma_spi2_tx);

    /* I2S2 interrupt Init */
    HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SPI2_IRQn);
  }
}

void HAL_I2S_MspDeInit(I2S_HandleTypeDef* i2sHandle)
{
  if(i2sHandle->Instance==SPI1)
  {
    /* Peripheral clock disable */
    __HAL_RCC_SPI1_CLK_DISABLE();

    /**I2S1 GPIO Configuration
    PA5     ------> I2S1_CK
    PA6     ------> I2S1_SDI
    PC4     ------> I2S1_MCK
    PA15(JTDI)     ------> I2S1_WS
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_15);

    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_4);

    /* I2S1 DMA DeInit */
    HAL_DMA_DeInit(i2sHandle->hdmarx);

    /* I2S1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(SPI1_IRQn);
  }
  else if(i2sHandle->Instance==SPI2)
  {
    /* Peripheral clock disable */
    __HAL_RCC_SPI2_CLK_DISABLE();

    /**I2S2 GPIO Configuration
    PC1     ------> I2S2_SDO
    PB10     ------> I2S2_CK
    PB12     ------> I2S2_WS
    PC6     ------> I2S2_MCK
    */
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1|GPIO_PIN_6);

    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_12);

    /* I2S2 DMA DeInit */
    HAL_DMA_DeInit(i2sHandle->hdmatx);

    /* I2S2 interrupt Deinit */
    HAL_NVIC_DisableIRQ(SPI2_IRQn);
  }
}

 

 
if (HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*)&output_buffer, 1) != HAL_OK)

and

"The HAL_I2S_RxCpltCallback doesn't do anything right now and the I2S2 is not started with the DMA."

Do you mistype, and should be I2S1 is not started?

 

Anyway, I never tested I2S + dma transferring only one word, but I envision that uCPU would have hard time to figure out when to fire TransferComplete & TransferHalfComplete interrupts, since half of 1 is 0 in integers.

Try to increase size of data to be transferred.

What is the size of output_buffer?

What memory it's located?

Has DMA access to this memory?

 

 

Sorry wrote the wrong function, I2S2 is not started, the code running is initially is:

void Start_I2S1_Receive(void)
{
	if (HAL_I2S_Receive_DMA(&hi2s1, (uint16_t*)&input_buffer, 1) != HAL_OK) 
	{
		Error_Handler();
	}
}

A follow up.

I have also tried setting up SAI, here all the clocks are correct, but I again experience stutter.

I have tried with a lot of different buffer sizes.