本文禁止转载。
本文提供了几种不切换ARM编译器版本的情况下解决该问题的方法。
在编写程序时,
大概编写的即使这样一个程序,这个96个字节的变量定义在main函数内部,上面还定义了一些其他变量
编译的时候遇到错误:
Build started: Project: ble_app_uart_pca10056_s140
*** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'
Build target 'nrf52840_xxaa'
linking...
.\_build\nrf52840_xxaa.axf: Internal fault: [0xb3b91b:5060750]
.\_build\nrf52840_xxaa.axf: Please contact your supplier.
".\_build\nrf52840_xxaa.axf" - 2 Error(s), 0 Warning(s).
Target not created.
Build Time Elapsed: 00:00:01
这个错误具体的原因及解决方法如下:
这个是ARM官方的一个解决方案。但是官方的这个解决方案好像并不是能够解决问题。
本文提供了一种新的解决方式。
首先介绍一下这个问题产生的原因,这个问题主要是因为ARM编译器版本产生的
具体的,是这两个版本产生了问题。 升级到6.13版本理论上就可以解决该问题了。
但是,升级ARM编译器的版本是比较耗时的。
首先,要下载新的ARM版本,然后要做一系列的配置,让keil5 开发环境能够支持6.13的ARM编译器。
但是这个配置是耗时的,这个配置可以到网上去搜索对应的参考解决方案。
但是可能不一定能成功。(我具体的没试过,我觉得太浪费时间了,之前在另一款IDE中,是不得不升级ARM编译器的版本,我才升级的,配置过程比较繁琐)
为什么升级ARM编译器的版本不一定成功?
This issue was solved in Arm Compiler version 6.13 which will be part of Keil MDK version 5.29.
因为官方介绍的是keil版本是5.29
而我的版本是5.27
我想,这条路还是算了吧。万一升级不成功,还要先升级keil5 的版本。为了解决这么个ARM编译器的错误,不至于,不值得浪费这么多时间。
我当前的keil环境下,有这么几个ARM编译器的版本,都尝试了切换了一下,编译,继续报错。
所以感觉,这不应该是ARM6.11和6.12 存在的问题,应该是以前的版本都有类似的问题。
官方提供了几种解决方案:
尝试了一下,都不行,
第一种方法,更改优化方案,优化方案从-O0 到-O3,都不行
第二种方法,勾选掉 One ELF Section per Function,不行。这个其实也是一种优化方案,意思就是对没有调用到的函数就直接优化掉,不要放到最终的ELF二进制文件中
以上两种方法,官方也都认为是不安全的。
第三种方法,修改Scatter 文件
可是我们也没有应用到Scatter文件,所以这种也不行
最后,提出我的几种解决方案。
(1)把这个96字节的数组变量放到全局变量中去定义,放在main函数之外,错误没有了
(2)把这个96字节的数组变量加上static 关键字,错误没有了。加上static关键字之后,不管是放在main函数里面还是main函数外面,错误都解决
(3)定义这个96字节的数组变量的时候,不要赋初值,然编译器给他赋初值。错误解决。
(4)给这96个字节的数组扩展为97个字节的数组,但是最后一个成员不要赋值。
之所以提出这个第四点方案,是基于第三点优化方案的考虑。当时不想把这个数组放在全局变量中,或者加上static关键字。第三点就取消掉定义的时候赋初值。然编译器默认给这个数组赋初值(一般情况下,默认赋初值就是为0)
然后我想,是不是ARM编译器赋初值之后 ,这个bug就自动规避掉了,我就扩展数组,扩大一个字节,最后一个字节不赋初值,然后发现好像确实是如自己所预测的那样。
如果大家遇到这个问题,能定位出来是哪个变量导致这个问题,可以尝试使用我这种方式,让编译器默认赋初值,然后自己在别的地方给这个变量手动赋值(虽然这种方式不是我们想要的,我们的编程习惯中一般是定义的时候即赋初值)
如果大家不想这么解决,就按照官方的介绍,首先先升级keil的版本,然后再升级ARM的版本。
这两个升级版本不在本文介绍范围之内