AnsweredAssumed Answered

STM32F411 - HAL driver - I2S full duplex - ext_SD issue

Question asked by elgarbe on Jun 4, 2015
Latest reply on Jun 5, 2015 by elgarbe
Hi, I'm continue fighting with full-duplex configuration of STM32F411.
I have an audio codec with MIC input and speaker output. I connect DOUT pin from the CODEC to PC3 (I2S_Dat) line. So it will be my Rx pin. Then I connect DIN from de codec to PC2 (I2S_ext) line. So it will be my Tx pin.
I configure (with Cube MX) the I2S and DMA stream as follow:

/* 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_16B;
  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   
    PC2     ------> I2S2_ext_SD
    PC3     ------> I2S2_SD
    PA6     ------> I2S2_MCK
    PB10     ------> I2S2_CK
    PB12     ------> I2S2_WS
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    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(GPIOC, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    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);
 
    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_AF6_SPI2;
    HAL_GPIO_Init(GPIOA, &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_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    /* Peripheral DMA init*/
   
    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_MDATAALIGN_HALFWORD;
    hdma_spi2_rx.Init.Mode = DMA_NORMAL;
    hdma_spi2_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    HAL_DMA_Init(&hdma_spi2_rx);
 
    __HAL_LINKDMA(hi2s,hdmarx,hdma_spi2_rx);
 
    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_MDATAALIGN_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;
    HAL_DMA_Init(&hdma_i2s2_ext_tx);
 
    __HAL_LINKDMA(hi2s,hdmatx,hdma_i2s2_ext_tx);
 
  /* USER CODE BEGIN SPI2_MspInit 1 */
 
  /* USER CODE END SPI2_MspInit 1 */
  }
 
}

first questions: what hi2s2.Init.Mode = I2S_MODE_MASTER_RX; means? how do I choos between MASTER_RX and MASTER_TX?

Then my code is something like this:

int main(void)
{
  /* MCU Configuration----------------------------------------------------------*/
 
  /* 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_I2S2_Init();
 
  /* USER CODE BEGIN 2 */
  uint16_t i;
  for(i=0;i<BufferSize;i++)
  {
      InputBuffer[i]=0xFFFF;
      OutputBuffer[i]=0x0000;
  }
 
  HAL_I2SEx_TransmitReceive_DMA(&hi2s2, OutputBuffer, InputBuffer, BufferSize);
  while (1)
  {
  }
}

just initialize the buffers to see changes and then call the first DMA transmit_receive.
Finally I have code for each IRQ:

void DMA1_Stream3_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_spi2_rx);
}
 
/**
* @brief This function handles DMA1 Stream4 global interrupt.
*/
void DMA1_Stream4_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_i2s2_ext_tx);
}
 
/* USER CODE BEGIN 1 */
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
    //Recivimos todos los datos del micrófono, enviémoslo a los parlantes
    uint16_t i;
    for(i=0;i<20000;i++)
    {
        OutputBuffer[i]=InputBuffer[i];
    }
    HAL_I2SEx_TransmitReceive_DMA(&hi2s2, OutputBuffer, InputBuffer, 20000);
//    HAL_I2S_Receive_DMA(&hi2s2, InputBuffer, 10000);
 
}
 
void HAL_I2S_ext_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
//  HAL_I2SEx_TransmitReceive_DMA(&hi2s2, OutputBuffer, InputBuffer, 10000);
 
}
 
void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
{
 
}

I put a breack point on each ISR. When I run the project I see that there is just two interrupts and then stops, I mean, there is no new interrupts, just to of them. Input buffer is filled.
So, how do I need to do to obtain a continous stream of data using this HAL library?

BR!

Outcomes