【问题标题】:ARM Cortex-M3 startup fileARM Cortex-M3 启动文件
【发布时间】:2014-06-22 14:11:25
【问题描述】:

我正在修改 ARM Cortex-M3 微控制器的启动文件。到目前为止一切正常,但我有一个关于是否需要使用汇编代码来执行 BSS 块的零填充的问题。

默认情况下,启动文件中的复位中断如下所示:

// Zero fill the bss segment.
__asm(  "    ldr     r0, =_bss\n"
        "    ldr     r1, =_ebss\n"
        "    mov     r2, #0\n"
        "    .thumb_func\n"
        "    zero_loop:\n"
        "    cmp     r0, r1\n"
        "    it      lt\n"
        "    strlt   r2, [r0], #4\n"
        "    blt     zero_loop"
);

使用该代码,一切都按预期工作。但是,如果我将以前的代码更改为以下代码,它将停止工作:

// Zero fill the bss segment.
for(pui32Dest = &_bss; pui32Dest < &_ebss; )
{
    *pui32Dest++ = 0;
}

原则上,两个代码都应该做同样的事情(用零填充 BSS),但第二个代码由于某种我无法理解的原因不起作用。我相信 .thumb_func 指令必须在这里发挥作用,但我对 ARM 汇编器不是很熟悉。有什么想法或方向可以帮助我理解吗?谢谢!

编辑:顺便说一下,初始化数据段的代码(例如从 Flash 复制到 RAM)如下,并且工作正常。

// Copy the data segment initializers from flash to SRAM.
pui32Src = &_etext;
for(pui32Dest = &_data; pui32Dest < &_edata; )
{
    *pui32Dest++ = *pui32Src++;
}

编辑:为这两个函数添加了反汇编代码。

第一个组件看起来像:

  2003bc:   4806        ldr r0, [pc, #24]   ; (2003d8 <zero_loop+0x14>)
  2003be:   4907        ldr r1, [pc, #28]   ; (2003dc <zero_loop+0x18>)
  2003c0:   f04f 0200   mov.w   r2, #0

002003c4 <zero_loop>:
  2003c4:   4288        cmp r0, r1
  2003c6:   bfb8        it  lt
  2003c8:   f840 2b04   strlt.w r2, [r0], #4
  2003cc:   dbfa        blt.n   2003c4 <zero_loop>

第二个组件看起来像:

  2003bc:   f645 5318   movw    r3, #23832  ; 0x5d18
  2003c0:   f2c2 0300   movt    r3, #8192   ; 0x2000
  2003c4:   9300        str r3, [sp, #0]
  2003c6:   e004        b.n 2003d2 <ResetISR+0x6e>
  2003c8:   9b00        ldr r3, [sp, #0]
  2003ca:   1d1a        adds    r2, r3, #4
  2003cc:   9200        str r2, [sp, #0]
  2003ce:   2200        movs    r2, #0
  2003d0:   601a        str r2, [r3, #0]
  2003d2:   9a00        ldr r2, [sp, #0]
  2003d4:   f644 033c   movw    r3, #18492  ; 0x483c
  2003d8:   f2c2 0300   movt    r3, #8192   ; 0x2000
  2003dc:   429a        cmp r2, r3
  2003de:   d3f3        bcc.n   2003c8 <ResetISR+0x64>

【问题讨论】:

  • 它在什么意义上“停止工作”?
  • 挂起,执行没有到达主函数。对我来说,这可能与 ARM 与 Thumb 模式有关,也可能是循环错误(例如,它没有结束)。
  • 一般情况下,在完成C bootstrap,鸡和蛋之前,你不想做C,这样的问题是可以预料的。设置堆栈,清除 .bss 并将 .data 复制到 asm 中(最好是非内联),至少在触摸第一个 C 之前...
  • codered/lpcXpresso/precision32 的启动代码使用 c/c++,看起来和你正在做的非常相似。没有理由不能或不应该在 c 中。

标签: c assembly arm startup cortex-m3


【解决方案1】:

如果初始堆栈按照建议在.bss 部分中,您可以从反汇编中看到 C 代码失败的原因 - 它从堆栈加载当前指针,将递增的指针保存回堆栈,将位置归零,然后为下一次迭代重新加载递增的指针。如果您在使用堆栈时将它们的内容归零,就会发生坏事。

在这种情况下,打开优化可能会修复它(如果智能编译器实际尝试,它应该生成与汇编代码几乎相同的代码)。不过,更一般地说,在执行此类通常会在低于 C 运行时环境的级别上完成的事情时,考虑坚持使用汇编代码可能更安全——从期望环境已经存在的 C 代码引导 C 环境是有风险的最好,因为您只能希望代码不会尝试使用尚未设置的任何内容。

快速浏览一下(我不太熟悉 Cortex-M 开发的细节),似乎另一种/附加的解决方案可能是调整链接器脚本以将堆栈移动到其他地方。

【讨论】:

  • 为什么栈会在bss中?
  • @escrafford 我看不出有什么好的理由,但有人建议它在一个现已删除的答案中,在我的简短搜索中,我找到了一个这样做的链接器脚本示例,所以我猜想至少有一个工具链可以做到这一点。当然还有其他可能性,比如一个剩余的引导加载程序 sp 恰好与应用程序 .bss 重合,或者其他的东西(再看看 C 反汇编中的那些地址确实看起来有点狡猾)
猜你喜欢
  • 1970-01-01
  • 2014-06-08
  • 1970-01-01
  • 2016-03-01
  • 1970-01-01
  • 2012-05-15
  • 1970-01-01
  • 1970-01-01
  • 2017-12-03
相关资源
最近更新 更多