瞭解和使用no-OS及平台驅動程式
作者:ADI資深軟體工程師Mahesh Phalke
快速發展的技術需要軟體支援(硬體驅動程式和代碼示例)來簡化設計導入過程。本文介紹如何利用no-OS(無作業系統)驅動程式和平台驅動程式來建構ADI精密類比數位轉換器和數位類比轉換器的應用硬體,這些元件在速度、功耗、尺寸和解析度方面提供高水準的性能。
ADI提供基於no-OS驅動程式的嵌入式硬體示例來支援精密變換器。no-OS驅動程式負責元件配置、轉換器數據擷取、執行校準等,而基於no-OS驅動程式的硬體示例則便於將資料傳輸到主機進行顯示、儲存和進一步處理。
no-OS和平台驅動程式簡介
顧名思義,no-OS驅動程式設計用於通用(或無特定)作業系統。該名稱還表示這些驅動程式可以用在沒有任何OS支援的裸機(BareMetal)系統上。no-OS驅動程式目的在為給定精密轉換器的數位介面瀏覽提供進階API。no-OS驅動程式使用元件的這些API介面瀏覽、配置、讀取、寫入資料,而無需知道暫存器位址(記憶體映射)及其內容。
no-OS驅動程式利用平台驅動程式層來支援跨多個硬體/軟體平台複用相同的no-OS驅動程式,使硬體高度可移植。平台驅動程式層的使用將no-OS驅動程式隔絕開來,後者無需知道平台特定介面(如SPI、I2C、GPIO等)的低階細節,因此no-OS驅動程式不需要修改就能跨多個平台複用。
使用no-OS驅動程式
圖2顯示了no-OS驅動程式的典型代碼結構。




精密轉換器的no-OS驅動程式代碼通常包含在兩個以C程式設計語言編寫的原始檔案中:adxxxx.c和adxxxx.h,其中xxxx代表元件名稱(例如AD7606、AD7124等)。元件標頭檔(adxxxx.h)包含元件特定結構、列列舉、暫存器位址和位元遮罩的公共程式設計介面,將此檔包含到所需的原始檔案中便可使用這些公開瀏覽介面。元件原始檔案(adxxxx.c)包含介面的實現,用於初始化和移除元件、讀/寫元件暫存器、從元件讀取數據、擷取/設定元件特定參數等。
典型的no-OS驅動程式圍繞一組常見功能來建構:
- 元件特定暫存器位址、位元遮罩巨集、元件配置列舉、讀/寫元件特定參數(如過採樣、增益、基準電壓等)的結構的聲明。
- 透過no-OS驅動程式的元件初始化/移除函數以及元件特定的初始化和驅動程式結構與描述符初始化物理元件/解除元件初始化。
- 使用元件暫存器讀/寫函數瀏覽元件記憶體映射或暫存器詳細資訊,例如adxxxx_read_register()或adxxxx_write_register()。
no-OS驅動程式代碼使用
使用元件特定位址、位元遮罩、參數配置列舉和結構:
如前所述,adxxxx.h標頭檔包含所有元件特定列舉和結構的聲明,這些列舉和結構被傳遞到元件特定的函數或API以配置或訪問元件參數。具體情況如圖3所示。
圖3中顯示的adxxxx_config結構允許使用者選擇多工器通道並為其設定過取樣速率。此結構的成員(afe_mux_channel和oversampling)是存在於同一頭檔中的列舉,其包含這兩個欄位的所有可能值的數位常量,使用者可以選擇。
adxxxx.c檔中定義的adxxxx_set_adc_config()函數透過配置結構獲取使用者傳遞的配置/參數,並進一步調用adxxxx_spi_reg_write()函數,透過數位介面(在上例中是SPI)將資料寫入ADXXXX_REG_CONFIG元件暫存器。
使用no-OS驅動程式結構和初始化函數初始化元件:


除了元件配置列舉和結構之外,no-OS驅動程式還提供以下兩個結構:
- 元件初始化結構。
- 設備驅動程式結構。
元件初始化結構允許使用者在使用者應用程式碼中定義元件特定的參數和配置。初始化結構包含其他元件特定的參數結構和列舉的成員。圖5顯示了元件初始化結構的定義。


元件驅動程式結構透過元件初始化函數adxxxx_init()載入元件初始化參數。元件驅動程式結構是在運行時(動態)從堆空間中分配記憶體。元件驅動程式結構和元件初始化結構中聲明的參數幾乎完全相同。元件驅動程式結構是元件初始化結構的執行階段版本。
以下步驟說明典型的元件初始化函數和初始化流程:
- 第1步:在應用程式中創建元件初始化結構的定義(或實例)(例如struct adxxxx_init_params),以初始化用戶特定的元件參數和平台相關的驅動程式參數。參數在編譯期間定義。
注意:初始化結構中定義的參數因元件而異。

