Strange Issues and Solutions for Hardware I2C on STM32

1

Introduction

Recently, I’ve been working on my graduation project. The second board has arrived, and I’ve basically debugged all the components, with a few chips still having test code written for them.

Strange Issues and Solutions for Hardware I2C on STM32

One of the chips is the BMP280 barometric sensor, which worked perfectly on the first board, so I can rule out issues with the code or the schematic.

In this design, the BMP280 occupies a dedicated I2C1 bus, but during testing after soldering, I found that it could not establish complete communication with the BMP280.

Since all my components are hand-soldered, and this component is in a QFN package, I soldered it several times and even replaced the component, but the problem persisted.

Last night, I had a sudden idea and decided to fly the SCL and SDA lines of I2C1 to a nearby I2C bus, then during initialization, I disabled the I2C1 functionality and left it vacant.

Surprisingly, communication was established.

Strange Issues and Solutions for Hardware I2C on STM32

However, this solution was too ugly, so today I tried to find out why the original I2C1 could not communicate.

2

Strange Pin States

In GPIO, there is a read-only register IDR that records the pin levels measured by the chip’s master controller.

Strange Issues and Solutions for Hardware I2C on STM32

Querying the address value of the IDR register (the base address for GPIO in STM32U0 is 0x50000000, the offset for GPIOB is 0x400, and the offset for the IDR register is 0x10, so the IDR register for GPIOB is at 0x50000410) reveals that its value is 0x3EE2.

Strange Issues and Solutions for Hardware I2C on STM32

Both PB6 and PB7 are initialized to a normal high level, but after using I2C,

Strange Issues and Solutions for Hardware I2C on STM32

the value changes to 0x3E22, indicating that PB7/6 are always low.

Strange Issues and Solutions for Hardware I2C on STM32

After releasing the I2C1 bus and configuring it as a normal GPIO mode with open-drain output and pull-up, it still remains 0.

This abnormal state may be the reason why I2C1 cannot be used normally.

3

Deadlock in Hardware I2C?

In forums and from my usual understanding, occasionally someone mentions that the STM32 series’ hardware I2C has deadlock issues.

Strange Issues and Solutions for Hardware I2C on STM32

The general reason is that during data transmission, when the master receiver receives the last byte, it sends an ACK signal, which causes the slave to wait for data, thus leading to a bus deadlock. This is said to be a bug left by STM32’s hardware I2C to avoid Philips’s I2C patent.

However, the I2C patent expired years ago, and if I encountered this issue in the F103, I could understand it (I don’t think I’ve encountered deadlock issues with F103’s hardware I2C).

But for the STM32U0, as a newer product, having a bug that causes I2C deadlocks seems unreasonable.

4

Solutions

Later, to test what the voltage actually is, after initializing I2C, I found that the actual situation was that the voltage of SCL (PB6) was 2.5V+

Strange Issues and Solutions for Hardware I2C on STM32

This is a very classic floating voltage, indicating that the SCL pin is not being pulled up. Since I usually do not connect pull-up resistors, I rely on the internal pull-up of GPIO to act as a pull-up resistor.

Therefore, the problem is clearly with the internal pull-up of the SCL pin.

Strange Issues and Solutions for Hardware I2C on STM32

However, it is clearly stated in the code that it is using internal pull-up, and it is very strange that even though I2C4 is configured with internal pull-up mode, when I2C1 is connected to I2C4 (via flying leads), it still does not work. Moreover, enabling I2C1 also causes I2C4 to fail with the same issue.

Strange Issues and Solutions for Hardware I2C on STM32Strange Issues and Solutions for Hardware I2C on STM32Strange Issues and Solutions for Hardware I2C on STM32

After consulting the chip manual, I learned that the GPIO PUPDR register records the pull-up and pull-down status of the pins. Querying this address reveals that both PB6 and PB7 are normally pulled up, but the floating pin issue indeed exists. So I wondered if I could solve the problem by adding an external pull-up resistor.

When I connected a 4.9K pull-up resistor to I2C1, I found that the BMP280 worked normally.

Strange Issues and Solutions for Hardware I2C on STM32

Moreover, after using I2C, the value of the IDR register also showed a normal high level.

5

Questions

The main question is why the same I2C bus, one I2C1 cannot be used, while other I2C buses work normally.

Furthermore, if I enable I2C1 and connect it to other I2C buses, it causes the SCL pin of other I2C buses to be in a floating state, rendering them ineffective~~~ very strange.

Leave a Comment