一、概述
本文主要介紹在使用 Semidrive E3 與 I2C 設備通信時,如果出現 I2C 設備死鎖的情況,如何通過軟體配置解決該問題。
硬體設備:E3640 GATEWAY 開發板
軟體包:MCAL PTG3.0
調試器:J-Link
圖 1.1 E3640 Gateway 開發板
二、I2C 死鎖原因介紹
在 MCU 作為主設備通過 I2C 與 EEPROM 從設備進行通信時,如果主設備出現掉電復位,而從設備正在回復 ACK 或者回復的數據位是 0 時,即 SDA 被從設備拉低的狀態。此時主設備復位後將 SCL 會拉高,從設備會等到主設備拉低 SCL 接收數據,而主設備會等到從設備釋放 SDA 後再發送數據。從而出現主從設備互相等待的狀態,即死鎖的現象。
解決死鎖狀態的常見方法如下:
- 主設備在檢測到 SDA 拉低持續一段時間後,主設備通過控制從設備的復位引腳或者電源來復位從設備。但此方法需要從設備具備復位引腳,或者電路設計上主設備可以控制從設備的供電。
- 主設備在檢測到 SDA 拉低持續一段時間後,主設備通過 SCL 發送 9 個 clock 到從設備,此時從設備會認為主設備已經接收完成數據,從而釋放 SDA 為高電平。
- 在設計中添加看門狗或者死鎖恢復的 I2C 緩衝器,當出現死鎖現象時,會恢復死鎖狀態至正常狀態。
本文主要介紹第二種方法,通過軟體配置在 SCL 引腳上發送 9 個 clock 解決死鎖狀態。但建議通過硬體設計的方式,在主設備復位的同時復位從設備來避免死鎖的狀態出現。
三、軟體解決方案介紹
軟體解決辦法有兩種,一是通過配置寄存器,使用 I2C 的硬體模塊,在 SCL 引腳上自動發送 9 個 pulse;二是通過將 I2C 引腳配置成 GPIO,將 I2C 的 SCL 引腳配置為 GPIO 輸出,SDA 引腳配置為 GPIO 輸入,在 SCL 引腳上主動發送 9 個 pulse 波,類似模擬 I2C 的方式。
本文主要介紹的為配置寄存器的方式。
1. 寄存器介紹
當檢測到寄存器 INTR0 的中斷,且 bit 9 SDASTUCKLOW 為 1 時,則說明 SDA 被持續拉低一段時間,即可能出現死鎖現象。

圖 3.1 寄存器 SDASTUCKLOW bit 介紹
此時通過置位寄存器 PCR0 的 BUSCLR bit 為 1,在 SCL 上發送 pulse (最大 9),直到 SDA 重新回到高電平,在發送完 pulse 後,此 bit 會自動清 0。

圖 3.2 寄存器 BUSCLR bit 介紹
可以通過檢測 INTR0 的 BUSCLRPASS/BUSCLRERR 來檢測 bus clear 的結果。

圖 3.3 寄存器 BUSCLRERR 和 BUSCLRPASS bit 介紹
2. 代碼和測試記錄
本次測試使用 E3 GATEWAY 開發板,將 I2C SDA 引腳短接到地來模擬 I2C 死鎖現象。
使用 I2C 的 demo 進行測試,添加如下測試代碼,在 I2C 初始化結束並且檢測到 SDASTUCKLOW 置 1 後,調用 sdrv_i2c_clear_bus() 函數來進行 bus clr 功能解決死鎖現象。

圖 3.4 測試代碼
void sdrv_i2c_set_busclr(paddr_t base) 函數為置位 PCR0 的 BUSCLR bit,讓 E3 在 SCL 引腳上發出 9 個 pulse。
status_t sdrv_i2c_clear_bus(sdrv_i2c_t *ctrl) 函數調用 void sdrv_i2c_set_busclr(paddr_t base) 後,檢測 INTR0 的 BUSCLRPASS/BUSCLRERR bit 來確認 bus clear 的結果,並列印 log。
如下為示波器檢測到的波形,其中黃色為 SDA,藍色為 SCL。這裡配置的 I2C 為 400KHz 的通信頻率,所以發送的 pulse 周期為 2.5us。

圖 3.5 SCL 發送的波形
四、參考文檔
- 《SemiDrive_E3_SSDK_User_Guide》
如有更多需求,歡迎聯繫大聯大世平集團 ATU 部門:atu.sh@wpi-group.com 作者:Nostalgia
更多資訊,請掃碼關注我們!

評論
hello您好
4 個月前