重置后,ARM M4立即跳转到不可读的地址

时间:2018-12-07 00:42:48

标签: arm embedded bluetooth-lowenergy microcontroller

我正在研究Silicon Labs Thunderboard React(RD0057)上的一个项目,该项目上装有EFR32BG1xxxF256处理器(Cortex M4)。

最近,当我去对电路板进行编程和调试时,代码立即进入硬故障,然后再进入main。 (IACCVIOL和STKERR都设置了。)

我已经

  • 将代码还原为我知道已编译并运行的先前版本
  • 尝试了我拥有的另一个板
  • 使用J-Link适配器完全擦除了闪存并对其重新编程
  • 尝试了一个空的示例项目

所有结果相同

然后我单步执行代码,并看到在重置代码之后:

  • 从地址0xf210000开始
  • 一些看似无关的东西(4行)
  • 用0x4加载R3
  • 用R3加载R2(执行此R2后,在调试器中显示0xFFFFF)
  • bx R2(分支到ffffffe0,它表示“无法读取内存”并触发硬故障)

工具:  -Thunderboard React RD0057  -WSTK 4001A Rev A01(用作J-Link适配器)  -简单工作室  -蓝牙SDK 2.10.1

我需要找到一种方法来今晚晚些时候发布我的代码,但是这个问题听起来对任何人都熟悉吗?我认为它可能与代码无关,因为它发生在项目的已知良好版本和空示例项目中。任何帮助表示赞赏。

更新1:

Pastebin of Start of Binary,摘录前三项:

007c 0020 4da0 0000 49a0 0000 49a0 0000
49a0 0000 49a0 0000 49a0 0000 49a0 0000
49a0 0000 49a0 0000 49a0 0000 49a0 0000

我按照建议检查了二进制文件,并且头几项似乎是向量表(0x49A0束,我认为这意味着将地址加载到寄存器中)。

然后,我使用J链接“ J-Mem”读取芯片的内存。这显示了使用IDE对芯片(空白芯片)进行编程后的所有0xFFFF。然后,我使用J-Link命令行实用程序来刷新起始地址设置为0x00的二进制文件。然后再次读回内存,这似乎是成功的,其内容与bin文件匹配。执行此操作后,我便越过了之前导致硬故障的第一个负载和分支,但现在又在其他地方遇到了另一个硬故障。

  • 需要确定为什么IDE无法成功编写代码。假设某个偏移量设置有误,因为它似乎完全缺少闪存地址范围。
  • 需要确定此新的硬故障发生在哪里,以及这是我的代码还是其他奇怪的事情。

1 个答案:

答案 0 :(得分:2)

如果您有为arm / thumb构建的gnu binutils,请使用此

.thumb
.thumb_func
.global _start
_start:
.word 0x20001000
.word reset
.word hang
.word hang
.word hang
.thumb_func
reset:
    nop
    nop
    nop
    nop
    nop
    b reset
.thumb_func
hang:   b .

建立它

arm-none-eabi-as flash.s -o flash.o
arm-none-eabi-ld -Ttext=0 flash.o -o flash.elf
arm-none-eabi-objdump -D flash.elf > flash.list
arm-none-eabi-objcopy flash.elf -O binary flash.bin

不必是arm-none-eabi-它可以是arm-linux-gnueabi或其他任何arm-something-something。

检查列表文件,这是您启动cortex-m所需要的。

00000000 <_start>:
   0:   20001000    andcs   r1, r0, r0
   4:   00000015    andeq   r0, r0, r5, lsl r0
   8:   00000021    andeq   r0, r0, r1, lsr #32
   c:   00000021    andeq   r0, r0, r1, lsr #32
  10:   00000021    andeq   r0, r0, r1, lsr #32

00000014 <reset>:
  14:   46c0        nop         ; (mov r8, r8)
  16:   46c0        nop         ; (mov r8, r8)
  18:   46c0        nop         ; (mov r8, r8)
  1a:   46c0        nop         ; (mov r8, r8)
  1c:   46c0        nop         ; (mov r8, r8)
  1e:   e7f9        b.n 14 <reset>

00000020 <hang>:
  20:   e7fe        b.n 20 <hang>

flash中的第一个单词将为您加载到堆栈指针中,如果需要,您可以在引导程序代码中更改堆栈指针,这仅节省了一个步骤。下一个要复位或为1的复位地址,必须设置lsbit。重置位于0x0014以上,因此重置向量必须具有0x0014 | 1 = 0x0015。

其余所有引导程序都无关紧要。这将它置于一个简单的无限循环中,您可以使用调试器停止并继续,并在您重复停止并继续时希望在不同的地址找到它。

使用调试器可能比使用bin文件加载elf文件更容易。但同时该工具可能无法正确写入闪存,请使用该工具转储从0x00000000开始的几个单词

如果二进制文件不是以向量表开头的和/或向量表中的地址为偶数,则重置后将立即退出。

如果确实如此,那么我们需要进一步挖掘。请至少发布二进制文件的开头,最好是反汇编程序,一些向量表以及一些重置代码。