ChibiOS/HAL v3.0 STM32F1 I2C driver bug?
Posted: Tue Jan 05, 2016 11:09 am
Hi everyone,
There is an application based on ChibiOS/RT v2.6 that works fine without any known issues. It runs on STM32F105, and it uses the following ChibiOS drivers: USB, USB Serial, Serial (2x), I2C (master), and PAL; also it includes a custom CAN driver for both on-chip CAN interfaces. The I2C bus in this application is used to retrieve sensor measurements from two on-board sensors at the rate about 80 measurements per second. OS is mostly configured with default settings (max clock rate, default IRQ priorities, IRQ preemption enabled, etc).
Recently I had to port the application to ChibiOS/RT v3.0. The new OS has also been configured mostly with default settings: tickless mode, 16-bit ST counter at 2 kHz. When porting was finished, everything seemed to work fine except one problem with I2C described below.
The application seems to work fine as long as there is no activity on the CAN bus; but if either or both of the CAN bus interfaces are subjected to any traffic, the I2C driver would occasionally report failed transactions with return value MSG_RESET and error code I2C_ACK_FAILURE. The errors would appear approximately once-twice per second at highly irregular intervals. I suspected that there could be a cross-talk between CAN and I2C and inspected the board with a scope, but it turned out that the signals were perfectly well-formed and the hardware was performing well. Furthermore, it worked perfectly with Ch/RT v2.6, so it cannot be a hardware-only issue.
Also, I discovered that the frequency of I2C errors would depend on optimization levels in a very inconsistent way. Changing optimization between O1, O2, Os and switching between release and debug builds would randomly increase or decrease the frequency of errors.
Scope inspections revealed that there are random spikes at SDA that are not synchronized with SCL, which only occur while CAN is active:
(legend: trace 3 - SCL, trace 2 - SDA; trace 1 is irrelevant)
This observation made me suspect that there could be a problem in the new I2C driver that only appears while CAN is active. The first idea was to check whether CAN IRQ may preempt I2C IRQ, and it turned out that the priority of the CAN IRQ was higher. I raised priority of the I2C interrupt to the same level as CAN (2), and the problem seemingly disappeared (30 min run time under high CAN traffic without issues).
So, my question is, what am I doing wrong? Does it look like a bug in the I2C driver?
For reference, the custom CAN driver I'm using is available here: https://github.com/UAVCAN/libuavcan/blo ... 32_can.cpp
Thanks in advance,
Pavel.
There is an application based on ChibiOS/RT v2.6 that works fine without any known issues. It runs on STM32F105, and it uses the following ChibiOS drivers: USB, USB Serial, Serial (2x), I2C (master), and PAL; also it includes a custom CAN driver for both on-chip CAN interfaces. The I2C bus in this application is used to retrieve sensor measurements from two on-board sensors at the rate about 80 measurements per second. OS is mostly configured with default settings (max clock rate, default IRQ priorities, IRQ preemption enabled, etc).
Recently I had to port the application to ChibiOS/RT v3.0. The new OS has also been configured mostly with default settings: tickless mode, 16-bit ST counter at 2 kHz. When porting was finished, everything seemed to work fine except one problem with I2C described below.
The application seems to work fine as long as there is no activity on the CAN bus; but if either or both of the CAN bus interfaces are subjected to any traffic, the I2C driver would occasionally report failed transactions with return value MSG_RESET and error code I2C_ACK_FAILURE. The errors would appear approximately once-twice per second at highly irregular intervals. I suspected that there could be a cross-talk between CAN and I2C and inspected the board with a scope, but it turned out that the signals were perfectly well-formed and the hardware was performing well. Furthermore, it worked perfectly with Ch/RT v2.6, so it cannot be a hardware-only issue.
Also, I discovered that the frequency of I2C errors would depend on optimization levels in a very inconsistent way. Changing optimization between O1, O2, Os and switching between release and debug builds would randomly increase or decrease the frequency of errors.
Scope inspections revealed that there are random spikes at SDA that are not synchronized with SCL, which only occur while CAN is active:
(legend: trace 3 - SCL, trace 2 - SDA; trace 1 is irrelevant)
This observation made me suspect that there could be a problem in the new I2C driver that only appears while CAN is active. The first idea was to check whether CAN IRQ may preempt I2C IRQ, and it turned out that the priority of the CAN IRQ was higher. I raised priority of the I2C interrupt to the same level as CAN (2), and the problem seemingly disappeared (30 min run time under high CAN traffic without issues).
So, my question is, what am I doing wrong? Does it look like a bug in the I2C driver?
For reference, the custom CAN driver I'm using is available here: https://github.com/UAVCAN/libuavcan/blo ... 32_can.cpp
Thanks in advance,
Pavel.