AnsweredAssumed Answered

STM32F103 I2C Receive using DMA in Circular mode

Question asked by cardosi.carlo on Apr 22, 2016
Latest reply on May 3, 2016 by FTITI.Walid

I'm starting out using the CubeMX software to configure my NucleoF103 and one of my first test applications was the I2C bus. I got it working by polling.

Then I started looking into the DMA and can use DMA to receive in direct mode as well, using HAL_I2C_Master_Receive_DMA. So far, so good.

However, after reading the circular mode of the DMA description in the manual (which is very little...), I got the impression that if the DMA is configured in circular mode it would continuously call the HAL_I2C_Master_Receive_DMA function thus avoiding my having to worry about calling it.
However, this is not the case and the circular mode doesn't restart. The only way I got it running was by calling again the Receive_DMA function in the DMA complete interrupt function, which defeats the purpose.

Is this even possible, or is there something I may be missing?

/* 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_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
  GPIO_InitTypeDef GPIO_InitStruct;
  /* USER CODE BEGIN I2C1_MspInit 0 */
  /* USER CODE END I2C1_MspInit 0 */
    /**I2C1 GPIO Configuration   
    PB8     ------> I2C1_SCL
    PB9     ------> I2C1_SDA
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    /* Peripheral clock enable */
    /* Peripheral DMA init*/
    hdma_i2c1_rx.Instance = DMA1_Channel7;
    hdma_i2c1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_i2c1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_i2c1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_i2c1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_i2c1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_i2c1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_i2c1_rx.Init.Priority = DMA_PRIORITY_LOW;
    /* Peripheral interrupt init */
    HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
    HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
  /* USER CODE BEGIN I2C1_MspInit 1 */
  /* USER CODE END I2C1_MspInit 1 */

Thanks in advance.