0

ARM Cortex-M0 マイクロコントローラ (具体的には、STM32 Discovery 開発ボードの一部としての STM32F072B) 用のファームウェア コードを書いています。

私のリンカー スクリプトは特別なことは何もしません。ベクター テーブルに入力し、コードのすべてのテキスト セクションとデータ セクションをインクルードするだけです。

OUTPUT_FORMAT("elf32-littlearm")

MEMORY {
    ROM (rx) : ORIGIN = 0x00000000, LENGTH = 16K
    FLASH (r) : ORIGIN = 0x08000000, LENGTH = 64K
    RAM (rw)  : ORIGIN = 0x20000000, LENGTH = 16K
}

ENTRY(_start)

PROVIDE(__stack_top = ORIGIN(RAM) + LENGTH(RAM));


SECTIONS {

    .vector_table : {
        LONG(__stack_top);                  /* 00 */
        LONG(_start);                       /* 04 */  
        LONG(dummy_isr);                    /* 08 */
        LONG(dummy_isr);                    /* 0C */
        LONG(dummy_isr);                    /* 10 */
        LONG(dummy_isr);                    /* 14 */
        LONG(dummy_isr);                    /* 18 */
        LONG(dummy_isr);                    /* 1C */
        LONG(dummy_isr);                    /* 20 */
        LONG(dummy_isr);                    /* 24 */
        LONG(dummy_isr);                    /* 28 */
        LONG(dummy_isr);                    /* 2C */
        LONG(dummy_isr);                    /* 30 */
        LONG(dummy_isr);                    /* 34 */
        LONG(dummy_isr);                    /* 38 */
        LONG(dummy_isr);                    /* 3C */
        LONG(dummy_isr);                    /* 40 */
        LONG(dummy_isr);                    /* 44 */
        LONG(dummy_isr);                    /* 48 */
        LONG(dummy_isr);                    /* 4C */
        LONG(dummy_isr);                    /* 50 */
        LONG(dummy_isr);                    /* 54 */
        LONG(dummy_isr);                    /* 58 */
        LONG(dummy_isr);                    /* 5C */
        LONG(dummy_isr);                    /* 60 */
        LONG(dummy_isr);                    /* 64 */
        LONG(dummy_isr);                    /* 68 */
        LONG(dummy_isr);                    /* 6C */
        LONG(dummy_isr);                    /* 70 */
        LONG(dummy_isr);                    /* 74 */
        LONG(dummy_isr);                    /* 78 */
        LONG(dummy_isr);                    /* 7C */
        LONG(dummy_isr);                    /* 80 */
        LONG(dummy_isr);                    /* 84 */
        LONG(dummy_isr);                    /* 88 */
        LONG(dummy_isr);                    /* 8C */
        LONG(dummy_isr);                    /* 90 */
        LONG(dummy_isr);                    /* 94 */
        LONG(dummy_isr);                    /* 98 */
        LONG(dummy_isr);                    /* 9C */
        LONG(dummy_isr);                    /* A0 */
        LONG(dummy_isr);                    /* A4 */
        LONG(dummy_isr);                    /* A8 */
        LONG(dummy_isr);                    /* AC */
        LONG(dummy_isr);                    /* B0 */
        LONG(dummy_isr);                    /* B4 */
        LONG(dummy_isr);                    /* B8 */
        LONG(dummy_isr);                    /* BC */
    } > ROM AT > FLASH
    
    .text : {
        *(.text*)
    } > ROM AT > FLASH

    .rodata : {
        *(.rodata*)
        *(.data.rel.ro)
    } > FLASH

    .bss (NOLOAD) : {
        *(.bss*)
        *(COMMON)
    } > RAM

    .data : {
        *(.data*)
    } > RAM

    .ARM.exidx : {
       *(.ARM.exidx)
    } > FLASH

}

ELF ファイルをビルドしてリンクし、シンボルをダンプすると、ELF エントリ ポイントだけでなく、セクションで終わるアドレス.vector_tableもすべて 1 つずれていることがわかります。

[shell]$ llvm-objdump --syms zig-cache/bin/main-flash 

zig-cache/bin/main-flash:       file format elf32-littlearm

SYMBOL TABLE:
00000000 l    df *ABS*  00000000 main-flash
0000013c l       .text  00000000 $d.1
000000c0 l       .text  00000000 $t.0
000000c4 g     F .text  00000088 _start
000000c0 g     F .text  00000002 dummy_isr
20004000 g       *ABS*  00000000 __stack_top

[shell]$ llvm-objdump --full-contents --section=.vector_table zig-cache/bin/main-flash 

zig-cache/bin/main-flash:       file format elf32-littlearm

Contents of section .vector_table:
 0000 00400020 c5000000 c1000000 c1000000  .@. ............
 0010 c1000000 c1000000 c1000000 c1000000  ................
 0020 c1000000 c1000000 c1000000 c1000000  ................
 0030 c1000000 c1000000 c1000000 c1000000  ................
 0040 c1000000 c1000000 c1000000 c1000000  ................
 0050 c1000000 c1000000 c1000000 c1000000  ................
 0060 c1000000 c1000000 c1000000 c1000000  ................
 0070 c1000000 c1000000 c1000000 c1000000  ................
 0080 c1000000 c1000000 c1000000 c1000000  ................
 0090 c1000000 c1000000 c1000000 c1000000  ................
 00a0 c1000000 c1000000 c1000000 c1000000  ................
 00b0 c1000000 c1000000 c1000000 c1000000  ................
[shell]$ readelf -h zig-cache/bin/main-flash 
ELF Header:
...
  Entry point address:               0xc5

シンボル テーブルは_start0xC4 に表示されますが、リンカー スクリプトで定義されている ELF エントリ ポイントは_start0xC5 に設定されています。同様にdummy_isr、ベクトル テーブルに書き込まれるアドレスも 1 つずれています (dummy_isrシンボルは 0xC0 として定義され、リンカによって 0xC1 がベクトル テーブルに書き込まれます)。の分解により、とがそれぞれ 0xC0 と 0xC4 で始まることが.text確認されるため、リンカが書き込んでいるアドレスは間違っています。_dummy_isr_start

[shell]$ llvm-objdump --disassemble --section=.text zig-cache/bin/main-flash 
                                                               
zig-cache/bin/main-flash:       file format elf32-littlearm
                                                               

Disassembly of section .text:
                                                               
000000c0 <dummy_isr>:                                          
      c0: fe e7         b       #-4 <dummy_isr>   
      c2: c0 46         mov     r8, r8            
                               
000000c4 <_start>:
      c4: 82 b0         sub     sp, #8
      c6: 01 23         movs    r3, #1
      c8: d8 04         lsls    r0, r3, #19
      ca: 1c 49         ldr     r1, [pc, #112]
...

0xC1 と 0xC5 は有効な命令のアドレスでもなく、それぞれ命令の途中にあります。この不一致の原因は何ですか?

4

1 に答える 1