前言

我们都听说过 静态库和动态库 , 静态库大家都应该比较清楚,在单片机开发的时候,也经常用到。

动态库在 windows 和 linux 下很常见,例如: Windows中的dll,Linux中的so,可以将代码动态地从其他的存储介质,动态加载到RAM中

而动态库在单片机领域就很少见了

第一种动态库方案

参考链接 : https://whycan.com/t_8607.html

最近尝试了一下wifi/bt soc上,动态加载用户应用的方式。又学到很多没用的知识。

基本需求

  • 应用需要方便编译,使用比较通用的格式

    elf:还有谁?

  • 应用代码部分最好不占用ram,XIP方式运行

    elf: 呃呃呃,你再说一遍?

  • 用户开发简单,和普通的c一样,甚至可以用其他语言,rust、go等等,反正能编译成elf就行

    elf: smile

  • 支持cortex-m等MCU芯片

    cortex-m: 纳尼

  • 全兼容,基于新版本编译的同样代码,可以在旧版中使用,反过来也一样

elf动态加载、地址无关、cortex-m

  • gcc编译器使用-fPIC,产生的是got-based position independency。

    科普:GOT,Global Offset Table,说白了就是一个存放变量和函数的地址数组,在ram中,用户可以在GOT里实现重定位
    优点:随便乱来,反正地址都是loader决定
    缺点:arm-none-eabi-gcc有BUG,产生基于R9寄存器的GOT代码的时候,PLT(不用明白,反正就是一些代码,用于调用一些内/外部函数等等)里的代码访问GOT还是用PC+偏移,不是用R9寄存器。并且,已知这个BUG好几年前就有,ARM也不会去修复这个BUG。

  • clang/iar编译器使用-fropi -frwpi,mdk估计也是这个,产生的是embedded position independency。

    优点: 简单,R9只是指向data/bss/noinit的整块内存,不需要重定向

    缺点: 由于没有重定向,所以无法访问外部函数,因为没有从定向操作,也不能对外提供API
    workaround: VSF黑科技,自己实现PLT(支持动态库)

最终方案

  • 使用clang编译器编译elf,ARM今后主力支持这个,反正也免费

  • VSF host程序下的配置:

    VSF_USE_LOADER 使能加载器

    VSF_LOADER_USE_ELF 支持elf加载器

    VSF_LINUX_USE_APPLET linux子系统,支持applet(高大上的说法,其实就只是编译出来的elf)

    VSF_LINUX_APPLET_USE_XXXX linux下哪些头文件支持在applet里使用

  • VSF applet下的配置

    直接用vsf.linux仓库下,applet/vsf_usr_cfg.h: https://gitee.com/vsf-linux/vsf.linux/blob/main/applet/vsf_usr_cfg.h

  • applet应用开发

    头文件(包括C库头文件,位于simple_libc下): https://gitee.com/vsfteam/vsf/tree/master/source/shell/sys/linux/include

    直接使用linux的方式开发,如果再linux下可以用,按照applet目录下的编译命令,编译后就可以在vsf里使用。

    使用方法,下载到AIC8800M的内部flash中,然后,vsf的linux里,运行loaderelf 0xXXXXXXXX(flash中的地址)。

上图

第二种动态库方案

https://gitee.com/tutubinary/dynamic_loader