摘要
本應(yīng)用筆記描述了在 Windows 平臺(tái)使用 QEMU 運(yùn)行 RT-Thread 動(dòng)態(tài)模塊。
本文的目的和結(jié)構(gòu)
本文的目的和背景
RT-Thread 動(dòng)態(tài)模塊組件dlmodule提供了動(dòng)態(tài)加載程序模塊的機(jī)制。dlmodule 組件更多的是一個(gè) ELF 格式加載器,把單獨(dú)編譯的一個(gè) elf 文件的代碼段,數(shù)據(jù)段加載到內(nèi)存中,并對(duì)其中的符號(hào)進(jìn)行解析,綁定到內(nèi)核導(dǎo)出的 API 地址上。動(dòng)態(tài)模塊 elf 文件主要放置于 RT-Thread 下的文件系統(tǒng)上。
RT-Thread 的動(dòng)態(tài)模塊組件目前支持兩種格式:
.mo則是編譯出來(lái)時(shí)以.mo做為后綴名的可執(zhí)行動(dòng)態(tài)模塊。它可以被加載,并且系統(tǒng)中會(huì)自動(dòng)創(chuàng)建一個(gè)主線程執(zhí)行這個(gè)動(dòng)態(tài)模塊中的main函數(shù);同時(shí)這個(gè)main(int argc, char** argv)函數(shù)也可以接受命令行上的參數(shù)。
.so則是編譯出來(lái)時(shí)以.so做為后綴名的動(dòng)態(tài)庫(kù)。它可以被加載,并駐留在內(nèi)存中,并提供一些函數(shù)集由其他程序(內(nèi)核里的代碼或動(dòng)態(tài)模塊)來(lái)使用。
本文主要講解了在 Windows 平臺(tái)使用 QEMU 運(yùn)行 RT-Thread 動(dòng)態(tài)模塊。
本文的結(jié)構(gòu)
本文首先講解了如何使能 RT-Thread 動(dòng)態(tài)模塊組件,然后講解了如何基于 QEMU 運(yùn)行動(dòng)態(tài)模塊及動(dòng)態(tài)庫(kù)。
準(zhǔn)備工作
下載 RT-Thread 源碼,推薦下載3.1.0及以上版本。
下載 RT-Thread Env 工具,推薦下載1.0.0及以上版本。
下載 rtthread-apps 源代碼。
下載鏈接:
https://github.com/RT-Thread/rtthread-apps(請(qǐng)復(fù)制至外部瀏覽器打開(kāi))
使能動(dòng)態(tài)模塊組件
配置工程
在 Env 控制臺(tái)切換到 qemu-vexpress-a9 BSP 根目錄,然后輸入menuconfig命令打開(kāi)配置菜單。
進(jìn)入“ RT-Thread Components → POSIX layer and C standard library”菜單,按下圖箭頭所示打開(kāi) libc 和動(dòng)態(tài)模塊的配置選項(xiàng)。
進(jìn)入“RT-Thread Components → Device virtual file system”菜單打開(kāi)文件系統(tǒng)的配置選項(xiàng)。退出 menuconfig 并保存配置。
編譯工程
使用scons命令編譯工程。
運(yùn)行動(dòng)態(tài)模塊命令
編譯完成后使用qemu.bat命令運(yùn)行工程。按 Tab 鍵查看所有命令可以看到動(dòng)態(tài)模塊的兩個(gè)命令list_module和list_symbols,表明動(dòng)態(tài)模塊組件配置成功。
list_module命令可以查看當(dāng)前正在運(yùn)行的動(dòng)態(tài)模塊。
list_symbols命令可以查看動(dòng)態(tài)模塊可以使用的函數(shù)及其對(duì)應(yīng)的內(nèi)存地址。加載動(dòng)態(tài)模塊的時(shí)候會(huì)對(duì)其中的符號(hào)進(jìn)行解析,并綁定到對(duì)應(yīng)的函數(shù)地址上。
生成動(dòng)態(tài)模塊編譯依賴環(huán)境
關(guān)閉運(yùn)行的程序,在 Env 控制臺(tái)使用scons --target=ua -s命令生成編譯動(dòng)態(tài)模塊時(shí)需要包括的內(nèi)核頭文件搜索路徑及全局宏定義。
運(yùn)行動(dòng)態(tài)模塊
運(yùn)行最簡(jiǎn)單的動(dòng)態(tài)模塊
創(chuàng)建動(dòng)態(tài)模塊
獲取示例
下載 RT-Thread 動(dòng)態(tài)模塊工具庫(kù)rtthread-apps,rtthread-apps 的 tools 目錄放置了編譯動(dòng)態(tài)模塊需要使用到的 Python 和 SConscript 腳本。hello 目錄下的 main.c 是一個(gè)簡(jiǎn)單的動(dòng)態(tài)模塊使用示例,源代碼如下所示。
#include
這段代碼實(shí)現(xiàn)了一個(gè)最簡(jiǎn)單的 main 函數(shù),打印字符串“Hello world”。
設(shè)置環(huán)境變量
在 Env 控制臺(tái)切換到 rtthread-apps 根目錄(目錄所在全路徑不包含空格和中文字符),然后通過(guò)下面 2 條命令設(shè)置環(huán)境變量。
set RTT_ROOT=d: epository t-thread,設(shè)置 RTT_ROOT 為 RT-Thread 源代碼根目錄。
set BSP_ROOT=d: epository t-threadspqemu-vexpress-a9,設(shè)置 BSP_ROOT 為 qemu-vexpress-a9 BSP 根目錄。
編譯動(dòng)態(tài)模塊
使用scons --app=hello命令編譯動(dòng)態(tài)模塊。
在 rtthread-apps/hello 目錄下會(huì)生成動(dòng)態(tài)模塊文件 hello.mo。
將動(dòng)態(tài)模塊放入文件系統(tǒng)
編譯好的動(dòng)態(tài)模塊 hello.mo 需要放到文件系統(tǒng)下。qemu-vexpress-a9 BSP 會(huì)使用一個(gè)虛擬的 sd 卡設(shè)備 sd.bin,我們需要把動(dòng)態(tài)模塊放到這個(gè)虛擬的 sd 卡里面。對(duì)于物理設(shè)備來(lái)說(shuō),直接將動(dòng)態(tài)模塊添加到文件系統(tǒng)管理的存儲(chǔ)設(shè)備中就可以。這里需要使用到 Env 工具里面的一個(gè)小工具 fatdisk,它位于 Env 的 tools 目錄下,里面也提供了一份 fatdisk 的使用說(shuō)明。這里使用 fatdisk 用于把 PC 上本地的一個(gè)目錄轉(zhuǎn)換成 sd.bin 映像文件,這個(gè)映像文件是做為一個(gè) fat 文件系統(tǒng)而存在。
新建目錄
在 fatdisk 目錄下新建一個(gè) sd 目錄,并復(fù)制剛剛編譯的動(dòng)態(tài)模塊 hello.mo 文件到 sd 目錄。
修改配置文件
按照下面的配置修改 fatdisk 目錄下的配置文件 fatdisk.xml。
映像文件空間大小 disk_size 配置為了 5120Kbytes(大小可根據(jù)需要配置)。
映像文件的扇區(qū)大小 sector_size 需要配置為 512 KBytes。
要轉(zhuǎn)換目錄名 root_dir 配置為 sd,表示當(dāng)前目錄下的 sd 目錄。
指定生成的映像文件名稱 output 配置為 sd.bin。
strip 需要配置為 0。
生成映像文件
在 Env 控制臺(tái)切換到 fatdisk 根目錄,運(yùn)行fatdisk命令則會(huì)按照配置文件 fatdisk.xml 中的配置,把里面指定的目錄轉(zhuǎn)換成 flash 映像文件。
運(yùn)行成功則會(huì)在 fatdisk 目錄生成一個(gè) sd.bin 文件,大小為 5MB。
生成的映像文件 sd.bin 需要復(fù)制到 qemu-vexpress-a9 BSP 目錄。
運(yùn)行動(dòng)態(tài)模塊
在 Env 控制臺(tái)切換到 qemu-vexpress-a9 BSP 根目錄輸入qemu.bat命令運(yùn)行工程。
系統(tǒng)運(yùn)行起來(lái)后會(huì)看到文件系統(tǒng)初始化成功信息 “file system initialization done!”。
使用ls命令可以看到根目錄下的動(dòng)態(tài)模塊文件hello.mo。
輸入hello命令運(yùn)行動(dòng)態(tài)模塊 hello.mo??梢钥吹絼?dòng)態(tài)模塊main函數(shù)打印的字符串“Hello,world”
使用動(dòng)態(tài)模塊組件運(yùn)行動(dòng)態(tài)模塊的主要原理如下圖所示:
動(dòng)態(tài)模塊的初始化和清理函數(shù)
動(dòng)態(tài)模塊組件提供了2個(gè)擴(kuò)展的函數(shù)供用戶使用,分別是module_init()和module_cleanup()。
module_init()函數(shù)會(huì)在動(dòng)態(tài)模塊運(yùn)行前被執(zhí)行,用戶可以根據(jù)需要做一些初始化工作。
module_cleanup()函數(shù)會(huì)在動(dòng)態(tài)模塊運(yùn)行結(jié)束后在 idle 線程里回調(diào)一次,執(zhí)行用戶設(shè)置的清理工作。
RT-Thread 系統(tǒng)會(huì)自動(dòng)創(chuàng)建一個(gè)線程執(zhí)行動(dòng)態(tài)模塊中的 main 函數(shù),同時(shí)這個(gè)main(int argc, char* argv[])函數(shù)也可以接受命令行上的參數(shù)。這個(gè)線程默認(rèn)的優(yōu)先級(jí)等同空閑線程的優(yōu)先級(jí),線程堆棧默認(rèn)為2048字節(jié)。用戶可以在module_init()函數(shù)里修改這個(gè)線程的優(yōu)先級(jí)和堆棧。
示例代碼
基于前面簡(jiǎn)單的動(dòng)態(tài)模塊示例代碼 main.c 增加module_init()和module_cleanup()函數(shù)的使用,示例代碼如下所示。
#include
示例代碼主要實(shí)現(xiàn)了如下功能:
在動(dòng)態(tài)模塊的初始化函數(shù)里可以設(shè)置這個(gè)線程的優(yōu)先級(jí)和堆棧。
清理函數(shù)簡(jiǎn)單的打印信息。
main 函數(shù)解析命令行參數(shù)并打印出來(lái)。
請(qǐng)參考前面小節(jié)將此示例代碼生成的動(dòng)態(tài)模塊文件放到文件系統(tǒng)里,并將生成的映像文件 sd.bin 復(fù)制到 qemu-vexpress-a9 BSP 目錄。
運(yùn)行結(jié)果
在 Env 控制臺(tái)切換到 qemu-vexpress-a9 BSP 根目錄輸入qemu.bat命令運(yùn)行工程。
系統(tǒng)運(yùn)行起來(lái)后會(huì)看到文件系統(tǒng)初始化成功信息 “file system initialization done!”。
使用ls命令可以看到根目錄下的動(dòng)態(tài)模塊文件hello.mo。
輸入hello this is rt-thread!命令運(yùn)行動(dòng)態(tài)模塊 hello.mo。hello 后面的字符串為參數(shù)。
執(zhí)行到動(dòng)態(tài)模塊初始化函數(shù)module_init時(shí)會(huì)打印字符串 "this is module hello initial function!"。
執(zhí)行動(dòng)態(tài)模塊的 main 函數(shù)時(shí)會(huì)打印字符串 “hello world from RTT::dynamic module!”,命令行參數(shù)也依次打印了出來(lái)。
動(dòng)態(tài)模塊運(yùn)行結(jié)束后又執(zhí)行清理函數(shù)module_cleanup,打印字符串 "this is module hello cleanup function!"。
運(yùn)行動(dòng)態(tài)庫(kù)
創(chuàng)建動(dòng)態(tài)庫(kù)
獲取示例
下載 RT-Thread 動(dòng)態(tài)模塊工具庫(kù)rtthread-apps,rtthread-apps 的 lib 目錄下有一個(gè)簡(jiǎn)單的動(dòng)態(tài)庫(kù)示例的 lib.c,源代碼如下所示,它實(shí)現(xiàn)了 2 個(gè)簡(jiǎn)單的函數(shù)供使用。
#include
編譯動(dòng)態(tài)庫(kù)
編譯動(dòng)態(tài)庫(kù)之前需要先設(shè)置環(huán)境變量。然后使用scons --lib=lib命令編譯動(dòng)態(tài)庫(kù)。
在 rtthread-apps/lib 目錄下會(huì)生成動(dòng)態(tài)庫(kù)文件 lib.so。
請(qǐng)參考前面小節(jié)將動(dòng)態(tài)庫(kù)文件 lib.so 放到文件系統(tǒng)里,并將生成的映像文件 sd.bin 復(fù)制到 qemu-vexpress-a9 BSP 目錄。
運(yùn)行動(dòng)態(tài)庫(kù)
添加示例代碼
將以下示例代碼添加到 qemu-vexpress-a9 BSP applications 目錄下的 main.c 里。
#include
RT-Thread 動(dòng)態(tài)模塊組件也支持 POSIX 標(biāo)準(zhǔn)的 libdl API,此示例代碼調(diào)用 libdl API 運(yùn)行動(dòng)態(tài)庫(kù)。示例代碼首先根據(jù)動(dòng)態(tài)庫(kù)的路徑打開(kāi)動(dòng)態(tài)庫(kù)文件 lib.so,然后獲取動(dòng)態(tài)庫(kù)的 lib_func() 函數(shù)的地址并運(yùn)行此函數(shù)。之后獲取動(dòng)態(tài)庫(kù)的 add_func() 函數(shù)的地址,并傳入?yún)?shù) 3 和 4 運(yùn)行函數(shù)計(jì)算結(jié)果。最后關(guān)閉動(dòng)態(tài)庫(kù)。
運(yùn)行動(dòng)態(tài)庫(kù)
在 Env 控制臺(tái)切換到 qemu-vexpress-a9 BSP 根目錄,輸入scons命令重新編譯工程。編譯完成后輸入qemu.bat命令運(yùn)行工程。按 Tab 鍵可以看到新增的示例代碼命令dlmodule_Sample。
使用ls命令可以看到根目錄下的動(dòng)態(tài)庫(kù)文件 lib.so,輸入dlmodule_sample命令就可以運(yùn)行動(dòng)態(tài)庫(kù)示例代碼。
第一行運(yùn)行了 lib_func() 函數(shù)打印了字符串 “hello world from RTT::dynamic library!”
第二行運(yùn)行了 add_func() 函數(shù)計(jì)算了 3+4 并打印了相加結(jié)果 7。
-
WINDOWS
+關(guān)注
關(guān)注
4文章
3547瀏覽量
88768 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4332瀏覽量
62666
原文標(biāo)題:一文解析使用QEMU運(yùn)行RT-Thread動(dòng)態(tài)模塊(干貨分享)
文章出處:【微信號(hào):elecfans,微信公眾號(hào):電子發(fā)燒友網(wǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論