The problem is the code:

HAL_I2C_Master_Transmit_DMA (&hi2c1, (uint16_t)(MCP4725A0_ADDR_A00<<1), (uint8_t *)buffer, 2);

Though it returns HAL_OK but causes no response from slave device, but other version of this code: interruptive or blocking are works perfectly (Slave is DAC MCP4725 and master is STM32f746ng).

I've found the heart codes actually executing in this bad :( DMA code:

HAL_DMA_Start(&hdma_i2c1_tx, buffer, (uint32_t)&(hi2c1.Instance->TXDR), 2);
hi2c1.Instance->CR1 |= I2C_CR1_TXDMAEN;
I2C_TransferConfig(&hi2c1, (MCP4725A0_ADDR_A00<<1), (uint8_t)2, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE);

After running these code debugger shows the state of Both DMA and I2C are busy there is no new data on TXDR, and TXIS and TXE are both set. I think it means DMA does not respond to I2C TXIS despite TXDMAEN has been set. Note: buffer is placed at 0x2004,FFF4. Which is located on 0x2004,C000-0x2004,FFFF -> <<SRAM2 (16 KB)>> on the <<512-Mbyte Block 1 SRAM>> 0x2000,0000-0x3FFF,FFFF

As STM32f7 Reference manual told, I2C TXIE does not require to be set and setting TXDMAEN will cause to if TXIS set by hardware then rise request to DMA for data transfer from memory to I2C peripheral TXDR and this copying process cause to decrease embedded counter of I2C and after counter reaches 0 the transmission will end.

System configuration:

DMA is memory incremental byte sized in normal mode without FIFO using DMA1Stream6 memory to peripheral and the flow controller is DMA(!). I2C1 is in fast mode 7bit address, clock no stretch disabled and general call address detection enabled. HCLK clock is 150MHz on Power Regulator voltage scale 2. All catches are disabled and works on AXI flash interface. The NVIC is not important because even the first transfer does not occur.

CUBE generated code comparison with HAL example for stm32f746-discovery

HAL_I2C_Master_DMA() was exactly the same but the difference was in MspInit() I2C GPIO in example was set to PULLUP but NoPull in cube. (It must be not important since interruptive version worked). The last difference was Msp of example first enabled clock of GPIO, I2C and DMA then started to initialize their structure, but cube first enabled GPIO's clock then initiated it then enabled I2C Clock then initiated DMA then enabled DMA clock.

  • \$\begingroup\$ If the polling and interrupt modes already work, the DMA mode should work just as well. Perhaps you are doing something wrong. You are not even checking what the I2C transfer function returns as result code. Have you looked at I2C DMA transfer example code? \$\endgroup\$
    – Justme
    Commented Dec 28, 2021 at 12:17
  • \$\begingroup\$ @Justme It returns: HAL_OK. Yes I've seen them I tried to learn from their code, but I couldn't test that since that need 2 MCU. \$\endgroup\$ Commented Dec 28, 2021 at 12:55
  • \$\begingroup\$ So it returns HAL_OK. Then what do you do? Why would transmitting I2C need 2 MCUs, you can just take the DMA master transmit part. \$\endgroup\$
    – Justme
    Commented Dec 28, 2021 at 13:01
  • \$\begingroup\$ @Justme Ok I will start the research and post the result. \$\endgroup\$ Commented Dec 28, 2021 at 13:03
  • \$\begingroup\$ At what address and in which of the STM32F7's internal RAM blocks is your buffer located? \$\endgroup\$
    – brhans
    Commented Dec 28, 2021 at 14:30

1 Answer 1


Many thanks to @Justme. The problem was placed on `HAL_I2C_MspInit().

According to the "difference between example and CUBE generated code" section of the question I've moved:
__HAL_RCC_I2C1_CLK_ENABLE(); right before
and the code now works fine!

This is a bug in CubeMX embedded on CubeIDE 1.8 but I don't know how to report it to STmicroelectronics or maybe it's the bug of HAL library 1.16.1 of F7 itself.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.