Skip to main content
Explorer
August 5, 2024
Solved

STM32H732 I2S Unstable Clocks (Stutter)

  • August 5, 2024
  • 5 replies
  • 3347 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.

    This topic has been closed for replies.
    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

    Explorer
    August 5, 2024

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

    GkatsosAuthor
    Explorer
    August 6, 2024

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

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

     

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

    What's the primary I2S clock source?

    Is that stable?

    JW

    GkatsosAuthor
    Explorer
    August 7, 2024

    I am using the HSI -> PPL2P -> SPI1

    Screenshot 2024-08-07 192448.png

    GkatsosAuthorAnswer
    Explorer
    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.