linux 内存 动态加载,Static_Module: 本项目在MCU(STM32)平台实现类似于Linux内核模块的动态加载功能,但不是将模块加载到内存(SRAM)而是加载到Flash。 所以叫做...

Static Module Demo

介绍

本项目在MCU(STM32)平台实现类似于Linux内核模块的动态加载功能,但不是将模块加载到内存(SRAM)而是加载到Flash。

所以叫做静态加载,而被加载的模块就叫静态模块。

软件架构

本演示项目有两个工程,分别是APP工程和Module工程。前者是常规应用工程,是芯片的入口;Module工程类似于静态库,不能单独运行而依赖于APP,但它编译生成的目标文件内所有符号均已链接。两个工程各自单独编译,烧录时也可以分开单独烧录。

软件架构说明

APP和Module的Flash和SRAM空间各自分开并且固定排布,Module空间位于APP空间之后并紧密相连;

APP和Mouule都有常规的中断向量表,并且都位于各自FLASH的起始地址;

APP的中断向量表是芯片的入口,而Module的中断向量表由APP调用;

APP和Module都各自维护一张公开的函数向量表:APP_Vector_t、Module_Vector_t;跨区域的函数调用即是通过函数向量表内的函数指针实现;

Module的Reset_Handler由于不是芯片的入口,所以可以修改其原型;APP在调用Module的Reset_Handler时获取模块的函数向量表并告知APP的函数向量表给模块;此时APP和Module都获取得到对方的函数向量表,两者也就连接起来了。

Module的主要接口

Module由于不是程序主体而只是功能的扩展,所以不能执行带有死循环的函数,也就不能执行Module里的main函数。(本项目的Module工程里没有main函数实现。)

Reset_Handler:位于中断向量表内,依然是Module的入口,但供APP调用;

init:位于函数向量表内,用于执行整体(全局变量、外设等)的初始化;

schedule: 位于函数向量表内,相当于不带死循环的main函数。

Module的Reset_Handler

常规的应用中,芯片复位时其程序入口为Reset_Handler。Reset_Handler要负责初始化C语言运行时环境(主要是DATA段及BSS段内变量的初始化)并调用main函数。

由于Module的Reset_Handler并不是芯片的入口而由APP调用,其实现就是整个架构的关键。本项目Module的Reset_Handler的实现如下:

void Reset_Handler(const APP_Vector_t *app, Module_Vector_t *module)

{

_initialize_data(& _sidata, & _sdata, & _edata);

_initialize_bss(& _sbss, & _ebss);

Module_SetAppVector(app);

Module_GetModuleVector(module);

}

其主要工作有两个:初始化DATA段、BSS段及跟APP交换函数向量表。函数向量表一但确定,跨区域的函数调用就畅通无阻了。

Module的中断处理函数的进入

为了在Module内灵活使用(APP未占用的)外设资源,需要处理Module的中断服务。而Module的中断向量表并不是芯片的入口而由APP调用,那么就需要从APP的中断向量表跳转到Module的中断向量表。

在APP的中断向量表内,未使用的中断服务其实都是Default_Handler的别名(并且都是弱(weak)符号)。而APP未使用的中断有可能会被Module使用;所以只要修改APP的Default_Handler,使其跳转到Module那边就行了。本项目的APP的Default_Handler实现如下:

void __attribute__ ((weak)) Default_Handler(void)

{

typedef void (* IrqHandler_t)(void);

extern unsigned int _eflash; // 来自链接脚本,指向Flash末尾

uint32_t isrNum;

IrqHandler_t *moduleIsrVector;

IrqHandler_t handler;

if(Main_IsModuleLoaded())

{

moduleIsrVector = (IrqHandler_t *) & _eflash;

isrNum = __get_IPSR();

handler = moduleIsrVector[isrNum];

handler();

}

else

{

__DEBUG_BKPT();

while(1);

}

}

其中_eflash定义于链接脚本,其值指向APP的Flash空间的末尾即Module的Flash的起始亦即Module的中断向量表。

Default_Handler的主要工作为:当Module已经载入时,获取当前的中断号并直接跳转到Module的中断服务函数;当Module未载入时,则进行常规处理,进入死循环。

使用说明

本项目基于STM32CubeIDE实现,硬件平台为NUCLEO-F446RE,即MCU为STM32F446RE。在IDE内很容易就可以切换到其他硬件平台。

APP和Module工程都包含一个跟git代码仓库挂钩的版本头文件version.h,这个文件是在编译时自动通过python脚本(version.py)生成的。所以要保证电脑内安装有python解释器才能通过编译。(PS:Linux和Windows 10已内置python)。

参与贡献

Fork 本仓库

新建 Feat_xxx 分支

提交代码

新建 Pull Request

特技

使用 Readme_XXX.md 来支持不同的语言,例如 Readme_en.md, Readme_zh.md

你可以 https://gitee.com/explore 这个地址来了解 Gitee 上的优秀开源项目

GVP 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目

Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 https://gitee.com/gitee-stars/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值