以下文章來源于嵌入式系統(tǒng)專家之聲
作者:Clemens Valens(Elektor) 編譯:何靈淵
摘要
Zephyr是一個(gè)針對(duì)資源受限設(shè)備優(yōu)化的小型、可縮放、多體系架構(gòu)實(shí)時(shí)操作系統(tǒng)(RTOS)。Zephyr由Linux基金會(huì)維護(hù)[1],是一個(gè)以構(gòu)建業(yè)界最佳的RTOS為目標(biāo)的開源合作項(xiàng)目。近年來,Zephyr OS在嵌入式開發(fā)中的知名度逐漸增加,新的微控制器和開發(fā)板都支持Zephyr。本文將深入討論Zephyr RTOS的技術(shù)細(xì)節(jié)。
Zephyr有著可縮放性,這讓它能夠?qū)挿旱剡m用于資源限制各不相同的多種設(shè)備。Zephyr模塊化的結(jié)構(gòu)讓開發(fā)者能夠只包括他們需要的組件,從而降低系統(tǒng)尺寸,達(dá)到系統(tǒng)的可縮放性。Zephyr在網(wǎng)站上聲稱可以在內(nèi)存小到8KB,大到GB的系統(tǒng)上運(yùn)行。
1. 寬泛的硬件支持
Zephyr支持眾多體系結(jié)構(gòu),包括Arm、x86、RISC-V、Xtensa、MIPS等,并借由Nios2和MicroBlaze軟核支持FPGA。本文成文時(shí),Zephyr支持超過600種開發(fā)板,包括Arduino UNO R4 Minima、GIGA R1 WiFi和Portenta H7、多種ESP32板、BBC micro:bit的所有版本、樹莓派Pico(甚至是樹莓派4B+)、nRF51和nRF52板、NXP MIMXRT1010-EVK和其家族,以及STM32 Nucleo和Discovery家族。以上我只列舉了在Elektor上常看到的開發(fā)板,還有其他許多Zephyr支持的硬件。
除了包含處理器的開發(fā)板,Zephyr還支持許多附加板(背板),并包括了各類接口和超過150種傳感器的驅(qū)動(dòng)。
2. 多任務(wù)、網(wǎng)絡(luò)和電源管理
作為一款實(shí)時(shí)操作系統(tǒng)(RTOS),Zephyr提供搶占式多任務(wù)調(diào)度、任務(wù)間通信和實(shí)時(shí)時(shí)鐘支持。OS還支持多種網(wǎng)絡(luò)技術(shù)與協(xié)議,例如TCP/IP、藍(lán)牙、IEEE 802.15.4(在Zigbee中使用)、MQTT、NFS與LoRaWAN。網(wǎng)絡(luò)支持加上電源管理功能讓Zephyr適合強(qiáng)調(diào)能源效率的物聯(lián)網(wǎng)(IoT)應(yīng)用和使用電池驅(qū)動(dòng)的設(shè)備。
Zephyr中的一組軟件庫和中間件能夠簡(jiǎn)化常見的任務(wù),像是通信協(xié)議、文件系統(tǒng)和設(shè)備驅(qū)動(dòng)。
Zephyr還針對(duì)安全認(rèn)證設(shè)計(jì),比如ISO 26262,這讓它適用于安全關(guān)鍵應(yīng)用。
3. 受Linux啟發(fā)
Zephyr并不是Linux,但是它借鑒了Linux的概念、技術(shù)和工具。例如Zephyr使用Kconfig配置操作系統(tǒng),硬件的屬性和配置則用設(shè)備樹規(guī)范(Device Tree Specification——DTS)[2]描述。因此,Linux開發(fā)者能快速上手Zephyr編程。
4. 開源
Zephyr使用較為寬松的Apache 2.0許可證,允許商業(yè)和非商業(yè)用途。Zephyr的用戶社區(qū)提供支持和文檔,你也可以加入社區(qū)。
5. 嘗試Zephyr
我一直都想要嘗試Zephyr,但是我對(duì)它的第一印象不太好,所以就一直沒有深入了解。我之前遇到的主要問題(除了順利編譯源代碼以外)是它需要一個(gè)能對(duì)目標(biāo)控制器進(jìn)行編程的連接器,這對(duì)于創(chuàng)客不太友好。多虧了Arduino和其引導(dǎo)程序,我們不再需要特別的編程工具。
5.1 選擇一個(gè)開發(fā)板
自從我上次嘗試Zephyr以來,其發(fā)展日新月異。今天,Zephyr支持超過600種不同的微控制器開發(fā)板,你很可能已經(jīng)擁有幾塊支持Zephyr的開發(fā)板了。閱讀詳細(xì)的支持列表,我發(fā)現(xiàn)我已經(jīng)擁有十幾塊支持Zephyr的開發(fā)板了。
5.2 BBC micro:bit
我嘗試了許多塊開發(fā)板,最后決定在BBC micro:bit上進(jìn)行實(shí)驗(yàn)(見圖1,取決于型號(hào),Zephyr使用目標(biāo)名bbc_microbit或者bbc_microbit_v2)。micro:bit除了很常見以外,它對(duì)Zephyr的支持可能是最好的,所有的外設(shè)都可以使用,而且有樣例代碼。最好的是,編程和調(diào)試都不需要額外的工具。流行的ESP-WROOM-32(Zephyr目標(biāo)名esp32_devkitc_wroom)也是個(gè)很好的選擇,但是調(diào)試需要外部工具。
圖1:迷你的BBC micro:bit開發(fā)板非常適合嘗試Zephyr RTOS。誰能想到了為了讓兒童學(xué)習(xí)MakeCode(一門類似Scratch的圖形語言)的小板子也適合幫助一位專業(yè)嵌入式軟件開發(fā)者熟悉一款工業(yè)級(jí)RTOS呢?
Arduino GIGA R1 WiFi也是一個(gè)不錯(cuò)的備選方案,但是使用Zephyr的時(shí)候會(huì)覆寫它的引導(dǎo)程序。即使之后你可以手動(dòng)恢復(fù),這也會(huì)添加不需要的副作用。
官方說法是Arduino UNO R4 Minima需要SWD(串行線調(diào)試)連接器。許多其他開發(fā)板也需要SWD,包括樹莓派Pico。但是我發(fā)現(xiàn)使用dfu-util(見下文)可以繞過這一要求。和GIGA R1類似,Arduino引導(dǎo)程序會(huì)被覆蓋。
5.3 使用仿真器
如果你沒有合適的開發(fā)板,但是還是非常想要嘗試Zephyr,Zephyr內(nèi)建QEMU仿真器支持(只在Linux和macOS上),讓你可以虛擬地運(yùn)行和測(cè)試應(yīng)用。Antmicro的Renode也能達(dá)到同樣效果,但是我沒有親自嘗試。
5.4 安裝Zephyr
我在運(yùn)行Windows 11的計(jì)算機(jī)上安裝了Zephyr,我沒有嘗試Linux或macOS。在線可以找到詳細(xì)的安裝指南[3],所有步驟都非常清晰,我不需要尋找其他參考資料。按照指南,我使用了虛擬的Python環(huán)境,這意味著需要把創(chuàng)建環(huán)境的命令記下來,因?yàn)槊看伍_始開發(fā)時(shí)都需要用到。如果你使用Windows PowerShell,可以運(yùn)行腳本activate.ps1;命令行中則是activate.bat批處理文件。Windows PowerShell處理編譯器和鏈接器輸出的表現(xiàn)會(huì)更好(圖2)。
圖2:Zephyr的west構(gòu)建工具是針對(duì)命令行終端設(shè)計(jì)的,Windows的cmd.exe雖然也可以運(yùn)行,但它不是一個(gè)終端。Windows PowerShell是一個(gè)終端,更適合運(yùn)行構(gòu)建。
Zephyr包括兩個(gè)部分,OS本身和包含一組MCU工具鏈的軟件開發(fā)套件(SDK)。截至本文成文,有21套不同的工具鏈。
OS和SDK并不需要在同一個(gè)位置安裝,在我的環(huán)境中兩個(gè)總共需要12GB的存儲(chǔ)空間,你可以刪除不需要的工具鏈以節(jié)約空間。
安裝完成后,讓我們測(cè)試安裝是否成功。通過下面的命令構(gòu)建一個(gè)樣例代碼,上傳到開發(fā)板上(將
west build -p always -b
如果你想直接使用上述命令,必須先更改工作路徑。運(yùn)行下面的命令(.venv表示你正在虛擬環(huán)境中):
(.venv)
如果樣例能成功構(gòu)建,運(yùn)行下面的命令將其上傳到開發(fā)板上:
west flash
板上的“默認(rèn)”LED會(huì)以0.5Hz的速率開始閃爍。
前面已經(jīng)提到過,燒錄可能需要額外的編程工具,像是J-Link適配器,或是另一種JTAG/SWD兼容的編程器(圖3)。west程序也必須能夠找到驅(qū)動(dòng)程序(即在搜索路徑中,對(duì)Windows而言是%PATH%),如果不能的話程序會(huì)告知你(但是消息經(jīng)常又長(zhǎng)又難以理解)。
圖3:在許多情況下(不是全部),你都需要一個(gè)JTAG或者SWD編程/調(diào)試工具來進(jìn)行你的Zephyr實(shí)驗(yàn)。
在BBC micro:bit V2上,第一次燒錄的時(shí)候我需要參考標(biāo)準(zhǔn)micro:bit編程步驟將HEX文件手工復(fù)制到板上,之后flash命令就可以順利運(yùn)行了??蓤?zhí)行的zephyr.hex文件在zephyrprojectzephyruildzephyr路徑中。
Arduino板的默認(rèn)flash命令(UNO R4 Minima和GIGA R1 WiFi)需要將dfu-util編程工具加入到搜索路徑中(在啟動(dòng)虛擬環(huán)境之前)。這一工具在Arduino IDE中可以找到,但是具體路徑取決于你的環(huán)境(默認(rèn)為%HOMEPATH%AppDataLocalArduino15packagesarduino oolsdfu-util<最新的Arduino版本>)。開發(fā)板還必須在DFU模式下,按下reset按鍵兩次即可。當(dāng)LED開始“呼吸”時(shí)你就可以燒錄程序了。
5.5 閃燈(Blinky)樣例的兼容性
你也許注意到了,我建議用Arduino UNO R4 Minima開發(fā)板運(yùn)行閃燈樣例,而不是BBC micro:bit,這是因?yàn)楸M管板上有25個(gè)LED(不包括電源指示),它們和閃燈樣例并不兼容。ESP-WROOM-32也有類似問題,但是R4 Minima沒有。
GIGA R1也與樣例兼容,板上的MCU有兩個(gè)核(Cortex M4和M7),Zephyr允許你在構(gòu)建命令中使用arduino_giga_r1_m4或者arduino_giga_r1_m7來選擇其一。構(gòu)建和燒錄閃燈樣例兩次,一次M4,一次M7,你就可以發(fā)現(xiàn)兩個(gè)核互為獨(dú)立。GIGA有RGB LED,閃燈樣例在不同核上會(huì)使用不同的顏色,M4為藍(lán)色,M7為紅色。還可以通過改變閃爍速率(samplesasiclinkysrcmain.c中的SLEEP_TIME_MS)進(jìn)一步區(qū)分兩次運(yùn)行的行為。
5.6 Hello World
對(duì)于缺少用于閃爍的LED的開發(fā)板而言,下面是在串口輸出字符串的hello_world樣例:
west build -p always -b
west flash
這一樣例在BBC micro:bit和ESP-WROOM-32上都可以運(yùn)行。要看到輸出字符串的話,需要在你的計(jì)算機(jī)上運(yùn)行任一串口終端程序。數(shù)據(jù)率一般為115200(115200,n,8,1)。消息只會(huì)輸出一次,如果錯(cuò)過了就需要對(duì)開發(fā)板進(jìn)行重置(圖4)。
圖4:hello_world樣例很簡(jiǎn)短,如果打開串口終端太慢的話就會(huì)錯(cuò)過輸出。
在R4 Minima和GIGA R1上,串口輸出在1號(hào)引腳上,而不是使用Arduino IDE時(shí)的USB-C端口。這是因?yàn)閁SB端口是MCU的外設(shè),而不在一個(gè)單獨(dú)的芯片上。Zephyr是一個(gè)模塊化和可擴(kuò)展的OS,每一個(gè)模塊和外設(shè)都需要被專門啟用。在工程的配置文件中可以啟用外設(shè),我們?cè)诤竺鏁?huì)討論。
對(duì)于沒有內(nèi)建串口到USB轉(zhuǎn)換器的開發(fā)板,你必須找到串口(MCU上有超過一個(gè)端口時(shí),一般為0號(hào)端口)并通過外置的串口到USB轉(zhuǎn)換器連接到你的計(jì)算機(jī)。
6. 進(jìn)階實(shí)驗(yàn)
如果你已經(jīng)能夠在你的開發(fā)板上運(yùn)行閃燈和hello_world樣例,接下來你就可以開始創(chuàng)建你的第一個(gè)應(yīng)用了。如果只有一個(gè)樣例能運(yùn)行,你應(yīng)該調(diào)試另一個(gè)樣例,因?yàn)榻酉聛淼膬?nèi)容很快會(huì)變得復(fù)雜起來。
雖然BBC micro:bit和閃燈樣例不兼容,這并不會(huì)有什么嚴(yán)重的影響,我還是選擇它作為實(shí)驗(yàn)板。Zephyr中還有幾個(gè)針對(duì)它的樣例(在samplesoardsbc_microbit文件夾中),“顯示”(display)樣例比單一LED閃爍樣例要更好。Zephyr只針對(duì)600多種支持的開發(fā)板的不到5%提供了樣例。另外,許多樣例是更加進(jìn)階或者少見的用例。
當(dāng)你針對(duì)BBC micro:bit、ESP-WROOM-32或者其他不兼容的開發(fā)板構(gòu)建閃燈樣例時(shí),編譯會(huì)給出一個(gè)難以理解的錯(cuò)誤。錯(cuò)誤信息想要告訴你,led0是一個(gè)未知的對(duì)象,led0是默認(rèn)的閃燈LED(類似Arduino中的LED_BUILTIN)。micro:bit有著可以連接LED和其他外設(shè)的擴(kuò)展端口,讓我們將其中一個(gè)定義為led0。
在此之前,讓我們復(fù)制一份samples/basic/blinky文件夾作為備份。下面的步驟中我們會(huì)修改samples/basic/blinky中的內(nèi)容。
6.1 設(shè)備樹
為了定義led0,我們需要使用設(shè)備樹。設(shè)備樹由一個(gè)或者更多文本文件定義,其中列出了電路板上或者控制器中的外設(shè)和可用存儲(chǔ)。在Zephyr中,這些文件的后綴名為.dts或.dtsi(i表示include——包含),一個(gè)文件可以包含另一個(gè)文件。處理器.dtsi文件在dts文件夾中,開發(fā)板.dts和.dtsi文件在boards文件夾中,兩個(gè)文件夾內(nèi)容都按照處理器架構(gòu)分類。
你可以使用Visual Studio Code中的DeviceTree插件[4]查看DTS/DTSI文件,這一插件支持語法高亮和查找,增加文件的可讀性(DTS文件的語法類似C語言)。圖5所示的是nRF51822(BBC micro:bit V1的核心)的.dtsi文件的一部分,開發(fā)板的DTS文件包含這一文件。注意到uart0的狀態(tài)是“disabled”(禁用),但是在開發(fā)板的DTS文件中將其覆蓋為“okay”,即可以使用,gpio2和i2c0也是同樣。
圖5:nrf51822.dtsi文件的一部分,從右側(cè)的縮略圖可以看到文件十分長(zhǎng)。
6.2 設(shè)備樹中的I2C總線
圖6所示的是BBC micro:bit的.dts文件的一部分,其中展示了I2C總線的設(shè)備樹。micro:bit的總線上有一個(gè)或兩個(gè)傳感器(根據(jù)不同的V1板種類有所不同),在樹中分別為mma8653fc和lsm303agr(后者中有兩個(gè)傳感器,所以在樹中出現(xiàn)兩次)。前者狀態(tài)為“okay”,后者則為“disabled”,這對(duì)我的初代micro:bit V1開發(fā)板而言是正確的。
圖6:設(shè)備樹的這一部分代表了BBC micro:bit板的I2C總線,而不是處理器;出自bbc_microbit.dts文件。
片段中所示的傳感器與FXOS8700和MMA8653FC兼容,在I2C總線上的地址為0x1d,兩個(gè)被聲明的中斷信號(hào)(int)分別與GPIO引腳27和28相連。該傳感器有一個(gè)代碼樣例供實(shí)驗(yàn)用:
west build -p always -b bbc_microbit samples/sensor/fxos8700
west flash
這個(gè)樣例無法在BBC micro:bit V2上工作,因?yàn)槠湓O(shè)備樹上的傳感器有所不同。
樣例的輸出如圖7所示。
圖7:samples/sensor/fxos8700樣例在BBC micro:bit上的輸出。
6.3 設(shè)備樹的覆蓋
回到前面提到過的led0,設(shè)備樹中沒有提及l(fā)ed0,所以我們需要進(jìn)行添加。我們可以直接在設(shè)備樹文件中添加,但這并不正確,開發(fā)板上并沒有l(wèi)ed0。正確的方法是在設(shè)備樹上添加一個(gè)覆蓋層,已有的設(shè)備樹會(huì)根據(jù)覆蓋文件的內(nèi)容進(jìn)行擴(kuò)展(新的項(xiàng)目)或是覆寫(項(xiàng)目已經(jīng)在樹中存在)。在這里我們需要添加新的項(xiàng)目。
覆蓋文件必須放置在工程文件夾的boards子文件夾中。當(dāng)這一子文件夾存在時(shí),構(gòu)建過程會(huì)在其中搜索名為
圖8:讓BBC micro:bit V1與閃燈樣例兼容的設(shè)備樹覆蓋文件。
6.4 增加一個(gè)閃燈LED
Zephyr針對(duì)LED有一個(gè)特殊的設(shè)備樹關(guān)鍵字leds。當(dāng)創(chuàng)建一個(gè)節(jié)點(diǎn)(分支)時(shí),你可以起任何名字,但是需要將其放置在leds下,這樣才能覆蓋已有的leds節(jié)點(diǎn)。這一新節(jié)點(diǎn)會(huì)被添加到設(shè)備樹的根上,所以在節(jié)點(diǎn)前添加一個(gè)正斜杠“/”,在DT語言中表示根。下一行代表這一分支與Zephyr內(nèi)建的gpio-leds驅(qū)動(dòng)兼容(驅(qū)動(dòng)的接口可以在zephyrincludezephyrdriversled.h中找到)。
6.5 子節(jié)點(diǎn)
接下來是一組LED子節(jié)點(diǎn),因?yàn)槲抑挥幸槐KLED,所以只有一個(gè)子節(jié)點(diǎn)led_0,我將其標(biāo)記為led0。標(biāo)簽(label)是可選的,但是標(biāo)簽讓你可以在設(shè)備樹的其他地方引用這一節(jié)點(diǎn)。另外,應(yīng)用中(開發(fā)者)可以通過標(biāo)簽訪問節(jié)點(diǎn)和節(jié)點(diǎn)的屬性。
一個(gè)子結(jié)點(diǎn)必須指定設(shè)備的屬性,這里的設(shè)備是LED,必需屬性只有GPIO引腳,可選標(biāo)簽可以用于向應(yīng)用提供文檔或是用戶可讀信息,除此之外沒有其他用途。
GPIO引腳我選擇了1,即micro:bit擴(kuò)展連接器上的2號(hào)大孔。如果你使用BBC micro:bit V2的話,在這里使用4(而不是1)。
6.6 創(chuàng)建一個(gè)別稱
接下來這一步是閃燈樣例所必需的:為我們的LED創(chuàng)建led0別稱(alias)。你也許會(huì)覺得為子節(jié)點(diǎn)添加一個(gè)標(biāo)簽就足夠了,但實(shí)際上并非如此。閃燈樣例使用DT_ALIAS宏訪問LED子節(jié)點(diǎn),所以我們必須配合這個(gè)宏。這個(gè)宏需要使用別稱,因此我們?cè)谠O(shè)備樹中添加了aliases塊。如果閃燈樣例使用的是DT_NODELABEL宏,別稱就沒有必要了,因?yàn)檫@個(gè)宏會(huì)直接獲取led0子節(jié)點(diǎn)。標(biāo)簽和別稱同為led0會(huì)有些令人疑惑,這是為了后面能夠更好地解釋。
6.7 Zephyr宏
盡管在C/C++編程中宏的名聲并不好,Zephyr大量使用宏。有許多像DT_ALIAS和DT_NODELABEL這樣的宏幫助應(yīng)用和配置工具從設(shè)備樹提取信息,Zephyr手冊(cè)的“設(shè)備樹API”(“Devicetree API”)章節(jié)有對(duì)它們的介紹。
一個(gè)有趣的發(fā)現(xiàn):許多(也許是全部?)Zephyr宏都要求參數(shù)為小寫字母和數(shù)字,其他符號(hào)都會(huì)被替代為下劃線,這被稱為“小寫字母和下劃線兼容”。舉例來說,如果我將LED子節(jié)點(diǎn)標(biāo)記為L(zhǎng)ED-0(而不是led0),那么傳遞給DT_NODELABEL的參數(shù)將會(huì)成為led_0,即DT_NODELABEL(led_0),這是因?yàn)椤?’不是字母或者數(shù)字,而且字母必須都為小寫。換言之,對(duì)于使用設(shè)備樹宏的應(yīng)用開發(fā)者而言,下劃線就是一個(gè)通配符,led_0可以指led_0、led-0、Led_0、LED-0或者ledé0等等。建議你仔細(xì)閱讀Zephyr的宏文檔。
6.8 你不能犯錯(cuò)誤
注意,如果你在設(shè)備樹上犯了錯(cuò)誤,編譯器會(huì)顯示致命錯(cuò)誤,而并不會(huì)提供有用的信息。
6.9 純凈構(gòu)建
當(dāng)你修改設(shè)備樹時(shí),你很可能會(huì)經(jīng)常需要重新構(gòu)建你的應(yīng)用。為了加快速度,去掉build命令中的“-p always”(p代表pristine——純凈),這樣命令就不會(huì)從頭構(gòu)建所有文件。但是,如果你在逐個(gè)嘗試不同的樣例,你需要保留這個(gè)選項(xiàng),否則你會(huì)看到構(gòu)建文件夾不正確的錯(cuò)誤。
flash命令也會(huì)運(yùn)行最后執(zhí)行的build命令,所以每次你做出更改之后可以直接運(yùn)行flash命令。
6.10 使用設(shè)備驅(qū)動(dòng)
閃燈樣例通過調(diào)用gpio_pin_toggle_dt()函數(shù)改變LED的狀態(tài),該函數(shù)在GPIO驅(qū)動(dòng)中。這一方法當(dāng)然沒有問題,Zephyr還另外有一組LED驅(qū)動(dòng)。使用LED驅(qū)動(dòng)可以讓代碼變得更可讀,還可以提高程序的彈性和可移植性。這是因?yàn)長(zhǎng)ED驅(qū)動(dòng)可以快速替換,應(yīng)用代碼不需改變。Zephyr的可縮放性和模塊化在這里就體現(xiàn)出來了。
6.11 Kconfig的圖形用戶界面
將LED設(shè)備驅(qū)動(dòng)整合到程序中需要幾個(gè)步驟。首先,重新配置工程以包含驅(qū)動(dòng)。工程的配置由Kconfig處理,即在Linux中使用的內(nèi)核構(gòu)建配置系統(tǒng)。有多種方式可以和Kconfig交互,其中一種是通過圖形用戶界面(GUI)。在Zephyr中通過以下命令打開圖形界面:
west build -t guiconfig
GUI需要些時(shí)間才會(huì)打開,你會(huì)看到類似圖9這樣的界面,其中可以看到許多當(dāng)前工程的信息。為了保證Kconfig能夠配合你的工程,在運(yùn)行GUI前先進(jìn)行一次純凈構(gòu)建(-p always選項(xiàng))。
圖9:Kconfig工程配置工具的GUI,其中有許多選項(xiàng)。
6.12 眾多的配置選項(xiàng)
先花一點(diǎn)時(shí)間熟悉Kconfig的配置樹,點(diǎn)擊加號(hào)展開分支,點(diǎn)擊選項(xiàng)進(jìn)行標(biāo)記,在下方的面板中能看到說明??梢钥吹絧rintf()的浮點(diǎn)數(shù)支持是一個(gè)C++語言支持的配置選項(xiàng)。與此類似,還可以在Build and Link Features(構(gòu)建和鏈接功能)中找到編譯器優(yōu)化選項(xiàng)。
配置樹中有許多選項(xiàng),Device Driver(設(shè)備驅(qū)動(dòng))分支下的選項(xiàng)和我們相關(guān)。展開分支,向下滾動(dòng),LED驅(qū)動(dòng)大概是在一半的位置:Light Emitting Diode (LED) Drivers(LED驅(qū)動(dòng)),選中這一選項(xiàng)。選項(xiàng)下的子分支不需要改變,保持默認(rèn)值即可(圖10)。點(diǎn)擊Save(保存)鍵,記下窗口底端顯示的配置文件位置,之后你可以打開這一文件查看內(nèi)容。最后關(guān)閉GUI。
圖10:選擇Light Emitting Diode (LED) Drivers(LED驅(qū)動(dòng)),子分支的值保持默認(rèn)不變。
接下來在構(gòu)建時(shí)就不要使用-p always選項(xiàng)了,否則會(huì)將你前面改變的配置復(fù)原。之后會(huì)介紹如何將選項(xiàng)永久保存。
6.13 使用LED設(shè)備驅(qū)動(dòng)的閃燈樣例
現(xiàn)在我們可以編寫新的閃燈程序了,見圖11。首先包含設(shè)備和LED驅(qū)動(dòng)的頭文件,然后在主函數(shù)中通過DEVICE_DT_GET_ANY宏從設(shè)備樹取得LED設(shè)備的引用。注意到宏的參數(shù)“gpio_leds”是“小寫字母和下劃線兼容”的,對(duì)應(yīng)設(shè)備樹中l(wèi)eds節(jié)點(diǎn)compatible(兼容)屬性的值“gpio-leds”(上文已經(jīng)解釋過)。如果你傳入了錯(cuò)誤的參數(shù),程序無法找到節(jié)點(diǎn),會(huì)輸出“No device with compatible gpio-leds found”(無法找到具有g(shù)pio-leds兼容的設(shè)備)。如果設(shè)備的status屬性被設(shè)為“disabled”,同樣的消息也會(huì)出現(xiàn)。
圖11重新編寫了 Blinky 程序以與 LED 設(shè)備驅(qū)動(dòng)程序一起使用。請(qǐng)注意,該代碼沒有局限在某種開發(fā)板。該程序可以在任何設(shè)備驅(qū)動(dòng)中列出了 gpio_leds(或 GPIO-LED) 設(shè)備樹的開發(fā)板上運(yùn)行。
Zephyr將兼容用作名詞這件事需要花時(shí)間習(xí)慣,上面的錯(cuò)誤信息不意味著沒有兼容的設(shè)備,而是沒有設(shè)備的“兼容”屬性的值為“gpio-leds”(也就是“gpio_leds”,下劃線替代了a到z和0到9以外的字符)。
第二個(gè)檢查驗(yàn)證設(shè)備是否正確地初始化,如果是的話,我們將繼續(xù)。
在無限while()循環(huán)中,代碼通過驅(qū)動(dòng)提供的led_on和led_off命令[6]點(diǎn)亮和熄滅LED,參數(shù)0代表DEVICE_DT_GET_ANY宏找到的第一個(gè)(也是唯一一個(gè))設(shè)備,也就是led0。
6.14 檢查返回值
因?yàn)槲覀兪褂迷O(shè)備驅(qū)動(dòng),而不是在硬件寄存器層直接切換GPIO引腳狀態(tài),所以應(yīng)當(dāng)檢查驅(qū)動(dòng)函數(shù)調(diào)用的返回值,確保沒有發(fā)生錯(cuò)誤。驅(qū)動(dòng)必須提供函數(shù)和回調(diào),也有可選的功能。舉例來說,LED驅(qū)動(dòng)必須實(shí)現(xiàn)led_on和led_off,但是led_blink是可選的。在本實(shí)驗(yàn)中,led_blink未被實(shí)現(xiàn),如果你調(diào)用的話,什么也不會(huì)發(fā)生。這一函數(shù)存在,但是其中沒有內(nèi)容,返回值會(huì)告訴你這一點(diǎn)。一般來講,檢查每個(gè)函數(shù)調(diào)用的返回值是良好的編程習(xí)慣。
通過下面的命令構(gòu)建和上傳程序(注意沒有添加-p always選項(xiàng)):
west build -b bbc_microbit samples/basic/blinky
west flash
6.15 配置工程
當(dāng)LED以0.5HZ的頻率開始閃爍,就說明我們的程序能夠運(yùn)行。這時(shí)我們需要永久保存當(dāng)前的配置,打開閃燈文件夾prj.conf文件,添加下面一行(Kconfig配置文件使用Python語法,不像設(shè)備樹使用C語言語法):
CONFIG_LED=y
為了檢查配置成功,進(jìn)行一次純凈構(gòu)建,并將可執(zhí)行文件上傳到開發(fā)板上。
6.16 調(diào)試
如果你的開發(fā)板允許調(diào)試(比如BBC micro:bit),或者你有合適的調(diào)試工具,運(yùn)行下面的命令進(jìn)行調(diào)試:
west debug
該命令會(huì)啟動(dòng)GDB服務(wù)器,并打開GDB命令行界面(圖12)。你可以在線學(xué)習(xí)如何使用GDB,這一部分不屬于本文的范疇之內(nèi)。
圖12:BBC micro:bit有原生gdb調(diào)試支持,不需要額外的工具。
7. Zephyr與Arduino的對(duì)比
現(xiàn)在你上手了Zephyr,你可能會(huì)想:為什么要使用它?Arduino難道不是更簡(jiǎn)單?Arduino與Zephyr類似,支持許多處理器架構(gòu)和數(shù)百款開發(fā)板。Arduino還有著數(shù)千種驅(qū)動(dòng)和軟件庫,如果一款應(yīng)用或者一個(gè)軟件庫使用Arduino核心API,它可以被快速移植到有著類似外設(shè)的兼容平臺(tái)上。Arduino的軟件也是開源的,所以Zephyr有什么優(yōu)勢(shì)?
Zephyr是作為一款工業(yè)級(jí)、健壯的RTOS設(shè)計(jì)的,支持任務(wù)調(diào)度、內(nèi)存管理和設(shè)備驅(qū)動(dòng)等功能。Zephyr能夠適應(yīng)不同的項(xiàng)目復(fù)雜度,從小型的IoT設(shè)備到復(fù)雜的嵌入式系統(tǒng)。Zephyr提供更大的彈性,但是需要開發(fā)者對(duì)嵌入式開發(fā)有著深入的理解。
Arduino提供一定的實(shí)時(shí)性,但它不是一款RTOS,而是一款強(qiáng)調(diào)簡(jiǎn)潔和易用的單線程應(yīng)用框架。Arduino將許多底層細(xì)節(jié)都進(jìn)行了抽象化,讓它對(duì)初學(xué)者非常友好。對(duì)于更加復(fù)雜的應(yīng)用,Arduino可以在RTOS上使用,例如Mbed OS。將Arduino核心API移植到Zephyr的工作正在進(jìn)行中。
在下一個(gè)項(xiàng)目中是否要使用Zephyr取決于你。至少你應(yīng)該稍微進(jìn)行嘗試,畢竟Zephyr會(huì)為任何一位嵌入式開發(fā)者的簡(jiǎn)歷添彩。
8. 進(jìn)一步的閱讀
本文到這里就結(jié)束了,你應(yīng)該已經(jīng)發(fā)現(xiàn)Zephyr OS很復(fù)雜,學(xué)習(xí)曲線也比較陡峭。我希望本文讓你的學(xué)習(xí)過程變得簡(jiǎn)單了一些,但這些只是基礎(chǔ)知識(shí),關(guān)于Zephyr還有非常多需要學(xué)習(xí)的課題。參考資料[8]和[9]包含一些我認(rèn)為有用的內(nèi)容。
-
微控制器
+關(guān)注
關(guān)注
48文章
7424瀏覽量
150797 -
嵌入式
+關(guān)注
關(guān)注
5056文章
18957瀏覽量
301688 -
Linux
+關(guān)注
關(guān)注
87文章
11196瀏覽量
208674 -
RTOS
+關(guān)注
關(guān)注
21文章
809瀏覽量
119349 -
Zephyr
+關(guān)注
關(guān)注
0文章
17瀏覽量
5946
原文標(biāo)題:Zephyr RTOS入門 —— 復(fù)雜但是強(qiáng)大
文章出處:【微信號(hào):麥克泰技術(shù),微信公眾號(hào):麥克泰技術(shù)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論