とあるエンジニアの備忘log
ラベル
U-Boot
の投稿を表示しています。
すべての投稿を表示
ラベル
U-Boot
の投稿を表示しています。
すべての投稿を表示
2014年10月24日金曜日
ELCE 2014 & U-Boot Mini Summit in Düsseldorf
[昨年](/2013/10/elce-2013-u-boot-mini-summit-in.html)に引き続き、今年も [Embedded Linux Conference Europe](http://events.linuxfoundation.org/events/embedded-linux-conference-europe) と [U-Boot Mini Summit](http://www.denx.de/wiki/U-Boot/MiniSummitELCE2014) に行ってきました。 今年の開催地はドイツのデュッセルドルフでした。 最寄り駅。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvU2vUZ2dgEpz-wuYUUsTvIumWtBxsELBegJ4y75WZvcHSZzTirnBWhdycpE8coBahgIKOAn7QWILl7GxXzM5YwR0PzjEJdQcvl10kM0GG6URs7p9g7Icdqc1w9B5yuEtBmX88MEGnPYk/s1600/bahnhof.jpg) 会場までの道。のどかです。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUQH8TMoT8LSkCRlhMiuVHgahULjnx-gKpoS8dtJI12ruY8YBLQ5BnyBlt1XLzbmBGagEdcHgcL3co6xvnkkmcfdxjfpSqPI0FLQU4p9hgUWB0sCjzn3MwV3K07XUmXCaimjm2rKXL-8Q/s1600/strasse.jpg) 会場の Congress Centre Düsseldorf [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZQts4lTwctbF1jByHv61IZVZ87B_yfJLE9qBeXYFHwoxMX5s-7avzL4zSL2OUSrAhf93TH7ebQmPpKhgQA8PTlmgOyEQ_lzxA7NoV1GqQTxWqluXG-0GqXHuhp2ptgtqD-AHo9Wx3TOo/s1600/ccd.jpg) [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDtLsiM2sHt1SFff9dpk1v5BCLJZ3zGcRNubdaywjsXJrrNh2kQ-USOFtg3ZrmeD41vB_wKk3veNz8zkU3h2Voe6du3Q6C3qEi871JjeZGkf9PGejCAMu8Jy1A0UzBx1x8L1cgAExe5rQ/s1600/willkommen.jpg) メインのホール。もうすぐ始まります。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPKVf935Z5oz8ohCp0Ig1mSVs1tmbX9UHbkbzrNqLv8vF6qPK-snusFuaMCdpFTkuDA9ne_DXG3pA2QhQeen3MUJErtMSoWUsUZe6nlrI5l0NR3WbWpbeAWlntbFixASSHdLq4TgQaMjg/s1600/haupthalle.jpg) こちらは [U-Boot Mini Summit 2014](http://www.denx.de/wiki/U-Boot/MiniSummitELCE2014) の会場。14:30 からは自分のプレゼンです。ドキドキ。。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilphpMhijvWI1raCipv8tB-qRiKrUWPjPUUy1l3GR60uJvJcqv6vLRbxwYAQtyTE7_yRAKBTI9MGhh2NLpDsdxni9wROcq3ShU1ybPXyYGHWYNN3_Ik9KeZoe5MLmfMmLo6AbNYXwTzs8/s1600/uboot_summit2014.jpg) [ELCE2014](http://events.linuxfoundation.org/events/embedded-linux-conference-europe) の ARCHIVE ページにプレゼンしているところが載っていた。(なんだかビミョーな表情) [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0_rAhLrcAWGYxbXr97UfwmSbRe6YI8F_bjpN-OpWFNlIqnbKaa-GUwerqOZa5iqmLOO9VTYl6pv6r7bdZZ6czZOAt_qfaJAbthklSZ2lVlEkx5QLhBLTwXZDkfJXQydGoNE8AUmmxcUc/s1600/my_talk.jpg) プレゼンもなんとか無事に終えて、ホッ。 スライドは[こちら](http://www.denx.de/wiki/U-Boot/MiniSummitELCE2014)からダウンロード可能。 最後に集合写真。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoos58upKdKkAZoaaFFLL_TJH7W_K7ajNKR-h4_mVvQ_Uy7aogS9ZV1FT6cqifT1rMdcn2KnA6ob6cvv_qVvdPJgpfuN84mx0YirUey0MzEionCMmt8HMHACp4Pmhc9sW8o5qkUBfkFQw/s1600/U-Boot-Mini-Summit-2014.jpg) 夜は Füchschen というビアレストランで飲み会。「地球の歩き方」に載っていたので、結構有名なお店なんでしょうか。 [](http://3.bp.blogspot.com/-24yopBmKYuA/VEJ99dSgiLI/AAAAAAAAMTE/VqQMGbOw-zM/s1600/uboot_beer_summit2014.jpg) 3 日目のステージには Linus が登場。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMpV0FxTfzMAhF0O2t21PpAnE8foXjLOxNLcx3NSCQSBuypENbIuoL0tWsQPOapKcVldQF59ATgSr9emaNxroRsAMzmuSJXgT9BC4XNd0RYyP5cDAfYa61QVODq9s364i2KxVIKch0xVI/s1600/linus_elce2014.jpg) 去年(左)は「XL サイズしか残ってません!」と言われてしまったが、今年(右)はちゃんと MサイズのTシャツがもらえました。 [](http://3.bp.blogspot.com/-5v0pDM_PuEE/VEKFiIfyqeI/AAAAAAAAMTw/SWAGetnc7sY/s1600/elce_shirts.jpg) U-Boot の発展に貢献したということで、 DENX から素敵な贈り物を頂きました。一応 USBメモリとしても使えます。 [](http://1.bp.blogspot.com/-wqV3CcFKuPM/VEWo94kbeQI/AAAAAAAAMUo/eZGI-hKrcYo/s1600/denx_usb_memory.jpg)
2014年7月15日火曜日
U-Boot と Linux Kernel のメインラインで Zynq を動かす 2014年7月版
本日 U-Boot 2014.07 がリリースされました。 [前回](/2014/05/u-boot-linux-kernel-zynq-201404.html)から U-Boot の方のやり方が少し変わったので、今回もまとめておきます。 具体的には、 v2014.04 で動かなくなっていた DTB を使った U-Boot のブートシーケンスが動くようになっていたり、 煩雑な工程のいくつかが不要になっています。 使用するのは、 - U-Boot 2014.07 - Linux Kernel 3.15 - Zynq ZC706 ボード とします。 ### STEP0: DTC (Device Tree Compiler) の準備 ##### Input Files Required - None ##### Output Files Produced - `dtc`: Device Tree Compiler ##### Task Description U-Boot を Device Tree 付きでビルドするには version 1.4 以降の DTC が必要になる。 ディストリビューションに標準で用意されている DTC では不足するかもしれないのでバージョンを確認。 $ dtc -v Version: DTC 1.3.0 バージョンが 1.4.0 よりも古い場合は、自分でビルドします。 $ git clone git://git.kernel.org/pub/scm/utils/dtc/dtc.git でソースを取ってきて $ make $ make install でビルドとインストールができる。 `$(HOME)/bin` の下に `dtc` が入るので PATH を通しておく。 ### STEP1: U-Boot のビルド ##### Input Files Required - `dtc` - ARM Cross Compiler - `ps7_init.c`: ISE / Vivado で "Export Hardware for SDK" を実行すると出力される - `ps7_init.h`: ISE / Vivado で "Export Hardware for SDK" を実行すると出力される ##### Output Files Produced - `u-boot-dtb.bin`: U-Boot の RAWバイナリと u-boot をコンフィグレーションする DTB を連結したもの - `u-boot-dtb.img`: `u-boot-dtb.bin` に uImage ヘッダーをつけたもの - `spl/u-boot-spl.bin`: U-Boot SPLの RAWバイナリ - `tools/mkimage`: U-Boot で扱うイメージを生成するツール。 ##### Task Description $ git clone git://git.denx.de/u-boot.git $ cd u-boot $ git checkout v2014.07 でソース取得して、v2014.07 タグをチェックアウト。 (何かあっても自分で対処できる人は masterブランチでやってもOK) あとで、Kernel を TFTP でダウンロードしたいので、`include/configs/zynq-common.h` を開いて、適当なところに #define CONFIG_IPADDR 192.168.11.2 #define CONFIG_SERVERIP 192.168.11.1 #define CONFIG_ETHADDR 00:0a:35:00:01:22 の3行を足す。 `CONFIG_IPADDR` は Zynqボードに割り振る IPアドレス、 `CONFIG_SERVERIP` は TFTP サーバーのアドレスに合わせて下さい。 MACアドレスは、(他のネットワーク機器と被らなければ)適当でいい。 TFTP サーバーがなくても、動かすことはできるので、ない人は上記はスキップして下さい。 さらに、 `ps7_init.c`, `ps7_init.h` を U-Boot の `board/xilinx/zynq` ディレクトリにコピーする。 このファイルが、 FSBL の代わりをするための、肝になるファイルです。 あとは $ make zynq_zc70x_config $ make CROSS_COMPILE=arm-linux-gnueabi- DEVICE_TREE=zynq-zc706 のようにして、コンフィグレーションとビルドをする。 もしくは $ make zynq_zc70x_config all CROSS_COMPILE=arm-linux-gnueabi- DEVICE_TREE=zynq-zc706 のように 1行で、コンフィグレーションとビルドを同時にすることもできる。 `ps7_init.c` と `ps7_init.h` が warning を出しますが、気にしなくてもOK。 気になる人は、関数のプロトタイプの引数部に `void` を足してください。 ### STEP2: Linux Kernel のビルド ##### Input Files Required - ARM Cross Compiler ##### Output Files Produced - `arch/arm/boot/zImage`: Kernel Image - `arch/arm/boot/dts/zynq-zc706.dtb`: Kernel をコンフィグレーションする DTB (Device Tree Blob) (従来、 U-Boot から Kernel を起動するときは `arch/arm/boot/uImage` を使っていたが、これは使わない。) ##### Task Description $ git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git $ cd linux $ git checkout v3.15 でソース取得して、v3.15 タグをチェックアウト。 (何かあっても自分で対処できる人は masterブランチでやってもOK) 以下のようにして ARMv7 Multi な設定にする。 $ make ARCH=arm multi_v7_defconfig ここで $ make ARCH=arm menuconfig をして、少々設定をいじる。 Device Drivers ---> Block devices ---> [*] RAM block device support (16384) Default RAM disk size (kbytes) のようにたどり、 `RAM block device support` にチェックを入れ、 `Default RAM disk size` を `16384` に設定する。 もう一つ Device Drivers ---> Character devices ---> [ ] Legacy (BSD) PTY support のようにたどり、`Legacy (BSD) PTY support` のチェックを外す。 あとは $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- でビルド。 ### STEP3: Ramdisk のダウンロード ##### Input Files Required - None ##### Output Files Produced - `arm_ramdisk.image.gz`: Kernel がマウントする init ramdisk (を gzip 圧縮したもの) ##### Task Description [こちら](http://www.wiki.xilinx.com/Build+and+Modify+a+Rootfs) から arm_ramdisk.image.gz をダウンロードする。 ### STEP4: ITB (Image Tree Blob) の生成 ##### Input Files Required - `linux/arch/arm/boot/zImage` - `arm_ramdisk.image.gz` - `linux/arch/arm/boot/dts/zynq-zc706.dtb` - `u-boot/tools/mkimage` カレントディレクトリから見て、上記の配置になっているとする。 ##### Output Files Produced - `fit.itb`: U-Boot から Kernel を起動するためのイメージ ##### Task Description Kernel Image, Ramdisk, DTB (Device Tree Blob) を一つにまとめた ITB というのを作ります。 ITB を作るには、 ITS(Image Tree Source) を記述して、 `mkimage` に食わせます。 以下の内容を `fit.its` というファイルに記述する。 /dts-v1/; / { description = "Kernel, ramdisk and FDT blob"; #address-cells = <1>; images { kernel@1 { description = "Linux Kernel 3.15 configured with multi_v7_defconfig"; data = /incbin/("linux/arch/arm/boot/zImage"); type = "kernel"; arch = "arm"; os = "linux"; compression = "none"; load = <0x00008000>; entry = <0x00008000>; hash@1 { algo = "md5"; }; }; ramdisk@1 { description = "Ramdisk for Zynq"; data = /incbin/("arm_ramdisk.image.gz"); type = "ramdisk"; arch = "arm"; os = "linux"; compression = "gzip"; load = <0x00000000>; entry = <0x00000000>; hash@1 { algo = "sha1"; }; }; fdt@1 { description = "FDT for ZC706"; data = /incbin/("linux/arch/arm/boot/dts/zynq-zc706.dtb"); type = "flat_dt"; arch = "arm"; compression = "none"; hash@1 { algo = "crc32"; }; }; }; configurations { default = "config@1"; config@1 { description = "Zynq ZC706 Configuration"; kernel = "kernel@1"; ramdisk = "ramdisk@1"; fdt = "fdt@1"; }; }; }; あとは以下のようにすれば、`fit.itb` ができる。 $ u-boot/tools/mkimage -f fit.its fit.itb ### STEP5: JTAG (Slave Boot) から U-Boot と Linux を起動する ##### Input Files Required - `u-boot-dtb.bin`: STEP1 で作成したもの - `fit.itb`: STEP4 で作成したもの - `xmd`: ISE / Vivado のインストールディレクトリに入っている - `ps7_init.tcl`: ISE / Vivado から "Export Hardware for SDK" を実行すると出力される - `stub.tcl`: Xilinx のページからダウンロードできる `ug873-design-files.zip` の中に入っている - `fpga.bit`: ISE / Vivado で生成した FPGA bit file (Optional) ##### Task Description `fit.itb` を TFTP の公開ディレクトリに置く。(TFTP 環境のない人はスキップして下さい) Zynq ボードのブートモードの選択スイッチを JTAG に合わせて電源入れる。JTAG でボードと接続し、XMD を開く。 $ xmd XMD のプロンプトから以下を実行する。(FPGA は必要なければダウンロードしなくても良い) XMD% connect arm hw ;# Open JTAG connection XMD% rst -slcr ;# Reset the whole system XMD% fpga -f fpga.bit ;# Download FPGA bit file (Optional) XMD% source ps7_init.tcl XMD% ps7_init ;# Initialize DDR, IO pins, etc. XMD% ps7_post_config ;# Enable level shifter XMD% source stub.tcl ;# start CPU1 XMD% targets 64 ;# connect to CPU0 XMD% dow -data u-boot-dtb.bin 0x04000000 ;# Download u-boot to address 0x04000000 XMD% con 0x04000000 ;# start CPU0 from address 0x04000000 なお、毎回これを打ち込むのも面倒ですので、 `foo.tcl` に書いておきましょう。 XMD% source foo.tcl で XMD から読み込むか、シェルから $ xmd -tcl foo.tcl とすればよいです。 U-Boot のプロンプトが出た後、放っておくと、自動的に TFTPサーバーから `fit.itb` をダウンロードして、 Linux が起動する。 TFTP サーバーがない場合は、`con 0x04000000` の前に XMD% dow -data fit.itb 0x02000000 とすれば、 JTAG 経由で `fit.itb` をダウンロードできるので(時間かかりますが、、) あとは U-Boot のプロンプトから > bootm 2000000 と入力して Linux を起動させる。 ### STEP6: SDカード用のブートイメージを作成する ##### Input Files Required - `u-boot/spl/u-boot-spl.bin`: STEP1 で作成したもの ##### Output Files Produced - `boot.bin` ##### Task Description `bootgen` を使わずに `boot.bin` を作成する方法を紹介します。 u-boot-xlnx のコードを取ってきます。 git clone git://github.com/Xilinx/u-boot-xlnx.git `tools` ディレクトリの下に `zynq-boot-bin.py` という Python スクリプトが 入っているので、これを `~/bin` かどこか適当な PATH にコピーする。 あとは zynq-boot-bin.py -o boot.bin -u u-boot/spl/u-boot-spl.bin とすれば、 `boot.bin` ができます。 BIF ファイルを記述しなくてもいい分、こちらの方が簡単だと思います。 ### Step7: SDカードから U-Boot と Linux Kernel を起動する ##### Input Files Required - `boot.bin`: STEP6 または STEP6B で作成したもの - `u-boot-dtb.img`: STEP1 で作成したもの - `fit.itb`: STEP4 で作成したもの ##### Task Description FAT でフォーマットしたSDカードに `boot.bin`, `u-boot-dtb.img`, `fit.itb` をコピー。 SDカードを Zynq ボードに挿し、ブートモードの選択スイッチを SD カードに合わせて電源入れる。 ### 補足 U-Boot の起動時に以下の Warning メッセージが出ると思いますが、気にしなくていいです。 Warning: Your board does not use generic board. Please read doc/README.generic-board and take action. Boards not upgraded by the late 2014 may break or be removed. これは開発者向けの情報です。次回のリリースでは修正されているはず。 消したい人は `include/configs/zynq-common.h` に #define CONFIG_SYS_GENERIC_BOARD を足す。
2014年5月28日水曜日
Device Tree アクセス関数まとめ (DTC & U-Boot)
Device Tree Compiler や U-Boot に入っている Device Tree アクセス関数をまとめました。 ### `_fdt_nodename_eq` (fdt_ro.c:17) static int _fdt_nodename_eq(const void *fdt, int offset, const char *s, int len) DTB `fdt` の DT structure の先頭から `offset` の位置の文字列(`0` または `@` で終端されている)と 文字列 `s` (長さ `len`) を比較し、 一致すれば `1` を、一致しなければ `0` を返す。 ### `fdt_string` (fdt_ro.c:78) const char *fdt_string(const void *fdt, int stroffset) DTB `fdt` の DT strings の先頭から `stroffset` の位置の文字列へのポインタを返す。 ### `_fdt_string_eq` (fdt_ro.c:83) static int _fdt_string_eq(const void *fdt, int stroffset, const char *s, int len) DTB `fdt` の DT strings の先頭から `stroffset` の位置の文字列と、 文字列 `s` (長さ `len`) を比較する。 長さも、文字列も一致すれば `1` を、それ以外は `0` を返す。 `strcmp` と論理が逆なので注意する。 ### `_nextprop` (fdt_ro.c:108) static int _nextprop(const void *fdt, int offset) DTB `fdt` の DT structure の先頭から `offset` の位置のタグを調べ、プロパティならば `offset` を返す。 それ以外は負のエラーコードを返す。 ### `fdt_subnode_offset_namelen` (fdt_ro.c:132) int fdt_subnode_offset_namelen(const void *fdt, int offset, const char *name, int namelen) DTB `fdt` の DT structure の先頭から `offset` 位置 (ノード先頭を指していないといけない)のノードから見て、 1つ下の階層のサブノードのうち、ノード名 `name` (長さ `namelen`) のものを探す。 見つかれば、そのサブノードのオフセット位置を返し、見つからなかったり、エラーの場合は負のエラーコードを返す。 ### `fdt_subnode_offset` (fdt_ro.c:151) int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name) DTB `fdt` の DT structure の先頭から `offset` 位置 (ノード先頭をさしていないといけない)のノードから見て、 1つ下の階層のサブノードのうち、ノード名 `name` のものを探す。 見つかれば、そのサブノードのオフセット位置を返し、見つからなかったり、エラーの場合は負のエラーコードを返す。 ### `fdt_path_offset` (fdt_ro.c:157) int fdt_path_offset(const void *fdt, const char *path) DTB `fdt` から `path` のパスのノードを探し、そのオフセット位置を返す。 見つからない場合や、エラーの場合は負のエラーコードを返す。 `path` が `'/'` で始まらない場合はエイリアスとみなされる。 ### `fdt_get_name` (fdt_ro.c:201) const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) DTB `fdt` の DT structure の先頭から `nodeoffset` 位置 (ノード先頭を指していないといけない) のノードの名前を返す。 `len` に `NULL` 以外が与えられていると、ノード名の長さを詰めて返す。 エラーの場合は、`NULL` を返し、 `len` には負のエラーコードを詰める。 ### `fdt_first_property_offset` (fdt_ro.c:221) int fdt_first_property_offset(const void *fdt, int nodeoffset) DTB `fdt` の DT structure の先頭から `nodeoffset` 位置 (ノード先頭を指していないといけない) の最初のプロパティ位置のオフセットを返す。 見つからないときや、エラーの場合は負のエラーコードを返す。 ### `fdt_get_property_by_offset` (fdt_ro.c:239) const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int offset, int *lenp) DTB `fdt` の DT structure の先頭から `offset` 位置がプロパティ先頭かを確認し、 プロパティならば、そのポインタを返し、 `lenp` (に `NULL` 以外が与えられていれば)にプロパティ値の長さを詰める。 プロパティでなければ、`NULL` を返し、`lenp` には エラーコードを詰める。 ### `fdt_get_property_namelen` (fdt_ro.c:260) const struct fdt_property *fdt_get_property_namelen(const void *fdt, int offset, const char *name, int namelen, int *lenp) DTB `fdt` の DT structure の先頭から `offset` 位置 (ノード先頭を指していないといけない) のノードからプロパティ名が `name` (長さ `namelen`)のものを探し、見つかれば、そのプロパティへのポインタを返し、 `lenp` (に`NULL` 以外が与えられていれば)にプロパティ値の長さを詰める。 見つからない場合やエラーの場合は、`NULL` を返し、`lenp` にエラーコードを詰める。 ### `fdt_get_property` (fdt_ro.c:284) const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp) DTB `fdt` の DT structure の先頭から `offset` 位置 (ノード先頭を指していないといけない) のノードからプロパティ名が `name` のものを探し、見つかれば、そのプロパティへのポインタを返し、 `lenp` (に`NULL` 以外が与えられていれば)にプロパティ値の長さを詰める。 見つからない場合やエラーの場合は、`NULL` を返し、`lenp` にエラーコードを詰める。 ### `fdt_getprop_namelen` (fdt_ro.c:251) const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, const char *name, int namelen, int *lenp) DTB `fdt` の DT structure の先頭から `offset` 位置 (ノード先頭を指していないといけない) のノードからプロパティ名が `name` (長さ `namelen`)のものを探し、見つかれば、そのプロパティの値へのポインタを返し、 `lenp` (に`NULL` 以外が与えられていれば)にプロパティ値の長さを詰める。 見つからない場合やエラーの場合は、`NULL` を返し、`lenp` にエラーコードを詰める ### `fdt_getprop_by_offset` (fdt_ro.c:265) const void *fdt_getprop_by_offset(const void *fdt, int offset, const char **namep, int *lenp) DTB `fdt` の DT structure の先頭から `offset` 位置 (プロパティ先頭を指していないといけない) のプロパティの値へのポインタを返す。 `namep` に `NULL` 以外が与えられていれば、プロパティ名を詰め、 `lenp` に `NULL` が与えられていれば、プロパティ値の長さを詰める。 エラーのときは、 `NULL` を返し、 `lenp` に (`NULL`以外が与えられていれば、エラーコードを詰める) ### `fdt_getprop` (fdt_ro.c:276) const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp) DTB `fdt` の DT structure の先頭から `offset` 位置 (ノード先頭を指していないといけない) のノードからプロパティ名が `name` のものを探し、見つかれば、そのプロパティの値へのポインタを返し、 `lenp` (に`NULL` 以外が与えられていれば)にプロパティ値の長さを詰める。 見つからない場合やエラーの場合は、`NULL` を返し、`lenp` にエラーコードを詰める ### `fdt_get_phandle (fdt_ro.c:282)` uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) DTB `fdt` の DT structure の先頭から `offset` 位置 (ノード先頭を指していないといけない) のノードからプロパティ "phandle" の値を返す。 "phandle" が見つからない場合は、 "linux,phandle" の値を返す。 見つからない場合は `0` を返す。 ### `fdt_get_alias_namelen` (fdt_ro.c:299) const char *fdt_get_alias_namelen(const void *fdt, const char *name, int namelen) ノード `name` の別名(エイリアス)を文字列として返す。 エイリアスは `"/aliases"` ノードに格納されているので、そのノードからプロパティ名 `name` (長さ `namelen`) のものを探し、そのプロパティ値を返す。 見つからない場合は `NULL` を返す。 ### `fdt_supernode_atdepth_offset` (fdt_ro.c:368) int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int supernodedepth, int *nodedepth) DTB `fdt` の DT structure の先頭から `nodeoffset` 位置 (ノード先頭を指していないといけない)のノード の親(直接の親とは限らない)のうち、 `supernodedepth` の深さのもののオフセットを返す。 見つからない場合は、負のエラーコードを返す。 `nodedepth` に `NULL` 以外が与えられていれば、自身の階層の深さを詰める。 ### `fdt_node_depth` (fdt_ro.c:404) int fdt_node_depth(const void *fdt, int nodeoffset) DTB `fdt` の DT structure の先頭から `nodeoffset` 位置 (ノード先頭を指していないといけない)のノード の深さを返す。 エラーの場合は、負のエラーコードを返す。 ### `int fdt_parent_offset(const void *fdt, int nodeoffset)` (fdt_ro.c:416) int fdt_parent_offset(const void *fdt, int nodeoffset) DTB `fdt` の DT structure の先頭から `nodeoffset` 位置 (ノード先頭を指していないといけない)のノード の直接の親ノードのオフセット位置を返す。 エラーの場合は、負のエラーコードを返す。 ### `fdt_node_offset_by_prop_value` (fdt_ro.c:425) int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const char *propname, const void *propval, int proplen) DTB `fdt` の DT structure 領域の `startoffset` 位置から検索開始し、 プロパティ名 `propname` と プロパティ値 `propval` の組み合わせを持つノードが見つかると そのノードへのオフセットを返す。 見つからない場合やエラーの場合は、負のエラーコードを返す。 ### `fdt_node_offset_by_phandle` (fdt_ro.c:452) int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) DTB `fdt` の DT structure の先頭から探索し、phandle `phadle` を持つノードを返す。 見つからない場合や、エラーの場合は、府のエラー番号を返す。nodeoffset` 位置 (ノード先頭を指していないといけない)のノード の直接の親ノードのオフセット位置を返す。 ### `fdt_stringlist_contains` (rdt_ro.c:477) int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) 1つまたはそれ以上の文字列の連結 `strlist` (長さ `listlen`) 中に、文字列 `str` が含まれていれば `1`を、それ以外は `0` を返す。 ### `fdt_node_check_compatible` (rdt_ro.c:570) int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible) DTB `fdt` の DT structure の先頭から `offset` 位置 (ノード先頭を指していないといけない) のノードから `"compatible"` という名前のプロパティを探し、その値中に文字列 `compatible` があれば(compatible であれば)、`0` を返す。 compatible でない場合は、 `1` を返す。 ノードが `"compatible"` というプロパティを持たない場合や、その他エラーの場合は、負のエラーコードを返す。 ### `fdt_node_offset_by_compatible` (fdt_ro.c:585) int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible) DTB `fdt` の DT structure 領域の `startoffset` 位置から検索開始し、 `compatible` に対して compatible なノードを返す。 見つからなかったり、エラーの場合は、負のエラーコードを返す。 ### `fdt_offset_ptr` (fdt.c:77) const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) DTB `fdt` の DT structure の先頭から `offset` バイト目の位置のポインタを返す。 DT structure 領域をオーバーランしないかチェックするため、アクセスする長さを `len` に与える。 ### `fdt_next_tag` (fdt.c:93) uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) DTB `fdt` の DT structure の先頭から `startoffset` バイト目にあるタグを返す。 戻り値は `FDT_BEGIN_NODE`, `FDT_END_NODE`, `FDT_PROP`, `FDT_END`, `FDT_NOP`。 `FDT_END` は DT structure の最後に達したか、エラーを意味する。 次のタグの位置を `nextoffset` に詰める。エラー終了の場合は `nextoffset` にエラーコードを詰める。 ### `_fdt_check_node_offset` (fdt.c:143) int _fdt_check_node_offset(const void *fdt, int offset) DTB `fdt` の DT structure の先頭から `offset` バイト目がノードの先頭かをチェックする。 ノード先頭であれば、次のタグの `offset` 値を返し、それ以外は `-FDT_ERR_BADOFFSET` を返す。 ### `_fdt_check_prop_offset` (fdt.c:152) int _fdt_check_prop_offset(const void *fdt, int offset) DTB `fdt` の DT structure の先頭から `offset` バイト目がプロパティの先頭かをチェックする。 プロパティの先頭であれば、次のタグの `offset` 値を返し、それ以外は `-FDT_ERR_BADOFFSET` を返す。 ### `fdt_next_node` (fdt.c:120) int fdt_next_node(const void *fdt, int offset, int *depth) DTB `fdt` の DT structure の先頭から `offset` バイト目 (ノードを指していないといけない)から探索を開始し、次のノードを探す。 見つかれば、そのノードのオフセット位置を返す。 `depth` に `NULL` 以外が与えられていれば、階層を降りたり昇ったりするたびに、 `depth` を増減させる。 これは、繰り返し探索するときに、現在の階層の深さを記憶するのに使われる。 `depth` が負になるとそれ以上探索しない。 DT structure の終端に達した時や、見つからないとき、エラーの時は負のエラーコードを返す。 ### `fdt_first_subnode` (fdt.c:160) int fdt_first_subnode(const void *fdt, int offset) DTB `fdt` の DT structure の先頭から `offset` バイト目 (ノードを指していないといけない)から探索を開始し、最初のサブノードを探す。 見つかれば、そのノードのオフセットを位置を返す。見つからないときは、 `-FDT_ERR_NOTFOUND' を返す。 ### `fdt_next_subnode` (fdt.c:171) int fdt_next_subnode(const void *fdt, int offset) DTB `fdt` の DT structure の先頭から `offset` バイト目 (ノードを指していないといけない)から探索を開始し、次のサブノードを探す。 見つかれば、そのノードのオフセットを位置を返す。見つからないときは、 `-FDT_ERR_NOTFOUND' を返す。 ### `_fdt_find_string` (fdt.c:229) const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) 1つまたはそれ以上の文字列の連結 `strtab` (長さ `tabsize`) 中に、文字列 `s` が含まれているか検索する。 見つかると、そのポインタ位置を返す。見つからない場合は `NULL` を返す。 ### `_fdt_blocks_misordered` (fdt_rw.c:58) static int _fdt_blocks_misordered(const void *fdt, int mem_rsv_size, int struct_size) DTB `fdt` の構造を再構築する必要があるか判定する。 FDB の構造は常に Mermory Reserve Map, DT structure, DT strings の順に並んでいる必要がある。 `mem_rsv_size` には Memory Reserve Map のサイズ、`struct_size` には DT structure のサイズを渡す。 Mermory Reserve Map が DT structure 領域にオーバーラップしないか、 DT structuret が DT strings 領域にオーバーラップしないか、さらには DT strings の最後が DTB 全体のサイズを超えないかをチェックする。 再構築の必要があれば、`1`、それ以外は `0` を返す。 ### `_fdt_splice` (fdt_rw.c:97) _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) DTB `fdt` のポインタ位置 `splicepoint` から始まる、長さ `oldlen` 分のデータを、長さ `newlen` に変更するために、隙間を拡張したり、詰めたりする。 成功すると `0`、失敗すると負のエラーコードを返す。 ### `_fdt_splice_struct` (fdt_rw.c:123) static int _fdt_splice_struct(void *fdt, void *p, int oldlen, int newlen) DTB `fdt` のポインタ位置 `splicepoint` から始まる、長さ `oldlen` 分のデータを、長さ `newlen` に変更するために、隙間を拡張したり、詰めたりする。 さらに、DT structuret のサイズと、DT strings へのオフセットのヘッダー情報を更新する。 成功すると `0`、失敗すると負のエラーコードを返す。 ### `_fdt_splice_string` (fdt_rw.c:137) static int _fdt_splice_string(void *fdt, int newlen) DTB `fdt` の DT strings の末尾に、長さ `newlen` 分のスペースを確保し、 DT strings サイズのヘッダー情報を更新する。 成功すると `0`、失敗すると負のエラーコードを返す。 ### `_fdt_find_add_string` (fdt_rw.c:150) static int _fdt_find_add_string(void *fdt, const char *s) DTB `fdt` の DT strings 領域を検索し、文字列 `s` が見つかれば、そこへのオフセットを返す。 見つからない場合は、DT strings 領域の末尾に追加し、オフセットを返す。 失敗すると負のエラーコードを返す。 ### `_fdt_resize_property` (fdt_rw.c:205) static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, int len, struct fdt_property **prop) DTB `fdt` の DT structuret の先頭から `nodeoffset` 位置 (ノード先頭を指していないといけない) のノードからプロパティ名が `name` のものを探し、そのプロパティの長さを `len` にリサイズし、 `prop` にそのプロパティのポインタを返す。 成功すれば `0`、失敗すれば負のエラーコードを返す。 ### `_fdt_add_property` (fdt_rw.c:223) static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, int len, struct fdt_property **prop) DTB `fdt` の DT structuret の先頭から `nodeoffset` 位置(ノード先頭を指していないといけない) のノードに新しいプロパティ (プロパティ名 `name`、プロパティ値の長さ `len`)を追加する。 同名のプロパティがすでに存在しているかはチェックしない。 追加したプロパティへのポインタを `prop` に詰めて返す。 ### `fdt_setprop` (fdt_rw.c:274) int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len) DTB `fdt` の DT structuret の先頭から `nodeoffset` 位置(ノード先頭を指していないといけない) のノードの `name` というプロパティの値を `val` (長さ `len`) に書き変える。 `name` という名前のプロパティがまだ存在していない場合は新しく追加する。 成功すれば `0` を返し、失敗すれば負のエラーコードを返す。 ### `fdt_add_subnode_namelen` (fdt_rw.c:334) int fdt_add_subnode_namelen(void *fdt, int parentoffset, const char *name, int namelen) DTB `fdt` の DT structuret の先頭から `parentoffset` 位置(ノード先頭を指していないといけない)のノードに 名前 `name` (長さ `namelen`) のサブノードを追加する。 サブノードは、親ノードのプロパティの直後に追加される。 すでに同名のサブノードが存在する場合は失敗する。 成功すると、追加されたサブノードへのオフセットを返す。失敗すると、負のエラーコードを返す。 ### `fdt_add_subnode` (fdt_rw.c:375) int fdt_add_subnode(void *fdt, int parentoffset, const char *name) DTB `fdt` の DT structuret の先頭から `parentoffset` 位置(ノード先頭を指していないといけない)のノードに 名前 `name` のサブノードを追加する。 サブノードは、親ノードのプロパティの直後に追加される。 すでに同名のサブノードが存在する場合は失敗する。 成功すると、追加されたサブノードへのオフセットを返す。失敗すると、負のエラーコードを返す。 ### `_fdt_packblocks` (fdt_rw.c:394) static void _fdt_packblocks(const char *old, char *new, int mem_rsv_size, int struct_size) アドレス `old` 上の DTB をアドレス `new` 上に再構築する。 新しい DTB の Memory Reserve Map サイズは `mem_rsv_size` に、 DT structuret サイズは `struct_size` となる。 ### `fdt_open_into` (fdt_rw.c:416) int fdt_open_into(const void *fdt, void *buf, int bufsize) DTB `fdt` をバッファ `buf` (サイズ `bufsize`) に読み出す。 通常は、そのままコピーされるだけだが、必要があるときには `_fdt_packblocks` 関数を呼び出して、リフォーマットする。 ### `fdt_pack` (fdt_rw.c:480) int fdt_pack(void *fdt) DTB `fdt` の余分な Memory Reserve Map 領域を詰めて、再パッキングする。
2014年5月27日火曜日
LinuxCon Japan 2014
5月20-22日に LinuxCon Japan に行ってきました。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnDSE3YSGlVd92Y1Jy3qIN4-f8H-rtNjf3zHLLehaJKp60Cf97irXzB1PCU7FJD3lcAtIIYpU7ldZVSPybHiK62jZ28NxpdtMqLHNErrkmD7Q7CX9Mq56SMBQnkSCHLBu4iyU3if9LtWg/s1600/lcj2014_board.jpg)
[](http://2.bp.blogspot.com/-PS8zFY4Lm6c/U4KCVMzxQxI/AAAAAAAAKlM/QnoL2icWPzE/s1600/lcj2014.jpg) 2日目最後のステージに Linus が登場。 会場が一斉に写真を取り出すも、「カメラは後にしてくれ」と言っているところ。
[](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1e2YaUhEUWCpTcfAvfGqK130rwo0CpFOMMYFm_yMBt1609wybYQ0xNAw1wOYzSwkcoXnUbA2tGDHEUGwwEXTYi5ycJCkwPi_i9YvrCapa35t1OWmpSAXGyqZ0dRbBrriIQmrenukhyEU/s1600/lcj2014_tshirt.jpg) クールなメッセージ入りの Tシャツ。 今回は日本人向け Mサイズがもらえたのでよかった。 [](http://3.bp.blogspot.com/-MTwKQ9qrExM/U4KCreXG2DI/AAAAAAAAKlw/DocyhdH2hHU/s1600/uboot_summit.jpg) U-Boot の開発者と再会。 屋形船での飲み会。
2014年5月13日火曜日
U-Boot と Linux Kernel のメインラインで Zynq を動かす 2014年4月版
[以前](/2014/01/u-boot-linux-kernel-zynq.html)、2014年1月時点での U-Boot と Linux のメインラインで Zynq を動かす方法を紹介しました。 その後、コード(特に U-Boot)が大きく変わっているので、 2014年4月時点での動かし方を紹介することにします。 使用するのは、 - U-Boot 2014.04 - Linux Kernel 3.14 - Zynq ZC706 ボード です。 その前に、 Zynq のブートシーケンスを復習しておきましょう。 Active Boot (= JTAG ブート以外)は 1. Boot ROM 2. FSBL 3. U-Boot 4. Linux Kernel というのが、Xilinx が公式にサポートしているブートシーケンスで、 [Xilinx Wiki ページ](http://www.wiki.xilinx.com/)もこのやり方を紹介しています。 最近の U-Boot では 1. Boot ROM 2. U-Boot SPL 3. U-Boot 4. Linux Kernel というブートシーケンスも可能になっています。 SPL というのは Secondary Progmam Loader の略です。 DRAM 等のメモリを初期化し、U-Boot 本体を NAND, MMC 等のデバイスからロードするための、 より小さなブートローダーといったものです。 U-Boot の標準のインフラとして用意されています。 詳しく知りたい人は U-Boot の `doc/README.SPL` を読んでください。 これを選択するメリットは、 FSBL (First Stage Boot Loader) を生成するために、 XSDK (Xilinx SDK) を起動しなくても済む、ということです。 さらに簡略化した 1. Boot ROM 2. U-Boot SPL 3. Linux Kernel というブートシーケンスもあります。 (Falcon ブートといいます) これのメリットは U-Boot 本体をスキップすることで、より高速に Linux を起動できることです。 ただし、現時点ではサポートが限定的でまともに動かすのは難しいので、今回は割愛します。 おそらく、そう遠くないうちにまともに動かせるようになると思いますが。 以下では、 U-Boot 2014.04 から可能になった SPL を用いたブートのやり方を紹介します。 ### STEP1: U-Boot のビルド ##### Input Files Required - ARM Cross Compiler - `ps7_init.c`: ISE / Vivado で "Export Hardware for SDK" を実行すると出力される - `ps7_init.h`: ISE / Vivado で "Export Hardware for SDK" を実行すると出力される ##### Output Files Produced - `u-boot.bin`: U-Boot 本体の RAWバイナリ - `u-boot.img`: `u-boot.bin` に uImage ヘッダーをつけたもの - `spl/u-boot-spl.bin`: U-Boot SPLの RAWバイナリ - `tools/mkimage`: U-Boot で扱うイメージを生成するツール。 ##### Task Description $ git clone git://git.denx.de/u-boot.git $ cd u-boot $ git checkout v2014.04 でソース取得して、v2014.04 タグをチェックアウト。 (何かあっても自分で対処できる人は masterブランチでやってもOK) まず、少々ソースコードをいじらなくてはなりません。 `include/configs/zynq-common.h` を開き、以下のように `CONFIG_OF_CONTROL` ~ `CONFIG_RSA` までを無効にする。 --- a/include/configs/zynq-common.h +++ b/include/configs/zynq-common.h @@ -199,6 +199,7 @@ #define CONFIG_FIT #define CONFIG_FIT_VERBOSE 1 /* enable fit_format_{error,warning}() */ +#if 0 /* FDT support */ #define CONFIG_OF_CONTROL #define CONFIG_OF_SEPARATE @@ -207,6 +208,7 @@ /* RSA support */ #define CONFIG_FIT_SIGNATURE #define CONFIG_RSA +#endif /* Extend size of kernel image for uncompression */ #define CONFIG_SYS_BOOTM_LEN (20 * 1024 * 1024) なんで、上記を無効にするかというと、前回の U-Boot 2014.01 では U-Boot を DeviceTree 付きで動かしたのですが、コードのマージが中途半端に行われたために、 2014.04 で再び `CONFIG_OF_CONTROL` が動かなくなってしまったためです。 頑張って動かすことはできるのですが、 Linux Kernel から DeviceTree の記述をいろいろと持ってこなくてはいけなかったり、 SPL から u-boot.img + DeviceTree をロードするのにコード修正したりと、 いろいろと修正箇所が多いので、無効にしてしまった方が楽です。 また、あとで、Kernel を TFTP でダウンロードしたいので、`include/configs/zynq-common.h` の適当なところに #define CONFIG_IPADDR 192.168.11.2 #define CONFIG_SERVERIP 192.168.11.1 #define CONFIG_ETHADDR 00:0a:35:00:01:22 の3行を足す。 `CONFIG_IPADDR` は Zynqボードに割り振る IPアドレス、 `CONFIG_SERVERIP` は TFTP サーバーのアドレスに合わせて下さい。 MACアドレスは、(他のネットワーク機器と被らなければ)適当でいい。 TFTP サーバーがなくても、動かすことはできるので、ない人は上記はスキップして下さい。 さらに、 `ps7_init.c`, `ps7_init.h` を U-Boot の `board/xilinx/zynq` ディレクトリにコピーする。 このファイルが、 FSBL の代わりをするための、肝になるファイルです。 また touch board/xilinx/xil_io.h で、空の `xil_io.h` を作る。 (`ps7_init.c` が `xil_io.h` をインクルードしているので、これがないとエラーになる。) あとは $ make zynq_zc70x_config $ make CROSS_COMPILE=arm-linux-gnueabi- のようにして、コンフィグレーションとビルドをする。 もしくは $ make zynq_zc70x_config all CROSS_COMPILE=arm-linux-gnueabi- のように 1行で、コンフィグレーションとビルドを同時にすることもできる。 `ps7_init.c` と `ps7_init.h` が warning を出しますが、気にしなくてもOK。 気になる人は、関数のプロトタイプの引数部に `void` を足してください。 ### STEP2: Linux Kernel のビルド ##### Input Files Required - ARM Cross Compiler ##### Output Files Produced - `arch/arm/boot/zImage`: Kernel Image - `arch/arm/boot/dts/zynq-zc706.dtb`: Kernel をコンフィグレーションする DTB (Device Tree Blob) (従来、 U-Boot から Kernel を起動するときは `arch/arm/boot/uImage` を使っていたが、これは使わない。) ##### Task Description $ git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git $ cd linux $ git checkout v3.14 でソース取得して、v3.14 タグをチェックアウト。 (何かあっても自分で対処できる人は masterブランチでやってもOK) 以下のようにして ARMv7 Multi な設定にする。 $ make ARCH=arm multi_v7_defconfig ここで $ make ARCH=arm menuconfig をして、少々設定をいじる。 Device Drivers ---> Block devices ---> [*] RAM block device support (16384) Default RAM disk size (kbytes) のようにたどり、 `RAM block device support` にチェックを入れ、 `Default RAM disk size` を `16384` に設定する。 もう一つ Device Drivers ---> Character devices ---> [ ] Legacy (BSD) PTY support のようにたどり、`Legacy (BSD) PTY support` のチェックを外す。 あとは $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- でビルド。 ### STEP3: Ramdisk のダウンロード ##### Input Files Required - None ##### Output Files Produced - `arm_ramdisk.image.gz`: Kernel がマウントする init ramdisk (を gzip 圧縮したもの) ##### Task Description [こちら](http://www.wiki.xilinx.com/Build+and+Modify+a+Rootfs) から arm_ramdisk.image.gz をダウンロードする。 ### STEP4: ITB (Image Tree Blob) の生成 ##### Input Files Required - `linux/arch/arm/boot/zImage` - `arm_ramdisk.image.gz` - `linux/arch/arm/boot/dts/zynq-zc706.dtb` - `u-boot/tools/mkimage` カレントディレクトリから見て、上記の配置になっているとする。 ##### Output Files Produced - `fit.itb`: U-Boot から Kernel を起動するためのイメージ ##### Task Description Kernel Image, Ramdisk, DTB (Device Tree Blob) を一つにまとめた ITB というのを作ります。 ITB を作るには、 ITS(Image Tree Source) を記述して、 `mkimage` に食わせます。 以下の内容を `fit.its` というファイルに記述する。 /dts-v1/; / { description = "Kernel, ramdisk and FDT blob"; #address-cells = <1>; images { kernel@1 { description = "Linux Kernel 3.14 configured with multi_v7_defconfig"; data = /incbin/("linux/arch/arm/boot/zImage"); type = "kernel"; arch = "arm"; os = "linux"; compression = "none"; load = <0x00008000>; entry = <0x00008000>; hash@1 { algo = "md5"; }; }; ramdisk@1 { description = "Ramdisk for Zynq"; data = /incbin/("arm_ramdisk.image.gz"); type = "ramdisk"; arch = "arm"; os = "linux"; compression = "gzip"; load = <0x00000000>; entry = <0x00000000>; hash@1 { algo = "sha1"; }; }; fdt@1 { description = "FDT for ZC706"; data = /incbin/("linux/arch/arm/boot/dts/zynq-zc706.dtb"); type = "flat_dt"; arch = "arm"; compression = "none"; hash@1 { algo = "crc32"; }; }; }; configurations { default = "config@1"; config@1 { description = "Zynq ZC706 Configuration"; kernel = "kernel@1"; ramdisk = "ramdisk@1"; fdt = "fdt@1"; }; }; }; あとは以下のようにすれば、`fit.itb` ができる。 $ u-boot/tools/mkimage -f fit.its fit.itb ### STEP5: JTAG (Slave Boot) から U-Boot と Linux を起動する ##### Input Files Required - `u-boot.bin`: STEP1 で作成したもの - `fit.itb`: STEP4 で作成したもの - `xmd`: ISE / Vivado のインストールディレクトリに入っている - `ps7_init.tcl`: ISE / Vivado から "Export Hardware for SDK" を実行すると出力される - `stub.tcl`: Xilinx のページからダウンロードできる `ug873-design-files.zip` の中に入っている - `fpga.bit`: ISE / Vivado で生成した FPGA bit file (Optional) ##### Task Description `fit.itb` を TFTP の公開ディレクトリに置く。(TFTP 環境のない人はスキップして下さい) Zynq ボードのブートモードの選択スイッチを JTAG に合わせて電源入れる。JTAG でボードと接続し、XMD を開く。 $ xmd XMD のプロンプトから以下を実行する。(FPGA は必要なければダウンロードしなくても良い) XMD% connect arm hw ;# Open JTAG connection XMD% rst -slcr ;# Reset the whole system XMD% fpga -f fpga.bit ;# Download FPGA bit file (Optional) XMD% source ps7_init.tcl XMD% ps7_init ;# Initialize DDR, IO pins, etc. XMD% ps7_post_config ;# Enable level shifter XMD% source stub.tcl ;# start CPU1 XMD% targets 64 ;# connect to CPU0 XMD% dow -data u-boot.bin 0x04000000 ;# Download u-boot to address 0x04000000 XMD% con 0x04000000 ;# start CPU0 from address 0x04000000 なお、毎回これを打ち込むのも面倒ですので、 `foo.tcl` に書いておきましょう。 XMD% source foo.tcl で XMD から読み込むか、シェルから $ xmd -tcl foo.tcl とすればよいです。 U-Boot のプロンプトが出た後、放っておくと、自動的に TFTPサーバーから `fit.itb` をダウンロードして、 Linux が起動する。 TFTP サーバーがない場合は、`con 0x04000000` の前に XMD% dow -data fit.itb 0x02000000 とすれば、 JTAG 経由で `fit.itb` をダウンロードできるので(時間かかりますが、、) あとは U-Boot のプロンプトから > bootm 2000000 と入力して Linux を起動させる。 ### STEP6: SDカード用のブートイメージを作成する ##### Input Files Required - `u-boot/spl/u-boot-spl.bin`: STEP1 で作成したもの - `bootgen`: ISE / Vivado のインストールディレクトリに入っている ##### Output Files Produced - `boot.bin` ##### Task Description `foo.bif` というファイル(名前適当でよい)に以下のように記述する。 image: { [bootloader,load=0x00000000,startup=0x00000000]u-boot/spl/u-boot-spl.bin } そして $ bootgen -image foo.bif -w on -o boot.bin とすると、`boot.bin` ができる。SDカードのブートイメージは必ず `boot.bin` というファイル名でないといけないので注意する。 ### STEP6B: SDカード用のブートイメージを作成する (もうちょっと簡単なやり方) ##### Input Files Required - `u-boot/spl/u-boot-spl.bin`: STEP1 で作成したもの ##### Output Files Produced - `boot.bin` ##### Task Description `bootgen` を使わずに `boot.bin` を作成する方法を紹介します。 u-boot-xlnx のコードを取ってきます。 git clone git://github.com/Xilinx/u-boot-xlnx.git `tools` ディレクトリの下に `zynq-boot-bin.py` という Python スクリプトが 入っているので、これを `~/bin` かどこか適当な PATH にコピーする。 あとは zynq-boot-bin.py -o boot.bin -u u-boot/spl/u-boot-spl.bin とすれば、 `boot.bin` ができます。 BIF ファイルを記述しなくてもいい分、こちらの方が簡単だと思います。 なお、 u-boot-xlnx だと、 `zynq-boot-bin.py` が Makefile からフックされていて、 make すると自動で `boot.bin` までできるので、更に楽なのですが、 (しかもローカルでいろいろとソースをいじくらなくても動く) ここのページではあくまで、メインラインでやることを目指しています。 ### Step7: SDカードから U-Boot と Linux Kernel を起動する ##### Input Files Required - `boot.bin`: STEP6 または STEP6B で作成したもの - `u-boot.img`: STEP1 で作成したもの - `fit.itb`: STEP4 で作成したもの ##### Task Description FAT でフォーマットしたSDカードに `boot.bin`, `u-boot.img`, `fit.itb` をコピー。 SDカードを Zynq ボードに挿し、ブートモードの選択スイッチを SD カードに合わせて電源入れる。 ### STEP8: FSBL を使ったブートシーケンス 上記の通り、 SPL を使ったブートシーケンスを紹介しましたが、 従来通りの FSBL を使ったブートシーケンスも可能です。 その場合は U-Boot に `ps7_init.c` と `ps7_init.h` をコピーしたり、 `xil_io.h` を作ったりする必要はないです。 STEP6 の部分を以下のようにアレンジすればよいです。 ##### Input Files Required - `fsbl.elf`: FSBL (First Stage Boot Loader)。XSDK で生成。 - `fpga.bit`: FPGA bit file (Optional) - `u-boot/u-boot.bin`: STEP1 で作成したもの - `bootgen`: ISE / Vivado のインストールディレクトリに入っている ##### Output Files Produced - `boot.bin` ##### Task Description `foo.bif` というファイル(名前適当でよい)に以下のように記述する。 image: { [bootloader]fsbl.elf fpga.bit [load=0x04000000,startup=0x04000000]u-boot/u-boot.bin } FPGA Bit file のダウンロードが不要なら `fpga.bit` の行は削除してよい。 あとは $ bootgen -image foo.bif -w on -o boot.bin とすると、`boot.bin` ができるので、 FAT でフォーマットしたSDカードに `boot.bin` と `fit.itb` をコピー。 ### 今後の開発の行方 Zynq は U-Boot の中でも、特に頻繁に更新されている SoC で、今後もやり方が変わっていく可能性が高いです。 今回、ローカルでソースをいじくっている部分のいくつかは、修正パッチを投稿しておいたので、 次のリリースではもうちょっと楽になるはず。 U-Boot 2014.04 ではまともに動いてませんが、 DeviceTree を使った U-Boot のコンフィグレーションに移行していくでしょう。 最終的には、 `ps7_init.c` と `ps7_init.h` をコピーすることもなくなり、 すべての情報を DeviceTree から読み込むようになるだろう。 (と、コードを書いている Xilinx のエンジニアは語っておりました。)
2014年1月21日火曜日
U-Boot と Linux Kernel のメインラインで Zynq を動かす
[以前](/2014/01/zynq-2.html)、U-Boot と Linux をソースからビルドして Zynq 上で動かすには、[Wiki Page](http://www.wiki.xilinx.com/) を読むのがわかりやすいと書きました。 このページを参照しながら、やっている人も多いのではと思います。 Xilinx は GitHub に[ローカルな開発リポジトリ](https://github.com/Xilinx) を持っていて、 Wiki Page もこのリポジトリを使っています。 ここでは、Xilinx のリポジトリではなく、U-Boot と Linux Kernel のメインラインからコードを持ってきて、 Linux をブートさせるやり方を紹介します。 ちょうど、本日(=2014.1.21) U-Boot 2014.01 がリリースされました。 このリリースから Zynq の各種ボードサポートが U-Boot のメインラインにマージされたので、 Xilinx ローカルリポジトリを追跡しなくても動かせるようになりました。 また、前日 (=2014.1.20) には Linux 3.13 がリリースされましたので、これを使ってみます。 今回使うのは - U-Boot 2014.01 - Linux Kernel 3.13 - Zynq ZC706 ボード です。 ただし、Wiki Page で紹介されているやり方と結構違います。主な違いは - U-Boot 自身のコンフィグレーションにも Device Tree が必要 - Kernel のイメージは、従来のレガシー uImage ではなく、 FIT (Flattened uImage Tree) を使う - Kernel の defconfig は `multi_v7_defconfig` を使う 入門者には何言っているかわからないかもしれないが、以下で丁寧に手順を説明します。 ### STEP0: DTC (Device Tree Compiler) の準備 ##### Input Files Required - None ##### Output Files Produced - `dtc`: Device Tree Compiler ##### Task Description U-Boot を Device Tree 付きでビルドするには version 1.4 以降の DTC が必要になる。 ディストリビューションに標準で用意されている DTC では不足するかもしれないのでバージョンを確認。 $ dtc -v Version: DTC 1.3.0 バージョンが 1.4.0 よりも古い場合は、自分でビルドします。 $ git clone git://git.kernel.org/pub/scm/utils/dtc/dtc.git でソースを取ってきて $ make $ make install でビルドとインストールができる。 `$(HOME)/bin` の下に `dtc` が入るので PATH を通しておく。 ### STEP1: U-Boot のビルド ##### Input Files Required - `dtc` - ARM Cross Compiler ##### Output Files Produced - `u-boot-dtb.bin`: U-Boot の RAWバイナリと U-Boot をコンフィグレーションする DTB を連結したもの - `tools/mkimage`: U-Boot で扱うイメージを生成するツール。 (Wiki Page では `u-boot` を使っているが、これは使わない。) ##### Task Description $ git clone git://git.denx.de/u-boot.git $ cd u-boot $ git checkout v2014.01 でソース取得して、v2014.01 タグをチェックアウト。 (何かあっても自分で対処できる人は masterブランチでやってもOK) あとで、Kernel を TFTP でダウンロードしたいので、`include/configs/zynq-common.h` を開いて、適当なところに #define CONFIG_IPADDR 192.168.11.2 #define CONFIG_SERVERIP 192.168.11.1 #define CONFIG_ETHADDR 00:0a:35:00:01:22 の3行を足す。 `CONFIG_IPADDR` は Zynqボードに割り振る IPアドレス、 `CONFIG_SERVERIP` は TFTP サーバーのアドレスに合わせて下さい。 MACアドレスは、(他のネットワーク機器と被らなければ)適当でいい。 TFTP サーバーがなくても、動かすことはできるので、ない人は上記はスキップして下さい。 あとは $ make zynq_zc70x_config $ make CROSS_COMPILE=arm-linux-gnueabi- DEVICE_TREE=zynq-zc706 のようにして、コンフィグレーションとビルドをする。 もしくは $ make zynq_zc70x CROSS_COMPILE=arm-linux-gnueabi- DEVICE_TREE=zynq-zc706 のように 1行で、コンフィグレーションとビルドを同時にすることもできる。 ### STEP2: Linux Kernel のビルド ##### Input Files Required - ARM Cross Compiler ##### Output Files Produced - `arch/arm/boot/zImage`: Kernel Image - `arch/arm/boot/dts/zynq-zc706.dtb`: Kernel をコンフィグレーションする DTB (Device Tree Blob) (従来、 U-Boot から Kernel を起動するときは `arch/arm/boot/uImage` を使っていたが、これは使わない。) ##### Task Description $ git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git $ cd linux $ git checkout v3.13 でソース取得して、v3.13 タグをチェックアウト。 (何かあっても自分で対処できる人は masterブランチでやってもOK) 以下のようにして ARMv7 Multi な設定にする。 $ make ARCH=arm multi_v7_defconfig ここで $ make ARCH=arm menuconfig をして、少々設定をいじる。 Device Drivers ---> Block devices ---> [*] RAM block device support (16384) Default RAM disk size (kbytes) のようにたどり、 `RAM block device support` にチェックを入れ、 `Default RAM disk size` を `16384` に設定する。 もう一つ Device Drivers ---> Character devices ---> [ ] Legacy (BSD) PTY support のようにたどり、`Legacy (BSD) PTY support` のチェックを外す。 あとは $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- でビルド。 ### STEP3: Ramdisk のダウンロード ##### Input Files Required - None ##### Output Files Produced - `arm_ramdisk.image.gz`: Kernel がマウントする init ramdisk (を gzip 圧縮したもの) ##### Task Description [こちら](http://www.wiki.xilinx.com/Build+and+Modify+a+Rootfs) から arm_ramdisk.image.gz をダウンロードする。 ### STEP4: ITB (Image Tree Blob) の生成 ##### Input Files Required - `linux/arch/arm/boot/zImage` - `arm_ramdisk.image.gz` - `linux/arch/arm/boot/dts/zynq-zc706.dtb` - `u-boot/tools/mkimage` カレントディレクトリから見て、上記の配置になっているとする。 ##### Output Files Produced - `fit.itb`: U-Boot から Kernel を起動するためのイメージ ##### Task Description Kernel Image, Ramdisk, DTB (Device Tree Blob) を一つにまとめた ITB というのを作ります。 ITB を作るには、 ITS(Image Tree Source) を記述して、 `mkimage` に食わせます。 以下の内容を `fit.its` というファイルに記述する。 /dts-v1/; / { description = "Kernel, ramdisk and FDT blob"; #address-cells = <1>; images { kernel@1 { description = "Linux Kernel 3.13 configured with multi_v7_defconfig"; data = /incbin/("linux/arch/arm/boot/zImage"); type = "kernel"; arch = "arm"; os = "linux"; compression = "none"; load = <0x00008000>; entry = <0x00008000>; hash@1 { algo = "md5"; }; }; ramdisk@1 { description = "Ramdisk for Zynq"; data = /incbin/("arm_ramdisk.image.gz"); type = "ramdisk"; arch = "arm"; os = "linux"; compression = "gzip"; load = <0x00000000>; entry = <0x00000000>; hash@1 { algo = "sha1"; }; }; fdt@1 { description = "FDT for ZC706"; data = /incbin/("linux/arch/arm/boot/dts/zynq-zc706.dtb"); type = "flat_dt"; arch = "arm"; compression = "none"; hash@1 { algo = "crc32"; }; }; }; configurations { default = "config@1"; config@1 { description = "Zynq ZC706 Configuration"; kernel = "kernel@1"; ramdisk = "ramdisk@1"; fdt = "fdt@1"; }; }; }; あとは以下のようにすれば、`fit.itb` ができる。 $ u-boot/tools/mkimage -f fit.its fit.itb ### STEP5: JTAG (Slave Boot) から U-Boot と Linux を起動する ##### Input Files Required - `u-boot-dtb.bin`: STEP1 で作成したもの - `fit.itb`: STEP4 で作成したもの - `xmd`: ISE / Vivado のインストールディレクトリに入っている - `ps7_init.tcl`: ISE / Vivado から "Export Hardware for SDK" を実行すると出力される - `stub.tcl`: Xilinx のページからダウンロードできる `ug873-design-files.zip` の中に入っている - `fpga.bit`: ISE / Vivado で生成した FPGA bit file (Optional) ##### Task Description `fit.itb` を TFTP の公開ディレクトリに置く。(TFTP 環境のない人はスキップして下さい) Zynq ボードのブートモードの選択スイッチを JTAG に合わせて電源入れる。JTAG でボードと接続し、XMD を開く。 $ xmd XMD のプロンプトから以下を実行する。(FPGA は必要なければダウンロードしなくても良い) XMD% connect arm hw ;# Open JTAG connection XMD% rst -slcr ;# Reset the whole system XMD% fpga -f fpga.bit ;# Download FPGA bit file (Optional) XMD% source ps7_init.tcl XMD% ps7_init ;# Initialize DDR, IO pins, etc. XMD% ps7_post_config ;# Enable level shifter XMD% source stub.tcl ;# start CPU1 XMD% targets 64 ;# connect to CPU0 XMD% dow -data u-boot-dtb.bin 0x04000000 ;# Download u-boot to address 0x04000000 XMD% con 0x04000000 ;# start CPU0 from address 0x04000000 なお、毎回これを打ち込むのも面倒ですので、 `foo.tcl` に書いておきましょう。 XMD% source foo.tcl で XMD から読み込むか、シェルから $ xmd -tcl foo.tcl とすればよいです。 U-Boot のプロンプトが出た後、放っておくと、自動的に TFTPサーバーから `fit.itb` をダウンロードして、 Linux が起動する。 TFTP サーバーがない場合は、`con 0x04000000` の前に XMD% dow -data fit.itb 0x02000000 とすれば、 JTAG 経由で `fit.itb` をダウンロードできるので(時間かかりますが、、) あとは U-Boot のプロンプトから > bootm 2000000 と入力して Linux を起動させる。 ### STEP6: SDカード用のブートイメージを作成する ##### Input Files Required - `fsbl.elf`: FSBL (First Stage Boot Loader)。XSDK で生成。 - `fpga.bit`: FPGA bit file (Optional) - `u-boot/u-boot-dtb.bin`: STEP1 で作成したもの - `bootgen`: ISE / Vivado のインストールディレクトリに入っている ##### Output Files Produced - `boot.bin` ##### Task Description `foo.bif` というファイル(名前適当でよい)に以下のように記述する。 image: { [bootloader]fsbl.elf fpga.bit [load=0x04000000,startup=0x04000000]u-boot/u-boot-dtb.bin } FPGA Bit file のダウンロードが不要なら `fpga.bit` の行は削除してよい。 ELF ファイルはロードアドレスとエントリーアドレスを自動抽出してくれるが、 バイナリの場合は `load=` と `startup=` で指定する必要がある。 あとは $ bootgen -image foo.bif -w on -o boot.bin とすると、`boot.bin` ができる。SDカードのブートイメージは必ず `boot.bin` というファイル名でないといけないので注意する。 ### Step7: SDカードから U-Boot と Linux Kernel を起動する ##### Input Files Required - `boot.bin`: STEP6 で作成したもの - `fit.itb`: STEP4 で作成したもの ##### Task Description FAT でフォーマットしたSDカードに `boot.bin` と `fit.itb` をコピー。 SDカードを Zynq ボードに挿し、ブートモードの選択スイッチを SD カードに合わせて電源入れる。 ### ZC706 以外のボードの場合 動作確認はしていないが、上記とほぼ同じやり方でできずはず。 U-Boot のビルドの部分が、ZC702 ボードなら $ make zynq_zc70x CROSS_COMPILE=arm-linux-gnueabi- ZED ボードならば $ make zynq_zed CROSS_COMPILE=arm-linux-gnueabi- となる。 U-Boot の `boards.cfg` というファイルを見れば、自分のボードに対応するコマンドがわかる。 Linux の Device Tree も `arch/arm/boot/dts` ディレクトリに各ボードごとの DTB ができているので、それを使う。 ### その他参照資料 - Device Tree を用いた U-Boot のコンフィグレーションについて知りたい場合は U-Boot ソースツリーの `doc/README.fdt-control` を参照 - ITS (Image Tree Source) の書き方を知りたい場合は U-Boot ソースツリーの `doc/uImage.FIT/` 以下のドキュメント参照 - XMD の使い方は Xilinx の資料 "Embedded System Tools Reference Manual" 参照 - FSBL の作り方は Xilinx の資料 "Zynq-7000 All Programmable SoC: Concepts, Tools, and Techniques" 5章を参照 - Bootgen をもっと詳しく知りたい場合は Xilinx の資料 "Zynq-7000 All Programmable SoC Software Developers Guide" 参照 ### ご注意 ここに記載の内容は 2014年1月時点のソースでのやり方ですので、今後もこのやり方が通用するかはわかりません。 コードはめまぐるしく変わっていきますので。
2013年10月29日火曜日
ELCE 2013 & U-Boot Mini Summit in Edinburgh
先週、Embedded Linux Conference Europe と U-Boot Mini Summit に参加するために、イギリスはエジンバラまで行ってきました。
ホテル - 会場間の町並み。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirPj1P8i3rIuxPdODUlhZjJwJFKJ6ugt3vUbiRTXBgQO5rs-30szPXSYOxnU4DsS3UlelF4dv87vY2f2N5AVYvAJGsObiy11i7I68bAAKsBqquLm2WBLCHwSF45DhqdB47U_Y6KgAw8xI/s1600/street.jpg)
23日夜はレセプションイベントがありました。会場のNational Museum of Scotland。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRYu550R-0KFixTu2VojCQJOBXi5s-tQFzYukiCUvOeFtK6EXVhmp6dpBIbiiEhVT15TzVeLQYFMu2NU8MxjESXyPF35RHFcMO56-qMVLegyzLy8VwAyYVE8BLZqknEDwnd_7VNCX5oDw/s1600/nmos.jpg)
レセプションではディナーやカジノを楽しむことができます。自分はルーレットやってました。
途中までは、ビギナーズラックでかなり勝ちました。最終的に全部なくなりましたが。。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNqiimLiEcp09ugfVIsCDepZxetSK6AC8zqb7RtglVS0neEygw8Dghte6SLwnwKPpYGNJ6ef0YMvNb2yGjhs_zgnxW0Gfdp4CKBIJbwj8L_KUrJqovwvVxyGnz0vDcXZiHN2xLM5-BQw0/s1600/casino.jpg)
ELCE 会場の Edinburgh International Conference Centre。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0ZFnsNxeg3eh4xOLrYsE3EkkTwAW1fhY_WLWTUFP2NHXync90YvJ9-bxCKaNX1uNfgnWd3IiXQLhH0MTuPu2psYD2s8f4ArCfaQ5MWSwela9cjGK5ITqrnbAn9R9yCwDkv0QDLdDMyeI/s1600/eicc.jpg)
受付や休憩場所のある Strathblane Hall の様子。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0cMFCbFM8dkDPmu1lVAfjveSDkNg4ASr1XQ_yi1IfUwQWcIY8WkXgu6fIAWvk5RAvKq4lxZPMq5ymIiGR24FZdBPVsiK8kLfk-vup-C4mxSBzV7OmTpgiDV0qJKR_RKolouGDN9kUJuQ/s1600/strath.jpg)
Chris Simmonds 氏による Keynote。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY6NYWUZZZ0X72IoFEymIlFrfmfM_J-7d3nTF9eP-qS_QkOph_XTDb4tmoDlQSvWsEyAOUFVj7qxWL4PVL4fk2uSeFv-1tY86sx9nghkiD6Vcxiwbdvjb0FD9O18hAB0-lOULK3D92AgU/s1600/keynote.jpg)
同会場で開催された U-Boot Mini Summit にも参加。
こちらはこじんまりとした感じ。聴衆は30〜40人くらいだったでしょうか。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTatXYS2Q8QQYvIN0q6zw9092y3hyJjUUrCTzUlA3r1RcgvMVabfsQCmy8ogySyOnx70__TOH3ydUcuitJbW35l9hYxWk3NE4EAx2sOp6lEhK4Oo3-TI2spOO5acyWxTYX3vR5OWP1CHw/s1600/uboot.jpg)
私が最近投稿していたパッチがスライドで紹介されているところ。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilI5ZAuElXLNObhvqdftwhMRw8AGyRTDHf2skwS7d3HlHTyEyOKuFNdZJcgEkKC25shTSbvXODAxcPXVwoJyLgI23ggZXiB7-GiPh9gFIQiPoXMfVevXZ-0BbhiAv9qeWLefMQMqEOoRc/s1600/uboot2.jpg)
24日夜は、U-Boot 開発陣で飲みに行きました。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL9tOETkiGiBUFfOw-oKKqq1hni0E6Hr4wsciWyL_y0yKxU_Y9u22TBNZXu-UZgBsiG5o1ewXTJbRGplyJ2BRHBE9V7nnL95b4wdmUajN_Vc7Vfr2CmQ9Xqmc7CI58kX2MhIvSyWJR-9A/s1600/bar.jpg)
Closing Gameの様子。 [](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcR0mL889R_KmIaNb0TVX0gDIg3YYOAmIYCYRR6V5Xch9cAeWzqdpZSlPpKvcDDA-hV-h3zaNJZ8u-RfrK9T1YJAvjwC6Z41YmgKpcuctMNO2wTrfaSy3OUTbMueSwXs_dLYJom30t0bw/s1600/closing.jpg) あるアンケートに対して、答えた人数が多い回答を当てていく。
3回 Strike すると、回答権が相手チームに渡り、当てるとポイントを Steal できる。
要するに、昔やってた「関口宏のクイズ100人に聞きました」ですね。
勉強にもなり、かつ楽しい一時でした。 普段 ML でやりとりしている人と直接会って話ができたのも良かったです。 来年の開催地はデュッセルドルフ。また行きたいです。
前の投稿
ホーム
登録:
投稿 (Atom)