AnsweredAssumed Answered

FULL DUPLEX SPI DMA RX from not firing interrupts

Question asked by alexandre.dauphi.001 on Jun 20, 2016
Latest reply on Jun 20, 2016 by alexandre.dauphi.001
Hi everyone,

I'm trying to use  I2S2 of a  STM32F405RG custom board in full duplex.

I generate my code with CubeMx:

This is my I2S and DMA initialization :

static 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_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;
  if (HAL_I2S_Init(&hi2s2) != HAL_OK)
  {
    Error_Handler();
  }
}
 
static void MX_DMA_Init(void)
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();
  /* DMA interrupt init */
  /* DMA1_Stream3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
  /* DMA1_Stream4_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
}

 and in the file stm32f4xxhal_msp.c

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 */
        __HAL_RCC_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_FREQ_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_FREQ_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_FREQ_LOW;
        GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
        /* Peripheral DMA init*/
 
        hdma_i2s2_ext_rx.Instance = DMA1_Stream3;
        hdma_i2s2_ext_rx.Init.Channel = DMA_CHANNEL_0;
        hdma_i2s2_ext_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        hdma_i2s2_ext_rx.Init.PeriphInc = DMA_PINC_DISABLE;
        hdma_i2s2_ext_rx.Init.MemInc = DMA_MINC_ENABLE;
        hdma_i2s2_ext_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
        hdma_i2s2_ext_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
        hdma_i2s2_ext_rx.Init.Mode = DMA_CIRCULAR;
        hdma_i2s2_ext_rx.Init.Priority = DMA_PRIORITY_LOW;
        hdma_i2s2_ext_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
 
        hdma_i2s2_ext_rx.XferCpltCallback = Transfer_RX_I2S2_M0_Complete;
        hdma_i2s2_ext_rx.XferM1CpltCallback = Transfer_RX_I2S2_M1_Complete;
        hdma_i2s2_ext_rx.XferErrorCallback = Transfer_RX_I2S2_Error;
 
        if (HAL_DMA_Init(&hdma_i2s2_ext_rx) != HAL_OK)
        {
            Error_Handler();
        }
        __HAL_LINKDMA(hi2s,hdmarx,hdma_i2s2_ext_rx);
 
        hdma_spi2_tx.Instance = DMA1_Stream4;
        hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0;
        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_HALFWORD;
        hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
        hdma_spi2_tx.Init.Mode = DMA_CIRCULAR;
        hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;
        hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
 
        hdma_spi2_tx.XferCpltCallback = Transfer_TX_I2S2_M0_Complete;
        hdma_spi2_tx.XferM1CpltCallback = Transfer_TX_I2S2_M1_Complete;
        hdma_spi2_tx.XferErrorCallback = Transfer_TX_I2S2_Error;
 
        if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)
        {
            Error_Handler();
        }
 
        __HAL_LINKDMA(hi2s,hdmatx,hdma_spi2_tx);
 
        /* USER CODE BEGIN SPI2_MspInit 1 */
 
        /* USER CODE END SPI2_MspInit 1 */
    }
 
}


 And my interrupt handler :
void DMA1_Stream3_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Stream3_IRQn 0 */
 
  /* USER CODE END DMA1_Stream3_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_i2s2_ext_rx);
  /* USER CODE BEGIN DMA1_Stream3_IRQn 1 */
 
  /* USER CODE END DMA1_Stream3_IRQn 1 */
}
 
/**
* @brief This function handles DMA1 stream4 global interrupt.
*/
void DMA1_Stream4_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Stream4_IRQn 0 */
 
  /* USER CODE END DMA1_Stream4_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_spi2_tx);
  /* USER CODE BEGIN DMA1_Stream4_IRQn 1 */
 
  /* USER CODE END DMA1_Stream4_IRQn 1 */
}

And my I2S with DMA are started with the following function :

volatile uint32_t *I2S2_DR = &SPI2->DR;             // Address of the data register of the SPI2     : TX
volatile uint32_t *I2S2ext_DR = &I2S2ext->DR;       // Address of the data register of the I2Sext   : RX
 
    if (HAL_DMAEx_MultiBufferStart_IT(&hdma_i2s2_ext_rx,
            (uint32_t) I2S2ext_DR, (uint32_t) &pingIN_I2S2[0],
            (uint32_t) &pongIN_I2S2[0], BufferSize) != HAL_OK) {
        Error_Handler();
    }
    I2S2ext->I2SCFGR |= SPI_I2SCFGR_I2SE;                           // I2S Enable
    I2S2ext->CR2 |= SPI_CR2_TXDMAEN;                                // Tx buffer DMA interrupt enable
 
    if (HAL_DMAEx_MultiBufferStart_IT(&hdma_spi2_tx,
            (uint32_t) &pingOUT_I2S2[0], (uint32_t) I2S2_DR,
            (uint32_t) &pongOUT_I2S2[0], BufferSize) != HAL_OK) {
        Error_Handler();
    }
    SPI2->I2SCFGR |= SPI_I2SCFGR_I2SE;                          // I2S Enable
    SPI2->CR2 |= SPI_CR2_TXDMAEN;

The problem is that the interrupt of the RX DMA is never generated.

There is no problems for the Tx interrupt. The interrupt is generated periodically when the transfert is complete.

I don't know where this problem could come from.
I used the same functions on a other target (stm32f411 ) and the I2S3 works well with DMA in full duplex mode.

thanks you for your help

Outcomes