在嵌入式開發領域,開發者常陷入一個陷阱:「軟體磨損(Software wears out)。」 因為程式碼與硬體綁定得太緊,導致硬體一換,程式碼就得重寫。
這樣的程式碼不叫軟體(Software),而叫韌體(Firmware)

Uncle Bob 強調:「雖然軟體依存在韌體上,但韌體依存在硬體上,軟體本身不該成為韌體。」

一、軟體建置的三個活動#

引用 Kent Beck 的觀點,軟體建置應包含三階段,但大多數嵌入式工程師只停留在第一階段:

  1. 讓它工作 (Make it work): 這最難。確保程式碼能跑在目標硬體上。
    如果只停在這,你得到的是一堆亂七八糟的程式碼。
  2. 把它做對 (Make it right): 重構程式碼,讓它結構良好、易於維護。這需要架構思維。
  3. 讓它變快 (Make it fast): 優化效能。

整潔的嵌入式架構,目標是讓我們能順利進行到第二階段,從「讓程式碼工作」轉向「建構長壽有用的程式碼」。

二、目標硬體瓶頸 (The Target-Hardware Bottleneck)#

嵌入式開發最大痛點是 「只能在目標硬體上測試」

  • 流程慢: 修改 ➡️ 編譯 ➡️ 燒錄 ➡️ 重啟 ➡️ 測試。這迴圈太長了
  • 解法: 如果架構分層得當,大部分的業務邏輯應能在 主機(PC) 上測試,而不需要硬體參與

三、分層策略:隔離硬體與韌體#

為避免軟體被韌體汙染,我們必須明確界定三層結構:

  1. 軟體 (Software): 純粹的業務邏輯。完全不知硬體存在
  2. 韌體 (Firmware): 負責與硬體溝通的低層程式碼
  3. 硬體 (Hardware): 物理裝置

Figure 29.1: Three layers

Figure 29.2: Hardware must be separated

Figure 29.3: Software and firmware line

抽象層全名問題解法效益
HALHardware Abstraction Layer軟體直接控制 GPIO 或暫存器建立 HAL;軟體呼叫 Led.TurnOn()硬體更換時,軟體層不用改
PALProcessor Abstraction Layer程式碼依賴 vendor_cpu.h將處理器特定功能隔離在 PAL 中不被特定 CPU 綁架
OSALOperating System Abstraction Layer直接使用 OS API(如 FreeRTOS)定義 OSAL 介面(如 OS_TaskCreate可更換 OS,可離線測試

Figure 29.4: The hardware abstraction layer

Figure 29.5: Adding in an operating system

Figure 29.6: The operating system abstraction layer

硬體是細節,處理器是細節,作業系統也是細節。
一個整潔的嵌入式架構,能透過 HAL 和 OSAL 將這些細節隔離。
這不僅能讓程式碼在不同硬體間移植,更重要的是,
它讓你能脫離硬體進行離線測試(Off-target Testing),大幅提升開發速度與品質。