Linux I2C 故障注入

基於 GPIO 的 I2C 匯流排主控驅動可以配置為提供故障注入功能。然後,它旨在連線到另一個 I2C 匯流排,該匯流排由正在測試的 I2C 匯流排主控驅動。GPIO 故障注入驅動可以在總線上建立特殊狀態,其他 I2C 匯流排主控驅動應優雅地處理這些狀態。

一旦 Kconfig 選項 I2C_GPIO_FAULT_INJECTOR 被啟用,在核心 debugfs 檔案系統中將有一個名為 'i2c-fault-injector' 的子目錄,通常掛載在 /sys/kernel/debug。每個 GPIO 驅動的 I2C 匯流排都會有一個單獨的子目錄。每個子目錄將包含用於觸發故障注入的檔案。下面將描述這些檔案及其預期用例。

線狀態

“scl”

讀取此檔案,可以獲取 SCL 的當前狀態。寫入此檔案,可以改變其狀態,使其強制為低電平或再次釋放。因此,透過使用“echo 0 > scl”命令,您將 SCL 強制置為低電平,從而無法進行通訊,因為正在測試的匯流排主控將無法進行時鐘操作。它應該檢測到 SCL 無響應的狀況,並向更高層報告錯誤。

“sda”

讀取此檔案,可以獲取 SDA 的當前狀態。寫入此檔案,可以改變其狀態,使其強制為低電平或再次釋放。因此,透過使用“echo 0 > sda”命令,您將 SDA 強制置為低電平,從而無法傳輸資料。正在測試的匯流排主控應該檢測到此狀況並觸發匯流排恢復(參見 I2C 規範第 4 版,第 3.1.16 節),使用 Linux I2C 核心的輔助函式(參見 'struct bus_recovery_info')。然而,匯流排恢復不會成功,因為 SDA 將一直被固定為低電平,直到您使用“echo 1 > sda”再次手動釋放它。可以利用“不完整傳輸”類故障注入器進行自動釋放測試。

不完整傳輸

以下故障注入器會建立 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’相比,存在兩個區別

  1. 傳送的訊息將是寫入訊息

  2. 在地址位元組之後,將傳輸一個 0x00 位元組。然後,在 ACK 處停止。

這是一個非常微妙的狀態,當 SCL 上發生更多時鐘脈衝時,裝置會設定為將任何資料寫入暫存器 0x00(如果它有暫存器)。這就是為什麼匯流排恢復(最多 9 個時鐘脈衝)必須檢查 SDA 或傳送額外的 STOP 條件以確保匯流排已釋放的原因。否則,隨機資料將被寫入裝置!

仲裁丟失

在這裡,我們希望模擬正在測試的主控在多主控設定中與另一個主控失去匯流排仲裁的情況。

“lose_arbitration”

此檔案僅供寫入,您需要寫入仲裁干擾的持續時間(單位為微秒,最大為 100 毫秒)。呼叫程序將休眠並等待下一個匯流排時鐘。然而,該程序是可中斷的。

仲裁丟失是透過等待正在測試的主控將 SCL 拉低,然後將 SDA 拉低一段時間來實現的。因此,傳送的 I2C 地址應該被破壞,並且應該被正確檢測到。這意味著傳送的地址應該包含大量‘1’位,以便能夠檢測到損壞。此地址不需要有裝置,因為仲裁丟失應該提前檢測到。另請注意,SCL 的下降是透過中斷進行監控的,因此中斷延遲可能會導致前幾個位未被破壞。在其他情況下空閒的總線上使用此故障注入器的一個良好起點是

# echo 200 > lose_arbitration &
# i2cget -y <bus_to_test> 0x3f

傳輸期間崩潰

一旦正在測試的主控開始傳輸,此故障注入器將引發核心崩潰。這通常意味著匯流排主控驅動的狀態機將被非正常中斷,匯流排可能陷入異常狀態。使用此功能檢查您的關機/重啟/啟動程式碼是否能處理此場景。

“inject_panic”

此檔案僅供寫入,您需要寫入檢測到傳輸開始與誘導核心崩潰之間的延遲(單位為微秒,最大為 100 毫秒)。呼叫程序將休眠並等待下一個匯流排時鐘。然而,該程序是可中斷的。

傳輸的開始是透過等待正在測試的主控將 SCL 拉低來檢測的。使用此故障注入器的一個良好起點是

# echo 0 > inject_panic &
# i2cget -y <bus_to_test> <some_address>

請注意,不需要有裝置偵聽您正在使用的地址。然而,結果可能會因此而異。