2017-11-28 23:53:32 +08:00
|
|
|
Linux I2C fault injection
|
|
|
|
=========================
|
|
|
|
|
|
|
|
The GPIO based I2C bus master driver can be configured to provide fault
|
|
|
|
injection capabilities. It is then meant to be connected to another I2C bus
|
|
|
|
which is driven by the I2C bus master driver under test. The GPIO fault
|
|
|
|
injection driver can create special states on the bus which the other I2C bus
|
|
|
|
master driver should handle gracefully.
|
|
|
|
|
|
|
|
Once the Kconfig option I2C_GPIO_FAULT_INJECTOR is enabled, there will be an
|
|
|
|
'i2c-fault-injector' subdirectory in the Kernel debugfs filesystem, usually
|
|
|
|
mounted at /sys/kernel/debug. There will be a separate subdirectory per GPIO
|
|
|
|
driven I2C bus. Each subdirectory will contain files to trigger the fault
|
|
|
|
injection. They will be described now along with their intended use-cases.
|
|
|
|
|
|
|
|
"scl"
|
|
|
|
-----
|
|
|
|
|
|
|
|
By reading this file, you get the current state of SCL. By writing, you can
|
|
|
|
change its state to either force it low or to release it again. So, by using
|
|
|
|
"echo 0 > scl" you force SCL low and thus, no communication will be possible
|
|
|
|
because the bus master under test will not be able to clock. It should detect
|
|
|
|
the condition of SCL being unresponsive and report an error to the upper
|
|
|
|
layers.
|
|
|
|
|
|
|
|
"sda"
|
|
|
|
-----
|
|
|
|
|
|
|
|
By reading this file, you get the current state of SDA. By writing, you can
|
|
|
|
change its state to either force it low or to release it again. So, by using
|
|
|
|
"echo 0 > sda" you force SDA low and thus, data cannot be transmitted. The bus
|
|
|
|
master under test should detect this condition and trigger a bus recovery (see
|
|
|
|
I2C specification version 4, section 3.1.16) using the helpers of the Linux I2C
|
|
|
|
core (see 'struct bus_recovery_info'). However, the bus recovery will not
|
|
|
|
succeed because SDA is still pinned low until you manually release it again
|
|
|
|
with "echo 1 > sda". A test with an automatic release can be done with the
|
2018-06-29 17:12:46 +08:00
|
|
|
following class of fault injectors.
|
2017-11-28 23:53:32 +08:00
|
|
|
|
2018-06-29 17:12:46 +08:00
|
|
|
Introduction to incomplete transfers
|
|
|
|
------------------------------------
|
|
|
|
|
|
|
|
The following fault injectors create situations where SDA will be held low by a
|
|
|
|
device. Bus recovery should be able to fix these situations. But please note:
|
|
|
|
there are I2C client devices which detect a stuck SDA on their side and release
|
|
|
|
it on their own after a few milliseconds. Also, there might be an external
|
|
|
|
device deglitching and monitoring the I2C bus. It could also detect a stuck SDA
|
|
|
|
and will init a bus recovery on its own. If you want to implement bus recovery
|
|
|
|
in a bus master driver, make sure you checked your hardware setup for such
|
|
|
|
devices before. And always verify with a scope or logic analyzer!
|
|
|
|
|
|
|
|
"incomplete_address_phase"
|
|
|
|
--------------------------
|
2017-11-28 23:53:32 +08:00
|
|
|
|
|
|
|
This file is write only and you need to write the address of an existing I2C
|
2018-06-29 17:12:46 +08:00
|
|
|
client device to it. Then, a read transfer to this device will be started, but
|
|
|
|
it will stop at the ACK phase after the address of the client has been
|
2017-11-28 23:53:32 +08:00
|
|
|
transmitted. Because the device will ACK its presence, this results in SDA
|
|
|
|
being pulled low by the device while SCL is high. So, similar to the "sda" file
|
|
|
|
above, the bus master under test should detect this condition and try a bus
|
|
|
|
recovery. This time, however, it should succeed and the device should release
|
2018-06-29 17:12:46 +08:00
|
|
|
SDA after toggling SCL.
|
|
|
|
|
2018-06-29 17:12:47 +08:00
|
|
|
"incomplete_write_byte"
|
|
|
|
-----------------------
|
|
|
|
|
|
|
|
Similar to above, this file is write only and you need to write the address of
|
|
|
|
an existing I2C client device to it.
|
|
|
|
|
|
|
|
The injector will again stop at one ACK phase, so the device will keep SDA low
|
|
|
|
because it acknowledges data. However, there are two differences compared to
|
|
|
|
'incomplete_address_phase':
|
|
|
|
|
|
|
|
a) the message sent out will be a write message
|
|
|
|
b) after the address byte, a 0x00 byte will be transferred. Then, stop at ACK.
|
|
|
|
|
|
|
|
This is a highly delicate state, the device is set up to write any data to
|
|
|
|
register 0x00 (if it has registers) when further clock pulses happen on SCL.
|
|
|
|
This is why bus recovery (up to 9 clock pulses) must either check SDA or send
|
|
|
|
additional STOP conditions to ensure the bus has been released. Otherwise
|
|
|
|
random data will be written to a device!
|
|
|
|
|