AnsweredAssumed Answered

I2S problem on stm32f411 and HAL

Question asked by elgarbe on Sep 17, 2015
Latest reply on Sep 24, 2015 by elgarbe
I'm working on stm32f411 since a couple of month. I drive an audio codec. It is configured with I2C and the sound is drive by I2S. In my application I need to send a tone and hear at the same time a response. So I use full duplex.
After some test I found that there is a desincronization between data out and Word Selection when I put a delay between two transmit/receive calling.
This code works ok:

int main(void)
{
    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();
 
    /* Configure the system clock */
    SystemClock_Config();
 
    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_I2C1_Init();
    MX_I2S2_Init();
 
    for(i=0;i<2*SAMPLES;i+=2)
    {
        //Canal L
        OutputBuffer[i] = 0xAAAAAAAA;
        //Canal R
        OutputBuffer[i+1] = 0;
    }
    //Initialize codec
    codec_init();
    HAL_Delay(1500);
 
    HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t *)OutputBuffer, (uint16_t *)InputBuffer, 2*SAMPLES);
    while(1)
    {
 
    }
}
 
 
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
    HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t *)OutputBuffer, (uint16_t *)InputBuffer, 2*SAMPLES);
}

that is, I call transmitreceive and on RXCplt Callback I call transmitreceive again. This way I see the data on my osccilloscope ok, and if I put a tone on the OutputBuffer I can hear that.

But, this code doesn't work:
int main(void)
{
    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();
  
    /* Configure the system clock */
    SystemClock_Config();
  
    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_I2C1_Init();
    MX_I2S2_Init();
  
    for(i=0;i<2*SAMPLES;i+=2)
    {
        //Canal L
        OutputBuffer[i] = 0xAAAAAAAA;
        //Canal R
        OutputBuffer[i+1] = 0;
    }
    //Initialize codec
    codec_init();
    HAL_Delay(1500);
  
        while(1)
    {
          HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t *)OutputBuffer, (uint16_t *)InputBuffer, 2*SAMPLES);
          HAL_Dealy(500);
    }
}

that is, I call on a loop transmitreceive function, and no code on RxCplt Callback. In this case I hear 3 tone ok, 3 tone wrong, 3 tone ok, 3 tone wrong. And if I put 0xAAAAAAAA on the buffer I could measure this on the oscilloscope:
https://www.flickr.com/photos/117247358@N03/21290671600/in/dateposted-public/
here data is ok

but after a couple of transfer I obtain this:
https://www.flickr.com/photos/117247358@N03/21290681330/in/dateposted-public/

and after a couple of transfer I obtain the first picture.

So if I put a delay without any transmit/receive calling, the output signal gets desinchorinzed from WS some times.

I test that with TransmitReceive_IT and with TransmitReceive.

My init code:

void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct;
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
 
    __PWR_CLK_ENABLE();
 
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
 
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 7;
    RCC_OscInitStruct.PLL.PLLN = 196;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
    RCC_OscInitStruct.PLL.PLLQ = 4;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
 
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
    PeriphClkInitStruct.PLLI2S.PLLI2SN = 271;
    PeriphClkInitStruct.PLLI2S.PLLI2SM = 12;
    PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
 
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
 
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
}
 
/* I2S2 init function */
/* I2S2 init function */
void MX_I2S2_Init(void)
{
 
  hi2s2.Instance = SPI2;
  hi2s2.Init.Mode = I2S_MODE_MASTER_RX;
  hi2s2.Init.Standard = I2S_STANDARD_PHILLIPS;
  hi2s2.Init.DataFormat = I2S_DATAFORMAT_24B;
  hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
  hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_44K;
  hi2s2.Init.CPOL = I2S_CPOL_LOW;
  hi2s2.Init.ClockSource = I2S_CLOCK_PLL;
  hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE;
  HAL_I2S_Init(&hi2s2);
 
}
 
