堆栈指针在 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 汇编中编写是棘手的。此代码存在三个问题。
.vector_interrupt
部分没有进入二进制文件,因为它没有 ALLOC 属性。 objcopy
忽略没有 ALLOC 属性的部分。结果,初始堆栈指针和重置向量为零。要解决此问题,部分属性应显示为 "xa":
.section .vector_interrupt, "xa"
另一个问题:初始堆栈指针未对齐。将其更改为:
.word 0x20008000
这是假设 MCU 至少有 32KB RAM。
- 分支目标地址应将 LSB 位设置为 1 以指示 Thumb 模式。 Cortex-M4 仅支持 Thumb 指令集,因此在尝试跳转到偶地址时会产生错误。为了让汇编程序生成正确的地址值,
.thumb_func
应该在 each 标识分支目标的标签之前。
见https://sourceware.org/binutils/docs/as/ARM-Directives.html
我正在尝试为 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 汇编中编写是棘手的。此代码存在三个问题。
.vector_interrupt
部分没有进入二进制文件,因为它没有 ALLOC 属性。objcopy
忽略没有 ALLOC 属性的部分。结果,初始堆栈指针和重置向量为零。要解决此问题,部分属性应显示为 "xa":.section .vector_interrupt, "xa"
另一个问题:初始堆栈指针未对齐。将其更改为:
.word 0x20008000
这是假设 MCU 至少有 32KB RAM。
- 分支目标地址应将 LSB 位设置为 1 以指示 Thumb 模式。 Cortex-M4 仅支持 Thumb 指令集,因此在尝试跳转到偶地址时会产生错误。为了让汇编程序生成正确的地址值,
.thumb_func
应该在 each 标识分支目标的标签之前。
见https://sourceware.org/binutils/docs/as/ARM-Directives.html