Does STM32 Hardware I2C Have Bugs?

There has been a rumor circulating that the STM32 hardware I2C design has bugs, and it is better not to use it, as software I2C is more reliable. For a long time, to avoid unnecessary trouble, I have never used hardware I2C, mainly because software I2C is also quite convenient and can be used on almost any port.

Recently, I designed a board that uses I2C, so I decided to test whether the hardware I2C is as bad as some people say.

Testing hardware: STM32F407VET6 + AT24C64
Testing software: STM32CubeMX v6.1.1
HAL library: STM32CubeF4 Firmware Package V1.25.2
STM32CubeMX Configuration
Using STM32CubeMX for configuration is very convenient, and I won’t go into detail about clock and other basic configurations. The I2C configuration is as follows:
Does STM32 Hardware I2C Have Bugs?
The speed mode here is set to standard mode, with a clock speed of 100K. If higher performance is required, Fast mode with a clock speed of 400K can be selected.
After the configuration is complete, generate the code.
Writing Code
After the code is generated, you can directly call the functions to read and write data:
HAL_I2C_Mem_Read
HAL_I2C_Mem_Write
You can refer to the code comments for function parameters.
When writing data to the 24CXX series EEPROM, it is important to note that when writing across pages, a certain delay is required; otherwise, the write operation may fail. The page sizes vary for different capacities.
Additionally, for capacities below 24C16, the address is 8 bits, while for capacities above 24C32, the address is 16 bits. When calling the read and write functions, it is necessary to choose between I2C_MEMADD_SIZE_8BIT or I2C_MEMADD_SIZE_16BIT. The test used a 24C64, so I chose I2C_MEMADD_SIZE_16BIT.
To facilitate operations, I encapsulated the read and write functions further to handle various cases of cross-page writing, allowing for continuous writing to any address. The program is as follows:
#include "at24c64.h"
#include "i2c.h"
#define AT24CXX_ADDR_READ   0xA1
#define AT24CXX_ADDR_WRITE   0xA0
#define PAGE_SIZE   32
/** * @brief        Read multiple bytes of data continuously from any address of AT24C64 * @param        addr —— Address to read data (0-65535) * @param        dat  —— Address to store read data * @retval        Success —— HAL_OK*/
uint8_t At24cxx_Read_Amount_Byte(uint16_t addr, uint8_t* recv_buf, uint16_t size){
    return HAL_I2C_Mem_Read(&hi2c2, AT24CXX_ADDR_READ, addr, I2C_MEMADD_SIZE_16BIT, recv_buf, size, 0xFFFFFFFF);
}
/** * @brief        Write multiple bytes of data continuously to any address of AT24C64 * @param        addr —— Address to write data (0-65535) * @param        dat  —— Address to store written data * @retval        Success —— HAL_OK*/
uint8_t At24cxx_Write_Amount_Byte(uint16_t addr, uint8_t* dat, uint16_t size){
    uint8_t i = 0;
    uint16_t cnt = 0;        // Count of written bytes
    /* For the starting address, there are two cases to consider */
    if(0 == addr % PAGE_SIZE )    {
        /* The starting address is exactly the beginning of a page */
        /* For the number of bytes to be written, there are two cases to consider */
        if(size <= PAGE_SIZE)        {
            // If the number of bytes to be written does not exceed one page, write directly
            return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, dat, size, 0xFFFFFFFF);
        }
        else        {
            // If the number of bytes to be written exceeds one page, write the entire page in a loop
            for(i = 0;i < size/PAGE_SIZE; i++)            {
                HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, &dat[cnt], PAGE_SIZE, 0xFFFFFFFF);
                HAL_Delay(3);
                addr += PAGE_SIZE;
                cnt += PAGE_SIZE;
            }
            // Write the remaining bytes
            return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, &dat[cnt], size - cnt, 0xFFFFFFFF);
        }
    }
    else    {
        /* The starting address is offset from the beginning of a page */
        /* For the number of bytes to be written, there are two cases to consider */
        if(size <= (PAGE_SIZE - addr%PAGE_SIZE))        {
            /* Can write all within this page */
            return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, dat, size, 0xFFFFFFFF);
        }
        else        {
            /* Cannot finish writing in this page */
            // First, finish writing this page
            cnt += PAGE_SIZE - addr%PAGE_SIZE;
            HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, dat, cnt, 0xFFFFFFFF);
            addr += cnt;
            HAL_Delay(3);
            // Loop to write full page data
            for(i = 0;i < (size - cnt)/PAGE_SIZE; i++)            {
                HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, &dat[cnt], PAGE_SIZE, 0xFFFFFFFF);
                HAL_Delay(3);
                addr += PAGE_SIZE;
                cnt += PAGE_SIZE;
            }
            // Write the remaining bytes
            return HAL_I2C_Mem_Write(&hi2c2, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE_16BIT, &dat[cnt], size - cnt, 0xFFFFFFFF);
        }                }
}
Test Results
After testing, the hardware I2C read and write operations on the EEPROM were normal. No so-called bugs were found. Of course, this is just a test of one device targeting EEPROM on the M4 core; verification is still required for other cores (like M3) and other I2C devices.
Conclusion
Using hardware I2C is relatively simple, as it does not require manual timing adjustments, but it can only use a fixed set of pins.
Software simulated I2C can use any pins, and it is relatively easy to port for different MCUs, but timing adjustments can be cumbersome for MCUs operating at different frequencies.
Both have their advantages and disadvantages, and the choice should be based on actual needs.
  • Super valuable content: The most comprehensive I2C tutorial, absolutely worth saving! (A lengthy article, recommended for collection)

  • Understanding the I2C bus

-End-

“If useful, please share”

Copyright statement: This article is reproduced from the internet, and the copyright belongs to the original author. If there is any infringement, please contact us for removal!

Click below“Hardware Engineer”to follow, choose“Pin/Star the public account”

Technical electronic content delivered to you first-hand

👇

Does STM32 Hardware I2C Have Bugs?
  • What is inside an IGBT module?

  • An engineer’s hardcore microcontroller programming philosophy

  • Several interesting circuits

  • Replacing STM32 with Huada HC32, these details must be seen!

  • USB external power supply and lithium battery automatic switching circuit design, have you learned these essentials?

  • Common peripheral circuit design, hardware circuit design references and precautions

If you like it, please like + view, this is the biggest encouragement for good articles
Does STM32 Hardware I2C Have Bugs?

Leave a Comment