【Maker電子學】I2C 界面解密 — PART 5 時脈擴展

作者:Bird

上一篇文章【Maker電子學】I2C 界面解密—PART 4,我們用 EEPROM 作爲例子,完整說明了用 I2C(以下寫作 I2C) 界面存取暫存器的方式與操作週邊 IC 的方法。這一次我們要進入到 I2C 界面比較少人接觸到的一個協定:時脈擴展(clock stretching)。

關鍵的 Wired-AND

我們之前在講 I2C 實體層時說過,I2C bus 上的所有裝置都透過 SDA 和 SCL 兩根線以 wired-OR 的方式連接在一起。我們再來複習一下 wired-AND 的運作方式:

  • 當所有的裝置都輸出 high 時,bus 上的狀態才會是 high
  • 只要有任何一個裝置輸出 low,bus 上的狀態就會是 low

換句話說,任何一個裝置都能藉由驅動 bus 來讓 bus 變 low,但它沒辦法主動讓 bus 變成 high;只有當大家都輸出 high(也就是不驅動 bus)時,bus 的狀態才會因爲 pull-up 電阻而變成 high。

(圖片來源:Bird 提供)

上圖是 I2C 裝置內部連接 SDA/SCL 訊號的電路示意圖。每個裝置連接到 SDA 或 SCL 都有一個 low-side 的驅動電路用來把 SDA/SCL 的狀態拉到 low,但它沒有 high-side 的驅動電路,因此當 I2C 關閉 low-side,驅動電晶體時,它就是「不驅動」的狀態,也就是說接腳是在 high-Z 的狀態,彷彿這支腳沒有連接到 bus 上一般。

除了驅動 bus 爲 low 的電晶體外,SDA/SCL 都還有另一個電路叫做 input buffer,這是讓 I2C 裝置可以讀取 SDA/SCL 的狀態所使用的。

我們都知道 SDA 是雙向的接腳,它可能是由 master 驅動、slave 接收,也有可能是 slave 驅動、master 接收。不管是 master 還是 slave,當他們需要讀取 SDA 的狀態時,就會透過 input buffer 去感測 SDA 的狀態。

那麼 SCL 呢?

根據我們之前的說明,由於 I2C 的 clock 是由 master 產生,因此在傳輸過程中 SCL 似乎都只由 master 驅動,如此一來,master 似乎用不到 SCL 的 input buffer?非也非也,在我們今天要談的重點—時脈擴展(clock stretching)的狀態中,master 的 SCL input buffer 就扮演了很重要的角色。

忙不過來時

時脈擴展(clock stretching)這個功能,是設計用來讓動作比較慢的 slave 裝置在忙不過來時,通知 master「慢點、慢點」的方法。

(圖片來源:Bird 提供)

在一個正常的傳輸週期中,SCL 會穩定地由 master 產生。當 SCL 爲 low 時,SDA 的狀態可以變化;當 SCL 爲 high 時,SDA 的狀態必需維持穩定不變,以便接收方可以在 SCL 爲 high 的這段時間中偵測、取樣 SDA 的狀態。

如果 slave 在接收資料的過程中,覺得它忙不過來,需要延長一點時間來喘口氣時,它就會驅動 SCL,把 SCL 拉到 low 的狀態。

原來 slave 也可以驅動 SCL 呀?!

我們來看看,當 slave 主動去驅動 SCL 時,bus 上會發生什麼事。

(圖片來源:Bird 提供)

上圖是一個很典型的 clock stretching 時脈圖。Master 在某個傳輸週期的其中一個 byte 中,依序對 slave 送出 bit 7、bit 6、bit 5。送完 bit 5 之後,slave 因爲某些內部的因素,覺得自己忙不過來,需要喘口氣,它就在 bit 5 結束後,把 SCL 拉到 low,開始 clock stretching。

此時 master 應該也在 bit 5 結束時,同步把 SCL 拉到 low,並趁著 SCL 爲 low 的這段時間改變 SDA 的狀態,讓 bit 4 的狀態出現在 SDA 上。Master 準備完 SDA 的狀態,就會放掉 SCL,讓 SCL 變爲 high,藉此通知 slave 可以 bit 4 了。

但就在 master 放掉 SCL 的那個 moment,它發現 SCL 並沒有一如預期地變成 high,而是維持在 low,這時 master 就知道,slave 藉著拉住 SCL 要求進入 clock stretch 的狀態。

藉由拉住 SCL 讓它不要變成 high,slave 可以有多一點時間處理 master 送過來的資料或是進行內部的其他工作,直到 slave 有能力繼續接收 master 傳來的資料時,它才會放掉 SCL,讓它變成 high,正式進入 bit 4 的讀取週期。

爲了收到來自 slave 的 clock stretching 請求,master 在送出每一個 clock 時,都會同時監聽 SCL 的狀態,看看有沒有人拉住 SCL 將它保持在 low。此時 master 裝置的 SCL input buffer 就扮演了很重要的角色。Master 在送出 SCL 上的 clock 時,並非勇往直前地一直送,而是在每一個放開 SCL 的瞬間去聽聽看 SCL 是否有隨著 master 的放開而變成 high,還是有人拉住它請求 clock stretching。

