2014-11-25 41 views
3

我想通过编写自己的启动代码和链接器脚本来了解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 
+1

我在github.com/dwelch67上有例子。它看起来像在重置处理程序之前需要.thumb和.thumb_func。不知道.long是否转换为一个.word(32位),这是您想要的向量表的大小。如果你反汇编(arm -...- objdump -D yourelffile),这应该解释很多关于什么是或不在工作。向量表应该有32位入口,除了堆栈外,它们都应该是奇数。应该没有arm指令(大多数情况下只有thumbv1)等等。 – 2014-11-25 05:32:53

+0

我不确定'.thumb'是因为它在最小的例子中工作,没有任何关于这个的。此外,我使用作为向量表的参考,所以我认为它很好。我还会附上反汇编代码 – 2014-11-25 12:32:40

+0

实际上,当我通读您的回购协议时,是不是'.thumb'节与我的'isr_vectors'一样工作?它只是第一个代码。 – 2014-11-25 12:39:13

回答

4

我解决了它。仔细阅读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 

我不明白的根本原因还,但这个工程。

更新

显然dwelch是正确的。在我原来的代码中,如果我在.global之前放置.thumb_func,它就可以工作。似乎需要该指令才能生成正确的代码。

+1

抱歉,我在阅读本文之前在上面添加了一条评论。正如我的其他评论指出,反汇编告诉所有的0xC8是一个大红旗,偶数编号的地址不会在任何cortex-m上工作,有些人做+1(危险)或| 1不那么危险,或者.thumb_func,丑陋,但似乎是GNU工具想要的。 – 2014-11-25 19:35:32

0

如果您将-mthumb添加到您的汇编程序选项中(您目前在CFLAGS中),则在Reset_Handler之前不应该需要.thumb_func

-mthumb指示汇编程序创建Thumb指令,而不是ARM。