AnsweredAssumed Answered

STM32F4 I2C with DMA not working

Question asked by Victor Douet on Dec 7, 2017

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

Outcomes