【发布时间】:2015-01-22 23:44:22
【问题描述】:
我正在尝试通过编写自己的启动代码和链接器脚本来学习 ARM 处理器的启动过程。我使用的芯片是 LPC810,我按照http://midibel.com/blink0.html 中的示例进行操作,这两个示例都适用于我的电路板,所以电路没问题。然后,我尝试实现 Exception 和 IRQ 处理程序的完整列表,但随后代码无法启动。我只有一个从 NUCLEO 板上断开的 st-link,但我不知道如何调试它。另外,LPC 芯片只是插在面包板上,所以我会尽量避免连接更多的线,因为许多孔已经被 ISP 编程线使用或阻塞了。
这是链接器脚本lpc810.ld:
ENTRY(Reset_Handler);
MEMORY {
FLASH(rx) : ORIGIN = 0x0, LENGTH = 0x1000 /* 4K */
RAM(rwx) : ORIGIN = 0x10000000, LENGTH = 0x400 /* 1K */
}
SECTIONS {
. = ORIGIN(FLASH);
.text : {
KEEP(* (.isr_vectors));
. = ALIGN(4);
__vec_end__ = .;
/*. = 0xC4;*/ /* End of vectors */
* (.text);
. = ALIGN(4);
__end_text__ = .;
} > FLASH
__flash_sdata__ = .;
.data : AT(__flash_sdata__){
__data_start__ = .;
* (.data);
. = ALIGN(4);
__data_end__ = .;
} > RAM
.bss : {
__bss_start__ = .;
* (.bss);
. = ALIGN(4);
_bss_end__ = .;
}
__stack_top = ORIGIN(RAM) + LENGTH(RAM);
}
_end = .;
PROVIDE(end = .);
这是启动代码crt0.S:
/*
This is the startup file for LPC81x. The C definition of the vector tables are defined in vector.c
*/
.section .isr_vectors
.align 2
.long __stack_top
.long Reset_Handler
.long NMI_Handler
.long HardFault_Handler
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long SVCall_Handler
.long 0
.long 0
.long PendSV_Handler
.long SysTick_Handler
.long 0
/* IRQ 0 */
.long SPI0_IRQ
.long SPI1_IRQ
.long 0
.long UART0_IRQ
.long UART1_IRQ
.long UART2_IRQ
.long 0
.long 0
/* IRQ 8 */
.long I2C0_IRQ
.long SCT_IRQ
.long MRT_IRQ
.long CMP_IRQ
.long WDT_IRQ
.long BOD_IRQ
.long 0
.long WKT_IRQ
/* IRQ 16 */
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
/* IRQ 24 */
.long PININT0_IRQ
.long PININT1_IRQ
.long PININT2_IRQ
.long PININT3_IRQ
.long PININT4_IRQ
.long PININT5_IRQ
.long PININT6_IRQ
.long PININT7_IRQ
.text
.align
.global Reset_Handler
Reset_Handler:
b main
我知道我应该初始化 .data .bss 和其他东西,但由于最小的例子没有初始化它们,问题可能不在那里。包含符号的vector.c:
extern void Reset_Handler(void);
extern void NMI_Handler(void);
extern void HardFault_Handler(void);
extern void SVCall_Handler(void);
extern void PendSV_Handler(void);
extern void SysTick_Handler(void);
extern void SPI0_IRQ(void);
extern void SPI1_IRQ(void);
extern void UART0_IRQ(void);
extern void UART1_IRQ(void);
extern void UART2_IRQ(void);
extern void I2C0_IRQ(void);
extern void SCT_IRQ(void);
extern void MRT_IRQ(void);
extern void CMP_IRQ(void);
extern void WDT_IRQ(void);
extern void BOD_IRQ(void);
extern void WKT_IRQ(void);
extern void PININT0_IRQ(void);
extern void PININT1_IRQ(void);
extern void PININT2_IRQ(void);
extern void PININT3_IRQ(void);
extern void PININT4_IRQ(void);
extern void PININT5_IRQ(void);
extern void PININT6_IRQ(void);
extern void PININT7_IRQ(void);
__attribute__((naked))
void _unhandled_exception(void) {
for(;;);
}
void NMI_Handler(void) __attribute__((weak, alias("_unhandled_exception")));
void HardFault_Handler(void) __attribute__((weak, alias("_unhandled_exception")));
void SVCall_Handler(void) __attribute__((weak, alias("_unhandled_exception")));
void PendSV_Handler(void) __attribute__((weak, alias("_unhandled_exception")));
void SysTick_Handler(void) __attribute__((weak, alias("_unhandled_exception")));
void SPI0_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void SPI1_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void UART0_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void UART1_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void UART2_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void I2C0_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void SCT_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void MRT_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void CMP_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void WDT_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void BOD_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void WKT_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void PININT0_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void PININT1_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void PININT2_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void PININT3_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void PININT4_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void PININT5_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void PININT6_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
void PININT7_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
教程中基本未修改的main.c:
/*
BLINK0:
A minimal "Blinky" for NXP-LPC810 miniboard
A single-file example using only out-of-the-box arm-gcc compiler and no crt0
Using default reset state values for everything
Pressing the ISP button will change blink rate
WARN: due to missing crt0 - no init of data/bss (see blink1 ;) )
*/
typedef unsigned int volatile * vp;
void main()
{
*(vp)0x4000c1c0 = 0xffffffbfUL; // PINENABLE0 (disable SWclk/dio)
*(vp)0xa0002000 |= (1 << 2); // DIR0 (set pinio-2 to output)
for (;;)
{
*(vp)0xa0002100 ^= (1 << 2); // PIN0 - toggle LED
// Some busy loop waiting...
volatile long vaste = *(vp)0xa0002100 & (1 << 1) ? 250000 : 50000; // PIN0 (fast blink when ISP pressed)
while (vaste > 0) --vaste;
}
}
我正在使用的CFLAGS:
CFLAGS=-Os -mthumb -mcpu=cortex-m0plus -nostartfiles -Wl,-T$(LDS),-nostdlib,-Map=$(TGT).map
更新
这是arm-none-eabi-objdump -d生成的反汇编代码:
main.elf:文件格式elf32-littlearm
Disassembly of section .text:
00000000 <_unhandled_exception-0xc4>:
0: 10000400 .word 0x10000400
4: 000000c8 .word 0x000000c8
8: 000000c5 .word 0x000000c5
c: 000000c5 .word 0x000000c5
...
2c: 000000c5 .word 0x000000c5
...
38: 000000c5 .word 0x000000c5
3c: 000000c5 .word 0x000000c5
40: 00000000 .word 0x00000000
44: 000000c5 .word 0x000000c5
48: 000000c5 .word 0x000000c5
4c: 00000000 .word 0x00000000
50: 000000c5 .word 0x000000c5
54: 000000c5 .word 0x000000c5
58: 000000c5 .word 0x000000c5
...
64: 000000c5 .word 0x000000c5
68: 000000c5 .word 0x000000c5
6c: 000000c5 .word 0x000000c5
70: 000000c5 .word 0x000000c5
74: 000000c5 .word 0x000000c5
78: 000000c5 .word 0x000000c5
7c: 00000000 .word 0x00000000
80: 000000c5 .word 0x000000c5
...
a4: 000000c5 .word 0x000000c5
a8: 000000c5 .word 0x000000c5
ac: 000000c5 .word 0x000000c5
b0: 000000c5 .word 0x000000c5
b4: 000000c5 .word 0x000000c5
b8: 000000c5 .word 0x000000c5
bc: 000000c5 .word 0x000000c5
c0: 000000c5 .word 0x000000c5
000000c4 <_unhandled_exception>:
c4: e7fe b.n c4 <_unhandled_exception>
...
000000c8 <Reset_Handler>:
c8: e000 b.n cc <__end_text__>
ca: 46c0 nop ; (mov r8, r8)
Disassembly of section .text.startup:
000000cc <main>:
cc: 4b0d ldr r3, [pc, #52] ; (104 <__end_text__+0x38>)
ce: 2241 movs r2, #65 ; 0x41
d0: 4252 negs r2, r2
d2: 601a str r2, [r3, #0]
d4: 4b0c ldr r3, [pc, #48] ; (108 <__end_text__+0x3c>)
d6: 2104 movs r1, #4
d8: 681a ldr r2, [r3, #0]
da: b082 sub sp, #8
dc: 430a orrs r2, r1
de: 601a str r2, [r3, #0]
e0: 4b0a ldr r3, [pc, #40] ; (10c <__end_text__+0x40>)
e2: 2104 movs r1, #4
e4: 681a ldr r2, [r3, #0]
e6: 404a eors r2, r1
e8: 601a str r2, [r3, #0]
ea: 681b ldr r3, [r3, #0]
ec: 079a lsls r2, r3, #30
ee: d501 bpl.n f4 <main+0x28>
f0: 4b07 ldr r3, [pc, #28] ; (110 <__end_text__+0x44>)
f2: e000 b.n f6 <main+0x2a>
f4: 4b07 ldr r3, [pc, #28] ; (114 <__end_text__+0x48>)
f6: 9301 str r3, [sp, #4]
f8: 9b01 ldr r3, [sp, #4]
fa: 2b00 cmp r3, #0
fc: ddf0 ble.n e0 <main+0x14>
fe: 9b01 ldr r3, [sp, #4]
100: 3b01 subs r3, #1
102: e7f8 b.n f6 <main+0x2a>
104: 4000c1c0 .word 0x4000c1c0
108: a0002000 .word 0xa0002000
10c: a0002100 .word 0xa0002100
110: 0003d090 .word 0x0003d090
114: 0000c350 .word 0x0000c350
arm-none-eabi-nm -n生成的符号表:
000000c4 W BOD_IRQ
000000c4 W CMP_IRQ
000000c4 W HardFault_Handler
000000c4 W I2C0_IRQ
000000c4 W MRT_IRQ
000000c4 W NMI_Handler
000000c4 W PendSV_Handler
000000c4 W PININT0_IRQ
000000c4 W PININT1_IRQ
000000c4 W PININT2_IRQ
000000c4 W PININT3_IRQ
000000c4 W PININT4_IRQ
000000c4 W PININT5_IRQ
000000c4 W PININT6_IRQ
000000c4 W PININT7_IRQ
000000c4 W SCT_IRQ
000000c4 W SPI0_IRQ
000000c4 W SPI1_IRQ
000000c4 W SVCall_Handler
000000c4 W SysTick_Handler
000000c4 W UART0_IRQ
000000c4 W UART1_IRQ
000000c4 W UART2_IRQ
000000c4 T _unhandled_exception
000000c4 T __vec_end__
000000c4 W WDT_IRQ
000000c4 W WKT_IRQ
000000c8 T Reset_Handler
000000cc T __end_text__
000000cc T __flash_sdata__
000000cc T main
10000000 T _bss_end__
10000000 T __bss_start__
10000000 T __data_end__
10000000 T __data_start__
10000000 T _end
10000400 A __stack_top
main.map:
Memory Configuration
Name Origin Length Attributes
FLASH 0x0000000000000000 0x0000000000001000 xr
RAM 0x0000000010000000 0x0000000000000400 xrw
*default* 0x0000000000000000 0xffffffffffffffff
Linker script and memory map
0x0000000000000000 . = ORIGIN (FLASH)
.text 0x0000000000000000 0xcc
*(.isr_vectors)
.isr_vectors 0x0000000000000000 0xc4 crt0.o
0x00000000000000c4 . = ALIGN (0x4)
0x00000000000000c4 __vec_end__ = .
*(.text)
.text 0x00000000000000c4 0x0 main.o
.text 0x00000000000000c4 0x2 vectors.o
0x00000000000000c4 SVCall_Handler
0x00000000000000c4 PININT5_IRQ
0x00000000000000c4 HardFault_Handler
0x00000000000000c4 SysTick_Handler
0x00000000000000c4 SPI1_IRQ
0x00000000000000c4 PendSV_Handler
0x00000000000000c4 NMI_Handler
0x00000000000000c4 CMP_IRQ
0x00000000000000c4 SPI0_IRQ
0x00000000000000c4 WKT_IRQ
0x00000000000000c4 PININT0_IRQ
0x00000000000000c4 PININT2_IRQ
0x00000000000000c4 PININT6_IRQ
0x00000000000000c4 PININT1_IRQ
0x00000000000000c4 MRT_IRQ
0x00000000000000c4 WDT_IRQ
0x00000000000000c4 UART2_IRQ
0x00000000000000c4 PININT7_IRQ
0x00000000000000c4 SCT_IRQ
0x00000000000000c4 I2C0_IRQ
0x00000000000000c4 PININT4_IRQ
0x00000000000000c4 BOD_IRQ
0x00000000000000c4 UART0_IRQ
0x00000000000000c4 _unhandled_exception
0x00000000000000c4 PININT3_IRQ
0x00000000000000c4 UART1_IRQ
*fill* 0x00000000000000c6 0x2
.text 0x00000000000000c8 0x4 crt0.o
0x00000000000000c8 Reset_Handler
0x00000000000000cc . = ALIGN (0x4)
0x00000000000000cc __end_text__ = .
0x00000000000000cc __flash_sdata__ = .
.glue_7 0x00000000000000cc 0x0
.glue_7 0x0000000000000000 0x0 linker stubs
.glue_7t 0x00000000000000cc 0x0
.glue_7t 0x0000000000000000 0x0 linker stubs
.vfp11_veneer 0x00000000000000cc 0x0
.vfp11_veneer 0x0000000000000000 0x0 linker stubs
.v4_bx 0x00000000000000cc 0x0
.v4_bx 0x0000000000000000 0x0 linker stubs
.text.startup 0x00000000000000cc 0x4c
.text.startup 0x00000000000000cc 0x4c main.o
0x00000000000000cc main
.iplt 0x0000000000000118 0x0
.iplt 0x0000000000000000 0x0 crt0.o
.rel.dyn 0x0000000000000118 0x0
.rel.iplt 0x0000000000000000 0x0 crt0.o
.data 0x0000000010000000 0x0 load address 0x00000000000000cc
0x0000000010000000 __data_start__ = .
*(.data)
.data 0x0000000010000000 0x0 main.o
.data 0x0000000010000000 0x0 vectors.o
.data 0x0000000010000000 0x0 crt0.o
0x0000000010000000 . = ALIGN (0x4)
0x0000000010000000 __data_end__ = .
.igot.plt 0x0000000010000000 0x0 load address 0x00000000000000cc
.igot.plt 0x0000000000000000 0x0 crt0.o
.bss 0x0000000010000000 0x0 load address 0x00000000000000cc
0x0000000010000000 __bss_start__ = .
*(.bss)
.bss 0x0000000010000000 0x0 main.o
.bss 0x0000000010000000 0x0 vectors.o
.bss 0x0000000010000000 0x0 crt0.o
0x0000000010000000 . = ALIGN (0x4)
0x0000000010000000 _bss_end__ = .
0x0000000010000400 __stack_top = (ORIGIN (RAM) + 0x400)
0x0000000010000000 _end = .
0x0000000010000000 PROVIDE (end, .)
LOAD main.o
LOAD vectors.o
LOAD crt0.o
START GROUP
LOAD /usr/lib/gcc/arm-none-eabi/4.8.2/armv6-m/libgcc.a
LOAD /usr/lib/gcc/arm-none-eabi/4.8.2/../../../arm-none-eabi/lib/armv6-m/libc.a
END GROUP
OUTPUT(main.elf elf32-littlearm)
.comment 0x0000000000000000 0x1f
.comment 0x0000000000000000 0x1f main.o
0x20 (size before relaxing)
.comment 0x0000000000000000 0x20 vectors.o
.ARM.attributes
0x0000000000000000 0x30
.ARM.attributes
0x0000000000000000 0x32 main.o
.ARM.attributes
0x0000000000000032 0x32 vectors.o
.ARM.attributes
0x0000000000000064 0x22 crt0.o
【问题讨论】:
-
我在 github.com/dwelch67 上有示例。看起来您在重置处理程序之前需要一个 .thumb 和一个 .thumb_func 。不确定 .long 是否转换为 .word(32 位),这是您想要的向量表大小。如果您反汇编(arm-...-objdump -D yourelffile),那应该可以解释很多有关什么工作或不工作的信息。向量表应该有 32 位条目,当然除了堆栈之外,它们都应该是奇数。应该没有 arm 指令(大部分只有 thumbv1)等。
-
我不确定
.thumb,因为它在最小的示例中工作,而没有任何相关内容。另外,我使用 community.arm.com/docs/DOC-8769> 作为向量表的参考,所以我认为它很好。我还要附上反汇编代码 -
实际上,当我阅读您的回购时,
.thumb部分的工作方式与我的isr_vectors不一样吗?它只是进入代码的第一个部分。 -
你的重置看起来不对 0xC8 是一个手臂地址,而 cortex-m0 不会这样做。不知道你是如何摆脱重置的。
-
如果有多种方法可以使用 gnu 工具做事,我一点也不感到惊讶。归根结底,还是拆解说明了一切。
标签: assembly linker arm startup interrupt