Open4

Arduinoの出力バイナリを眺める会

okuokuokuoku

月曜にはWioTerminalとMaix Amigoが届いちゃうので、それぞれのArduino環境でビルドされるバイナリを眺めてSDK作りの参考にしたい。

... 実はESP32とRaspberryPi Picoも届くんだけど、これらはちゃんとした(CMakeベースの)C SDKがあるのでSDKのコンテンツを眺めるだけで十分な情報が得られる。Arduinoはビルドを抽象化しているのでビルドされるバイナリの実物を見ないと安心できない。

okuokuokuoku

WioTerminal

スケッチのバイナリを取得するには、 "スケッチ" → "コンパイルしたバイナリを出力" 。WioTerminalの場合は直接.binを書き込んでいるようだ。

$ file Blink.ino.wio_terminal.bin
Blink.ino.wio_terminal.bin: data

... HEXと違って.bin、つまり生バイナリではどのアドレスに書いているか判らないので直接 TEMP 見るか。。

oku@stripe /cygdrive/c/Users/oku/AppData/Local/Temp/arduino_build_302759
$ ls
Blink.ino.bin*  Blink.ino.hex*  build.options.json*  includes.cache*  preproc/
Blink.ino.elf*  Blink.ino.map*  core/                libraries/       sketch/

マップファイルをアップロードしてみた。

https://gist.github.com/okuoku/c25f2b4030c02b3b845328d14daf8b84

容量削減のため、ArduinoCoreを含めた全体がソースコードからビルドされていて、dead code strip用に1関数1セクションになっていることがわかる。この辺の指定は、ArduinoCoreがわにある。

compiler.c.flags=-mcpu={build.mcu} -mthumb
   -c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections
   -fdata-sections -nostdlib --param max-inline-insns-single=500 -MMD
   -D__SKETCH_NAME__="""{build.project_name}"""
...
compiler.ldflags=-mcpu={build.mcu} -mthumb -Wl,--cref
  -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all 
  -Wl,--warn-common -Wl,--warn-section-align -u _printf_float -u _scanf_float 
  -Wl,--wrap,_write -u __wrap__write

WioTerminalのためには更に追加のCFLAGS、LDFLAGSがあり、特にメモリ上のレイアウトを指定するldscriptはそこで指定されている。

https://github.com/Seeed-Studio/ArduinoCore-samd/blob/28c4ac5980a0393f7417c773c5d8fa4f5283b379/variants/wio_terminal/linker_scripts/gcc/flash_with_bootloader.ld

flash_with_bootloader.ldflash_without_bootloader.ld の2つがあるが、後者は使われていないようだ。

oku@stripe ~/repos/ArduinoCore-samd/variants/wio_terminal/linker_scripts/gcc
$ git diff --no-index flash_with_bootloader.ld flash_without_bootloader.ld
diff --git a/flash_with_bootloader.ld b/flash_without_bootloader.ld
index c582eb9..513edcc 100644
--- a/flash_with_bootloader.ld
+++ b/flash_without_bootloader.ld
@@ -25,7 +25,7 @@
  */
 MEMORY
 {
-  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
   RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
 }

@@ -58,6 +58,7 @@ MEMORY
  *   __StackLimit
  *   __StackTop
  *   __stack
+ *   __ram_end__
  */
 ENTRY(Reset_Handler)

@@ -67,9 +68,6 @@ SECTIONS
        {
                __text_start__ = .;

-               KEEP(*(.sketch_boot))
-
-               . = ALIGN(0x4000);
                KEEP(*(.isr_vector))
                *(.text*)

@@ -200,13 +198,13 @@ SECTIONS
         * used for linker to calculate size of stack sections, and assign
         * values to stack symbols later */
        .stack_dummy (COPY):
-       {       __StackStart = .;
+       {
                *(.stack*)
        } > RAM

        /* Set stack top to end of RAM, and stack limit move down by
         * size of stack_dummy section */
-       __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+       __StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
        __StackLimit = __StackTop - SIZEOF(.stack_dummy);
        PROVIDE(__stack = __StackTop);

Bootloaderとしてflash先頭16KiBを使用していて、セクション .sketch_bootが使われている。↑ の .map ファイルを見ればわかるように、このセクションの内容は実際のビルドでは空になっているので、特に気にする必要は無い。

書き込みプロセス

Bossa 1.8を使っている。

seeed_wio_terminal.upload.tool=bossac18
seeed_wio_terminal.upload.protocol=sam-ba
tools.bossac18.path={runtime.tools.bossac-1.8.0-48-gb176eee.path}
tools.bossac18.cmd=bossac
tools.bossac18.upload.params.verbose=-i -d
tools.bossac18.upload.params.quiet=
tools.bossac18.upload.pattern="{path}/{cmd}" {upload.verbose} --port={serial.port.file} -U -i --offset={upload.offset} -w -v "{build.path}/{build.project_name}.bin" -R

BossaはARM sam-baのFOSS代替で、GitHubにある。

https://github.com/shumatech/BOSSA

okuokuokuoku

Maixduino

https://maixduino.sipeed.com/en/get_started/install.html

CDN版とそうでないものの2つある、が、違いはないようだ。。

古すぎてMaix Amigoをサポートしてない。。まず適当に ↑ のjsonでボードをインストールした後、 Arduino ディレクトリにサブディレクトリ hardware/Maixduino を掘ってチェックアウトすることでGitリポジトリをボードとして使用できる:

oku@stripe /cygdrive/c/Users/oku/Documents/Arduino/hardware/Maixduino
$ git clone https://github.com/sipeed/Maixduino k210

(READMEの手順は間違っているのでうまくいかない。)

... しかもMapファイルが出てこないな。。まぁ適当にパッチして出力させた。

diff --git a/platform.txt b/platform.txt
index 03fe6d8..622cab5 100644
--- a/platform.txt
+++ b/platform.txt
@@ -28,7 +28,7 @@ compiler.c.flags=-c {compiler.debug.flags} {compiler.both.flags} {compiler.prepr

 compiler.cpp.flags=-c {compiler.debug.flags} {compiler.both.flags} "-I{runtime.platform.path}/libraries/SPI/src" {compiler.preproc.flags} -std=gnu++17 -g -Wno-error=unused-variable -Wno-error=unused-function -Wno-error=unused-const-variable

-compiler.ld.flags=-mcmodel=medany -mabi=lp64f -march=rv64imafc -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -fno-zero-initialized-in-bss -Os -ggdb -nostartfiles -static -Wl,--gc-sections -Wl,-static -Wl,--whole-archive -Wl,--no-whole-archive -Wl,-EL -Wl,--no-relax -T {build.ldscript}
+compiler.ld.flags=-mcmodel=medany -mabi=lp64f -march=rv64imafc -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -fno-zero-initialized-in-bss -Os -ggdb -nostartfiles -static -Wl,--gc-sections -Wl,-static -Wl,--whole-archive -Wl,--no-whole-archive -Wl,-EL -Wl,--no-relax -T {build.ldscript} "-Wl,-Map,{build.path}/{build.project_name}.map"

 compiler.S.flags=-c {compiler.debug.flags} {compiler.both.flags} {compiler.preproc.flags} -g -x assembler-with-cpp -D __riscv64

https://gist.github.com/okuoku/5cfed980dbe9bd17a0255c8962efa6c6

書き込みプロセス

open-ec ( https://github.com/rgwan/open-ec ) モードの kflash(内製の書き込みツール)。

https://github.com/sipeed/kflash.py