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