ARMV6编译器使用O0优化时单片机程序卡死的解决方案

控制/MCU

1840人已加入

描述

开发遇到了这个问题,上网找到了一篇解决方法,实测有效,在此分享给大家。

最近使用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的文件,添加以下代码:

char *_sys_command_string(char *cmd, int len){
 return 0;
}




//__asm(".global __ARM_use_no_argv
	" "__ARM_use_no_argv:
	")

编译器

编译器

要么你定义一个_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编译器所有优化选项。

编辑:黄飞

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分