- 第2步:在應用程式碼中創建元件驅動程式結構的指標實例(變數)。
使用者應用程式需要創建元件驅動程式結構的單一指標實例。將此實例傳遞給所有no-OS驅動程式API/函數以存取元件特定參數。應用程式碼中定義的此指標實例指向堆中動態分配的記憶體,這是透過no-OS驅動程式中定義的元件初始化函數(如adxxxx_init())完成的。

- 第3步:調用元件初始化函數以初始化元件和其他平台特定的周邊。

no-OS驅動程式中定義的adxxxx_init()函數用adxxx_init_param結構傳遞的使用者特定參數初始化元件。元件驅動程式結構的指標實例和元件初始化結構的實例作為兩個參數傳遞給此初始化函數。使用者應用程式碼可以多次調用adxxxx_init()函數,只要調用初始化函數之後再調用元件移除函數來平衡。
透過元件暫存器讀/寫函數存取記憶體映射(暫存器內容)如圖6所示


使用者可以透過no-OS驅動程式元件特定的adxxx_read/write()函數存取元件暫存器內容(例如產品ID、暫存區值、OSR等)。
大多數情況下,使用者不會直接使用暫存器存取函數。元件特定的函數透過這些暫存器存取函數(如adxxxx_spi_reg_read/write())來調用。如果可能,建議使用元件配置和狀態API來存取元件記憶體映射,而不要使用直接暫存器存取函數,因為這樣能確保元件驅動程式結構與元件中的配置保持同步。
平台驅動程式
平台驅動程式是包裝平台特定API的硬體抽象層(HAL)之一。它們由no-OS元件驅動程式或使用者應用程式碼調用,使後者可以獨立於底層硬體和軟體平台。平台驅動程式包裝了平台特定的低階硬體功能,例如SPI/I2C初始化和讀/寫、GPIO初始化和讀/寫、UART初始化和接收/發送、用戶特定的延遲、中斷等。
SPI平台驅動程式模組的典型檔結構如圖7所示。


使用平台驅動程式
平台驅動程式代碼通常包含在以C/C++程式設計語言編寫的三個原始檔案中。
1) spi.h: 這是一個與平台無關的檔,包含SPI功能所需的元件結構和列舉。此標頭檔中定義的C程式設計介面沒有平台依賴性。
初始化和元件結構中聲明的所有參數對任何平台上的SPI介面都是通用的。
元件初始化結構中使用的void *extra參數允許用戶傳遞額外的參數,這些參數可以是所用平台特定的。
SPI驅動程式結構和SPI初始化結構中聲明的參數幾乎完全相同。SPI驅動程式結構是SPI初始化結構的執行階段版本。
2) spi.cpp/.c: 此檔包含spi.h檔中聲明的函數的實現,這些函數用於初始化特定平台的SPI周邊以及讀/寫資料。廣義的「平台」是指硬體微控制器(目標元件)和軟體(如RTOS或Mbed-OS)的組合。此檔依賴於平台,移植到其他平台時需要修改。
圖9詳細說明了Mbed平台的SPI介面,並顯示了如何使用這些介面和元件初始化/驅動程式結構來初始化SPI和讀/寫資料。






3) spi_extra.h: 此檔包含其他元件結構或列舉,其特定於給定平台。它允許用戶應用程式碼提供通用spi.h檔中未涉及的配置。例如,SPI接腳可能隨平台而異,因此可以作為這些平台特定的額外結構的一部分增加。
移植平台驅動程式
平台驅動程式可以從一個平台(微控制器)移植到另一個平台;若要移植,通常需要創建平台特定的.cpp/.c和_extra.h文件。平台驅動程式駐留在微控制器單元供應商提供的元件特定硬體抽象層(HAL)之上的一層。因此,為將平台驅動程式從一個平台移植到另一個平台,與調用供應商提供的HAL中存在的函數或API相關的平台驅動程式代碼需要做一些細微改動。
圖12區分了基於Mbed的SPI平台驅動程式和 ADuCM410 SPI平台驅動程式。
ADI no-OS儲存庫和平台驅動程式的GitHub原始程式碼連結可參考: Analog Devices Wiki 和 GitHub 頁面。
為no-OS驅動程式做出貢獻
ADI no-OS驅動程式已開源並託管在GitHub上。驅動程式不僅支援精密轉換器,也支援許多其他ADI產品,如加速度計、收發器、光電元件等。任何熟悉原始程式碼的人都可以為這些驅動程式做貢獻,方式是提交變更和創建拉取請求來審核這些變更。
有許多示例項目可以在Linux和/或Windows環境中運行。許多示例專案是用硬體描述性語言(HDL)開發的,以便在Xilinx®、Intel®等公司開發的FPGA以及由不同供應商開發的目標處理器上運行。
如需無作業系統的系統的no-OS軟體驅動程式(用C編寫),請瀏覽 ADI no-OS GitHub儲存庫。
ADI Wiki頁面提供了 使用Mbed和ADuCMxxx平台為精密轉換器開發的示例。