void HAL_I2S_MspInit(I2S_HandleTypeDef* hi2s)
{
 
  GPIO_InitTypeDef GPIO_InitStruct;
  if(hi2s->Instance==SPI2)
  {
  /* USER CODE BEGIN SPI2_MspInit 0 */
 
  /* USER CODE END SPI2_MspInit 0 */
    /* Peripheral clock enable */
    __SPI2_CLK_ENABLE();
 
    /**I2S2 GPIO Configuration
    PB12     ------> I2S2_WS
    PB13     ------> I2S2_CK
    PB14     ------> I2S2_ext_SD
    PB15     ------> I2S2_SD
    PC6     ------> I2S2_MCK
    */
    GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = GPIO_PIN_14;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF6_I2S2ext;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
    /* Peripheral DMA init*/
 
    hdma_i2s2_ext_tx.Instance = DMA1_Stream4;
    hdma_i2s2_ext_tx.Init.Channel = DMA_CHANNEL_2;
    hdma_i2s2_ext_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_i2s2_ext_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_i2s2_ext_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_i2s2_ext_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_i2s2_ext_tx.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_i2s2_ext_tx.Init.Mode = DMA_NORMAL;
    hdma_i2s2_ext_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_i2s2_ext_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    hdma_i2s2_ext_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_i2s2_ext_tx.Init.MemBurst = DMA_MBURST_SINGLE;
    hdma_i2s2_ext_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
    HAL_DMA_Init(&hdma_i2s2_ext_tx);
 
    __HAL_LINKDMA(hi2s,hdmatx,hdma_i2s2_ext_tx);
 
    hdma_spi2_rx.Instance = DMA1_Stream3;
    hdma_spi2_rx.Init.Channel = DMA_CHANNEL_0;
    hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_spi2_rx.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_spi2_rx.Init.Mode = DMA_NORMAL;
    hdma_spi2_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    hdma_spi2_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_spi2_rx.Init.MemBurst = DMA_MBURST_SINGLE;
    hdma_spi2_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
    HAL_DMA_Init(&hdma_spi2_rx);
 
    __HAL_LINKDMA(hi2s,hdmarx,hdma_spi2_rx);
 
  /* USER CODE BEGIN SPI2_MspInit 1 */
 
  /* USER CODE END SPI2_MspInit 1 */
  }
}
 
void HAL_I2S_MspDeInit(I2S_HandleTypeDef* hi2s)
{
 
  if(hi2s->Instance==SPI2)
  {
  /* USER CODE BEGIN SPI2_MspDeInit 0 */
 
  /* USER CODE END SPI2_MspDeInit 0 */
    /* Peripheral clock disable */
    __SPI2_CLK_DISABLE();
 
    /**I2S2 GPIO Configuration
    PB12     ------> I2S2_WS
    PB13     ------> I2S2_CK
    PB14     ------> I2S2_ext_SD
    PB15     ------> I2S2_SD
    PC6     ------> I2S2_MCK
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
 
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_6);
 
    /* Peripheral DMA DeInit*/
    HAL_DMA_DeInit(hi2s->hdmatx);
    HAL_DMA_DeInit(hi2s->hdmarx);
  }
  /* USER CODE BEGIN SPI2_MspDeInit 1 */
 
  /* USER CODE END SPI2_MspDeInit 1 */
}
 
/**
  * Enable DMA controller clock
  */
void MX_DMA_Init(void)
{
  /* DMA controller clock enable */
  __DMA1_CLK_ENABLE();
 
  /* DMA interrupt init */
  HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 2, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
  HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 2, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
 
}
 
/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{
 
  GPIO_InitTypeDef GPIO_InitStruct;
 
  /* GPIO Ports Clock Enable */
  __GPIOC_CLK_ENABLE();
  __GPIOH_CLK_ENABLE();
  __GPIOA_CLK_ENABLE();
  __GPIOB_CLK_ENABLE();
 
 
  /*Configure GPIO pin : PA8 */
  GPIO_InitStruct.Pin = GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
}
 
I2C_HandleTypeDef hi2c1;
 
/* I2C1 init function */
void MX_I2C1_Init(void)
{
 
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
  HAL_I2C_Init(&hi2c1);
 
}
 
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
 
  GPIO_InitTypeDef GPIO_InitStruct;
  if(hi2c->Instance==I2C1)
  {
  /* USER CODE BEGIN I2C1_MspInit 0 */
 
  /* USER CODE END I2C1_MspInit 0 */
 
    /**I2C1 GPIO Configuration
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA
    */
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    /* Peripheral clock enable */
    __I2C1_CLK_ENABLE();
 
    /* Peripheral interrupt init*/
    HAL_NVIC_SetPriority(I2C1_EV_IRQn, 2, 0);
    HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
    HAL_NVIC_SetPriority(I2C1_ER_IRQn, 2, 0);
    HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
  /* USER CODE BEGIN I2C1_MspInit 1 */
 
  /* USER CODE END I2C1_MspInit 1 */
  }
}
 
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c)
{
 
  if(hi2c->Instance==I2C1)
  {
  /* USER CODE BEGIN I2C1_MspDeInit 0 */
 
  /* USER CODE END I2C1_MspDeInit 0 */
    /* Peripheral clock disable */
    __I2C1_CLK_DISABLE();
 
    /**I2C1 GPIO Configuration
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7);
 
    /* Peripheral interrupt Deinit*/
    HAL_NVIC_DisableIRQ(I2C1_EV_IRQn);
 
    HAL_NVIC_DisableIRQ(I2C1_ER_IRQn);
 
  }
  /* USER CODE BEGIN I2C1_MspDeInit 1 */
 
  /* USER CODE END I2C1_MspDeInit 1 */
}

My question is, Is it a bug or am I doing something wrong? The thing that I don't understand is why allways 8 bits are cut and put on the other channel...

Thank and best regards

Outcomes