みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

BBBでu-bootのスタンドアロンアプリを試す

はじめに

u-bootのスタンドアロンアプリのサンプルを動かす。

ターゲットはBeagleBone Black(BBB)

ただ、BBBを使うといろいろと罠がある。

動いてるu-bootが違う

SDカードにMLOを含めてu-bootやカーネルを入れたはずなのに、UARTコンソールで表示されるu-bootのバージョンが違う。

これは 電源投入時にUSERボタンを押していない場合はeMMCに書き込まれたu-bootが起動する から。

スタンドアロンアプリの作成

u-bootとスタンドアロンアプリはYoctoで作成した。

下記を実行するとu-bootが出来上がる。

$ bitbake virtual/bootloader

それと一緒にbuild/tmp/work/beaglebone_yocto-poky-linux-gnueabi/u-boot/1_2020.01-r0/build/examples/standaloneスタンドアロンアプリが出来上がる。

今回試すバイナリは下記。

ファイル名 概要
hello_world elfファイル
hello_world.bin バイナリファイル

これらのファイルはSDカードのbootパーティション(FAT)に書き込む。

スタンドアロンアプリの実行

elfの実行

u-bootでelfを実行するには下記のような手順になる。

  1. fatからメモリにファイルをロードする
  2. bootelfで実行する

実際には下記のようなコマンドで実行する。

=> fatload mmc 0 82000000  hello_world
=> bootelf 82000000
## Starting application at 0x80300001 ...
Example expects ABI version 9
Actual U-Boot ABI version 9
Hello World
argc = 0
argv[0] = "<NULL>"
Hit any key to exit ..

この時点で若干の違和感はあったが、とりあえず動いた。

バイナリの実行

u-bootでバイナリを実行するには下記のような手順になる。

  1. fatからメモリにファイルをロードする
  2. goで実行する
=> fatload mmc 0 80300000 hello_world.bin
=> go 80300000
## Starting application at 0x80300000 ...
undefined instruction
pc : [<80300008>]          lr : [<9ff64457>]
reloc pc : [<60b9e008>]    lr : [<80802457>]
sp : 9df38b18  ip : 00000000     fp : 00000002
r10: 9df4ca70  r9 : 9df41eb0     r8 : 9ffd3334
r7 : 9ff79e75  r6 : 00000002     r5 : 80300000  r4 : 9df4ca74
r3 : 80300000  r2 : 9df4ca74     r1 : 9df4ca74  r0 : 00000001
Flags: nzCv  IRQs off  FIQs on  Mode SVC_32
Code: ffff0000 ffff0000 41f0e92d 46084605 (f000460e)
Resetting CPU ...

あれ?

bootelfとgoで指定するアドレスが異なるのはbootelfではu-bootがelfを解釈してプログラムを適切な場所にロードして実行するため。 bootelfの場合はファイルをロードする場所とプログラムをロードする場所が異なっている。

goの場合は直接実行するのでプログラムが実行されるアドレスへあらかじめファイルをロードする必要がある。

プログラムが実行されるアドレスの根拠はu-bootのCONFIG_STANDALONE_LOAD_ADDRの値。

./arch/arm/config.mk:CONFIG_STANDALONE_LOAD_ADDR = 0x80300000

しかし動かない。

動かない原因

bootelf実行時のログをよく読むと下記のようになっている。

## Starting application at 0x80300001 ...

なので、下記のように実行してみた。

=> fatload mmc 0 80300000 hello_world.bin
=> go 80300001
## Starting application at 0x80300001 ...
Example expects ABI version 9
Actual U-Boot ABI version 9
Hello World
argc = 1
argv[0] = "80300001"
argv[1] = "<NULL>"
Hit any key to exit ...

## Application terminated, rc = 0x0

動く。

この1バイトなに?

よくわからなかったのでつぶやいて見たところ@ciniml先生からレスが。

readelfすると確かにThumb-2だ。

ファイル属性
  Tag_CPU_name: "7-A"
  Tag_CPU_arch: v7
  Tag_CPU_arch_profile: アプリケーション
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-2
  Tag_ABI_PCS_wchar_t: 2
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-バイト
  Tag_ABI_align_preserved: 末端の SP を除き 8-バイト
  Tag_ABI_enum_size: int
  Tag_ABI_optimization_goals: Aggressive Size

1バイトってか、フラグの1ビットだった。

まとめ

Thumb2の時はアドレス指定に注意。