欢迎光临散文网 会员登陆 & 注册

【开发经验】关于ARMV6编译器-O0优化不能进main的解决方案

2022-06-07 10:38 作者:捉住一只皮皮虾  | 我要投稿

最近使用keil 的ARMV6编译器的开发项目的时候遇到了这样一个问题——使用-O0优化时候复位单片机程序直接卡死(感觉根本没有执行),使用除-O0优化外的选项全都能通过。

所使用AC6编译器及优化配置

打开仿真之后程序直接卡在了 BKPT 0xAB


仿真截图

一般出现这种问题,根据以往经验可能是程序中使用了标准输入输出函数,例如 printf  格式化输出,所以打开了编译器提供的标注输入输出的补丁,即使用printf 等函数之后函数会直接返回,而不是进入一个断点 BKPT 0xAB

在程序中使用printf 也能正确返回。

可以看到执行 printf 时候直接返回了。但是问题并没有解决,程序依然卡在 BKPT 0xAB。

那肯定不是标准输入输出的问题。在网上搜索一圈之后,百度的答案是 “换ARMV5 编译器”。。。你猜猜看我为啥要用AC6,给你邦邦两拳(开玩笑啦)。而谷歌的答案更是不知所云,只好继续自己想办法。

当我勾选微库之后,这个问题居然解决了。。。

当然你可以看到,一旦勾选微库,keil会提醒你微库和C++不兼容。因为我编写的是C++项目,所以坚决不能使用微库,因此放弃了这个想法。

这时候发下堆栈中有两个函数调用_ARM_get_argv _sys_command_string 

_sys_command_string 正是断点位置,这两个函数一定是编译器自动生成并链接的,因为我们并没有编写这两个函数,关于编译器相关的东西 help一般都有解释,于是我打开了help 搜索 _sys_command_string

搜索结果中的第三条,解释了 在不同编译器优化等级的区别,其中提到了:

   “ 如果你的main函数是不带参数的,编译器会应用一些特定的优化,针对ARMV5编译器的所有优化等级,而ARMV6只针对-O0之外的优化等级”


Note的第四段话给出了解决方法

因此我们建立一个名为armv6O0fix.c的文件,添加以下代码:

要么你定义一个_sys_command_string 函数里面什么都不干,函数原型是help搜到的。要么按照help里提的,链接一个空的汇编函数,你写个void __ARM_use_no_argv(void){} 应该也是可以的。个人建议定义一个 _sys_command_string 函数,因为如果你定义了__ARM_use_no_argv而选择了非ARMV5或ARMV6 -OO优化以外的选项,则会和编译器自动生成的函数发生冲突。且_asm汇编只适用于ARMV6。而 _sys_command_string可以完美应用于ARMV5和V6编译器所有优化选项。

至此问题解决!

【开发经验】关于ARMV6编译器-O0优化不能进main的解决方案的评论 (共 条)

分享到微博请遵守国家法律