電気回路/z-turn/基本事項 の履歴(No.3)
更新z-turn board とは†
http://www.myirtech.com/list.asp?id=502
zynq-7000 を載せた MYIR の SoC ボードです
ユーザーI/O が豊富なので、周辺機器をたくさん繋ぎたい場合には他になかなか選択肢がないです
ただ、あまりメジャーなボードじゃないので情報が少なくて大変です。
とりあえずこのページの内容が判明したおかげで、ようやく開発に移れます。
通常の起動†
- 付属の SD カードを Micro_SD ポートに挿す
- USB キーボードを USB_OTG ポートに挿す
- HDMI ケーブルでディスプレイと繋ぐ
- 電源コードを挿す
これで Linux が起動する
ただし、HDMI の IP が試用版なので、30分するとディスプレイの表示が消える
USB ケーブルで起動†
- 付属の SD カードを Micro_SD ポートに挿す
- USB_UART ポートへ PC からの USB ケーブルを挿す
- PC に新しい COM ポートが増える
- Silicon Labs CP210x USB to UART Bridge (COMx)
- この COM ポートをターミナルソフトで開く
- ボーレート 115,200 baud
- データ 8bit
- パリティ none
- ストップ 1bit
- フロー制御 none
- リセットを押す
- 必要に応じて Ethernet ケーブルを繋ぐ
これで、ターミナルソフトから Linux のコンソールにアクセスできる
起動用 SD カードを新規作成する†
z-turn 上で Linux が立ち上がった状態では、
LANG:console $ df Filesystem 1K-blocks Used Available Use% Mounted on /dev/root 3546736 1466584 1880272 44% / none 77172 560 76612 1% /run none 5120 0 5120 0% /run/lock none 385856 8 385848 1% /run/shm /dev/mmcblk0p1 197676 28001 169676 15% /media/boot $ mount /dev/root on / type ext4 (rw) none on /proc type proc (rw,noexec,nosuid,nodev) none on /sys type sysfs (rw,noexec,nosuid,nodev) devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620) none on /run type tmpfs (rw,noexec,nosuid,size=10%,mode=0755) none on /run/lock type tmpfs (rw,noexec,nosuid,nodev,size=5242880) none on /run/shm type tmpfs (rw,nosuid,nodev) /dev/mmcblk0p1 on /media/boot type vfat (rw,nosuid,nodev,uid=0,gid=0,shortname=mixed,dmask=0077,utf8=1,showexec,flush,uhelper=udisks) $ ls / bin dev home lost+found mnt proc run selinux sys usr boot etc lib media opt root sbin srv tmp var $ ls /media/boot 7z010-hdmi.bit BOOT.bin uEnv-ramdisk.txt 7z010-lcd.bit System Volume Information uEnv-ubuntu.txt 7z010.bit devicetree-7ic.dtb uEnv.txt 7z020-hdmi.bit devicetree-hdmi-1080p.dtb uImage 7z020-lcd.bit devicetree-hdmi-720p.dtb uramdisk.image.gz 7z020.bit devicetree.dtb
のようになっていて、
- /media/boot にマウントされた /dev/mmcblk0p1
- 起動用ファイルが入っており、FAT32 なので Windows からでも読める
- / にマウントされた /dev/root
- Linux 用ファイルが入っており、ext4 なので Windows からは読めない
の2つが SD カードの2つのパーティション。
新しい SD カードにこの2つのパーティションを用意するのは Windows からだと難しいので、VirtualBox 内の Linux を使うと良い
http://marsee101.blog19.fc2.com/blog-entry-2818.html を参考に、
- 新しい SD カードを PC の SD カードリーダに挿す
- VirtualBox 上の Linux コンソールを開く
- VirtualBox のメニュー [デバイス]-[USB]-[Card Reader] にチェックを入れる
- lsblk で SD カードを見つける
- fdisk で2つパーティションを作る
- 一旦 [デバイス]-[USB]-[Card Reader] のチェックを消して、再度付ける
- mkfs でパーティションをフォーマットする
- mount でマウントする
- z-turn 付属の DVD を PC に挿入
- lsblk で DVD を見つける
- mount でマウントする
- /media/cdrom0/02-Images/Ubuntu/sd_partitions/ の中身を SD カードへ書き込む
LANG:console $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 10G 0 disk ├─sda1 8:1 0 9.6G 0 part / ├─sda2 8:2 0 1K 0 part └─sda5 8:5 0 466M 0 part [SWAP] sdf 8:80 1 7.4G 0 disk sr0 11:0 1 2.3G 0 rom $ sudo fdisk /dev/sdf $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 10G 0 disk ├─sda1 8:1 0 9.6G 0 part / ├─sda2 8:2 0 1K 0 part └─sda5 8:5 0 466M 0 part [SWAP] sdf 8:80 1 7.4G 0 disk ├─sdf1 8:81 1 64M 0 part └─sdf2 8:82 1 7.4G 0 part sr0 11:0 1 2.3G 0 rom $ sudo mkfs.msdos -n boot /dev/sdf1 $ sudo mkfs.ext4 -L root /dev/sdf2 $ sudo mkdir /mnt/sdcard1 $ sudo mount /dev/sdf1 /mnt/sdcard1 $ sudo mkdir /mnt/sdcard2 $ sudo mount /dev/sdf2 /mnt/sdcard2 $ mount /dev/sr0 $ cd /mnt/sdcard1 $ sudo tar fxz /media/cdrom0/02-Images/Ubuntu/sd_partitions/part0.tar.gz $ sudo mv part0/* . $ sudo rmdir part0 $ cd /mnt/sdcard2 $ sudo tar fxz /media/cdrom0/02-Images/Ubuntu/sd_partitions/part1.tar.gz $ sudo mv part1/* . $ sudo rmdir part1
Zynq のブートローダを理解する†
独自のロジックを PL 領域 (Programmable Logic) に読み込んで、 Linux 上のソフトから使える状態になるまでには、次のようなブートプロセスが走ることになる。
- Processing System 内部にハードコードされた BootROM が SD カードの BOOT.bin から [bootloader] のついた領域を PS 内 RAM へロードして実行する
- BOOT.bin には FSBL (First Stage Boot Loader) と呼ばれるプログラムに [bootloader] を付けて保存しておく。FSBL が *.bit ファイルを読み込むことで PS および PL 領域の初期化を行い、さらに第2ステージのブートローダを起動する。
- 第2ステージのブートローダが Linux カーネルやデバイスツリーなどをロードして、Linux へ制御を移す
- アプリケーションコードは Linux 上の実行ファイルとしておき Linux コマンドとして実行する
z-turn の起動メッセージを読むと、
始めに表示されるのは、
LANG:console U-Boot 2013.10-svn7 (Apr 20 2015 - 20:49:24) Memory: ECC disabled DRAM: 1 GiB myir_board_init MMC: zynq_sdhci: 0 SF: Detected W25Q128BV with page size 256 Bytes, erase size 4 KiB, total 16 MiB *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial Net: Gem.e000b000 Hit any key to stop autoboot: 3
- U-Boot というプログラムが走っている
- 最後の行で Enter キーを押すと起動オプションを入力するためのコンソールが現れる
- print と打つと、環境変数の一覧を表示できる (http://marsee101.blog19.fc2.com/blog-entry-2927.html)
特に選択しない場合、
LANG:console Device: zynq_sdhci Manufacturer ID: 3 OEM: 5344 Name: SU04G Tran Speed: 50000000 Rd Block Len: 512 SD version 3.0 High Capacity: Yes Capacity: 3.7 GiB Bus Width: 4-bit reading uEnv.txt 395 bytes read in 20 ms (18.6 KiB/s) Loaded environment from uEnv.txt Importing environment from SD ...
と続き、ここで uEnv.txt というファイルが読み込まれる。
uEnv.txt の中身は
bootargs=console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0 load_image=fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image} uenvcmd=run mmc_loadbit_fat && echo Copying Linux from SD to RAM... && mmcinfo && run load_image && bootm ${kernel_load_address} - ${devicetree_load_address}
ここに出てくる環境変数の値は、
kernel_image=uImage kernel_load_address=0x2080000 devicetree_image=devicetree.dtb devicetree_load_address=0x2000000
となっているみたい。
ということは、これらを書き換えれば好きな内容をロードできるはず。
で、起動メッセージの続きは、
LANG:console Running uenvcmd ... Loading bitstream from SD/MMC/eMMC to RAM.. ... reading 7z020.bit 4045675 bytes read in 250 ms (15.4 MiB/s) design filename = "mys_xc7z020_trd;UserID=0XFFFFFFFF;Version=2014.4" part number = "7z020clg400" date = "2014/10/10" time = "14:37:26" bytes in bitstream = 4045564
となって、7z020.bit がこの段階で読み込まれる。
ということは、これを書き換えれば好きな内容をロードできるのかも。
さらにその後、
LANG:console zynq_load: Align buffer at 10006f to 100000(swap 1) Copying Linux from SD to RAM... ... reading uImage 3886152 bytes read in 253 ms (14.6 MiB/s) reading devicetree.dtb 17334 bytes read in 22 ms (768.6 KiB/s) ## Booting kernel from Legacy Image at 02080000 ... Image Name: Linux-3.15.0-xilinx Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 3886088 Bytes = 3.7 MiB Load Address: 00008000 Entry Point: 00008000 Verifying Checksum ... OK ## Flattened Device Tree blob at 02000000 Booting using the fdt blob at 0x2000000 Loading Kernel Image ... OK Loading Device Tree to 1fff8000, end 1ffff3b5 ... OK Starting kernel ... Booting Linux on physical CPU 0x0 Linux version 3.15.0-xilinx (tom@dev-server) (gcc version 4.6.1 (Sourcery CodeBench Lite 2011.09-50) ) #9 SMP PREEMPT Tue May 26 17:26:14 CST 2015
となるので、ここまでの起動順を整理すると、
- PS 内のブートローダ
- BOOT.bin
- FSBL
- u-boot
- 環境変数の設定
- uEnv.txt
- 7z020.bit (Logic)
- uImage (Linux-3.15.0-xilinx)
- devicetree.dtb
となってそう。
実際、(DVD)/02-Images/BOOT/boot.bif は、
the_ROM_image: { [bootloader]D:\BOOT\fsbl.elf D:\BOOT\u-boot.elf }
となっていて、BOOT.bin には fsbl と u-boot しか入っていないことが分かる。
ロジック部分は uEnv.txt の後で読み込んでる。
恐らく、下記の記事に近い公正になっているのでは、と思われる???
http://qiita.com/ikwzm/items/1734676d787e2693df47
標準のブートローダで気になる点†
せっかくの三色LEDが点滅しっぱなしになっている。
アプリケーションからは使えないのだろうか・・・
7z020.bin を生成してみる†
PS の設定を z-turn DVD から取ってくる†
(DVD)/05-ProgrammableLogic_Source/7Z020/mys-xc7z020-trd.rar
を使えばいいような気がする。
このプロジェクトは以下のように説明されている。
1. mys_xc7z020_trd.zip vivado project without display controller support, it's free to use.
上記 .rar ファイルの中身を C:\z-turn\mys-xc7z020-trd に展開する。
プロジェクトおよびIPのアップグレード†
mys-xc7z020-trd.xpr をダブルクリックして vivado を起動
プロジェクトファイルが古いと言われるので automatically upgrade する。
Xilinx 製 IP もいくつかアップグレードすべきと言われるので Report IP Status する。
画面下の IP Status で Upgrade Selected する。
design_1.bd を作成し直すか聞かれるけれど、このまま Generate を押しても以下のエラーが出てしまうので、
ここではスキップする。
デバッグ1†
何もせずに Generate すると出るエラー
[BD 41-759] The input pins (listed below) are either not connected or do not have a source port, and they don't have a tie-off specified. These pins are tied-off to all 0's to avoid error in Implementation flow. Please check your design and connect them as needed:
/xlconcat_0/In1
曰く、xlconcat_0 の In1 ピンが未接続ですよ、と。
もともとここには有償のディスプレイ IP である xylon:logicbricks:logicvc:3.02.a からの割り込み線が繋がっていたところ、この有償 IP を削除したために未接続となったもの。
ダミーを繋げばいい。
Diagram 上の何もないところで右クリックから、[Add IP..] を選び、[Constant] を追加する。
追加された xlconstant_0 をダブルクリックして、Width = 1, Value = 1 に設定(変更なし)。
&ref(): File not found: "constant-for-aux_intn-config.png" at page "電気回路/z-turn/基本事項";
xlconstant_0/dout[0:0] から xlconcat_0/In1[0:0] までドラッグすると線で繋がる。
intn は反転入力なので、ゼロになると割り込みが掛かる。1を入れておけば実質的に何もしない。
自分で追加した IP の割り込みを監視したくなったら Constant を削除して、繋ぎ直せばいい。
Block Design の生成†
IP Integrator の Generate Block Design ボタンを押して、
Synthesis Option は Global のまま OK
Bitstream の生成†
C:\z-turn\mys-xc7z020-trd\mys-xc7z020-trd.runs\impl_1\design_1_wrapper.bit
にファイルができる。
これを 7z020.bit と名前を変えて SD カードへコピー。
元のファイルは original/7z020.bit にでも入れておく。
デバッグ2†
これで起動しようとすると、起動時に以下のメッセージを出して止まってしまう。
LANG:console ... mmc0: new high speed SDHC card at address 0007 mmcblk0: mmc0:0007 SD8GB 7.42 GiB mmcblk0: p1 p2
本来ここは、
LANG:console ... mmc0: new high speed SDHC card at address 0007 mmcblk0: mmc0:0007 SD8GB 7.42 GiB mmcblk0: p1 p2 xylonfb video mode: 1280x720-32@60 Console: switching to colour frame buffer device 160x45 xylonfb 1 registered xylonfb 0 registered
のように、hdmi ドライバの設定が続くはずの部分。
つまり、Linux 側のデバイスツリー設定に xylonfb video が含まれているのが問題。
AXI-4 バスは、相手が存在しないアドレスを読みに行ったり書きに行ったりするとデッドロックするので、それで止まっちゃっているのだと思う。
デバイスツリーの構築†
devicetree.dtb などというのがデバイスツリーファイルだそうで、 これは devicetree.dts などというソースファイルをコンパイルしてバイナリ形式にしたものらしい。
dts : デバイスツリーソース
dtb : デバイスツリーバイナリ
http://marsee101.blog19.fc2.com/blog-entry-3485.html
によれば、
が元になっているらしい。
led_r { label = "led_r"; gpios = <&gpio0 0x72 0x1>; default-state = "on"; linux,default-trigger = "heartbeat"; }; led_g { label = "led_g"; gpios = <&gpio0 0x73 0x1>; default-state = "on"; linux,default-trigger = "heartbeat"; }; led_b { label = "led_b"; gpios = <&gpio0 0x74 0x1>; default-state = "on"; linux,default-trigger = "heartbeat"; };
この heartbeat というのが常に3色LEDが光っている理由っぽい。
linux,default-trigger = "none";
に変えれば自由に変更できるようになる?
や
を見ても hdmi のディスプレイドライバっぽいものは見えないので、 これをそのまま使えばディスプレイなしの dtb を作れそう。
Xilinx SDK で dtb を作る†
http://keitetsu.blogspot.jp/2015/02/xilinx-sdkdevice-tree.html
を参考にして、、、あれ?
z-turn の DVD に入っていたのは Linux 3.15.0-xilinx なのだけれど、
https://github.com/andreamerello/linux-zynq-stable/blob/P2016_I03_zturn_rgmii_id/arch/arm/boot/dts/zynq-zturn-myir.dts
のブランチは Linux 4.x のものばかりだ。
大丈夫かな???
あーと、http://qiita.com/spicemanjp/items/5054e536442248aad87c によると dtb を dts に直すこともできるらしい。そのほうが間違いないかも。
やってみよう。
LANG:console $ sudo apt-get install device-tree-compiler $ dtc -I dtb -O dts -o devicetree-hdmi-1080p.dts devicetree-hdmi-1080p.dtb
ちゃんとできた。
logiclk, logicvc の部分を削り、led_? の
linux,default-trigger = "heartbeat";
を
linux,default-trigger = "none";
に書き換えた。
LANG:console $ dtc -I dts -O dtb -o devicetree-wo-display.dtb devicetree-wo-display.dts
で dtb に戻して、devicetree.dtb として SD カードへ書き込んだところ、 ちゃんと起動するようになった。
まとめ†
FPGA に独自仕様の PL を組み込みつつ、USB 経由の UART 端末から制御可能な Linux を立ち上げられる SD カードを作成する手順をまとめる:
- SD カードにパーティションを切る
- 先頭に bootable な FAT32 で 32MB くらい
- 残りを Linux ext4
- z-turn DVD のディスクイメージからファイルをコピーする
- FAT32 側に入れるファイル
- BOOT.bin : DVD のまま
- uEnv.txt : DVD のまま
- 7z020.bit : DVD の mys-xc7z020-trd というプロジェクトをひな形にした PS + 独自 PL
- devicetree.dtb : DVD のものを一旦 .dts に直し、ディスプレイ関係を除いた .dtb を作る
- uImage : DVD のまま
- uramdisk.image.gz : DVD のまま
- ext4 側に入れるファイル
- まずはすべて DVD のまま
- 必要に応じて書き換える
独自 PL を組み込んで 7z020.bit を書き換えて、
それに応じたアプリケーションを開発すれば、
問題なく動くはず。
独自 PL を追加したり、それに対応して devicetree を書き換えたりしても、 FAT32 側の書き換えだけで済むのが良い感じ。