0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

在Windows平台使用QEMU运行RT-Thread动态模块

lPCU_elecfans 来源:未知 作者:李倩 2018-10-13 10:12 次阅读

摘要

本应用笔记描述了在 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 int main(int argc, char *argv[]) { printf("Hello, world "); return 0; }

这段代码实现了一个最简单的 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。

5120 512 sd sd.bin 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 #include /* 动态模块的初始化函数 */ void module_init(struct rt_dlmodule *module) { module->priority = 8; module->stack_size = 4096; printf("this is module %s initial function! ",module->parent.name); } /* 动态模块的清理函数 */ void module_cleanup(struct rt_dlmodule *module) { printf("this is module %s cleanup function! ",module->parent.name); } int main(int argc, char *argv[]) { int i; printf("hello world from RTT::dynamic module! "); /* 打印命令行参数 */ for(i = 0;i < argc;i ++)    {        printf("argv[%d]:%s ",i,argv[i]);    }    return 0; }

示例代码主要实现了如下功能:

在动态模块的初始化函数里可以设置这个线程的优先级和堆栈。

清理函数简单的打印信息。

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 int lib_func(void) { printf("hello world from RTT::dynamic library! "); return 0; } int add_func(int a, int b) { return (a + b); }

编译动态库

编译动态库之前需要先设置环境变量。然后使用scons --lib=lib命令编译动态库。

在 rtthread-apps/lib 目录下会生成动态库文件 lib.so。

请参考前面小节将动态库文件 lib.so 放到文件系统里,并将生成的映像文件 sd.bin 复制到 qemu-vexpress-a9 BSP 目录。

运行动态库

添加示例代码

将以下示例代码添加到 qemu-vexpress-a9 BSP applications 目录下的 main.c 里。

#include #include #include /* 动态库文件路径 */ #define APP_PATH "/lib.so" /* 函数指针类型 */ typedef int (*add_func_t)(int, int); typedef void (*lib_func_t)(void); int dlmodule_sample(void) { void* handle; lib_func_t lib_function; add_func_t add_function; /* 以RTLD_LAZY模式打开动态库文件,并获取动态库操作句柄 */ handle = dlopen(APP_PATH,RTLD_LAZY); if(!handle) { printf("dlopen %s failed! ",APP_PATH); return -1; } /* 根据动态库操作句柄handle,返回动态库函数lib_func()对应的地址 */ lib_function = (lib_func_t)dlsym(handle,"lib_func"); if(!lib_function) { printf("dlsym %p failed! ",handle); return -1; } /* 运行动态库函数 */ lib_function(); /* 根据动态库操作句柄handle,返回动态库函数add_func()对应的地址 */ add_function = (add_func_t)dlsym(handle,"add_func"); if(!add_function) { printf("dlsym %p failed! ",handle); return -1; } /* 运行动态库函数计算 3+4 并打印结果 */ printf("add_function result is:%d ",add_function(3,4)); /* 运行完毕根据操作句柄handle关闭动态库 */ dlclose(handle); return 0; } MSH_CMD_EXPORT(dlmodule_sample, dlmodule sample); int main(void) { printf("hello rt-thread! "); return 0; }

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

    浏览量

    88623
  • 函数
    +关注

    关注

    3

    文章

    4327

    浏览量

    62569

原文标题:一文解析使用QEMU运行RT-Thread动态模块(干货分享)

