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

Keil MDK 将不同文件中的特定数据链接到同一位置

最近在一个STM32的项目中,为了方便现场调试的抓取一些运行数据,就想在项目中增加类似于 linux 的串口终端,实现一些基本命令行的调试命令。本着开源优先的原则,一通搜索,最终选定了 xcmd 这个开源库。

XCMD 介绍 https://gitee.com/two_salted_eggs/xcmd.git

它有以下几个优点:

  • 移植十分简单
  • 资源占用很小
  • 支持历史记录
  • 支持命令自动补全
  • 支持注册快捷键
  • 支持 xcmd_cmd_register()/xcmd_key_register()方法注册命令或按键
  • 支持 XCMD_EXPORT_CMD()/XCMD_EXPORT_KEY()方法直接导出命令或按键,不需要额外运行注册函数

具体的移植过程看 readme.md 文件即可,参考 example 中的 demo, 不到 20分钟就能把例程在项目上跑起来了。
但是项目提供的 demo 没有启用 ENABLE_XCMD_EXPORT 选项,命令和按键是通过 xcmd_cmd_register()/xcmd_key_register() 在运行时注册。
如下图所示:
image

通过 xcmd_cmd_register()/xcmd_key_register() 注册命令和按键会有额外的RAM开销,如下图所示,每条命令也会有32bytes(32位的MCU)的链表项。
image

而通过 XCMD_EXPORT_CMD()/XCMD_EXPORT_KEY() 导出,则可以将命令和按键以常量表的方式放到 FLASH 中。
image

下面修改例程 “example\stm32\MDK\stm32f4xx” 以说明在 keil mdk 中,启用 ENABLE_XCMD_EXPORT 选项的步骤

  1. 首先打开工程文件 “Project/test.uvprojx”,编译项目,确保能正确编译完成。
    然后将 “Output” 目录下的文件 “test.sct” 复制一份到 “Project” 目录。
    打开工程配置页面(Options for Target),切换到 Linker 页面,去掉 “Use Memory Layout from Taget Dialog” 的选中状态,同时通过 ScatterFile 栏的 “...” 选择刚才复制到 “Project” 目录的 “test.sct” 文件。
    如下图所示:
    image

  2. 点击上图中的 “Edit...” 打开 “test.sct” 文件。如下,在 “ER_IROM1” 域添加下面 11~16 行的内容:
    下面添加的部分,链接器会按照字典顺序排序。这是在keil MDK中能使用 XCMD_EXPORT_CMD()/XCMD_EXPORT_KEY() 的关键点。

点击查看代码
1.     ; ************************************************************* 
2.     ; *** Scatter-Loading Description File generated by uVision *** 
3.     ; ************************************************************* 5.     LR_IROM1 0x08000000 0x00200000 { ; load region size_region 
6.       ER_IROM1 0x08000000 0x00200000 { ; load address = execution address 
7.           *.o (RESET, +First) 
8.           *(InRoot$$Sections) 
9.           .ANY (+RO) 
10.           .ANY (+XO) 
11.           *(a1_xcmd_cmd_list_start) 
12.           *(a2_xcmd_cmd_list) 
13.           *(a3_xcmd_cmd_list_end) 
14.           *(b1_xcmd_key_list_start) 
15.           *(b2_xcmd_key_list) 
16.           *(b3_xcmd_key_list_end) 
17.         } 
18.         RW_IRAM1 0x20000000 0x00030000 { ; RW data 
19.         .ANY (+RW +ZI) 
20.       } 
21.     }

  1. 打开 “inc\xcmd.h”, 将下面的代码:
点击查看代码
#define XCMD_EXPORT_CMD(_name, _func, _help)  XCMD_USED const xcmd_t XCMD_SECTION("_xcmd_cmd_list") \ xcmd_cmd_##_name={\ .name=#_name, \ .func=_func, \ .help=_help\ }; 
#define XCMD_EXPORT_KEY(_key, _func, _help)   XCMD_USED const xcmd_key_t XCMD_SECTION("_xcmd_key_list") \ xcmd_key_##_key={\ .key=_key, \ .func=_func, \ .help=_help\ }; 

改为下面所示内容:

点击查看代码
#if defined(__CC_ARM) || defined(__CLANG_ARM)
#define XCMD_EXPORT_CMD(_name, _func, _help)        XCMD_USED const xcmd_t XCMD_SECTION("a2_xcmd_cmd_list") \xcmd_cmd_##_name={\.name=#_name, \.func=_func, \.help=_help\};
#define XCMD_EXPORT_KEY(_key, _func, _help)         XCMD_USED const xcmd_key_t XCMD_SECTION("b2_xcmd_key_list") \xcmd_key_##_key={\.key=_key, \.func=_func, \.help=_help\};
#else
#define XCMD_EXPORT_CMD(_name, _func, _help)        XCMD_USED const xcmd_t XCMD_SECTION("_xcmd_cmd_list") \xcmd_cmd_##_name={\.name=#_name, \.func=_func, \.help=_help\};
#define XCMD_EXPORT_KEY(_key, _func, _help)         XCMD_USED const xcmd_key_t XCMD_SECTION("_xcmd_key_list") \xcmd_key_##_key={\.key=_key, \.func=_func, \.help=_help\};														
#endif	//#if defined(__CC_ARM) || defined(__CLANG_ARM)

  1. 打开 “src\xcmd_default_cmds.c”, 将下面的代码:
