必要なもの
arm-none-eabi-* とsrecord が必要。platformio を使ってるなら arm-none-eabi は ~/.platformio/packages/toolchain-gccarmnoneeabi/bin/ に入ってるので、パスを通すか Makefile を修正すればいい。
srecord は brew からインストールできる。
brew install srecord
エクスポートと make
"GCC (ARM Embedded)" でエクスポートする。
とりあえず make してみると、リンク以外はうまくいった。
vfprintf.c:(.text.__ssputs_r+0x46): undefined reference to `__wrap__malloc_r' vfprintf.c:(.text.__ssputs_r+0x66): undefined reference to `__wrap__realloc_r' vfprintf.c:(.text.__ssputs_r+0x72): undefined reference to `__wrap__free_r'
と言われてリンクできなかった。
Makefile のうち -Wl,--wrap,_malloc_r -Wl,--wrap,_free_r -Wl,--wrap,_realloc_r を消せばうまくいった。
Makefile は標準的な mbed とリンクしていることを想定していて、うまくいかないところがある。
mbed の代わりに mbed-dev をインポートしている場合以下の書きかえが必要
# SOFTDEVICE = mbed/TARGET_RBLAB_BLENANO/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s130_nrf51822_1_0_0/s130_nrf51_1.0.0_softdevice.hex SOFTDEVICE = ../mbed-dev/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s130_nrf51822_1_0_0/s130_nrf51_1.0.0_softdevice.hex
これで、make merge すると .build/combined.hex ができる。これを書きこめば使える。
メモリを32kb使えるようにする
mbed のオンラインコンパイラは BLE Nano v1.5 に対応しておらず、常に RAM を 16kb でしか使えない。実際にアプリケーションで使えるのは6kb程度となっていて、おそろしくキツい。
エクスポートしたらやりたいほうだいなので、リンカスクリプトを以下にように書きかえる。
--- mbed-dev/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_GCC_ARM/TARGET_MCU_NRF51_16K_S130/NRF51822.ld 2016-09-01 13:30:12.000000000 +0900 +++ NRF51822.ld 2016-09-01 22:39:00.000000000 +0900 @@ -3,7 +3,7 @@ MEMORY { FLASH (rx) : ORIGIN = 0x0001C000, LENGTH = 0x24000 - RAM (rwx) : ORIGIN = 0x20002800, LENGTH = 0x1800 + RAM (rwx) : ORIGIN = 0x20002800, LENGTH = 0x5800 } OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
メモリ量チェック用に main の最初にこんなのを書いている。
{ const uint32_t reason = NRF_POWER->RESETREAS; NRF_POWER->RESETREAS = 0xffffffff; // clear reason // reset cause should be shown everytime serial.printf("init [%x] sp:%x\r\n", reason, GET_SP()); }
以下にようになった
# LD スクリプト変更前 init [4] sp:20003fd0 # LD スクリプト変更後 init [4] sp:20007fd0
16kb のときメモリの最後は 0x20004000、32kb のときメモリの最後は 0x20008000 になるはずなので、main の最初の sp がこの値なら問題なく 32kb 使えているはず。
オンラインコンパイラでなんとかできないか
試行錯誤したけどダメだった。ARM は 0x00000000 から読んで MSP として初期化されるので、ここを書きかえれば初期スタックポインタの位置を移動できるはずだけど、生成された hex ファイルから該当部分だけを書きかえてもダメだった。
書きかえてブートさせてみると main までこないので、何か完全にハズれているらしい。リンカの段階でほかにも値を計算して書いてるのかもしれない。