简体   繁体   English

ARM Cortex-M3启动文件

[英]ARM Cortex-M3 startup file

I am modifying a startup file for an ARM Cortex-M3 microcontroller. 我正在修改ARM Cortex-M3微控制器的启动文件。 Everything works fine so far, but I have a question regarding the need of using assembler code to perform the zero-filling of the BSS block. 到目前为止,一切工作正常,但是我对使用汇编代码执行BSS块的零填充的需求有疑问。

By default the reset interrupt in the startup file looks as follows: 默认情况下,启动文件中的重置中断如下所示:

// 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"
);

Using that code everything works as expected. 使用该代码,一切都会按预期进行。 However if I change the previous code for the following it stops working: 但是,如果我更改以下内容的先前代码,它将停止工作:

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

In principle both codes should do the same (fill the BSS with zeros), but the second one does not work for some reason that I fail to understand. 原则上,两个代码都应该做相同的事情(用零填充BSS),但是第二个代码由于某些我无法理解的原因而无法工作。 I belive that the .thumb_func directive must play a role here, but I am not very familiar with ARM assembler. 我相信.thumb_func指令必须在这里起作用,但是我对ARM汇编器不是很熟悉。 Any ideas or directions to help me understanding? 有什么想法或方向可以帮助我理解吗? Thanks! 谢谢!

Edit : By the way, the code to initialize the data segment (eg copy from Flash to RAM) is as follows and works just fine. 编辑 :顺便说一句,用于初始化数据段(例如,从闪存复制到RAM)的代码如下,并且工作正常。

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

Edit : Added the dissasembled code for both functions. 编辑 :添加了两个功能的反汇编的代码。

Assembly for the first looks like: 第一次组装看起来像:

  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>

Assembly for the second looks like: 第二个程序集如下所示:

  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>

If the initial stack is in the .bss section as suggested, you can see from the disassembly why the C code fails - it's loading the current pointer from the stack, saving the incremented pointer back to the stack, zeroing the location, then reloading the incremented pointer for the next iteration. 如果初始堆栈如建议的那样位于.bss节中,您可以从反汇编中看到C代码失败的原因-它正在从堆栈中加载当前指针,将递增的指针保存回堆栈,将位置清零,然后重新加载下一次迭代的增量指针。 If you zero the contents of the stack while using them, Bad Things happen. 如果使用堆栈将堆栈的内容清零,则会发生不良情况。

In this case, turning on optimisation might fix it (a smart compiler should generate pretty much the same as the assembly code if it actually tries). 在这种情况下,启用优化可能会解决该问题(智能编译器如果实际尝试生成的代码,则应生成与汇编代码几乎相同的代码)。 More generally, though, it's probably safer to consider sticking with assembly code when doing things like this that would normally be done at a level below the C runtime environment - bootstrapping a C environment from C code which expects that environment to exist already is risky at best, since you can only hope the code doesn't attempt to use anything that's not yet set up. 不过,更一般而言,在执行此类操作(通常在低于C运行时环境的水平下执行)时考虑使用汇编代码可能更安全-从C代码引导C环境,因为C代码期望该环境已经存在会带来风险最好,因为您只能希望代码不要尝试使用尚未设置的任何内容。

After a quick look around (I'm not overly familiar with the specifics of Cortex-M development), it seems an alternative/additional solution might be adjusting the linker script to move the stack somewhere else. 快速浏览后(我不太熟悉Cortex-M开发的细节),看来替代/其他解决方案可能是调整链接程序脚本以将堆栈移动到其他位置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM