開源作業系統中系統驅動架構做的最好的無疑是Linux系統,Linux系統中設計精良的驅動架構、裝置樹等功能會硬體廠商對接驅動系統的成本降到很低,并且通過接入VFS系統統一了Linux系統驅動對應用程式提供的接口,為作業系統中使用驅動相關的應用程式在不同的Linux系統間的移植掃平了障礙。反觀傳統的RTOS系統大多數比較注重在核心功能的開發上,欠缺對驅動架構方面的設計。前文曾經提到過物聯網作業系統大多是從傳統RTOS系統發展而來的,是以大多數的物聯網作業系統在驅動架構上面的沒有經過太多設計,總結下來可以分為以下幾類:
- 完全沒有對裝置驅動進行任何定義
- 簡單定義了硬體接口層後完全由晶片廠實作
- 實作了簡單的裝置驅動,提供統一的應用程式通路接口
第1類和第2類系統對應用程式不太友好,即使是相同的作業系統上面寫的應用程式移植到不同平台後也會因為接口不一緻,或者是雖然接口形式一緻但接口底層實作的差别導緻應用程式大機率沒辦法跨平台移植或跨平台無需調試即可運作。第3類對應用程式的移植性比較友好,但有一個問題是,很多系統實作的通用驅動實作的都“過于簡單”,這就導緻有些硬體的總線的特性沒辦法被發揮出來,随着物聯網應用場景越來越複雜,其缺點也是越來越明顯。
在總結了物聯網領域裝置架構的問題之後,AliOS Things從“易用性”的角度出發進行設計,設計了下圖所示的驅動架構。

驅動架構對應用程式統一提供兩種類型的接口:
- AOS API,如aos_gpioc_get/ aos_gpioc_set等
- VFS API,即open/close/read/write/ioctl/poll等
AOS API對進行傳統RTOS應用開發的人比較友好。對于RAM/ROM要求非常嚴格的應用場景,可以直接呼叫AOS形式的API,減少對VFS驅動子系統的依賴,進而減少固件大小。
VFS API對Linux開發者比較友好,遵循POSIX接口定義,基于POSIX标準實作的應用程式在AliOS Things和其它遵循POSIX接口的作業系統之間互相移植就會簡便很多。
驅動架構定義了HAL API的标準,一般是由晶片廠商來實作的。HAL API的定義 的過程中主要考慮了以下兩點:
- 硬體強相關:隻有和硬體強相關的功能才會被定義到HAL API中
- 原子功能:所有HAL API功能都很獨立,很多API隻需要操作硬體的幾個寄存器就可以實作了
在HAL API和AOS API之間則是裝置驅動子系統的實作層。設計裝置驅動子系統的主要目的有兩個:
- 隔離性:将應用程式和HAL API隔離開,徹底解決應用和晶片廠之間的耦合關系
- 統一性:驅動程式隻依賴與驅動子系統提供的API,驅動子系統保證對應用層提供的API行為在不同平台之間是一緻的。
除了提供AOS或VFS API之外和定義HAL API的功能之外,驅動架構還提供了以下功能,下面講分别介紹
1、驅動自動分級加載機制
随着現代物聯網系統的應用場景越來越複雜,同一個物聯網硬體裝置對外設的需求也越來越多。不同驅動程式之間可能會存在依賴關系。為了能讓驅動開發者比較友善的将自己的驅動以子產品的方式添加到系統中和盡量減少添加/删除裝置驅動過程中所需要修改的代碼,設計了驅動自動加載機制。AliOS Things将裝置驅動一共分為9個級别,每個級别的驅動初始化聲明宏定義及其在系統啟動過程中的啟動順序如下表所示。
啟動順序 | 宏定義 | 段名稱定義 |
1 | CORE_DRIVER_ENTRY(driver_entry_api_name) | core_driver_entry |
2 | BUS_ DRIVER_ENTRY(driver_entry_api_name) | bus_driver_entry |
3 | EARLY_DRIVER_ENTRY(driver_entry_api_name) | early_driver_entry |
4 | VFS_ DRIVER_ENTRY(driver_entry_api_name) | vfs_driver_entry |
5 | LEVEL0_DRIVER_ENTRY(driver_entry_api_name) | level0_driver_entry |
6 | LEVEL1_DRIVER_ENTRY(driver_entry_api_name) | level1_driver_entry |
7 | LEVEL2_DRIVER_ENTRY(driver_entry_api_name) | level2_driver_entry |
8 | LEVEL3_DRIVER_ENTRY(driver_entry_api_name) | level3_driver_entry |
9 | POST_DRIVER_ENTRY(driver_entry_api_name) | post_driver_entry |
采用上面的宏定義進行初始化函數聲明之後,用同樣的宏定義聲明的函數指針會被分到一組中,相同組會在連結階段放到固件特定的代碼段中。系統啟動的時候,驅動架構會依次從這些特定的代碼段去讀取函數指針并呼叫這些函數指針指向的函數,每個段被編譯進的段名稱如上表所示。這套機制可以保證用不同宏定義聲明的多個驅動初始化函數會嚴格按照表格中從1到9的順序被呼叫,用相同宏定義聲明的多個驅動初始化函數則是随機的。
除此之外,驅動架構還提供了裝置背景初始化方式的宏定義(VFS_DRIVER_BG_ENTRY(driver_entry_api_name)),可以用于低優先級驅動初始化函數的聲明。被聲明做低優先級驅動的初始化函數會在被低優先級的線程在背景運作,通過這樣的方式可以提高整個系統啟動的速度。假設将将藍牙驅動初始化過程聲明成背景初始化(VFS_DRIVER_BG_ENTRY(bluetooth_drv_init, NULL, 4096)),正常加載過程和驅動分級加載過程的軟體流程的差異可以參考下圖所示的流程圖。