在 I2C bus 的規範中,clock stretching 的時間並沒有上限,換句話說,你愛把 SCL 拉住多久,就拉住多久,master 會等你等到天荒地老,直到你放開 SCL 後才繼續接下來的傳輸。之所以會有這樣的設計,是來自於 I2C 的 clock 規範。

I2C bus 的 clock 速度在不同版本的規格中有不同的上限(100 KHz、400 KHz、1 MHz、3.4 MHz 等),但它並沒有最低速度的限制。換句話說,驅動 SCL 的速度你要多慢都可以,而且也不用一直維持一樣的速度。Master 可以很隨意地驅動 SCL 一個 bit 後,停下來任意一段時間,再繼續下一個 SCL 週期,而 slave 也會乖乖的等下去。

I2C bus 的規範中有句話說「I2C bus is a DC bus」,講的就是這件事,在 I2C bus 發展之初,由於 IC 內部能用的電晶體數量不多,因此 I2C 的裝置可以用很簡單的非同步邏輯電路實作,完全不需要提供額外的 clock。

但這種允許無限制等待的協定也衍生出一些問題。當有裝置長時間把 SCL 拉住而癱瘓整個 bus 的運作時,你無從分辨它到底是 clock stretching 進行中,還是電路或裝置有問題。因此在後來一些基於 I2C bus 的衍生協定中,多半加入了 time out 的機制,同時也限制了最低的 clock 速度,以避免這種癱瘓 bus 的狀態被視爲正常。以 PC 上常用的 SMBus 來說,它的基礎協定仍是 I2C,但限制了最低 clock 爲 10 KHz,而且整個 bus 上不能超過 3.5 ms 沒有任何動作。

同時輸出輸入

時至今日,雖然大部分的 MCU 都已經有硬體的 I2C 模組支援,但偶爾我們還是需要用軟體的方法去實作、模擬 I2C。如果 MCU 的 I/O 接腳是必需要設定方向的典型 I/O 接腳,當我們要用 I/O 接腳去模擬 SDA/SCL 時,就會有輸出入方向的問題。

在 SDA 上這個問題還比較單純,因爲我們知道 master 的 SDA 何時是輸出、何時是輸入,因此只要按照 I2C 協定去切換 I/O 接腳的方向即可。比方說在送完第 8 個 bit 後,要讀取 acknowledge 時,就把模擬 SDA 的 I/O 接腳切成輸入,以讀取 SDA 的狀態,用以判斷 acknowledge。

但如果要實作 SCL 上的 clock stretching,你必須能「同時」輸出及輸入。所謂同時輸出輸入的意思,就是當你在 I/O 接腳上輸出一個狀態時,同時也要讀取這個狀態,因爲前面說過的 wired-AND 特性,當你輸出 low 時讀回來一定是 low,但當你輸出 high 是讀回來不一定是 high,你得讀了才知道有沒有人在偷偷拉 SCL。

在早期的 8051 上有種「quasi-bidirectional port」,它就是一種可以同時輸出和輸入的 I/O 接腳。這種 I/O 界面的輸出是 weak high-side 搭配 strong low-side,因此剛好跟 I2C 的設計理念很接近:你輸出 low 時一定是 low,但輸出 high 時不一定是 high,要看外部負載和 IC 內部的 weak high-side 驅動電路之間的平衡結果,而此時讀取 I/O 接腳的狀態就能知道這個平衡的結果。這種 I/O port 就很適合來實作軟體 I2C。

(圖片來源:Bird 提供)

但現今以 ARM Cortex-M 爲主流的 MCU 市場上已經少見這種 quasi-bidirectional 的設計。大部分的 I/O 接腳在使用前都需要設定方向,沒辦法在輸出狀態下直接讀取接腳的狀態。在這種條件下,如果要用 I/O 接腳搭配軟體模擬 I2C,又要實作 clock stretching 功能,就得用兩支 I/O 接腳來模擬 SCL 訊號,一支設爲 open-drain 的輸出,一支則設爲輸入。上圖就是這種用兩支 I/O 接腳來模擬 SCL 的方法。

小結

這一回我們聊了 I2C 協定中用來減緩傳輸速度的時脈擴展(clock stretching)協定,下一回我們再繼續探討當 I2C bus 上有多個 master 時,彼此之間要如何協調以避免打架的 bus 仲裁協定。

(責任編輯:賴佩萱)

Bird

Author: Bird

在外商圈電子業中闖蕩多年,經歷過 NXP、Sony、Crossmatch 等企業,從事無線通訊、影像系統、手機、液晶面板、半導體、生物辨識等不同領域產品開發。熱愛學習新事物,協助新創團隊解決技術問題。台大農機系、台科大電子所畢業,熱愛賞鳥、演奏管風琴、大提琴、法國號,亦是不折不扣的熱血 maker。

Share This Post On

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *