Linux I2C 故障注入
可以將基於GPIO的I2C總線master驅動程序配置為提供故障注入功能。然后,它被連接到另一個I2C總線,該總線由測試中的I2C總線master驅動程序驅動。GPIO故障注入驅動程序可以在總線上創建特殊的狀態,其他I2C總線master驅動程序應該優雅地處理這些狀態。
一旦Kconfig選項I2C_GPIO_FAULT_INJECTOR被啟用,Kernel debugfs文件系統中就會有一個' i2c-fault-injector '子目錄,通常掛載在/sys/ Kernel /debug。每個GPIO驅動的I2C總線將有一個單獨的子目錄。每個子目錄將包含觸發錯誤注入的文件。現在將描述它們及其預期的用例。
Wire states
“scl”
通過讀取該文件,您可以獲得SCL的當前狀態。通過書寫,你可以改變它的狀態,迫使它降低或再次釋放它。因此,通過使用“echo 0 > scl”,強制拉低scl,因此,沒有通信將是可能的,因為在測試中的總線主機將沒有時鍾。它應該檢測SCL沒有響應的情況,並向上層報告錯誤。
“sda”
通過讀取該文件,您可以獲得SDA的當前狀態。通過書寫,你可以改變它的狀態,迫使它降低或再次釋放它。因此,通過使用“echo 0 > sda”,您將迫使sda降低,因此,數據無法傳輸。被測試的總線主機應該使用Linux I2C核心的助手(參見' struct bus_recovery_info ')檢測這個條件並觸發總線恢復(參見I2C規范版本4,第3.1.16節)。但是,總線恢復不會成功,因為在您使用“echo 1 > SDA”再次手動釋放它之前,SDA仍然處於低位。使用“不完全傳輸”類故障注入器可以進行自動釋放測試。
不完整的傳輸(Incomplete transfers)
以下故障注入器創建的情況是SDA將被設備保持在較低的水平。總線恢復應該能夠修復這些情況。但是請注意:有一些I2C客戶端設備可以檢測到在他們這邊卡住的SDA,並在幾毫秒后釋放它。此外,可能有一個外部設備故障並監視I2C總線。它還可以檢測被卡住的SDA,並自己初始化總線恢復。如果您想在總線主驅動程序中實現總線恢復,請確保之前檢查了此類設備的硬件設置。並始終使用范圍或邏輯分析儀進行驗證!
“incomplete_address_phase”
該文件是只寫的,您需要將現有I2C客戶端設備的地址寫入該文件。然后,將啟動對該設備的讀傳輸,但它將在傳輸客戶端地址后的ACK階段停止。因為設備將ACK它的存在,這導致SDA被設備拉低,而SCL是高的。因此,類似於上面的“sda”文件,被測試的總線主機應該檢測這個條件並嘗試總線恢復。然而,這一次,它應該成功,設備應該在切換SCL后釋放SDA。
“incomplete_write_byte”
與上面類似,此文件是只寫的,您需要將現有I2C客戶端設備的地址寫入該文件。
注入器將再次在一個ACK階段停止,因此設備將保持低SDA,因為它承認數據。然而,與' incomplete_address_phase '相比,有兩個區別:
- 發送出去的消息將是寫消息
- 在地址字節之后,一個0x00字節將被傳輸。然后,在ACK停下。
這是一種非常微妙的狀態,當SCL上進一步發生時鍾脈沖時,設備被設置為將任何數據寫入寄存器0x00(如果它有寄存器)。這就是為什么總線恢復(多達9個時鍾脈沖)必須檢查SDA或發送額外的停止條件,以確保總線已被釋放。否則隨機數據將被寫入設備!
失去仲裁(Lost arbitration)
這里,我們想模擬在多主機設置中被測試的主機與另一個主機失去總線仲裁的情況。
“lose_arbitration”
這個文件是只寫的,你需要寫仲裁干擾的持續時間(以µs為單位,最大100ms)。然后調用進程將休眠並等待下一個總線時鍾。不過,這個過程是可中斷的。
仲裁損失是通過等待SCL下降,然后將SDA拉低一段時間來實現的。因此,發送出去的I2C地址應該被損壞,並且應該被正確地檢測到。這意味着發送的地址應該有很多“1”位,以便能夠檢測損壞。這個地址不需要設備,因為仲裁失敗應該提前檢測到。還要注意,SCL的下降是通過中斷來監視的,因此中斷延遲可能會導致第一個比特沒有損壞。在空閑總線上使用這個故障注入器的一個好的起點是:
# echo 200 > lose_arbitration & # i2cget -y <bus_to_test> 0x3f
傳輸過程中Panic
這個錯誤注入器會在master啟動傳輸時造成內核恐慌。這通常意味着總線master驅動程序的狀態機將不正常地中斷,總線可能會以一種不正常的狀態結束。使用這個來檢查您的shutdown/reboot/boot代碼是否可以處理這個場景。
“inject_panic”
這個文件是只寫的,您需要在檢測到的傳輸開始和引發的內核恐慌之間寫入延遲(以µs為單位,最大為100ms)。然后調用進程將休眠並等待下一個總線時鍾。不過,這個過程是可中斷的。通過等待SCL下降,被測試的主機檢測到傳輸的開始。使用這個故障注入器的一個好的起點是:
# echo 0 > inject_panic & # i2cget -y <bus_to_test> <some_address>
注意,不需要有一個設備監聽您正在使用的地址。不過,結果可能會因這一點而有所不同。
i2c-stub
描述
這個模塊是一個非常簡單的假I2C/SMBus驅動程序。它實現了六種類型的SMBus命令:寫快速、(r/w)字節、(r/w)字節數據、(r/w)字數據、(r/w) I2C塊數據和(r/w) SMBus塊數據。
在加載該驅動程序時,您需要提供芯片地址作為模塊參數,該驅動程序將僅對針對這些地址的SMBus命令作出反應。
不需要硬件,也不與此模塊相關聯。它將接受寫到指定地址的快速命令;它將通過從內存中讀取或寫入數組來響應其他命令(也響應指定的地址)。它還將發送它處理的每個命令的內核日志。
為所有字節操作實現了一個具有自增功能的指針寄存器。這允許像eeprom所支持的那樣連續讀取字節。
SMBus塊命令支持默認是禁用的,必須通過在功能模塊參數中設置相應的位(0x03000000)來顯式啟用。
為了配置SMBus塊操作的SMBus命令,必須編寫SMBus塊命令。寫可以是局部的。塊讀命令總是返回到目前為止用最大寫選擇的字節數。
典型的用例如下:
- 加載這個模塊
- 使用i2cset(來自i2c-tools項目)預加載一些數據
- 加載目標芯片驅動模塊
- 在內核日志中觀察其行為
在i2c-tools包中有一個名為i2c-stub-from-dump的腳本,它可以從芯片轉儲自動加載寄存器值。
參數
int chip_addr [10]:
芯片的SMBus地址
unsigned long functionality:
功能覆蓋,以禁用一些命令。有關合適的值,請參閱<linux/i2c.h>中的I2C_FUNC_*常量。例如,值0x1f0000只會啟用 quick、byte和byte data命令。
u8 bank_reg[10], u8 bank_mask[10], u8 bank_start[10], u8 bank_end[10]:
可選bank設置。它們告訴哪個寄存器中的哪個位選擇了活躍的bank,以及bank寄存器的范圍。
警告
如果你的目標驅動輪詢一些字節或字等待它改變,stub可能會鎖定它。使用i2cset解鎖。
如果您發送的垃圾信息足夠多,printk可能是有損的。這個模塊確實需要像relayfs這樣的東西。