文章出处:【微信号:elecfans,微信公众号:电子发烧友网】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    RT-Thread学习笔记】如何优雅地退出QEMU模拟器?

    RT-Thread学习笔记】如何优雅地退出QEMU模拟器?我想重新编译源码,再次运行新的代码,怎么办呢?如何才能退出这个QEMU命令行控制台?
    的头像 发表于 07-26 04:06 5941次阅读
    【<b class='flag-5'>RT-Thread</b>学习笔记】如何优雅地退出<b class='flag-5'>QEMU</b>模拟器?

    如何在windows和linux平台使用RT-Thread QEMU BSP,并运行RT-ThreadGUI示例

    开发板的情况下体验RT-ThreadRT-Thread使用QEMU模拟了ARM vexpress A9开发板,并提供了相关的板级支持包(BSP)。本文主要介绍
    的头像 发表于 02-08 08:50 1.4w次阅读
    如何在<b class='flag-5'>windows</b>和linux<b class='flag-5'>平台</b>使用<b class='flag-5'>RT-Thread</b> <b class='flag-5'>QEMU</b> BSP,并<b class='flag-5'>运行</b><b class='flag-5'>RT</b>-ThreadGUI示例

    如何在Ubuntu平台使用QEMU运行RT-Threadqemu-vexpress-a9BSP工程?

    本文描述了如何在 Ubuntu 平台使用 QEMU 运行 RT-Thread qemu-vexpress-a9 BSP 工程。
    发表于 03-30 07:40

    如何使用QEMU运行RT-Thread动态模块组件?

    本文描述了 Windows 平台使用 QEMU 运行 RT-Thread
    发表于 03-30 07:40

    怎么使用Eclipse开发RT-Thread

    Windows 平台使用 Eclipse 开发 RT-Thread qemu-vexpress-a9 BSP 工程的时候怎么使用 Ecl
    发表于 04-02 07:48

    Windows上使用VS Code开发RT-Thread qemu-vexpress-a9 BSP工程

    了。本文描述了 Windows 平台使用 VS Code 开发 RT-Thread qemu-vexpress-a9 BSP 工程。
    发表于 03-31 18:07

    Ubuntu平台开发RT-Thread文档中步骤搭建QEMU环境

    NimBLE 可在 QEMU 环境下搭配蓝牙 Control 芯片运行,目前 Ubuntu 18.04 下运行成功。QEMU 环境搭建主要
    发表于 07-27 11:19

    如何在Window及Ubuntu平台使用QEMU运行 RT-Thread qemu-vexpress-a9 BSP工程

    体验 RT-ThreadRT-Thread 提供了 QEMU 模拟的 ARM vexpress A9 开发板的板级支持包 (BSP)。本文主要介绍 Window
    发表于 10-26 15:19

    Windows平台使用VSCode调试 RT-Thread qemu-vexpress-a9 BSP工程

    摘要本应用笔记描述了 Windows 平台使用 VS Code 调试 RT-Thread qemu-vexpress-a9 BSP 工程。
    发表于 10-26 15:25

    Windows平台使用Eclipse调试RT-Thread qemu-vexpress-a9 BSP工程

    \\qemu-vexpress-a9 切换到 RT-Thread 源码文件夹下的 qemu-vexpress-a9 BSP 根目录,然后输入 scons 命令编译工程,如果编译正确无误,会在 BSP 目录下生成
    发表于 10-26 15:31

    RT-Thread BSP qemu-virt64-aarch64文件系统

      前言   前面大体上搭建了 RT-Thread BSP qemu-virt64-aarch64 的交叉编译环境,运行后发现,文件系统没有挂载上,感觉是没有 mkfs。   通过RT-Thr
    发表于 05-16 10:29

    RT-Thread软件包定义和使用

    RT-Thread软件包是运行RT-Thread物联网操作系统平台上,面向不同应用领域的通用软件组件 。RT-Thread 同时提供了开放
    的头像 发表于 05-21 11:29 1w次阅读
    <b class='flag-5'>RT-Thread</b>软件包定义和使用

    RT-Thread开源作品秀】基于RT-Thread的星务平台研究

    本作品为了验证星务软件RT-Thread系统运行的可行性,底层是否能够驱动星务软件,同时扩展RT-Thread应用范围。ART-Pi作为卫星下位机,...
    发表于 01-25 18:26 6次下载
    【<b class='flag-5'>RT-Thread</b>开源作品秀】基于<b class='flag-5'>RT-Thread</b>的星务<b class='flag-5'>平台</b>研究

    RT-Thread qemu mps2-an385 bsp移植制作 :环境搭建篇

    最近打算系统地研究一下 RT-Thread,包括 RT-Thread BSP 的移植,由于一直使用 QEMU 进行一些软件功能的验证,qemu
    的头像 发表于 08-02 14:45 619次阅读
    <b class='flag-5'>RT-Thread</b> <b class='flag-5'>qemu</b> mps2-an385 bsp移植制作 :环境搭建篇

    QEMU系列】不用开发板运行RT-Thread指南-ARM架构

    成为一个门槛。本文将详细介绍如何在QEMU虚拟机的Vexpress-A9平台运行RT-Thread,帮助开发者没有实际硬件开发板的情况下
    的头像 发表于 08-09 08:35 905次阅读
    【<b class='flag-5'>QEMU</b>系列】不用开发板<b class='flag-5'>运行</b><b class='flag-5'>RT-Thread</b>指南-ARM架构