[英]Cortex-M0+ Linker Script and Startup Code
我試圖通過編寫自己的啟動代碼和鏈接器腳本來學習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
我解決了 仔細閱讀http://community.arm.com/docs/DOC-8769后 ,我發現Reset_Handler
應該是一個函數,或者是.thumb_func
。 顯然子程序不起作用。 我所做的只是改變我的
.global Reset_Handler
Reset_Handler:
b main
至:
.func Reset_Handler, Reset_Handler
.type Reset_Handler, %function
.thumb_func
.align
Reset_Handler:
b main
.size Reset_Handler, . - Reset_Handler
.pool
.endfunc
我還不了解其根本原因,但這有效。
更新
顯然居住是對的。 在我的原始代碼中,如果我在.thumb_func
之前放置.global
,它就可以了。 似乎需要該指令來生成正確的代碼。
如果將-mthumb
添加到匯編程序選項(當前在CFLAGS
使用它),則在.thumb_func
之前不需要Reset_Handler
。
-mthumb
指示匯編程序創建Thumb指令,而不是ARM。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.