요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
=========================
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.
Wire states
===========
"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
"incomplete transfers" class of fault injectors.
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"
--------------------------
This file is write only and you need to write the address of an existing I2C
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
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
SDA after toggling SCL.
"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!
Lost arbitration
================
Here, we want to simulate the condition where the master under test loses the
bus arbitration against another master in a multi-master setup.
"lose_arbitration"
------------------
This file is write only and you need to write the duration of the arbitration
interference (in µs, maximum is 100ms). The calling process will then sleep
and wait for the next bus clock. The process is interruptible, though.
Arbitration lost is achieved by waiting for SCL going down by the master under
test and then pulling SDA low for some time. So, the I2C address sent out
should be corrupted and that should be detected properly. That means that the
address sent out should have a lot of '1' bits to be able to detect corruption.
There doesn't need to be a device at this address because arbitration lost
should be detected beforehand. Also note, that SCL going down is monitored
using interrupts, so the interrupt latency might cause the first bits to be not
corrupted. A good starting point for using this fault injector on an otherwise
idle bus is::
# echo 200 > lose_arbitration &
# i2cget -y <bus_to_test> 0x3f
Panic during transfer
=====================
This fault injector will create a Kernel panic once the master under test
started a transfer. This usually means that the state machine of the bus master
driver will be ungracefully interrupted and the bus may end up in an unusual
state. Use this to check if your shutdown/reboot/boot code can handle this
scenario.
"inject_panic"
--------------
This file is write only and you need to write the delay between the detected
start of a transmission and the induced Kernel panic (in µs, maximum is 100ms).
The calling process will then sleep and wait for the next bus clock. The
process is interruptible, though.
Start of a transfer is detected by waiting for SCL going down by the master
under test. A good starting point for using this fault injector is::
# echo 0 > inject_panic &
# i2cget -y <bus_to_test> <some_address>
Note that there doesn't need to be a device listening to the address you are
using. Results may vary depending on that, though.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
GPIO 기반 I2C 결함 주입기
1-15GPIO 기반 I2C 버스 마스터 드라이버는 결함 주입 기능을 제공하도록 구성할 수 있습니다. 이 드라이버를 시험 대상 I2C 버스 마스터가 구동하는 다른 I2C 버스에 연결하면, 시험 대상 드라이버가 정상적으로 처리해야 할 특수한 버스 상태를 만들 수 있습니다.
Kconfig 옵션 `I2C_GPIO_FAULT_INJECTOR`를 활성화하면 보통 `/sys/kernel/debug`에 마운트되는 커널 debugfs 아래에 `i2c-fault-injector` 하위 디렉터리가 생깁니다. GPIO로 구동하는 각 I2C 버스마다 별도 디렉터리가 있으며, 그 안의 파일로 각 결함을 발생시킵니다.
테스트 구성과 제어 위치를 정리합니다.
주입기와 시험 대상 마스터가 동일 버스 상태를 관찰합니다.
=========================
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과 SDA 선 상태 강제
16-42`scl` 파일을 읽으면 현재 SCL 상태를 얻고, 값을 쓰면 SCL을 Low로 강제하거나 다시 해제할 수 있습니다. `echo 0 > scl`은 SCL을 Low로 고정하므로 시험 대상 버스 마스터가 클록을 만들 수 없어 통신이 불가능해집니다. 드라이버는 SCL이 응답하지 않는 상태를 감지하고 상위 계층에 오류를 보고해야 합니다.
`sda` 파일도 읽기로 현재 상태를 얻고 쓰기로 Low 강제 또는 해제를 수행합니다. `echo 0 > sda`는 SDA를 Low로 고정해 데이터를 전송할 수 없게 만듭니다.
시험 대상 마스터는 고정된 SDA를 감지하고 I2C 명세 버전 4의 3.1.16절 및 Linux I2C core의 `struct bus_recovery_info` 도우미에 따라 버스 복구를 시작해야 합니다. 다만 SDA가 계속 Low로 고정되어 있으므로 `echo 1 > sda`로 수동 해제할 때까지 복구는 성공하지 않습니다. 자동 해제 동작은 불완전 전송 계열 주입기로 시험할 수 있습니다.
각 파일의 쓰기 효과와 기대 결과입니다.
수동으로 고정한 SDA는 자동 복구만으로 풀리지 않습니다.
Wire states
===========
"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
"incomplete transfers" class of fault injectors.
불완전 전송과 버스 복구
43-85다음 결함 주입기는 장치가 SDA를 Low로 유지하는 상황을 만듭니다. 버스 복구는 원칙적으로 이 상황을 고칠 수 있어야 합니다. 그러나 일부 I2C 클라이언트는 자신 쪽에서 SDA 고정을 감지한 뒤 몇 밀리초 후 스스로 해제하며, 외부 디글리치·감시 장치가 버스를 감시하다 자체 복구를 시작할 수도 있습니다.
버스 마스터 드라이버에 복구를 구현하기 전에는 이런 장치가 하드웨어 구성에 포함되어 있는지 확인해야 합니다. 실제 선 상태는 항상 오실로스코프나 로직 분석기로 검증해야 합니다.
쓰기 전용 `incomplete_address_phase`에는 존재하는 I2C 클라이언트 주소를 씁니다. 주입기는 해당 장치에 읽기 전송을 시작하고 주소 전송 뒤 ACK 단계에서 멈춥니다. 장치가 존재를 알리는 ACK를 내므로 SCL이 High인 동안 SDA가 Low로 당겨집니다. 시험 대상 마스터는 이를 감지해 복구해야 하며, 이번에는 SCL을 토글하면 장치가 SDA를 놓으므로 복구가 성공해야 합니다.
쓰기 전용 `incomplete_write_byte`에도 존재하는 클라이언트 주소를 씁니다. 주입기는 쓰기 메시지를 보내고 주소 바이트 다음에 `0x00`을 전송한 뒤 데이터 ACK 단계에서 멈춥니다. 장치가 데이터를 ACK하므로 SDA를 Low로 유지합니다.
이 상태에서 SCL 펄스가 더 발생하면 레지스터가 있는 장치는 레지스터 `0x00`에 이어지는 임의 데이터를 쓸 준비가 됩니다. 따라서 최대 9클록 펄스를 사용하는 버스 복구는 SDA를 확인하거나 추가 STOP 조건을 보내 버스가 해제되었음을 보장해야 합니다. 그렇지 않으면 장치에 임의 데이터가 기록될 수 있습니다.
두 주입기가 멈추는 위치와 복구 위험을 비교합니다.
레지스터 0x00에 임의 데이터가 쓰이지 않도록 버스 해제를 확인합니다.
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"
--------------------------
This file is write only and you need to write the address of an existing I2C
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
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
SDA after toggling SCL.
"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!
중재 상실 주입
86-111이 시험은 멀티 마스터 구성에서 시험 대상 마스터가 다른 마스터에게 버스 중재를 잃는 상황을 모사합니다.
쓰기 전용 `lose_arbitration` 파일에는 중재 방해 지속 시간을 µs 단위로 쓰며 최댓값은 100ms입니다. 호출 프로세스는 잠든 뒤 다음 버스 클록을 기다리고, 대기는 인터럽트할 수 있습니다.
주입기는 시험 대상 마스터가 SCL을 Low로 내릴 때까지 기다렸다가 일정 시간 SDA를 Low로 당깁니다. 그 결과 전송 중인 I2C 주소가 손상되며 마스터는 이를 올바르게 감지해야 합니다. 손상을 잘 드러내려면 전송 주소에 `1` 비트가 많이 포함되어야 합니다.
중재 상실은 주소의 장치가 응답하기 전에 검출되어야 하므로 해당 주소에 실제 장치가 없어도 됩니다. SCL 하강은 인터럽트로 감시하므로 인터럽트 지연 때문에 처음 몇 비트는 손상되지 않을 수 있습니다.
유휴 버스에서 시작하기 좋은 예는 백그라운드로 `echo 200 > lose_arbitration`을 실행하고 시험 버스의 `0x3f` 주소에 `i2cget`을 수행하는 것입니다.
주입 시간과 주소 선택 기준입니다.
SCL 하강 뒤 SDA를 강제로 낮춰 주소 비트를 손상시킵니다.
Lost arbitration
================
Here, we want to simulate the condition where the master under test loses the
bus arbitration against another master in a multi-master setup.
"lose_arbitration"
------------------
This file is write only and you need to write the duration of the arbitration
interference (in µs, maximum is 100ms). The calling process will then sleep
and wait for the next bus clock. The process is interruptible, though.
Arbitration lost is achieved by waiting for SCL going down by the master under
test and then pulling SDA low for some time. So, the I2C address sent out
should be corrupted and that should be detected properly. That means that the
address sent out should have a lot of '1' bits to be able to detect corruption.
There doesn't need to be a device at this address because arbitration lost
should be detected beforehand. Also note, that SCL going down is monitored
using interrupts, so the interrupt latency might cause the first bits to be not
corrupted. A good starting point for using this fault injector on an otherwise
idle bus is::
# echo 200 > lose_arbitration &
# i2cget -y <bus_to_test> 0x3f
전송 중 커널 패닉 주입
112-136이 결함 주입기는 시험 대상 마스터가 전송을 시작한 뒤 커널 패닉을 발생시킵니다. 버스 마스터 드라이버의 상태 기계가 비정상적으로 중단되고 버스가 특이한 상태로 남을 수 있으므로 종료, 재부팅, 부팅 코드가 이 상황을 처리하는지 확인할 수 있습니다.
쓰기 전용 `inject_panic` 파일에는 전송 시작 감지 시점부터 커널 패닉을 일으킬 때까지의 지연을 µs 단위로 기록하며 최댓값은 100ms입니다. 호출 프로세스는 잠든 뒤 다음 버스 클록을 기다리고, 대기는 인터럽트할 수 있습니다.
전송 시작은 시험 대상 마스터가 SCL을 Low로 내리는 순간을 기다려 검출합니다. 시작 예는 `echo 0 > inject_panic`을 백그라운드에서 실행한 뒤 시험 버스와 임의 주소에 `i2cget`을 수행하는 것입니다.
사용하는 주소를 듣는 장치가 반드시 존재할 필요는 없지만, 실제 장치의 존재 여부에 따라 결과가 달라질 수 있습니다.
전송 시작과 패닉 지연의 설정값입니다.
비정상 중단 뒤 다음 부팅이 버스를 정상화하는지 확인합니다.
Panic during transfer
=====================
This fault injector will create a Kernel panic once the master under test
started a transfer. This usually means that the state machine of the bus master
driver will be ungracefully interrupted and the bus may end up in an unusual
state. Use this to check if your shutdown/reboot/boot code can handle this
scenario.
"inject_panic"
--------------
This file is write only and you need to write the delay between the detected
start of a transmission and the induced Kernel panic (in µs, maximum is 100ms).
The calling process will then sleep and wait for the next bus clock. The
process is interruptible, though.
Start of a transfer is detected by waiting for SCL going down by the master
under test. A good starting point for using this fault injector is::
# echo 0 > inject_panic &
# i2cget -y <bus_to_test> <some_address>
Note that there doesn't need to be a device listening to the address you are
using. Results may vary depending on that, though.
요약·해설
gpio-fault-injection.rst:1-136GPIO 결함 주입기는 SCL·SDA의 비정상 상태와 전송 중단을 재현하여 버스 마스터의 오류 감지, 복구, 재부팅 복원력을 실제 파형과 함께 검증하게 합니다.
원문 분량과 핵심 검토 대상을 요약합니다.
문서의 주요 판단이나 전송 순서를 압축해 보여 줍니다.