【问题标题】:Cortex-M0+ Linker Script and Startup CodeCortex-M0+ 链接描述文件和启动代码
【发布时间】: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


【解决方案1】:

我解决了。仔细阅读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 是对的。在我的原始代码中,如果我将.thumb_func 放在.global 之前,它可以工作。似乎需要该指令来生成正确的代码。

【讨论】:

  • 对不起,我在阅读本文之前在上面添加了评论。正如我的其他评论指出的那样,反汇编告诉所有 0xC8 是一个大红旗,偶数地址不会在任何 cortex-m 上工作,有些人会做 +1(危险)或 |1 不那么危险,或 .thumb_func,丑陋但似乎是 gnu 工具想要的。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2017-05-12
    • 2018-02-21
    • 2019-12-13
    • 2017-03-24
    • 1970-01-01
    • 2020-03-22
    • 2017-02-04
    • 1970-01-01
    • 2020-12-24
    相关资源
    最近更新 更多