2、驅動線程/消息/事件模型
AliOS Things在3.3版版本中支援的彈性核心對驅動架構提出了比較高的要求,驅動架構既要能運作在宏核心架構下,又要能運作在微核心架構下,甚至還需要同時運作在核心态和使用者态。針對這種需求,AliOS Things設計了在适用于彈性核心架構下線程/消息/事件模型。
當裝置驅動運作在核心态的時候,核心功能可以通過直接函數調用的方式來調用驅動提供的服務;使用者态應用程式可以通過VFS接口或這是通過系統調用的方式通路AOS接口。

但當驅動運作在使用者态的時候,其它應用程式通路驅動提供的服務則需要通過RPC(Remote Procure Call,遠端過程調用)的方式。在這種情況下,AliOS Things隻提供VFS的服務通路方式,如上圖所示。這樣同一套硬體的驅動程式無需修改就可以運作在使用者态或核心态,跟RPC和VFS相關的邏輯全部由驅動架構完成,進而簡化硬體驅動程式的設計。微核心架構下驅動線程/消息模型的流程圖如下圖所示,詳細代碼可以檢視aos_device_register函數的實作,這裡就不進行詳細展開。

3、裝置驅動子系統
下表是各個裝置驅動子系統源代碼位置,接口定義頭檔案、使用案例說明以及晶片廠對接接口頭檔案所在位置。讀者可以根據自己的需求進行詳細解讀。
其中每個裝置驅動子系統都有對應的AOS API子產品和VFS API子產品,VFS API子產品是依賴于AOS API的。使用者可以根據需求選擇使用哪種類型的API。
項目 | 說明 |
源代碼位置 | components/drivers/peripheral |
接口頭檔案說明 | components/drivers/peripheral/<subsystem>/include/aos/driver |
使用案例說明 | components/drivers/peripheral/<subsystem>/example |
晶片廠對接接口頭檔案 | components/csi/csi2/include/drv/<subsystem>.h |
其中各驅動子系統在設計實作過程中可以滿足下表的場景需求。
驅動子系統類型 | 适用的場景 |
I2C | 同時和多個I2C從裝置使用不同的Clock頻率進行資料通信 |
SPI | 同時和多個SPI從裝置使用不同的參數設定(Clock頻率、有無CS及CS極性有效性)進行資料通信 |
MTD | 支援多分區,Nand Flash和Nor Flash |
UART | 相容POSIX的UART操作 |