【Maker電子學】I2C 界面解密 — PART 6 仲裁協定

作者:Bird

上一篇文章 【Maker電子學】I2C 界面解密 — PART 5 時脈擴展,我們聊了  I2C(以下寫作 I2C) 界面中比較少人接觸到的一個協定:時脈擴展(clock stretching),這是一個讓比較慢的裝置可以藉由延長 SCL 週期來向 master 溝通,請它慢一點的協定。這一回我們要來聊聊 I2C bus arbitration 機制,它是一個讓多個 master 在同一個 bus 上可以互相協調、避免踩來踩去的協定。

當 bus 上有很多主人時

我們剛開始聊 I2C 時,就說過 I2C 是一個 bus。台灣以前把 bus 翻成「匯流排」,而大陸則稱之爲「總線」,但反正它就是用來稱呼一個上面有兩個以上裝置的通訊線路。典型的 UART 只有 Tx 和 Rx 兩個裝置,因此它不是 bus;SPI 在不使用 CS 訊號時,也只允許一個 master 一個 slave 互相連接,因此它也不是 bus。

但 I2C 是 bus,它允許多個裝置,都靠 SDA/SCL 這兩根線連接在一起。

如果一個 I2C bus 上只有一個 master,那它就稱之爲 single-master I2C bus。由於 I2C 所有的傳輸都必需由 master 發起,而整個 bus 只有一個 master 可以藉由造出 START condition 來發起傳輸,因此這種 single-master 的 I2C bus 沒有什麼打架的問題(就像一間教室裡只有一個老師,而只有老師可以對學生問問題,沒被點到的學生完全不能發言一樣)。

但如果 I2C bus 同時有兩個、甚至更多的 master 呢?就像一間教室裡有兩個老師,雖然只有老師可以點學生起來問問題,但兩個老師有可能同時發言,彼此互相打斷,這時候我們就需要一些仲裁機制,也就是 bus arbitration,來避免這種同時發言、互相打斷的狀況。

先聽再說

在各種 bus arbitration 機制中,最基本的禮貌就是「先聽再說」:當你要說話時,先聽聽有沒有別人在說話,如果有的話就閉嘴,如果沒有別人在說話,你才可以說話。

早期的 Ethernet 和現在普遍使用的 Wi-Fi 都有很嚴謹的「先聽再說」禮貌。 Ethernet 的網路線和 Wi-Fi 的無線電頻道都是所謂的「共享傳輸介質」(shared media),這個傳輸介質是由所有連接到這個介質的裝置所共享。如果有人在傳輸,但你又硬要傳輸,不僅原來正在傳輸的訊號會被你破壞掉,你自己想要傳送的訊號也一樣會被破壞掉,這樣怎麼看這都是一個雙輸的局面,因此除了惡意想要搞破壞的人以外,不應該有人在聽到媒體上有別人在說話時,還硬要傳送訊號。

在 Ethernet 和 Wi-Fi 上這樣的機制叫做 CSMA – carrier sense multiple access,也就是藉由感測載波(carrier)來達成多人共享介質(multiple access)的目的。

I2C 的 bus arbitration 也遵循同樣的規矩和禮貌。當一個 master 要產生 START condition 時,它一定會先聽聽看 bus 上面有沒有別人在傳送訊號。在 I2C bus 的定義中,一旦發生 START condition,bus 就會進入忙碌狀態,直到 STOP condition 過後一小段時間,bus 才恢復閒置狀態,因此 master 會監聽 bus 上的 START 和 STOP condition,並確定 bus 在閒置狀態時,才會發送 START condition,開始自己的傳輸。

雖然「先聽再說」的策略大概可以避免 99% 以上的同時發言、互相打斷的問題,但總是有那意外,比如兩個 master 剛好同時起意要說話,又同時聽了 bus 上沒有其它人說話,就決定開口說話,而結果就是兩個 master 撞在一起。

要解決這個撞在一起之後的問題,根據 I2C 的規格說明,需要兩個機制:時脈同步(clock synchronization)和 bus 仲裁(arbitration)。

時脈同步

I2C bus 傳輸時的時脈大致上由 master 決定,再加上我們上次談過的 clock stretch 可以讓 slave 裝置參與一小部分。一個 bus 上的兩個 master 之間是完全不會有任何互相關聯的 clock source,不管是頻率、相位,兩者之間都不會有關聯,但接下來的 bus arbitration 機制會需要兩個 master 之間至少用同樣速度、同步的 clock 來發送資料,因此時脈同步就是爲了這個目的而設計的。

每個 I2C master 裝置中都有兩個 clock period counter,用來計算 SCL 爲 high 和 low 的時間長短。

(圖片來源:Bird 提供)

