cancel
Showing results for 
Search instead for 
Did you mean: 

I2C DMA not triggering callback function

DMedv.1
Associate II

Hi,

Could you please suggest a direction with my problem?

I try to read and write data to a sensor via i2c with DMA1 in an STM32 Nucleo F401 board where a FreeRTOS is running.

I can read the sensorata with polling methode, and next to the I2C an UART is running with the DMA2 correctly. I have checked and the MX_DMA_Init is running before the MX_I2C1_Init.

When I try to write to the sensor as a master with DMA(HAL_I2C_Master_Transmit_DMA) with the "i2c1 event interrupt" and "i2c1 error interrupt" disabled in the FreeRTOS the parattet tasks are just running fine just the callback HAL_I2C_MasterTxCpltCallback is not triggered.

And when i am enabling the" i2c1 event interrupt" and "i2c1 error interrupt" from the CubeMX two parallel task in the Free rtos are running at once and then no more parallel schedulling is happening and the HAL_I2C_EV_IRQHandler function is called periodically and leaving the function in the last else branch where the /* Do nothing */ is commented.

Could you please suggest what could i try to use the i2c with DMA?

Thank you,

1 ACCEPTED SOLUTION

Accepted Solutions
DMedv.1
Associate II

Finally found the solution. I summarise some issues I had:

HAL_I2C_Master_Transmit_DMA(i2cHandler, MPUADDR, i2cData, 2);

  1. The Deliverable data: The deliverable data must be global variable for DMA, otherwise when I am leaving the function/ or calling a destructor of the object the memory is freed and the DMA aburts.
  2. The delivery target in my case the i2cHandler must not be the copy of the original structure/objetc, because the callback function addresses are checked from parallel interrupts based on the original object and updated in the caling HAL_I2C_Master_Transmit_DMA function. If incorrect ending up in a loop in the HAL_I2C_EV_IRQHandler because teh hi2c->XferISR is alvais NULL.

What to check: If the I2C handler is exacly the same in the interrupt handler from the function or the name is different, but the new one only uses a pointer to the old one. In my case thy where not the same from the myin called hi2c1 and the function i2cHandler.

0693W00000YAX6XQAX.png 

The solution for me was to use the copy of the pointer only not the contant of the hendler.0693W00000YAX7LQAX.png3. With the STM32 H7 boards there is a memory allocation issue which is explaind with the solution in the below article.

https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices

View solution in original post

5 REPLIES 5
Foued_KH
ST Employee

Hello @DMedv.1​ ,

Please don't forget to set GPIO Pull-up/Pull-down to Pull-up.

The code didn't went into the callbacks because compiler removed them during optimization as it seemed to be unnecessary code .

Check results via an oscilloscope and Read/Write registers.

If nothings appears, please check the error flags set in the status register.

  • You can head over to NVIC Settings to enable the event and error interrupt, if using the interrupt mode.

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hi @KHALSI_Foued​ ,

Thank you for your replay, i changed the Pull-up/Pull-down to Pull-up. But it did not helped unfortunately.

I attached a capture with a Logic analyser. I am trying to get the error flag status.

The I2C_DMAError function is not called. And from the registers the fault masks is 0.

Hi @KHALSI_Foued​ 

I could only figure out the the state register remained HAL_I2C_STATE_BUSY_TX but everithing else looks fine to me.

Could you please have a look at on the registers if you can see something?

0693W00000YAOdIQAX.png

DMedv.1
Associate II

I Switch to a different device a Nucleo-H723ZG whwre at least the DMA transfer starts.

0693W00000YAWScQAP.pngBut happenes only for 1 cycle and the DMA failes with error code 1. What is the Transfer error.

#define HAL_DMA_ERROR_TE              (0x00000001U)    /*!< Transfer error                          */ 0693W00000YAWSrQAP.pngMy code now looks like this:

The transmisiion:

#define TX_LENGTH (16)

uint8_t i2cData[TX_LENGTH];

void I2C_Write8(uint8_t ADDR, uint8_t data)

{

   

    i2cData[0] = ADDR;

    i2cData[1] = data;

    uint8_t MPUADDR = (MPU_ADDR<<1);

    /* Clean D-cache */

    /* Make sure the address is 32-byte aligned and add 32-bytes to length, in case it overlaps cacheline */

    SCB_CleanDCache_by_Addr((uint32_t*)(((uint32_t)i2cData) & ~(uint32_t)0x1F), TX_LENGTH+32);

    HAL_I2C_Master_Transmit_DMA(&i2cHandler, MPUADDR, i2cData, TX_LENGTH);

    //HAL_Delay(100);

}

The I2C Init:

static void MX_I2C2_Init(void)

{

  /* USER CODE BEGIN I2C2_Init 0 */

  /* USER CODE END I2C2_Init 0 */

  /* USER CODE BEGIN I2C2_Init 1 */

  /* USER CODE END I2C2_Init 1 */

  hi2c2.Instance = I2C2;

  hi2c2.Init.Timing = 0x60404E72;

  hi2c2.Init.OwnAddress1 = 0;

  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;

  hi2c2.Init.OwnAddress2 = 0;

  hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;

  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;

  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

  if (HAL_I2C_Init(&hi2c2) != HAL_OK)

  {

    Error_Handler();

  }

  /** Configure Analogue filter

  */

  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)

  {

    Error_Handler();

  }

  /** Configure Digital filter

  */

  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)

  {

    Error_Handler();

  }

  /* USER CODE BEGIN I2C2_Init 2 */

  /* USER CODE END I2C2_Init 2 */

}

The DMA Init:

static void MX_DMA_Init(void)

{

  /* DMA controller clock enable */

  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */

  /* DMA1_Stream0_IRQn interrupt configuration */

  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 5, 0);

  HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);

  /* DMA1_Stream1_IRQn interrupt configuration */

  HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 5, 0);

  HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);

}

The initialization from the main:

 /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */

  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */

  MX_GPIO_Init();

  MX_DMA_Init();

  MX_USART3_UART_Init();

  MX_USB_OTG_HS_USB_Init();

  MX_SPI1_Init();

  MX_ETH_Init();

  MX_I2C2_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Init scheduler */

  osKernelInitialize();

Could you please suggest what I am doing wrongly?

DMedv.1
Associate II

Finally found the solution. I summarise some issues I had:

HAL_I2C_Master_Transmit_DMA(i2cHandler, MPUADDR, i2cData, 2);

  1. The Deliverable data: The deliverable data must be global variable for DMA, otherwise when I am leaving the function/ or calling a destructor of the object the memory is freed and the DMA aburts.
  2. The delivery target in my case the i2cHandler must not be the copy of the original structure/objetc, because the callback function addresses are checked from parallel interrupts based on the original object and updated in the caling HAL_I2C_Master_Transmit_DMA function. If incorrect ending up in a loop in the HAL_I2C_EV_IRQHandler because teh hi2c->XferISR is alvais NULL.

What to check: If the I2C handler is exacly the same in the interrupt handler from the function or the name is different, but the new one only uses a pointer to the old one. In my case thy where not the same from the myin called hi2c1 and the function i2cHandler.

0693W00000YAX6XQAX.png 

The solution for me was to use the copy of the pointer only not the contant of the hendler.0693W00000YAX7LQAX.png3. With the STM32 H7 boards there is a memory allocation issue which is explaind with the solution in the below article.

https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices