cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 I2C with DMA not working

Victor Douet
Associate
Posted on December 07, 2017 at 23:56

Hi everyone, 

I'm using one STM32F4 and I want to communicate with my LSM303 accelerometer. For that I'm using I2C, and just using I2C works fine but when I try to use DMA with it, it stops working. 

When I use HAL_I2C_Master_Transmit_DMA it works and I got the IRQHandler. But when after that I want to use HAL_I2C_Master_Receive_DMA it says that the State of the I2C is not ready... 

I read that the I2C was kind of messed up with the STM32FX but I don't understand why it's working fine without DMA.

Here's my I2C init : 

void MX_I2C2_Init(void)

{

  I2C_ST_INS.Instance = I2C2;

  I2C_ST_INS.Init.ClockSpeed = 400000;

   

I2C_ST_INS.Init.DutyCycle = I2C_DUTYCYCLE_2;

   

I2C_ST_INS.Init.OwnAddress1 = 0;

  I2C_ST_INS.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

  I2C_ST_INS.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;

  I2C_ST_INS.Init.OwnAddress2 = 0;

  I2C_ST_INS.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;

  I2C_ST_INS.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;

  HAL_I2C_Init(&I2C_ST_INS);

}

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)

{

  GPIO_InitTypeDef GPIO_InitStruct;

  if(i2cHandle->Instance==I2C1)

  {

      //Not useful for this post

  }

  else if(i2cHandle->Instance==I2C2)

  {

    GPIO_InitStruct.Pin = MASTER_IMUB_I2C_SDA_Pin|MASTER_IMUB_I2C_SCL_Pin;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

    GPIO_InitStruct.Pull = GPIO_PULLUP;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

    GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;

    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

__HAL_RCC_I2C2_CLK_ENABLE();

    /* DMA controller clock enable */

    __HAL_RCC_DMA1_CLK_ENABLE();

    

hdma_i2c2_rx.Instance = DMA1_Stream2;

    hdma_i2c2_rx.Init.Channel = DMA_CHANNEL_7;

    hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;

    hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE;

    hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE;

    hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

    hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

    hdma_i2c2_rx.Init.Mode = DMA_NORMAL;

    hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;

    hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;

    hdma_i2c2_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

    hdma_i2c2_rx.Init.MemBurst = DMA_MBURST_SINGLE;

    hdma_i2c2_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;

    if (HAL_DMA_Init(&hdma_i2c2_rx) != HAL_OK)

    {

      Error_Handler();

    }

    __HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c2_rx);

    

HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 0, 0);

 

HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);

    

hdma_i2c2_tx.Instance = DMA1_Stream7;

    hdma_i2c2_tx.Init.Channel = DMA_CHANNEL_7;

    hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;

    hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE;

    hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE;

    hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

    hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

    hdma_i2c2_tx.Init.Mode = DMA_NORMAL;

    hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;

    hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;

    hdma_i2c2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

    hdma_i2c2_tx.Init.MemBurst = DMA_MBURST_SINGLE;

    hdma_i2c2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;

    if (HAL_DMA_Init(&hdma_i2c2_tx) != HAL_OK)

    {

      Error_Handler();

    }

    __HAL_LINKDMA(i2cHandle,hdmatx,hdma_i2c2_tx);

   

HAL_NVIC_SetPriority(DMA1_Stream7_IRQn, 0, 0);

 

HAL_NVIC_EnableIRQ(DMA1_Stream7_IRQn);

  }

}

Do you have any ideas why it does not work when I'm using DMA with I2C ?

Thanks,

Victor

#i2c #stm32 #dma
1 REPLY 1
Victor Douet
Associate
Posted on December 08, 2017 at 00:10

Also I forgot to mention that when it hits the callback I2C_DMAXferCplt for the Master_Transmit_DMA it says that the CurrentState of the I2C_HandleTypeDef is still equal to HAL_I2C_STATE_BUSY_TX and therefor it does not put the state back to READY. That why it does not receive anything when I call the Master_Receive_DMA.

Victor