|
最近看到好多嵌入式操作系统都具有动态加载的相关功能,如Threadx和RT-Thread的moudle功能,但这些功能都与自身系统耦合很严重,大部分都要依赖于自己的工具链。考虑到MDK5使用的人最多,因此决定采用MDK5的相关工具链实现一个方便移植的动态加载实现。本程序中elf文件解析部分参照了RT-Thread的Moudle实现。实现过程中查阅了很多的资料,中间也遇到了蛮多的问题,索性最后都解决了 。非常感谢硬汉大哥的文档教程,在里面学到了很多东西,本帖也算是我对论坛的一点点回馈,希望能帮助到有需要的人,相关代码与工程我都会放到附件中,供大家参考。
1.什么是动态加载?
按照程序的加载方式进行分类,可以分为静态加载和动态加载。静态加载是指所以程序代码都在编译期予以确定,所有程序都需要存储在ROM中,程序尺寸受限于flash的尺寸,运行速度较快,无需预加载。动态加载是在编译期间,依靠函数或者其他手段,从其他的存储介质中将程序加载ram中运行,与静态加载相比更加灵活,可以很方便的进行程序升级,可以把暂时不需要使用的库释放掉,在需要使用的时候在将其加载到内存中,程序尺寸可以做的很大,可以很方便的实现APP程序。
2.程序功能介绍
本程序实现的是在STM32中实现程序的动态加载,使用起来与windows的dll类似。程序使用dl_load_lib加载相应的库文件到句柄中,加载成功后可使用dl_get_func,通过函数名获得相应函数指针,在不需要使用时可使用dl_destroy_lib对句柄进行释放。
3.程序使用平台介绍
本程序使用软件平台位MDK5的V6编译器,语法标准采用C99,移植了FATFS作为文件系统,使用楼主自己编写的内存管理函数进行动态内存的管理,硬件平台位STM32H743。
相关帖子:论坛首发,内存管理算法,支持malloc,realloc,align_alloc,配有内存碎片合并算法(v1.2)
https://www.armbbs.cn/forum.php? ... 6&fromuid=24016
(出处: 硬汉嵌入式论坛)
4.实现原理简介
实现STM32动态加载的问题主要有以下几个:
问题1:被动态加载的APP程序中,程序的基地址是伴随着动态内存变化的,这样就会产生重定位问题,APP中定义数据的地址也会随着程序基地址的改变而改变,如何将这种改变正确的传入到APP程序中?
解决方案:在我们编程时,编译输出的文件都有一种共同的文件格式:elf文件格式,elf文件格式有很多,其中有的elf文件中,携带了便于实现动态加载的相关信息,可以将重定位操作对代码的影响位置与影响方式以表格的形式表示,Windows,Linux也都是使用这种elf文件实现程序动态加载的。通过对这种特殊的elf文件进行解析,即可实现APP代码的相关数据的重定位。
问题2:如何生成这样特殊的elf文件呢?
解决方案:本程序使用的MDK5的V6编译器,利用了armlink中的BPABI中basic_platform特性,实现了这种特殊的elf文件生成。
问题3:主体程序是通过什么方式调用APP程序呢?
解决方案:主程序调用APP的程序有两种方法,第一种是直接通过APP的程序入口点进行调用,用于简单调用的情况,每个APP程序的程序入口点为APP程序中的dl_main函数,可以直接通过主体函数dl_get_entry获得APP程序入口点dl_main的函数指针,进而进行调用。第二种是通过函数名进行调用,使用dl_get_func,以函数名的方式在动态链接表中寻找对应的函数指针,进而进行调用。注意:当且仅当APP中定义的函数被DLL_EXPORT修饰时,此函数名才会出现在动态链接表中,才能被主题程序调用。
问题4:APP程序如何调用主体程序的部分函数?
解决方案:在主体程序与APP程序间,约定一个固定地址的程序向量表,主体程序把相关函数指针填入到向量表中,APP程序通过查表获取主体程序的函数指针,进而进行调用。
5.程序源码相关文件介绍
主体程序包含头文件dl_lib.h,.c文件全部加入到工程中即可使用。APP程序编写可以参照附件中的模板工程(源码有点多,有需要在介绍)
APP_Elf_Generate.zip
(21.54 KB, 下载次数: 420)
HOST_Elf_parsing.zip
(12.81 KB, 下载次数: 398)
|
评分
-
查看全部评分
|