堆栈指针在 ARM Cortex M4(Tiva C 系列 TM4C123GH6PM)启动时不加载

Stack Pointer does not load at the startup in ARM Cortex M4 (Tiva C Series TM4C123GH6PM)

我正在尝试为 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。

我做了以下修改: startup.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 的原因可能是:

– 非法未对齐访问

– 指令执行状态无效

– 异常错误 return

但我不明白是什么原因

在 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