我想通过编写自己的启动代码和链接器脚本来了解ARM处理器的启动过程。我使用的芯片是LPC810,我遵循http://midibel.com/blink0.html的例子,这两个例子都在我的电路板上工作,所以电路正常。然后,我尝试实现Exception和IRQ处理程序的完整列表,但是代码无法启动。我只有一个st链接从NUCLEO板断开,但我不知道如何调试它。此外,LPC芯片只是插在面包板上,所以我会尽量避免连接更多的导线,因为许多孔已被ISP编程线使用或阻塞。Cortex-M0 +链接器脚本和启动代码
这是链接描述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
和其他的东西,但自从小例子,没有初始化它们,问题可能不在于此。
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
更新
其中包含符号vector.c
这是通过产生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)等等。 – 2014-11-25 05:32:53
我不确定'.thumb'是因为它在最小的例子中工作,没有任何关于这个的。此外,我使用作为向量表的参考,所以我认为它很好。我还会附上反汇编代码 –
2014-11-25 12:32:40
实际上,当我通读您的回购协议时,是不是'.thumb'节与我的'isr_vectors'一样工作?它只是第一个代码。 – 2014-11-25 12:39:13