kubo39's blog

ただの雑記です。

STM32F3DISCOVERYでD言語のプログラムを実行する

LDCコンパイラでSTM32F3DISCOVERYで動く実行バイナリをいろいろ苦労して作成した。

いろいろ罠

LDCのオプションは罠だらけ

  • march,mcpuの指定が罠

    • float ABIの指定でhardが効かない、soft ABIとなる
  • tripleの指定が罠

    • eabihfだとsoft-float ABIになってしまう、gnueabihfにしないとhard-float ABIにならない
    • OSにunknownが指定できない、とりあえずLinuxを指定して対処

リンカまわり

  • エントリポイントが0x1バイトずれる
    • 外から-eオプションで渡して回避

最終的な実行バイナリ生成コマンド

$ ldc2 -mtriple=thumbv7em-none-linux-gnueabihf -c -g main.d
$ arm-none-eabi-ld main.o -e 0x8000009 -T layout.ld -nostartfiles -o main.bin

readelfの出力

  • エントリポイントアドレスが 0x8000009 になっていればよい
  • Float ABIが hard-float ABI になっていればよい
$ arm-none-eabi-readelf -h main.bin
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x8000009
  Start of program headers:          52 (bytes into file)
  Start of section headers:          1548 (bytes into file)
  Flags:                             0x5000400, Version5 EABI, hard-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         2
  Size of section headers:           40 (bytes)
  Number of section headers:         16
  Section header string table index: 13

objdumpの出力

このような内容になった

$ arm-none-eabi-objdump -Cd main.bin

main.bin:     file format elf32-littlearm


Disassembly of section .text:

08000000 <_reset-0x8>:
 8000000:       2000a000        .word   0x2000a000
 8000004:       08000009        .word   0x08000009

Disassembly of section _reset:

08000008 <_reset>:
 8000008:       b082            sub     sp, #8
 800000a:       202a            movs    r0, #42 ; 0x2a
 800000c:       9000            str     r0, [sp, #0]
 800000e:       9001            str     r0, [sp, #4]
 8000010:       e7ff            b.n     8000012 <_reset+0xa>
 8000012:       2000            movs    r0, #0
 8000014:       2800            cmp     r0, #0
 8000016:       d102            bne.n   800001e <_reset+0x16>
 8000018:       e7ff            b.n     800001a <_reset+0x12>
 800001a:       e7ff            b.n     800001c <_reset+0x14>
 800001c:       e7f9            b.n     8000012 <_reset+0xa>
 800001e:       b002            add     sp, #8
 8000020:       4770            bx      lr

OpenOCD

APTで入れたものであればこのような表示になる。

$ openocd -f board/stm32f3discovery.cfg
Open On-Chip Debugger 0.9.0 (2015-09-02-10:42)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
Info : The selected transport took over low-level target control. The results mi
ght differ compared to plain JTAG/SWD
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v16 API v2 SWIM v0 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 2.917647
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints

GDB

GDBでリモート接続する。

$ arm-none-eabi-gdb -q main.bin
Reading symbols from main.bin...done.
(gdb) target remote :3333
Remote debugging using :3333

loadしてSTM32F3DISCOVERYボード上で実行できるようにする。

(gdb) load
Loading section .text, size 0x8 lma 0x8000000
Loading section _reset, size 0x1a lma 0x8000008
Start address 0x8000008, load size 34
Transfer rate: 244 bytes/sec, 17 bytes/write.

エントリポイントは 0x08000009 となっているが、プログラムの先頭は 0x08000008 となっている。

(gdb) disas
Dump of assembler code for function main:
=> 0x08000008 <+0>:     sub     sp, #8
   0x0800000a <+2>:     movs    r0, #42 ; 0x2a
   0x0800000c <+4>:     str     r0, [sp, #0]
   0x0800000e <+6>:     str     r0, [sp, #4]
   0x08000010 <+8>:     b.n     0x8000012 <main+10>
   0x08000012 <+10>:    movs    r0, #0
   0x08000014 <+12>:    cmp     r0, #0
   0x08000016 <+14>:    bne.n   0x800001e <main+22>
   0x08000018 <+16>:    b.n     0x800001a <main+18>
   0x0800001a <+18>:    b.n     0x800001c <main+20>
   0x0800001c <+20>:    b.n     0x8000012 <main+10>
   0x0800001e <+22>:    add     sp, #8
   0x08000020 <+24>:    bx      lr
End of assembler dump.

ステップ実行で確認。たしかに動いているようだ。

(gdb) step
main () at main.d:13
13          auto x = 42;
(gdb) print x
$1 = 42
(gdb) step
14          y = x;
(gdb) print y
$2 = 42
(gdb) print &x
$3 = (int *) 0x20009ff8
(gdb) print &y
$4 = (int *) 0x20009ffc