点击查看代码
XCMD_EXPORT_CMD(help, cmd_help, "show this list") 
XCMD_EXPORT_CMD(clear, cmd_clear, "clear screen") 
XCMD_EXPORT_CMD(keys, cmd_keys, "show keys") 
XCMD_EXPORT_CMD(logo, cmd_logo, "show logo")

改为下面的内容:

点击查看代码
#if defined(ENABLE_XCMD_EXPORT) && (defined(__CC_ARM) || defined(__CLANG_ARM)) XCMD_USED const xcmd_t XCMD_SECTION("a1_xcmd_cmd_list_start") _xcmd_cmd_list_start = {"help", cmd_help, "show this list"}; XCMD_USED const xcmd_t XCMD_SECTION("a3_xcmd_cmd_list_end") _xcmd_cmd_list_end = {NULL, NULL, NULL}; 
#else XCMD_EXPORT_CMD(help, cmd_help, "show this list") 
#endif XCMD_EXPORT_CMD(clear, cmd_clear, "clear screen") 
XCMD_EXPORT_CMD(keys, cmd_keys, "show keys") 
XCMD_EXPORT_CMD(logo, cmd_logo, "show logo") 

  1. 打开 “src\xcmd_default_cmds.c”, 将下面的代码:
点击查看代码
XCMD_EXPORT_KEY(KEY_CTR_H, xcmd_del_char, "backspace") 
XCMD_EXPORT_KEY(KEY_BACKSPACE, xcmd_del_char, "delete") 

改为下面的内容:

点击查看代码
#if defined(ENABLE_XCMD_EXPORT) && (defined(__CC_ARM) || defined(__CLANG_ARM)) XCMD_USED const xcmd_key_t XCMD_SECTION("b1_xcmd_key_list_start") _xcmd_key_list_start = {KEY_CTR_H, xcmd_del_char, "backspace"}; XCMD_USED const xcmd_key_t XCMD_SECTION("b3_xcmd_key_list_end") _xcmd_key_list_end = {NULL, NULL, NULL}; 
#else XCMD_EXPORT_KEY(KEY_CTR_H, xcmd_del_char, "backspace") 
#endif XCMD_EXPORT_KEY(KEY_BACKSPACE, xcmd_del_char, "delete") 

修改后的代码可以参考我 fork 的副本

https://gitee.com/sqqdfny/xcmd/tree/dev-sqqdfny

http://www.zskr.cn/news/20428.html

相关文章:

  • OpenLayers地图交互 -- 章节十六:双击缩放交互详解 - 教程
  • CF1935E Distance Learning Courses in MAC
  • 静态内部类
  • SAP ABAP ALV 布局
  • 05_mysql备份方案
  • 10.13做题笔记
  • 详细介绍:微服务与面向服务编程(SOA)入门指南:从架构演进到 Spring Cloud 实践(初学者友好版)
  • LSNet
  • Webpack 构建速度优化
  • [模拟赛] 过关(pass)
  • 2025.10.13
  • 元宇宙的搜索引擎:如何在虚拟世界中查找信息 - 详解
  • 死锁的原因、表现以排查
  • 完整教程:文心大模型4.5:百度推出的新一代原生多模态基础大模型
  • day010
  • 详细介绍:DVWA | XSS 跨站脚本注入
  • 树莓派4B安装WiringPi使用gpio命令
  • 1分钟Get宠物神兽壁纸我家猫被问疯了!
  • 05_Mysql与图片的存储
  • 【Linux】权限 - 实践
  • 【左扬精讲】SRE 别慌!我用 服务器监控指标 讲 KNN 分类算法,从相似度计算到异常识别,都是咱运维人能懂的话(含代码)
  • Java实现业务数据报表的邮件定时发送功能
  • 编写Python自动化脚本,使用Autodesk Fusion辅助Ansys HFSS进行建模
  • 最好的感情
  • 深入解析:D018 vue+django 旅游图谱推荐问答系统|neo4j数据库|智能问答
  • 44. 开发商购买土地
  • 当AI与机器人走进生活:我们即将迎来的日常变革
  • net中使用了垃圾回收机制(GC)功能
  • 2025 超景深三维显微镜厂家 TOP10 推荐:三维成像技术的行业应用标杆​
  • 2025年国内铝单板工厂推荐/国内铝单板厂家/ 市场铝单板推/公司榜荐