當 SCL 從 high 變 low 時,這一回合想在 bus 上說話的 master 就會開始利用 SCL 的 low counter 來計算 SCL low 的長度。根據之前說過的 wired-AND 機制,只要有任何一個裝置把 SCL 拉低到 low,SCL 就會爲 low,因此雖然 master 有快有慢,各自送出的 SCL 速度可能不一樣,但這一段 SCL 爲 low 的時間長度,最終會由把 SCL 拉低最久的 master 獲勝,而其它速度比較快的 master 如果提早放掉 SCL,他們會發現 SCL 仍然維持在 low,因此就會繼續計算 SCL 爲 low 的時間,然後等待。

等到最慢的裝置終於放掉 SCL 時,整個 bus 的 SCL 變爲 high,這時大家就會開始計算 SCL 爲 high 的時間。同樣地,即使不同的裝置有快有慢,但由於 wired-AND 電路的特性,只要有任何一個裝置把 SCL 拉低,大家就會同時收到 SCL 變低的狀態,這時 SCL 爲 high 的時間就結束了。

藉由以上這一個週期,每個裝置內的 SCL low counter 和 high counter 都會變成一樣的長度:SCL 爲 low 的時間由把 SCL 拉低最久的那個 master 決定;SCL 爲 high 的時間由把 SCL 維持在 high 最短的那個 master 決定。從下一個 SCL 脈波開始,所有的 master 就會用這一組 SCL low/high 的時間,來同步產生接下來的 clock。

有了一致的 clock,大家傳送的 data bits 才對得齊,才能有接下來的仲裁機制。

仲裁

I2C bus 仲裁的機制其實非常簡單,但是它的結果卻很優雅。

每個 master 在傳送資料時,除了照著 SCL 的節奏去驅動 SDA 外,同時也會逐個 bit 監聽 SDA 上的狀態。如果 SDA 上的狀態與它驅動 SDA 的狀態不符,抱歉,它就出局了。

Wired-AND 電路在這裡再度發威:「你的 low 一定是 low,但你的 high 卻不一定是 high」。當一個 master 把 SDA 拉 low 時,SDA 一定是 low;但當一個 master 把 SDA 放開變成 high 時,SDA 卻不一定是 high。如果有其它人將 SDA 驅動爲 low,那 SDA 就會是 low。

因此,「仲裁的輸贏總發生在一個 master 將 SDA 放掉的時候」。每當它放開 SDA,就會很戒慎恐懼地監聽 SDA,如果 SDA 仍然爲 high,那麼它就安然渡過這個 bit,可以繼續傳輸,參與仲裁;如果 SDA 被別人驅動成 low,那它就輸掉了這一回合的仲裁,接下來的時間它就必需關閉 SDA 的驅動電路,不能繼續參與仲裁。

(圖片來源:Bird 提供)

因爲 I2C 傳輸的第一個 byte 是接收裝置的 slave address,這種仲裁機制的結果就會由這個 slave address 決定。目標 slave address 越小的 master,在仲裁中就會有越高的優先權,其中送往 slave address 0x00 的 master 會有最高的優先權,因爲它把 7 個 bit 的 slave address 都拉到 low。

如果兩個 master 同時要對同一個 slave address 發起傳輸,那麼想要執行寫入命令的 master 會比想要執行讀取命令的 master 具備較高的優先權,因為 R/W bit 的定義是:write 爲 0、read 為 1。

如果真的這麼剛好有如彗星撞地球的機率,兩個 master 同時要對同一個 slave 執行同樣的動作,那麼在第一個 byte 這個回合中就分不出勝負,仲裁會繼續進行到下一個 byte。

如果這個動作是寫入,那麼就會由寫入資料比較小的那個 master 勝出。比方說兩個 master 都要對同一個 slave 寫資料,一個寫 0x80,一個寫 0x00,那麼實際上在 SDA 上出現的資料會是 0x00,而且寫 0x80 的那個 master 在寫第一個 bit 時就會知道自己搶輸了,知難而退。

如果這個動作是讀取,那麼接下來的 byte 就會是由 slave 送出來,於是就沒有仲裁的問題,兩個 master 也會收到一模一樣的資料。

I2C bus 巧妙地利用 wired-AND 電路的特性以及協定的設計,讓 bus arbitration 這件事變得非常簡潔又優雅,而且最重要的是:在仲裁的過程中不會有任何資料錯誤或是消失,且取得仲裁優勢的那個 master 永遠能正確完成傳輸。

小結

這一回我們聊了當 I2C bus 上有兩個或更多的 master 裝置時,用來避免打架的 bus 仲裁協定,雖然它在現今的設計中比較少被用到,但這部分確實是 I2C 協定中非常美妙的一部分。下一回我們會進入 I2C bus 系列的最終回,讓我們再回到 I2C bus 實體層,來探討 I2C bus 的 pull-up 電阻與電路特性的關係以及如何處理不同電壓準位之間的 I2C bus 互通。

(責任編輯:賴佩萱)

Bird

Author: Bird

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

Share This Post On

Submit a Comment

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