我們用 SMART——Specific(具體)、Measurable(可衡量)、Achievable(可達成)、Relevant(具關聯)、Time-bound(有時限)——把每個故事拆成五天,作為每次動手造輪子前的五個檢查問題。
本篇是故事三「你的 I²C、SPI 我看不懂,先幫我包成 AT Command」的 Achievable 篇:利用現有工具與最小變更,做得到嗎?
本篇定位:提出由小到大的介面選項,避免直接跳到完整 AT Command。
帳攤開之後,會議的題目變了:不再是「要不要包 AT Command」,而是「那要給應用端什麼」。我們先做了一件早該做的事——盤點手上已有的,而不是想像還缺的。原廠參考驅動已能完成晶片初始化與原始值讀取,缺的是單位換算、錯誤處理與專案整合;SPI 那顆周邊的參考程式碼品質差一些,但暫存器表清楚。
把參考驅動接進專案,工作量比想像的實在,也比想像的有限:依原廠規定的函式簽章實作 I²C 讀寫與延遲掛勾,初始化匯流排時脈與上拉,依實際接腳接法選定正確的 7-bit 從機位址,把裝置 handle 傳進驅動,再把原廠錯誤碼對應到專案的錯誤型別;資料就緒中斷等真的用上才另外設定中斷腳位。這些都是有標準答案的活,不必發明什麼。那場「先幫我包成 AT Command」的會議還沒過去多久,第一筆溫度原始值就讀出來了,而我那份命令總表一行都還沒實作。
同時我們也用最小的方式驗證了應用端的真實需求:把他的應用邏輯過一遍,真正用到的只有三件事——讀值、設定取樣率、接資料就緒通知。不是「所有功能都要包」,就是三件事。
回頭看,最初那場會議裡只有兩個選項在對決:「你自己去讀暫存器表」和「幫你包一套 AT Command」。一個聽起來冷酷,一個聽起來貼心,於是貼心的贏了。但介面設計從來不是二選一,而是一道階梯;我們差點跳過中間所有的階,落在最貴的那一階上。
會跳過,是因為中間的選項沒有戲劇性。「補幾個函式」聽起來不像提案,「設計一套協定」才像。工程決策裡有一種隱形偏誤:選項的能見度和規模成正比,卻和合適度無關。另一個原因是需求沒被驗證過形狀——用「所有功能」去想像,只有最大的方案看起來夠用;用「三件事」去驗證,幾乎每一階都夠用。
事後我把這道階梯整理成固定的決策順序,往後有人說「幫我包一層」就從第一階走起,每往下一階,都要先拿出上一階不敷使用的證據:
每往下一階,付出的都很具體。一到二,多付幾個函式名與型別的設計工夫,換到編譯期檢查。二到三,多付一層要跟著晶片改版維護的轉接層,換到硬體差異被隔離。三到四,開始要處理序列化、逾時與失敗語意,呼叫不再保證等於執行。四到五,前一輪那三頁清單全部上身,全由自己供養。
第四階有個名詞得先分清楚,當時我們差點混用。同一顆處理器上的兩個行程要溝通,用的是作業系統既有的行程間通訊,管道、共享記憶體、訊息佇列都現成;兩顆處理器之間則是處理器間通訊(inter-processor communication),典型做法是共享記憶體上的 ring buffer 加 mailbox 中斷通知,Linux 側常見以 remoteproc 載入另一顆核心的韌體、用 RPMsg 收發,RTOS 側對應 OpenAMP。兩者名字只差一個音節,解的問題完全不同,把「第二顆處理器」丟給行程間通訊會搞錯邊界。
這個專案最後停在第二階,往第三階補了一小塊轉接層:介面說領域的語言,實作裡呼叫原廠驅動。「薄」不是形容詞,是三條可被審查的紀律:一,不改寫語意:原廠說晶片在忙,就回報忙,不自作主張重試或改口。二,不吞掉錯誤:每個原廠錯誤碼都要對應到一個上層看得見的錯誤,沒有「回傳成功但其實沒做」這種捷徑。三,不私藏狀態:不快取自己那份設定副本,要現值就去問晶片,免得兩份狀態哪天不一致。守住這三條,這層買到兩件事:應用端看不到暫存器與時序;感測器換型號時,改動關在這層裡。應用端工程師拿到標頭檔那天只問了一句「就這樣?」——對,就這樣,這正是重點。
第四階與第五階不是被否決,是被存檔,而存檔要有取出條件。我們把命令協定的觸發條件寫成三條,任一條成立就重啟評估:一、系統真的長出第二顆處理器,兩端各自燒錄、各自升級;二、介面要交給組織外的人使用,例如客戶、代工廠或第三方模組;三、兩側發布節奏分離,無法保證永遠一起改版。三條的共同點是通道與生命週期真的分家了——那時候命令協定不只合理,是正解。
這些判斷寫成一頁架構決策紀錄,欄位很少:當下停在哪一階、被否決的選項與理由、那三條觸發條件、條件成立時由誰重啟評估、重啟要補哪些證據。重點不在格式,在於它讓「暫時不做」有跡可循——沒有紀錄的擱置,過陣子會退化成「當初沒人想到」,同一場爭論再打一次。
「幫我包一層」永遠值得先反問一句:包到哪一階?高階介面確實能降低使用門檻,這正是驅動 API 與轉接層存在的理由;但降低門檻有很多階可選,不必每次都蓋跨海大橋。階梯的紀律不在永遠停在最低階,在升階要憑證據:沒有證據就往上跳,省下的是讀文件的力氣,欠下的是一層要永久維護的債。
照理說故事到這裡該圓滿了:應用端拿到好用的函式,晶片如期動起來。但那套命令總表沒有死透。一層介面該不該存在,最後到底是由誰、憑什麼認定的?