最近将 rt-thread 移植到 W806 上, 从 stm32F103 的 rt-htread 工程代码移植到 W806, 基本的 GPIO 和 UART 修改后能通过, 但运行出错. 经过排查, 问题出现在函数 rt_components_board_init () 中的__rt_init_rti_board_start 的宏定义 INIT_EXPORT (fn, level) , 凡是用到了对宏定义 INIT_EXPORT (fn, level) 的变量调用, 编译后对结构体变量 rt_object_container[]的内存空间都造成了破坏, 而且内存破坏的结果很奇怪, 原内存数据整体向后移动了若干字节. 相同的代码在 stm32F103 下编译后运行没有问题. 我已将该问题在联盛德官方提供 W806 的 DEMO 工程代码 WM_SDK_W806 上复现了, 我已经检查了 startup. s 和 gcc_csky. ld, 未发现什么错误, 目前怀疑可能是编译工具链在编译处理时有 bug, 编译是在 WIN 下, 编译工具链是 csky-elfabiv2-tools-mingw-minilibc-20210423. tar. gz (我查了下是最新版本, 下载地址: https: //occ. t-head. cn/community/download? id=3885366095506644992) .
问题描述如下:
正常编译后 rt_object_container 指向的内存空间前 4 字节应该是 01000000, 但实际编译后 rt_object_container 指向的内存空间前 4 字节是 00000000, 之前怀疑是 startup. s 启动初始化到 main 函数这个阶段对内存作了修改, 但没发现有内存拷贝的调用, 故怀疑编译工具链的 bug. 问题的重点是在宏定义 INIT_EXPORT (fn, level) 和这个宏定义所声明的变量__rt_init_rti_board_start 被调用了, 这两个关键点同时满足, 编译后就会对内存造成破坏.
以下是 WM_SDK_W806 修改后复现该问题的工程代码 (主要是增加了 main. h 和修改了 main. c 部分代码) .
WM_SDK_W806_DEBUG. zip
编译 WM_SDK_W806 的步骤:
1. 需要下载编译工具链解压到适当的目录,
2. 修改 WM_SDK_W806 代码工程中的文件. config 下的工具链路径 CONFIG_W800_TOOLCHAIN_PATH,
3. WM_SDK_W806 目录下直接直接执行 make.
请官方技术支持或有余力的同仁帮助分析下 bug 原因, 是否有其他出错可能.
下载了你的 demo, 关于你上述的问题暂时还没有腾出来时间去验证, 但是发现了一个问题, 感觉你没有理解 INIT_EXPORT 宏的 作用是什么, 要想使用该宏 是需要更改链接脚本的, 因为 INIT_EXPORT 宏的作用就是把函数的地址, 按照顺序放到 section 段内, 你如果不指定的话, gcc 编译在链接脚本里找不到该 section 的描述, 就会忽略此限定词, 你可以参考 RTthread 官方 BSP 中 CK802 的链接脚本的写法进行更改. 这是我的一点拙见哈
RT_USED const init_fn_t __rt_init_##fn SECTION (". rti_fn. " level) = &fn;
__rt_init_start = . ;
KEEP (* (SORT (. rti_fn*) ) )
__rt_init_end = . ;
非常感谢, 已经验证了, 确实是链接脚本缺少对 INIT_EXPORT 宏的 section 段指定.