当前位置: 首页 > news >正文

在keil 中使用__attribute__关键字实现静态加载

实现各个线程或者各个模块自动初始化加载,避免在main中手动调用各种init()函数,各个模块间可实现高度解藕

点击查看代码
/* 宏定义如下 */#define SECTION_DEF(_level)             __attribute__((used,__section__("LoadSection_"_level)))
#define SysLoad_Peripher1(func)         const SysLoad_Init_t SysLoad_Peripher1_##func SECTION_DEF("Peripher_1") = {func}
#define SysLoad_Peripher2(func)         const SysLoad_Init_t SysLoad_Peripher2_##func SECTION_DEF("Peripher_2") = {func}
#define SysLoad_Peripher3(func)         const SysLoad_Init_t SysLoad_Peripher3_##func SECTION_DEF("Peripher_3") = {func}
#define SysLoad_APP(init, app, tcb)     const SysLoad_App_t SysLoad_APP_##app SECTION_DEF("APP_1") = {init, app, {0, NULL, 56}}/* 调用代码如下 */
void    perFunc1(void)
{printk(DBG_LEVEL_INFO, "fnc1\r\n");return;
}
void    perFunc2(void)
{printk(DBG_LEVEL_INFO, "fnc2\r\n");return;
}
void    perFunc3(void)
{printk(DBG_LEVEL_INFO, "fnc3\r\n");return;
}SysLoad_Peripher3(perFunc2);
SysLoad_Peripher3(perFunc3);
SysLoad_Peripher3(perFunc1);SysLoad_Peripher2(perFunc2);
SysLoad_Peripher2(perFunc3);
SysLoad_Peripher2(perFunc1);SysLoad_Peripher1(perFunc2);
SysLoad_Peripher1(perFunc3);
SysLoad_Peripher1(perFunc1);

编译后的.map文件中可发现编译器分配各段地址时是以段的字符来排序的.同一段内的数据是以数据定义的顺序来分配。如下:

点击查看代码
LoadSection_Peripher_1$$Base             0x00006ad8   Number         0  main.o(LoadSection_Peripher_1)SysLoad_Peripher1_perFunc2               0x00006ad8   Data           4  main.o(LoadSection_Peripher_1)SysLoad_Peripher1_perFunc3               0x00006adc   Data           4  main.o(LoadSection_Peripher_1)SysLoad_Peripher1_perFunc1               0x00006ae0   Data           4  main.o(LoadSection_Peripher_1)LoadSection_Peripher_1$$Limit            0x00006ae4   Number         0  main.o(LoadSection_Peripher_1)LoadSection_Peripher_2$$Base             0x00006ae4   Number         0  main.o(LoadSection_Peripher_2)SysLoad_Peripher2_perFunc2               0x00006ae4   Data           4  main.o(LoadSection_Peripher_2)SysLoad_Peripher2_perFunc3               0x00006ae8   Data           4  main.o(LoadSection_Peripher_2)SysLoad_Peripher2_perFunc1               0x00006aec   Data           4  main.o(LoadSection_Peripher_2)LoadSection_Peripher_2$$Limit            0x00006af0   Number         0  main.o(LoadSection_Peripher_2)LoadSection_Peripher_3$$Base             0x00006af0   Number         0  main.o(LoadSection_Peripher_3)SysLoad_Peripher3_perFunc2               0x00006af0   Data           4  main.o(LoadSection_Peripher_3)SysLoad_Peripher3_perFunc3               0x00006af4   Data           4  main.o(LoadSection_Peripher_3)SysLoad_Peripher3_perFunc1               0x00006af8   Data           4  main.o(LoadSection_Peripher_3)LoadSection_Peripher_3$$Limit            0x00006afc   Number         0  main.o(LoadSection_Peripher_3)

自动加载或初始化方式如下:

