Skip to main content
Associate II
August 5, 2024
Solved

STM32H732 I2S Unstable Clocks (Stutter)

  • August 5, 2024
  • 5 replies
  • 3348 views

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.

Best answer by Gkatsos

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.

5 replies

MasterT
Lead II
August 5, 2024

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

GkatsosAuthor
Associate II
August 6, 2024

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

MasterT
Lead II
August 6, 2024

What is the dma mode? Is it possible that 

HAL_I2S_Transmit_DMA

restarts happened?

Better to post all your code.

GkatsosAuthor
Associate II
August 6, 2024

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

GkatsosAuthor
Associate II
August 6, 2024

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);
 }
}

 

MasterT
Lead II
August 6, 2024
 
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?

 

 

GkatsosAuthor
Associate II
August 6, 2024

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();
	}
}
waclawek.jan
Super User
August 7, 2024

What's the primary I2S clock source?

Is that stable?

JW

GkatsosAuthor
Associate II
August 7, 2024

I am using the HSI -> PPL2P -> SPI1

Screenshot 2024-08-07 192448.png

GkatsosAuthorBest answer
Associate II
August 8, 2024

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.