了解和使用no-OS及平臺驅(qū)動程序
ADI 公司提供基于no-OS 驅(qū)動程序的嵌入式固件示例來支持精密轉(zhuǎn)換器。no-OS驅(qū)動程序負責器件配置、轉(zhuǎn)換器數(shù)據(jù)采集、執(zhí)行校準等,而基于no-OS 驅(qū)動程序的固件示例則便于將數(shù)據(jù)傳輸?shù)街鳈C進行顯示、存儲和進一步處理。
本文引用地址:http://www.ex-cimer.com/article/202204/432918.htm1 no-OS和平臺驅(qū)動程序簡介
顧名思義,no-OS 驅(qū)動程序設(shè)計用于通用(或無特定)操作系統(tǒng)。該名稱還意味著這些驅(qū)動程序可以用在沒有任何OS 支持的裸機(BareMetal,亦稱裸金屬主機) 系統(tǒng)上。no-OS 驅(qū)動程序旨在為給定精密轉(zhuǎn)換器的數(shù)字接口訪問提供高API(Application Programming Interface,應(yīng)用程序接口),如圖1 所示。no-OS 驅(qū)動程序使用器件的這些API 接口訪問、配置、讀取、寫入數(shù)據(jù),而無需知道寄存器地址(存儲器映射)及其內(nèi)容。
no-OS 驅(qū)動程序利用平臺驅(qū)動程序?qū)觼碇С挚缍鄠€硬件/ 軟件平臺復(fù)用相同的no-OS 驅(qū)動程序, 使固件高度可移植。平臺驅(qū)動程序?qū)拥氖褂脤o-OS 驅(qū)動程序隔絕開來,后者無需知道平臺特定接口(如SPI(Serial Peripheral Interface,串行外設(shè)接口)、I2C(Inter-Integrated Circuit,集成電路總線)、GPIO(通用輸入輸出)等)的低級細節(jié),因此no-OS 驅(qū)動程序不需要修改就能跨多個平臺復(fù)用。
圖1 精密轉(zhuǎn)換器固件協(xié)議棧
2 使用no-OS驅(qū)動程序
圖2 顯示了no-OS 驅(qū)動程序的典型代碼結(jié)構(gòu)。
圖2 no-OS驅(qū)動程序代碼結(jié)構(gòu)
圖3 器件配置枚舉、結(jié)構(gòu)和API
精密轉(zhuǎn)換器的no-OS 驅(qū)動程序代碼通常包含在兩個以C 編程語言編寫的源文件中:adxxxx.c 和adxxxx.h,其中xxxx 代表器件名稱(例如AD7606、AD7124等)。器件頭文件(adxxxx.h) 包含器件特定結(jié)構(gòu)、枚舉、寄存器地址和位掩碼的公共編程接口,將此文件包含到所需的源文件中便可使用這些公開訪問接口。器件源文件(adxxxx.c) 包含接口的實現(xiàn),用于初始化和移除器件、讀/ 寫器件寄存器、從器件讀取數(shù)據(jù)、獲取/ 設(shè)置器件特定參數(shù)等。
典型的no-OS驅(qū)動程序圍繞一組常見功能來構(gòu)建。
1)器件特定寄存器地址、位掩碼宏、器件配置枚舉、讀/ 寫器件特定參數(shù)(如過采樣、增益、基準電壓等)的結(jié)構(gòu)的聲明。
2)通過no-OS 驅(qū)動程序的器件初始化/ 移除函數(shù)以及器件特定的初始化和驅(qū)動程序結(jié)構(gòu)與描述符初始化物理器件/ 解除器件初始化。
3)使用器件寄存器讀/ 寫函數(shù)訪問器件存儲器映射或寄存器詳細信息,例如adxxxx_read_register() 或adxxxx_write_register()。
3 no-OS驅(qū)動程序代碼使用
1)使用器件特定地址、位掩碼、參數(shù)配置枚舉和結(jié)構(gòu)
如前所述,adxxxx.h 頭文件包含所有器件特定枚舉和結(jié)構(gòu)的聲明,這些枚舉和結(jié)構(gòu)被傳遞到器件特定的函數(shù)或API 以配置或訪問器件參數(shù)。具體情況如圖3 所示。
圖3 中顯示的adxxxx_config 結(jié)構(gòu)允許用戶選擇多路復(fù)用器通道并為其設(shè)置過采樣率。此結(jié)構(gòu)的成員(afe_mux_channel 和oversampling) 是存在于同一頭文件中的枚舉,其包含這兩個字段的所有可能值的數(shù)字常量,用戶可以選擇。
adxxxx.c 文件中定義的adxxxx_set_adc_config() 函數(shù)通過配置結(jié)構(gòu)獲取用戶傳遞的配置/ 參數(shù),并進一步調(diào)用adxxxx_spi_reg_write() 函數(shù),通過數(shù)字接口(在上例中是SPI)將數(shù)據(jù)寫入ADXXXX_REG_CONFIG器件寄存器。
2)使用no-OS 驅(qū)動程序結(jié)構(gòu)和初始化函數(shù)初始化器件
圖4 器件初始化和驅(qū)動程序結(jié)構(gòu)的聲明
除了器件配置枚舉和結(jié)構(gòu)之外,no-OS 驅(qū)動程序還提供以下兩個結(jié)構(gòu):器件初始化結(jié)構(gòu)和設(shè)備驅(qū)動程序結(jié)構(gòu)。器件初始化結(jié)構(gòu)允許用戶在用戶應(yīng)用程序代碼中定義器件特定的參數(shù)和配置。初始化結(jié)構(gòu)包含其他器件特定的參數(shù)結(jié)構(gòu)和枚舉的成員。圖5 顯示了器件初始化結(jié)構(gòu)的定義。
器件驅(qū)動程序結(jié)構(gòu)通過器件初始化函數(shù)adxxxx_init() 加載器件初始化參數(shù)。器件驅(qū)動程序結(jié)構(gòu)是在運行時(動態(tài))從堆空間中分配內(nèi)存。器件驅(qū)動程序結(jié)構(gòu)和器件初始化結(jié)構(gòu)中聲明的參數(shù)幾乎完全相同。器件驅(qū)動程序結(jié)構(gòu)是器件初始化結(jié)構(gòu)的運行時版本。
以下步驟說明典型的器件初始化函數(shù)和初始化流程。
第1 步:在應(yīng)用程序中創(chuàng)建器件初始化結(jié)構(gòu)的定義(或?qū)嵗ɡ鐂truct adxxxx_init_params),以初始化用戶特定的器件參數(shù)和平臺相關(guān)的驅(qū)動程序參數(shù)。參數(shù)在編譯期間定義。
注意:初始化結(jié)構(gòu)中定義的參數(shù)因器件而異。
第2 步:在應(yīng)用程序代碼中創(chuàng)建器件驅(qū)動程序結(jié)構(gòu)的指針實例(變量)。
用戶應(yīng)用程序需要創(chuàng)建器件驅(qū)動程序結(jié)構(gòu)的單個指針實例。將此實例傳遞給所有no-OS 驅(qū)動程序API / 函數(shù)以訪問器件特定參數(shù)。應(yīng)用程序代碼中定義的此指針實例指向堆中動態(tài)分配的內(nèi)存,這是通過no-OS 驅(qū)動程序中定義的器件初始化函數(shù)(如adxxxx_init())完成的。
第3 步:調(diào)用器件初始化函數(shù)以初始化器件和其他平臺特定的外設(shè)。
no-OS 驅(qū)動程序中定義的adxxxx_init() 函數(shù)用adxxx_init_param結(jié)構(gòu)傳遞的用戶特定參數(shù)初始化器件。器件驅(qū)動程序結(jié)構(gòu)的指針實例和器件初始化結(jié)構(gòu)的實例作為兩個參數(shù)傳遞給此初始化函數(shù)。用戶應(yīng)用程序代碼可以多次調(diào)用adxxxx_init() 函數(shù),只要調(diào)用初始化函數(shù)之后再調(diào)用器件移除函數(shù)來平衡。
3)通過器件寄存器讀/ 寫函數(shù)訪問存儲器映射(寄存器內(nèi)容)
用戶可以通過no-OS 驅(qū)動程序器件特定的adxxx_read/write() 函數(shù)訪問器件寄存器內(nèi)容(例如產(chǎn)品ID、暫存區(qū)值、OSR 等),如圖6 所示。
大多數(shù)情況下,用戶不會直接使用寄存器訪問函數(shù)。器件特定的函數(shù)通過這些寄存器訪問函數(shù)(如adxxxx_spi_reg_read/write())來調(diào)用。如果可能,建議使用器件配置和狀態(tài)API 來訪問器件存儲器映射,而不要使用直接寄存器訪問函數(shù),因為這樣能確保器件驅(qū)動程序結(jié)構(gòu)與器件中的配置保持同步。
4 平臺驅(qū)動程序
平臺驅(qū)動程序是包裝平臺特定API 的硬件抽象層(HAL) 之一。它們由no-OS 器件驅(qū)動程序或用戶應(yīng)用程序代碼調(diào)用,使后者可以獨立于底層硬件和軟件平臺。平臺驅(qū)動程序包裝了平臺特定的低級硬件功能,例如SPI / I2C 初始化和讀/ 寫、GPIO 初始化和讀/ 寫、UART(Universal Asynchronous Receiver/Transmitter,通用異步收發(fā)傳輸器) 初始化和接收/ 發(fā)送、用戶特定的延遲、中斷等。
圖5 用戶應(yīng)用程序中的器件初始化結(jié)構(gòu)定義
圖6 訪問寄存器內(nèi)容
SPI平臺驅(qū)動程序模塊的典型文件結(jié)構(gòu)如圖7所示。
圖7 SPI平臺驅(qū)動程序代碼結(jié)構(gòu)
5 使用平臺驅(qū)動程序
平臺驅(qū)動程序代碼通常包含在以C/C++ 編程語言編寫的三個源文件中。
1)spi.h:這是一個與平臺無關(guān)的文件,包含SPI 功能所需的器件結(jié)構(gòu)和枚舉。此頭文件中定義的C 編程接口沒有平臺依賴性。
初始化和器件結(jié)構(gòu)中聲明的所有參數(shù)對任何平臺上的SPI接口都是通用的。器件初始化結(jié)構(gòu)中使用的void *extra 參數(shù)允許用戶傳遞額外的參數(shù),這些參數(shù)可以是所用平臺特定的。SPI 驅(qū)動程序結(jié)構(gòu)和SPI 初始化結(jié)構(gòu)中聲明的參數(shù)幾乎完全相同。SPI 驅(qū)動程序結(jié)構(gòu)是SPI 初始化結(jié)構(gòu)的運行時版本。
2)spi.cpp/.c:此文件包含spi.h 文件中聲明的函數(shù)的實現(xiàn),這些函數(shù)用于初始化特定平臺的SPI 外設(shè)以及讀/ 寫數(shù)據(jù)。廣義的“平臺”是指硬件微控制器(目標器件)和軟件(如RTOS 或Mbed-OS)的組合。此文件依賴于平臺,移植到其他平臺時需要修改。
圖9 詳細說明了Mbed 平臺的SPI 接口,并顯示了如何使用這些接口和器件初始化/驅(qū)動程序結(jié)構(gòu)來初始化SPI 和讀/ 寫數(shù)據(jù)。
圖8 SPI初始化和驅(qū)動程序結(jié)構(gòu)
圖9 SPI API或函數(shù)注意:增加的spi_init()和spi_write_and_read()代碼是節(jié)略代碼,為清楚起見而省略了細節(jié)
圖10 SPI額外的初始化和驅(qū)動程序結(jié)構(gòu)
3)spi_extra.h:此文件包含其他器件結(jié)構(gòu)或枚舉,其特定于給定平臺。它允許用戶應(yīng)用程序代碼提供通用spi.h 文件中未涉及的配置。例如,SPI 引腳可能隨平臺而異,因此可以作為這些平臺特定的額外結(jié)構(gòu)的一部分添加。
6 移植平臺驅(qū)動程序
平臺驅(qū)動程序可以從一個平臺(微控制器)移植到另一個平臺;若要移植,通常需要創(chuàng)建平臺特定的.cpp/.c 和_extra.h 文件。平臺驅(qū)動程序駐留在微控制器單元供應(yīng)商提供的器件特定硬件抽象層(HAL) 之上的一層。
因此,為將平臺驅(qū)動程序從一個平臺移植到另一個平臺,與調(diào)用供應(yīng)商提供的HAL 中存在的函數(shù)或API 相關(guān)的平臺驅(qū)動程序代碼需要做一些細微改動。
圖12 區(qū)分了基于Mbed 的SPI 平臺驅(qū)動程序和ADuCM410 SPI平臺驅(qū)動程序。ADIno-OS 存儲庫和平臺驅(qū)動程序的GitHub 源代碼鏈接可在ADI 公司W(wǎng)iki 和GitHub 頁面上找到。
圖11 Mbed平臺特定的SPI初始化實現(xiàn)
圖12 平臺驅(qū)動程序差異
7 為no-OS驅(qū)動程序做貢獻
ADI no-OS 驅(qū)動程序已開源并托管在GitHub 上。驅(qū)動程序不僅支持精密轉(zhuǎn)換器,也支持許多其他ADI 產(chǎn)品,如加速度計、收發(fā)器、光電器件等。任何熟悉源代碼的人都可以為這些驅(qū)動程序做貢獻,方式是提交變更和創(chuàng)建拉取請求來審核這些變更。
有許多示例項目可以在Linux 和/ 或Windows 環(huán)境中運行。許多示例項目是用硬件描述性語言(HDL) 開發(fā)的,以便在Xilinx、Intel 等公司開發(fā)的FPGA(FieldProgrammable Gate Array,現(xiàn)場可編程門陣列)以及由不同供應(yīng)商開發(fā)的目標處理器上運行。
(本文來源于《電子產(chǎn)品世界》雜志2022年3月期)
評論