嵌入式系統下硬件抽象層HAL的設計與實現

硬件抽象層對下必須檢驗查看目前硬件配置的能力與限制,以及未來可能的擴展性,對上得傾聽系統軟件得需求。簡單得說,HAL就是咱們系統的「硬件」,而「硬件」的功能就是它所提供的API,即全部上層的程序徹底不須要知道硬件與驅動程序的細節,只能經過HAL來操控硬件。按照這樣的邏輯,一般咱們實現HAL的流程以下:數據結構

  • 定義HAL的規模(Scope):根據需求分析上層的系統和應用程序須要哪些硬件功能,這些需求就是HAL必需要包含的基本模塊,而後再根據硬件配置,分析是否仍有目前系統沒用到的硬件功能,這些功能可能會在下一代產品中實現,咱們能夠爲其設計相應的HAL模塊的API,但能夠先不實現;
  • 定義HAL API
    • 系統工程師說明系統需求,包含系統對硬件事件的處理方式。
    • 固件工程師根據硬件功能,提供初版的HAL API定義文件;
    • 系統工程師協同固件工程師逐一review HAL API。
    • 在HAL API立項前,必須針對項目中的全部軟件工程師作詳細報告,收集建議,並作必要的修正。
  • 由固件工程師實現全部的HAL的功能,並執行每一個模塊的單元測試;
  • 固件工程師release初版HAL庫,由系統工程師負責整合測試。

因此HAL不過是驅動程序提供給上層應用的API標準而已。ide


一、HAL基本設計原則

HAL設計文件是以驅動來區分章節,不一樣的驅動由不一樣專長的工程師負責設計與編寫。所以設計文件的第一章是HAL基本設計原則,第二章是共享數據結構與常數定義。如下是設計原則:模塊化

  • 往前兼容,新版的HAL的API能夠變多,但不能減小;
  • HAL旨在對硬件作抽象化,不該與任何系統有直接關係。若OS對驅動有特殊需求(Linux有制式的驅動寫法),應由系統團隊根據需求自行在HAL之上再往上包一層high level driver。
  • 驅動模塊化,儘可能下降驅動間的耦合度。
  • 每一個驅動分別設計,但章節內的結構必須保持一致,主要包含如下信息:
    • 數據結構
    • API
    • 控制流程或狀態機
    • 會產生的硬件事件,以及事件傳遞流程
  • 每一個驅動模塊應該儘可能包裝如下的API,以保持全部驅動模塊的API風格一致:
    • Open():執行該設備的初始化(包含硬件的初始化、取得驅動所需的buffer、數據結構或配置的設定等)
    • Enable():驅動開始運行
    • Disable:驅動暫停運行
    • Close():關掉硬件設備,還回buffer,reset 驅動的數據結構或配置。
    • Set_Power_mode():設定該設備的power mode(full run、idle、sleep mode),即便該硬件不須要這種電壓管理,也要設計出空的Set_Power_mode函數,以保持全部驅動接口的一致性。
  • 驅動與電源管理的配合:驅動僅提供電源管理的機制,而電源管理的策略由系統的power manager 統一管控,即HAL中的每個驅動模塊都必須配合power manager 的需求,例如都必須實現Set_Power_mode() 這樣的API。
  • HAL的每一個驅動模塊都必須遵照共同的命名規則與API風格。
  • 統必定義HAL的系統配置:這些配置必須開放給系統使用,是的本項目不須要的驅動模塊或功能不會被鏈接進來。例如:
#include <hal.h>
#ifdef HAL_WITH_GPS //HAL_WITH_GPS爲HAL配置之一,定義在hal.h中
...
#endif

二、驅動程序與系統的溝通機制

系統與HAL的溝通方式有3種:函數

  • HAL API:系統能夠直接調用HAL開放的API。
  • ISR 與 硬件事件:當硬件產生中斷時,相應的ISR會執行;當ISR處理完後,可將硬件事件抽象化,包裝成硬件事件,往上層系統傳遞,傳遞的方式有:
    • 全局變量flag:當上層程序發現flag的值變化了,即表示發生了某硬件事件。但這種方法的時效性差,且還要注意Critical section的保護;
    • 在ISR內調用系統功能,如send_message()、wakeup_task()等,這是廣泛的作法,但破壞了HAL必須與上層系統無關的規範。
    • 好的作法是,HAL不決定傳遞硬件事件的機制,改成提供API,讓系統可「註冊」用以傳遞硬件事件的函數(回調函數callback function),ISR會在適當時機調用這些函數,至於系統如何處理硬件事件,ISR並不知道。
  • Callback:HAL 提供註冊callback function的API,並明確說明調用此callback function的時機。系統只要傳入function pointer,HAL即會在上述時機調用這些callback function。例如當HAL準備關機時,會去調用系統預線註冊的callback function,讓系統有機會作一些處理。

三、驅動接口

咱們以HAL裏重要的驅動——Audio爲例,看一下該驅動的接口。按照設計文件風格規範,必須先描述這個模塊中全部的API的關係:單元測試

HAL設計文件中的流程圖範例

HalAudEn

HalAudDis

HalAudSetSampleRate


獲取更多知識,請點擊關注:
嵌入式Linux&ARM
CSDN博客
簡書博客
知乎專欄測試

相關文章
相關標籤/搜索