嵌入式环境下创建无main()函数的MCU C语言项目实现问询
解决方案:拆分MCU项目为无main函数模块与调用项目(GCC+Eclipse)
项目A:无main()的函数存储模块
这个项目仅存放目标函数fun,并将其指针固定到指定Flash地址,无需main函数。
1. 核心代码
// 目标函数,添加noinline避免被编译器优化移除 int __attribute__((noinline)) fun(int a) { return a * 2; } // 将函数指针放入自定义段,由链接脚本定位到固定地址 int (* fun_ptr)(int) __attribute__((section(".fun1"))) = &fun;
2. 自定义链接脚本
创建或修改链接脚本(如projectA.ld),指定.fun1段的固定地址,同时规避链接时对main入口的依赖:
SECTIONS { // 分配项目A的代码段到不与项目B冲突的Flash地址(示例:0x601f0000) .text 0x601f0000 : { KEEP(*(.text)) } // 固定存放函数指针的段,地址与调用项目约定一致 .fun1 0x601f1000 : { KEEP(*(.fun1)) // 强制保留该段,防止被优化器丢弃 } // 数据段映射(按需配置,RAM地址需匹配MCU实际映射) .data : { *(.data) } >RAM AT>FLASH // BSS段配置 .bss : { *(.bss) } >RAM } // 设置空入口点,避免链接时因找不到main报错 ENTRY(__dummy_entry) __dummy_entry: b . // 原地循环,实际不会被执行
3. Eclipse编译配置
- 打开项目属性:
Properties > C/C++ Build > Settings - 进入
MCU GCC Linker > Miscellaneous,添加链接选项:-nostartfiles -nostdlib(跳过标准启动文件和库,避免寻找main) - 进入
MCU GCC Linker > Linker Script,选择刚才创建的projectA.ld - 编译后,用
objcopy生成二进制文件:arm-none-eabi-objcopy -O binary projectA.elf projectA.bin
项目B:带main()的调用模块
这个项目包含main函数,通过固定地址读取项目A中的函数指针并调用。
1. 核心代码
int res; void main(void) { // 从约定的Flash地址读取函数指针(volatile防止编译器优化地址读取操作) int (* fun_call_ptr)(int) = (int (*)(int))(*(volatile int*)0x601f1000); // 调用目标函数 res = fun_call_ptr(10); // 执行后res的值应为20 }
2. 链接脚本配置
使用MCU默认的链接脚本即可,只需确保项目B的Flash分配地址不重叠项目A的0x601f0000-0x601f1000区域(可根据实际MCU Flash映射调整)。
3. Eclipse编译配置
按常规MCU项目配置即可:使用标准启动文件、链接脚本和库,编译后生成projectB.bin。
加载与验证
- 使用MCU烧录工具,先将
projectA.bin烧录到Flash的0x601f0000起始地址(对应链接脚本中的.text段) - 再将
projectB.bin烧录到它的默认Flash起始地址(如STM32的0x08000000) - 运行MCU,项目B的
main函数会读取0x601f1000地址的指针,调用项目A中的fun函数。
关键注意事项
- 两个项目的编译选项必须一致:包括CPU架构、浮点ABI、优化等级等,避免函数调用约定不兼容
- 确保
0x601f1000地址属于MCU可访问的Flash区域,且未被外设或其他代码占用 - 用
KEEP(*(.fun1))和__attribute__((noinline))防止编译器/链接器优化掉目标函数和指针
内容的提问来源于stack exchange,提问作者Ivan Ivanenko
相关产品推荐
相关产品推荐

