【问题标题】:Stack Pointer does not load at the startup in ARM Cortex M4 (Tiva C Series TM4C123GH6PM)在 ARM Cortex M4(Tiva C 系列 TM4C123GH6PM)中,堆栈指针不会在启动时加载
【发布时间】:2017-11-15 02:29:09
【问题描述】:

我正在尝试为 Tiva C 启动板编写最简单的程序。堆栈指针值和程序计数器值自动取自闪存的前两个 32 位字。但是,出于某种原因,当我使用 gdb 进行调试时,堆栈指针变为 0x0。这会导致该程序失败。我正在使用此说明进行调试:

(gdb) target extended-remote :3333
(gdb) monitor reset halt
(gdb) load
(gdb) monitor reset init

汇编中的程序是startup.s:

        .syntax unified

        .section .vector_interrupt, "x"

    g_pfnVectors:
        .word 0x20007FFF
        .word _Reset

        .text
    .global _Reset
    _Reset:
        mov   r0, #0
        b stop

    stop:   
        add   r0, r0, #1
        b stop 

链接器文件 Tiva.lds:

ENTRY(_Reset)

MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}

SECTIONS {
        .vector_interrupt : {
        KEEP(*(.vector_interrupt));
    } > FLASH

    .text : {
        . = 0x0000026c;
        * (.text);
    } > FLASH

}

和生成文件:

gcc=arm-none-eabi-gcc
objcopy=arm-none-eabi-objcopy

FLAGS= -ggdb3 -nostdlib -std=c99 -mcpu=cortex-m4 \
       -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -Wall \
       -Werror -nostartfiles

csum.bin: csum.elf
    $(objcopy) -O binary csum.elf csum.bin

csum.elf: startup.s
    $(gcc) $(FLAGS) -T Tiva.lds -o csum.elf \
    startup.s

openocd:
    openocd -f ../openOCD/ek-tm4c123gxl.cfg

怎么了?

实现

我试图避免放置异常处理程序。但是,现在我把它们。问题是我在启动时遇到了 UsageFault。

我做了这个修改: 启动.s:

.syntax unified

        .section .vector_interrupt, "x"
g_pfnVectors:
        .word   _stack_start
        .word   _Reset
        .word   NMI           /* NMI Handler */
        .word   HardFault     /* Hard Fault Handler */
        .word   MemManage     /* MPU Fault Handler */
        .word   BusFault      /* Bus Fault Handler */
        .word   UsageFault    /* Usage Fault Handler */
        .word   0             /* Reserved */
        .word   0             /* Reserved */
        .word   0             /* Reserved */
        .word   0             /* Reserved */
        .word   SVC           /* SVCall Handler */
        .word   DebugMon      /* Debug Monitor Handler */
        .word   0             /* Reserved */
        .word   PendSV        /* PendSV Handler */
        .word   SysTick       /* SysTick Handler */

        .text
.global _Reset
_Reset:
        mov   r0, #0
        b stop

stop:   
        add   r0, r0, #1
        b stop               @ Infinite loop to stop execution



        .align  1
        .thumb_func
        .weak   Default_Handler
        .type   Default_Handler, %function
Default_Handler:
        b   .

/* Macro to define default handlers */
        .macro  def_handler handler_name
            .weak   \handler_name
            .set    \handler_name, Default_Handler
        .endm

        def_handler NMI
        def_handler HardFault
        def_handler MemManage
        def_handler BusFault
        def_handler UsageFault
        def_handler SVC
        def_handler DebugMon
        def_handler PendSV
        def_handler SysTick
        def_handler DEF_IRQHandler

Tiva.lds:

ENTRY(_Reset)

MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}

_stack_start = ORIGIN(SRAM)+LENGTH(SRAM);

SECTIONS {
        .text : {
            KEEP(*(.vector_interrupt));
            * (.text);
        } > FLASH

}

这是 arm-none-eabi-objdump -d csum.elf 的输出

csum.elf:     file format elf32-littlearm


Disassembly of section .text:

00000000 <g_pfnVectors>:
   0:   20008000    .word   0x20008000
   4:   00000040    .word   0x00000040
   8:   0000004d    .word   0x0000004d
   c:   0000004d    .word   0x0000004d
  10:   0000004d    .word   0x0000004d
  14:   0000004d    .word   0x0000004d
  18:   0000004d    .word   0x0000004d
    ...
  2c:   0000004d    .word   0x0000004d
  30:   0000004d    .word   0x0000004d
  34:   00000000    .word   0x00000000
  38:   0000004d    .word   0x0000004d
  3c:   0000004d    .word   0x0000004d

00000040 <_Reset>:
  40:   f04f 0000   mov.w   r0, #0
  44:   e7ff        b.n 46 <stop>

00000046 <stop>:
  46:   f100 0001   add.w   r0, r0, #1
  4a:   e7fc        b.n 46 <stop>

0000004c <BusFault>:
  4c:   f7ff bff8   b.w 4c <BusFault>

UsageFault 的原因可能是:

  • 未定义的指令

– 非法未对齐访问

– 指令执行时的无效状态

– 异常返回时出错

但我不知道是什么原因。

【问题讨论】:

  • 生成的二进制文件的前 8 个字节是什么?
  • 我想知道问题是否是因为向量表中的第二个条目应该不是重置处理程序(_Reset 在 0x0000026C 而向量表条目是 0x0000026A)。那
  • 您应该可以说.word _Reset 并让链接器修复正确的地址。而且我认为向量应该是奇数(因为它是拇指入口点)? [但是,“所有闪存都为零”听起来是更严重的问题!]
  • 您的 .bin 中没有任何内容。我希望它看起来与 .elf 相似(相同)。
  • 顺便说一句,base 16 转储将比 base 2 具有同样的表现力和紧凑性:)

标签: gcc arm cortex-m bare-metal


【解决方案1】:

在 ARM 汇编中编写是很棘手的。这段代码存在三个问题。

  1. .vector_interrupt 部分没有进入二进制文件,因为它没有 ALLOC 属性。 objcopy 忽略没有 ALLOC 属性的部分。结果,初始堆栈指针和复位向量为零。要解决此问题,部分属性应为“xa”:

    .section .vector_interrupt, "xa"
    
  2. 另一个问题:初始堆栈指针未对齐。将其更改为:

    .word 0x20008000
    

这是假设 MCU 至少有 32KB RAM。

  1. 分支目标地址的 LSB 位应设置为 1 以指示 Thumb 模式。 Cortex-M4 仅支持 Thumb 指令集,因此在尝试跳转到偶数地址时会产生错误。为了让汇编器生成正确的地址值,.thumb_func 应位于标识分支目标的 each 标签之前。

https://sourceware.org/binutils/docs/as/ARM-Directives.html

【讨论】:

  • bin 文件有变化吗?现在前两个单词中有非零吗?
  • 好。我们正在取得进展。现在我猜它在其他地方出错了?您可能需要对齐堆栈指针,我已经更新了答案。
  • 哦,我看到你已经解决了这个问题。现在,看到除了复位向量之外的所有指针都是奇数。正如所指出的,在 Thumb 模式下,分支地址应该是奇数。我不知道如何告诉编译器。也许在 _Reset 的定义之前解除.thumb_func 行?
  • 您可能希望在作为代码地址的 每个 标签之前使用 .thumb_func.type 指令。
  • 是的!奇迹般有效!我把 .thumb_func 放在 _Reset 之前。你能解释一下为什么需要 .thumb_func 吗?
猜你喜欢
  • 2017-06-23
  • 2017-12-03
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-14
相关资源
最近更新 更多