点击查看代码
/* 测试发现如果代码中未定义某个段的话就不能引用连接脚本中的$$Length标识符,编译器会报错。但是可以引用$$Base和$$Limit两个标识符,编译器只会报警忽略两个外部变量。原因不明?? 但是不有关系,只要有$$Base和$$Limit两个变量就可以定位段的位置和长度了 */extern int LoadSection_Peripher_3$$Base;
extern int LoadSection_Peripher_3$$Limit;
//extern int LoadSection_Peripher_3$$Length;extern int LoadSection_Peripher_2$$Base;
extern int LoadSection_Peripher_2$$Limit;
//extern int LoadSection_Peripher_2$$Length;extern int LoadSection_Peripher_1$$Base;
extern int LoadSection_Peripher_1$$Limit;
//extern int LoadSection_Peripher_1$$Length;{SysLoad_Init_t *pt;base = (uint32_t)(&LoadSection_Peripher_1$$Base);limit = (uint32_t)(&LoadSection_Peripher_1$$Limit);length = (limit - base)/sizeof(SysLoad_Init_t);printk(DBG_LEVEL_INFO, "base1=0x%08x, limit1=0x%08x, length1=0x%08x\r\n", base, limit, length);pt = (SysLoad_Init_t *)base;for(uint32_t i= 0; i < length; i++){pt->init();pt++;}}
打印结果如下:
点击查看代码
INFO:base1=0x00006a84, limit1=0x00006a90, length1=0x00000003
INFO:fnc2
INFO:fnc3
INFO:fnc1
http://www.zskr.cn/news/75034.html

相关文章:

  • FOXWELL NT809BT OBD2 BiDirectional Scan Tool: All Systems Diagnostics + 30+ Resets for EU/US Cars
  • obsidian dataviewjs查找冗余文件
  • 2025最新深圳餐饮食材配送服务商/厂家TOP5推荐!全品类供应+一体化服务权威榜单发布,赋能餐饮企业降本增效新生态
  • 树基础
  • 12.6笔记
  • 完整教程:新手做网站如何被百度快速收录教程
  • smartbits是啥
  • vxe-gantt 甘特图实现产品进度列表,自定义任务条样式和提示信息
  • Linux内核学习记录
  • ret2libc+一点点保护
  • 详细介绍:【数据库】国产数据库替代实战:金仓KES如何以“智能运维 + 低资源占用”年省百万运维成本?
  • 2025年广东地区湘菜供应链江西小炒社区厨房称重自选食材配送服务商TOP5评测!全品类供应+定制化服务权威榜单发布,赋能餐饮高效运营
  • 『NAS』在群晖部署一款好看的白板工具-Excalidraw
  • Ubuntu下,MySQL密码遗失时修改密码
  • 2025最新贵州伴手礼厂家/采购渠道/供应商/平台/卖场/超市TOP5推荐!地道风物+文化赋能权威榜单发布,甄选贵礼传递黔地心意
  • 001.makdown快速入门
  • Oracel VirtualBox安装Windows11时无法找到ISO文件或不满足系统要求
  • 构建个人知识库新选择:深度解析访答本地私有知识库
  • AIShareTxt入门:快速准确高效的为金融决策智能体提供股票实用的技术指标上下文
  • I know only one topic but I wear glasses in 20s
  • 云原生基石的试金石:基于 openEuler 部署 Docker 与 Nginx 的全景实录 - 指南
  • qemu如何和宿主机共享文件 - show
  • 2025贵州贵阳荣和酒坊采购渠道推荐!百年传承酱香白酒购买平台TOP5榜单发布,品味历史沉淀的醇香佳酿
  • UE5循环播放蒙太奇
  • 完整教程:神经网络—— 学习与感知器
  • 智能座舱
  • 团体设计天梯赛L1题解
  • 完整教程:乡镇外卖跑腿小程序开发实战:基于PHP的乡镇同城O2O
  • 关于博客后续
  • 2025.12.6博客