電気回路/z-turn/基本事項 のバックアップ(No.6)

更新


公開メモ

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 ポートをターミナルソフトで開く
  • リセットを押す
  • 必要に応じて Ethernet ケーブルを繋ぐ

これで、ターミナルソフトから Linux のコンソールにアクセスできる

起動用 SD カードを新規作成する

自作のロジックとプログラムを保存した SD カードを作りたいので、 新たに Linux 起動可能な SD カードを用意したい。

z-turn 上で Linux が立ち上がった状態で SD カードの状況を見ると、

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 をインストールして作業すると良い。

VirtualBox に Linux が入っていると、その他にも色々役立つ。

http://marsee101.blog19.fc2.com/blog-entry-2818.html を参考に、

  1. 新しい SD カードを PC の SD カードリーダに挿す
  2. VirtualBox 上の Linux コンソールを開く
  3. VirtualBox のメニュー [デバイス]-[USB]-[Card Reader] にチェックを入れる
  4. lsblk で SD カードに対応するデバイスを見つける
  5. fdisk で2つパーティションを作る
  6. 一旦 [デバイス]-[USB]-[Card Reader] のチェックを消して、再度付ける
  7. mkfs でパーティションをフォーマットする
  8. mount でマウントする
  9. z-turn 付属の DVD を PC に挿入
  10. lsblk で DVD を見つける
  11. mount でマウントする
  12. /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 のブートローダを理解する

Zynq が SD カードからロジックを PL 領域 (Programmable Logic) に読み込んで、 Linux を起動するまでには、次のようなブートプロセスが走ることになる。

  1. Processing System 内部にハードコードされた BootROM が SD カードの BOOT.bin から [bootloader] のついた領域を PS 内 RAM へロードして実行する
  2. BOOT.bin には FSBL (First Stage Boot Loader) と呼ばれるプログラムに [bootloader] を付けて保存しておく。FSBL が *.bit ファイルを読み込むことで PS および PL 領域の初期化を行い、さらに第2ステージのブートローダを起動する。
  3. 第2ステージのブートローダが Linux カーネルやデバイスツリーなどをロードして、Linux へ制御を移す
  4. アプリケーションコードは 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

となるので、ここまでの起動順を整理すると、

  1. PS 内のブートローダ
  2. BOOT.bin
    • FSBL
    • u-boot
    • 環境変数の設定
  3. uEnv.txt
  4. 7z020.bit (Logic)
  5. uImage (Linux-3.15.0-xilinx)
  6. 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 を生成してみる

ユーザーロジックを 7z020.bin という名前で保存しておけば、 起動時に読み込んでくれることが分かった。

ここには自作のIPなどを含んだ PL 領域の設定に加えて、 PS 領域を Linux を動かせるように初期化するための設定も必要になる。

PS の設定を z-turn DVD から取ってくる

PS 領域の設定を自分でするのは大変なので、

(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 を起動
open-project.png

プロジェクトファイルが古いと言われるので automatically upgrade する。
automatic-upgrade.png

Xilinx 製 IP もいくつかアップグレードすべきと言われるので Report IP Status する。
upgrade-ip.png

画面下の IP Status で Upgrade Selected する。
upgrade-selected-ip.png

design_1.bd を作成し直すか聞かれるけれど、このまま Generate を押しても以下のエラーが出てしまうので、 ここではスキップする。
skip-generate-output-products.png

ダミーの割り込み信号線を繋ぐ

上記ダイアログで何もせずに 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 ピンが未接続ですよ、と。
unconnected-xlconcat_0-In1.png

もともとここには有償のディスプレイ IP である xylon:logicbricks:logicvc:3.02.a からの割り込み線が繋がっていたところ、この有償 IP を削除したために未接続となったもの。

ダミーを繋げばいい。

Diagram 上の何もないところで右クリックから、[Add IP..] を選び、[Constant] を追加する。
constant-for-aux_intn-added.png

追加された 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 を削除して、繋ぎ直せばいい。
constant-for-aux_intn-connected.png

Block Design の生成

IP Integrator の Generate Block Design ボタンを押す。
generate-block-design-button.png

Synthesis Option は Global のままで OK

Bitstream の生成

generate-bitstream-button.png

いきなり Generate Bitstream を押せば、Synthesis, Implementation などの必要な処理を自動でやってくれて、

C:\z-turn\mys-xc7z020-trd\mys-xc7z020-trd.runs\impl_1\design_1_wrapper.bit

にファイルができる。

SD カードにコピー

上記の bit ファイルの名前を 7z020.bit に変えて SD カードへコピーする。

Vivado にファイルコピー用のボタンを用意する

  • [Tools]-[Custom Commands]-[Customize Commands...] を選択
  • 緑の矢印を押して "Copy Bitstream to SD card" というコマンドを作る
  • Run command: に下記コマンドを記入
file copy -force "C:/z-turn/mys-xc7z020-trd/mys-xc7z020-trd.runs/impl_1/design_1_wrapper.bit" "N:/7z020b.bit"

customize-commands-copy-bitstream.png

ツールバーにボタンができる

copy-bitstream-button.png

これを押すと、ファイルがコピーされる。

bitstream-copy-command-line.png

デバイスツリーから hdmi 関連を削除

これで起動しようとすると、起動時に以下のメッセージが出た後で止まってしまう。

LANG:console
...
mmc0: new high speed SDHC card at address 0007
mmcblk0: mmc0:0007 SD8GB 7.42 GiB
 mmcblk0: p1 p2

標準の SD カードで起動すると、ここは、

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

によれば、

https://github.com/andreamerello/linux-zynq-stable/blob/linux-4.4.6-zynq/arch/arm/boot/dts/zynq-zturn-myir.dts

が元になっているらしい?

		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";

に変えれば自由に変更できるようになる?
#実はこれ、変えなくてもできるらしい。やり方は DVD の Example を参照。

https://github.com/andreamerello/linux-zynq-stable/blob/linux-4.4.6-zynq/arch/arm/boot/dts/zynq-7000.dtsi

https://github.com/andreamerello/linux-zynq-stable/blob/linux-4.4.6-zynq/arch/arm/boot/dts/skeleton.dtsi

を見ても hdmi のディスプレイドライバっぽいものは見えないので、 これをそのまま使えばディスプレイなしの dtb を作れそう。

z-turn 付属の dtb を元にする

http://qiita.com/spicemanjp/items/5054e536442248aad87c によると、 既存の dtb を dts に直すことができるらしい。

つまり、上記の dts を使わなくても、 z-turn 付属の dtb を dts に直し、手直しをして dtb に書き戻せそう。

やってみよう。

LANG:console
$ sudo apt-get install device-tree-compiler
$ dtc -I dtb -O dts -o devicetree-hdmi-1080p.dts devicetree-hdmi-1080p.dtb

確かに dts ファイルが生成された。

logiclk, logicvc の部分を削り、led_? の

linux,default-trigger = "heartbeat";

linux,default-trigger = "none";

に書き換えたものを devicetree-wo-display.dts として保存した。

LANG:console
$ dtc -I dts -O dtb -o devicetree-wo-display.dtb devicetree-wo-display.dts

で dtb に戻して、devicetree.dtb として SD カードへ書き込んだところ、 ちゃんと Linux が起動するようになった。

led はちかちかしない代わりに付きっぱなしだ。 default-state = "off" とすべきだった。

自作 IP を Linux から制御するにはこの dts に自作 IP へのアクセスができるよう項目を書き加え、 dtb に直して保存すればいいはず。

Example を試してみる

ロジック側で定義したレジスタに Linux アプリケーションからアクセスする標準的な方法を知るために z-turn の DVD に含まれていた Example を試してみます。

led-test

(DVD)/04-Linux_Source/Examples/leds から、

  • led-test.c
  • Makefile

を ~/z-turn/led-test/ へコピー

LANG:console
$ make

これだけで led-test という実行ファイルができる。

root 以外の一般ユーザーで実行しようとするとエラーになるので、 sudo するか、あるいは setuid しなければならない。

LANG:console
$ ./led-test
 [usr_led1] Get trigger: 'none'
 Open /sys/class/leds/usr_led1/trigger failed!
$ sudo ./led-test
 [usr_led1] Get trigger: 'none'
 [usr_led1] Set trigger to 'none'
 [usr_led2] Get trigger: 'none'
 [usr_led2] Set trigger to 'none'
 [   led_r] Get trigger: 'none'
 [   led_r] Set trigger to 'none'
 [   led_g] Get trigger: 'none'
 [   led_g] Set trigger to 'none'
 [   led_b] Get trigger: 'none'
 [   led_b] Set trigger to 'none'
^C[usr_led1] Set trigger to 'none'
 [usr_led2] Set trigger to 'none'
 [   led_r] Set trigger to 'none'
 [   led_g] Set trigger to 'none'
 [   led_b] Set trigger to 'none'
$ sudo chown root:root led-test
$ sudo chmod u+s led-test
$ sudo chmod o+x led-test
$ ./led-test
 [usr_led1] Get trigger: 'none'
 [usr_led1] Set trigger to 'none'
 [usr_led2] Get trigger: 'none'
 [usr_led2] Set trigger to 'none'
 [   led_r] Get trigger: 'none'
 [   led_r] Set trigger to 'none'
 [   led_g] Get trigger: 'none'
 [   led_g] Set trigger to 'none'
 [   led_b] Get trigger: 'none'
 [   led_b] Set trigger to 'none'
 ^C[usr_led1] Set trigger to 'none'
 [usr_led2] Set trigger to 'none'
 [   led_r] Set trigger to 'none'
 [   led_g] Set trigger to 'none'
 [   led_b] Set trigger to 'none'

確かに LED が順に点灯する。

ソースコードを読む

led は物理的には次のように繋がれている:

  • USER_LED1 = MIO0 = E6
  • USER_LED2 = MIO9 = B5
  • LED_R = LN6 = R14
  • LED_G = LP7 = Y16
  • LED_B = LN7 = Y17

このうち MIO ポートはピン番号が事前に決まっている。

RGB の方は EMIO で、これは単に design_1 モジュールから外部に接続される信号線なので、 wrapper モジュールで適当に処理してトップレベルモジュールの外へ出さなければならない。

wrapper モジュールに

LANG:verilog
    output    [2:0]  LEDS;

というポートが用意されていて、

LANG:verilog
   assign LEDS[0]  =     PS_iRESETn   ?  ledr : arm_io_led_r;
   assign LEDS[1]  =     PS_iRESETn   ?  ledg : arm_io_led_g;
   assign LEDS[2]  =     PS_iRESETn   ?  ledb : arm_io_led_b;

   wire ledr      =     LED1_reg && SW[0];
   wire ledg      =     SW[1] ;
   wire ledb      =     SW[2] ;

   assign  gpio_0_tri_o[60] = arm_io_led_r;
   assign  gpio_0_tri_o[61] = arm_io_led_g;
   assign  gpio_0_tri_o[62] = arm_io_led_b;

のように design_1 の出力ポート gpio_0_tri_o と繋がっている。

ピン番号は制約ファイル system.xdc で次のように定義されている。

LANG:xdc
set_property PACKAGE_PIN Y16 [get_ports {LEDS[0]}]
set_property PACKAGE_PIN Y17 [get_ports {LEDS[1]}]
set_property PACKAGE_PIN R14 [get_ports {LEDS[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LEDS[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LEDS[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LEDS[0]}]

PS 設定の ZYNQ PS REGISTER SUMMARY VIEWER で発見した、関連しそうなレジスタ

  • MIO_PIN_00 : Address=0xF8000700 Width=32 Type=rw ResetValue=0x00000000
    • bit 0 : TRI_ENABLE
    • bit 1 : L0_SEL
    • bit 2 : L1_SEL
    • bit 4-3 : L2_SEL
    • bit 7-5 : L3_SEL
    • bit 8 : Speed
    • bit 11-9 : IO_Type
    • bit 12 : PULLUP
    • bit 13 : DisableRcvr
  • MIO_PIN_09 : Address=0xF8000724 Width=32 Type=rw ResetValue=0x00000000
  • MASK_DATA_0_LSW[15:0] : Address=0XE000A000
  • DIRM_0 : Address=0XE000A204
  • OEN_0 : Address = Address=0XE000A208

EMIO 内の位置:

  • LED_R = GPIO_60
  • LED_G = GPIO_61
  • LED_B = GPIO_62

led は dts で次のように定義されている。

/dts-v1/;

/ {
  #address-cells = <0x1>;
  #size-cells = <0x1>;
  compatible = "myir,zynq-zturn", "xlnx,zynq-7000";
  model = "MYIR Z-turn Development Board";

  amba {
    compatible = "simple-bus";
    #address-cells = <0x1>;
    #size-cells = <0x1>;
    interrupt-parent = <0x3>;
    ranges;

    gpio@e000a000 {
      compatible = "xlnx,zynq-gpio-1.0";
      #gpio-cells = <0x2>;
      clocks = <0x1 0x2a>;
      gpio-controller;
      interrupt-parent = <0x3>;
      interrupts = <0x0 0x14 0x4>;
      reg = <0xe000a000 0x1000>;
      emio-gpio-width = <0x40>;
      gpio-mask-high = <0x0>;
      gpio-mask-low = <0x5600>;
      xlnx,emio-gpio-width = <0x40>;
      xlnx,mio-gpio-mask = <0x5600>;
      linux,phandle = <0x5>;
      phandle = <0x5>;
    };

    gpio-leds {
      compatible = "gpio-leds";

      led_r {
        label = "led_r";
        gpios = <0x5 0x72 0x1>;
        default-state = "on";
        linux,default-trigger = "none";
      };

      led_g {
        label = "led_g";
        gpios = <0x5 0x73 0x1>;
        default-state = "on";
        linux,default-trigger = "none";
      };

      led_b {
        label = "led_b";
        gpios = <0x5 0x74 0x1>;
        default-state = "on";
        linux,default-trigger = "none";
      };

      usr_led1 {
        label = "usr_led1";
        gpios = <0x5 0x0 0x1>;
        default-state = "off";
        linux,default-trigger = "none";
      };
      
      usr_led2 {
        label = "usr_led2";
        gpios = <0x5 0x9 0x1>;
        default-state = "off";
        linux,default-trigger = "none";
      };
    };
  };
}; 

emio-gpio-width の 0x40 は 64 だ。
LED_RGB の 0x72-0x74 はそのままだと 114-116 なのでそのままだとピン番号と合わない。

mio の幅が 54 ピンなので、54 を引いてやると 60-62 となって、ぴったり一致する。

54 は 0x36 だけど、この値は dts には書かれていない。

0xe000a0?? の、
0x00-0x35 が mio の 0-53 ピンに相当して、
0x36-0x76 が emio の 0-63 ピンに相当するっぽい。

ソフト的には、例えば

LANG:c
  int fd = open("/sys/class/leds/usr_led1/trigger", O_RDONLY);
  ret = read(fd, tmp, sizeof(tmp));
  close(fd);

  int fd = open("/sys/class/leds/usr_led1/trigger", O_WRONLY);
  ret = write(fd, "none", strlen("none"));
  close(fd);

のようにして trigger を読み書きできる。これはコマンドラインから、

LANG:console
$ ls -l /sys/class/leds/usr_led1/trigger
 -rw-r--r-- 1 root root 4096 Jan 27 06:03 /sys/class/leds/usr_led1/trigger
$ cat /sys/class/leds/usr_led1/trigger
 [none] nand-disk mmc0 timer oneshot heartbeat backlight gpio cpu0 cpu1 default-on transient flash torch

などとしても確認できる。どうやら、このファイル?に書き込むのに root 権限が必要らしい。

trigger の内容から読み取れることには、この led のデバイスドライバは z-turn board 用に、あるいは少なくとも zynq 用に作られたもので、 恐らくカーネルに組み込まれている???

LANG:console
$ ls -l /sys/class/leds/usr_led1/*
 -rw-r--r-- 1 root root 4096 Jan 27 07:44 /sys/class/leds/usr_led1/brightness
 lrwxrwxrwx 1 root root    0 Jan 27 07:45 /sys/class/leds/usr_led1/device -> ../../../gpio-leds.2
 -r--r--r-- 1 root root 4096 Jan 27 07:45 /sys/class/leds/usr_led1/max_brightness
 lrwxrwxrwx 1 root root    0 Jan 27 07:45 /sys/class/leds/usr_led1/subsystem -> ../../../../../class/leds
 -rw-r--r-- 1 root root 4096 Jan 27 07:40 /sys/class/leds/usr_led1/trigger
 -rw-r--r-- 1 root root 4096 Jan 27 07:45 /sys/class/leds/usr_led1/uevent
 
 /sys/class/leds/usr_led1/power:
 total 0
 -rw-r--r-- 1 root root 4096 Jan 27 07:45 autosuspend_delay_ms
 -rw-r--r-- 1 root root 4096 Jan 27 07:45 control
 -r--r--r-- 1 root root 4096 Jan 27 07:45 runtime_active_time
 -r--r--r-- 1 root root 4096 Jan 27 07:45 runtime_status
 -r--r--r-- 1 root root 4096 Jan 27 07:45 runtime_suspended_time

brightness に 0 以外を書き込むと LED が点灯する。
max_brightness は 255 になっているけれど、1 より大きくしても明るさは変化しない。

デバイスドライバが必要っぽい?

上記を見る限り、デバイスドライバを書いてファイルシステムに載せてやると簡単にアクセスできるということみたい?

ビルトインデバイス

$ ls /lib/modules
 3.15.0-xilinx  3.2.0-1498-omap4
$  uname -r
 3.15.0-xilinx
$ cat /lib/modules/3.15.0-xilinx/modules.builtin
 kernel/kernel/configs.ko
 kernel/fs/binfmt_script.ko
 kernel/fs/mbcache.ko
 kernel/fs/configfs/configfs.ko
 kernel/fs/exportfs/exportfs.ko
 kernel/fs/ext2/ext2.ko
 kernel/fs/ext3/ext3.ko
 kernel/fs/ext4/ext4.ko
 kernel/fs/fat/fat.ko
 kernel/fs/fat/vfat.ko
 kernel/fs/fat/msdos.ko
 kernel/fs/jbd/jbd.ko
 kernel/fs/jbd2/jbd2.ko
 kernel/fs/jffs2/jffs2.ko
 kernel/fs/lockd/lockd.ko
 kernel/fs/nfs/nfs.ko
 kernel/fs/nfs/nfsv2.ko
 kernel/fs/nfs/nfsv3.ko
 kernel/fs/nls/nls_base.ko
 kernel/fs/nls/nls_cp437.ko
 kernel/fs/nls/nls_ascii.ko
 kernel/fs/nls/nls_iso8859-1.ko
 kernel/crypto/crypto.ko
 kernel/crypto/crypto_wq.ko
 kernel/crypto/crypto_algapi.ko
 kernel/crypto/aead.ko
 kernel/crypto/crypto_blkcipher.ko
 kernel/crypto/chainiv.ko
 kernel/crypto/eseqiv.ko
 kernel/crypto/seqiv.ko
 kernel/crypto/crypto_hash.ko
 kernel/crypto/pcompress.ko
 kernel/crypto/cryptomgr.ko
 kernel/crypto/ctr.ko
 kernel/crypto/ccm.ko
 kernel/crypto/aes_generic.ko
 kernel/crypto/arc4.ko
 kernel/crypto/crc32c_generic.ko
 kernel/crypto/rng.ko
 kernel/crypto/krng.ko
 kernel/block/deadline-iosched.ko
 kernel/block/cfq-iosched.ko
 kernel/drivers/base/firmware_class.ko
 kernel/drivers/base/regmap/regmap-i2c.ko
 kernel/drivers/base/regmap/regmap-spi.ko
 kernel/drivers/base/regmap/regmap-mmio.ko
 kernel/drivers/block/brd.ko
 kernel/drivers/block/loop.ko
 kernel/drivers/char/xilinx_devcfg.ko
 kernel/drivers/clk/clk-si570.ko
 kernel/drivers/connector/cn.ko
 kernel/drivers/cpufreq/cpufreq_stats.ko
 kernel/drivers/cpufreq/cpufreq_performance.ko
 kernel/drivers/cpufreq/cpufreq_powersave.ko
 kernel/drivers/cpufreq/cpufreq_userspace.ko
 kernel/drivers/cpufreq/cpufreq_ondemand.ko
 kernel/drivers/cpufreq/cpufreq_conservative.ko
 kernel/drivers/cpufreq/cpufreq-cpu0.ko
 kernel/drivers/dma/pl330.ko
 kernel/drivers/dma/xilinx/xilinx_axidma.ko
 kernel/drivers/dma/xilinx/xilinx_vdma.ko
 kernel/drivers/dma/xilinx/xilinx_axicdma.ko
 kernel/drivers/edac/edac_core.ko
 kernel/drivers/edac/zynq_edac.ko
 kernel/drivers/gpio/gpio-zynq.ko
 kernel/drivers/gpu/drm/drm_kms_helper.ko
 kernel/drivers/gpu/drm/drm.ko
 kernel/drivers/gpu/drm/i2c/adv7511.ko
 kernel/drivers/gpu/drm/xilinx/xilinx_drm.ko
 kernel/drivers/gpu/drm/xilinx/xilinx_drm_dp.ko
 kernel/drivers/gpu/drm/xylon/xylon_drm.ko
 kernel/drivers/hid/hid.ko
 kernel/drivers/hid/hid-generic.ko
 kernel/drivers/hid/hid-microsoft.ko
 kernel/drivers/hid/usbhid/usbhid.ko
 kernel/drivers/hwmon/hwmon.ko
 kernel/drivers/hwmon/pmbus/pmbus_core.ko
 kernel/drivers/hwmon/pmbus/pmbus.ko
 kernel/drivers/hwmon/pmbus/ucd9000.ko
 kernel/drivers/hwmon/pmbus/ucd9200.ko
 kernel/drivers/i2c/i2c-core.ko
 kernel/drivers/i2c/i2c-dev.ko
 kernel/drivers/i2c/i2c-mux.ko
 kernel/drivers/i2c/algos/i2c-algo-bit.ko
 kernel/drivers/i2c/busses/i2c-cadence.ko
 kernel/drivers/i2c/muxes/i2c-mux-pca954x.ko
 kernel/drivers/iio/industrialio.ko
 kernel/drivers/iio/industrialio-triggered-buffer.ko
 kernel/drivers/iio/kfifo_buf.ko
 kernel/drivers/iio/adc/xilinx-xadc.ko
 kernel/drivers/input/input-core.ko
 kernel/drivers/input/input-polldev.ko
 kernel/drivers/input/sparse-keymap.ko
 kernel/drivers/input/mousedev.ko
 kernel/drivers/input/evdev.ko
 kernel/drivers/input/keyboard/atkbd.ko
 kernel/drivers/input/keyboard/gpio_keys.ko
 kernel/drivers/input/keyboard/gpio_keys_polled.ko
 kernel/drivers/input/misc/adxl34x.ko
 kernel/drivers/input/misc/adxl34x-i2c.ko
 kernel/drivers/input/misc/gpio-beeper.ko
 kernel/drivers/input/mouse/synaptics_usb.ko
 kernel/drivers/input/touchscreen/ft5x0x.ko
 kernel/drivers/input/serio/serio.ko
 kernel/drivers/input/serio/serport.ko
 kernel/drivers/input/serio/libps2.ko
 kernel/drivers/leds/led-class.ko
 kernel/drivers/leds/leds-gpio.ko
 kernel/drivers/leds/trigger/ledtrig-timer.ko
 kernel/drivers/leds/trigger/ledtrig-oneshot.ko
 kernel/drivers/leds/trigger/ledtrig-heartbeat.ko
 kernel/drivers/leds/trigger/ledtrig-backlight.ko
 kernel/drivers/leds/trigger/ledtrig-gpio.ko
 kernel/drivers/leds/trigger/ledtrig-default-on.ko
 kernel/drivers/leds/trigger/ledtrig-transient.ko
 kernel/drivers/leds/trigger/ledtrig-camera.ko
 kernel/drivers/media/media.ko
 kernel/drivers/media/i2c/adv7604.ko
 kernel/drivers/media/platform/xilinx/xilinx-axi-video.ko
 kernel/drivers/media/platform/xilinx/xilinx-cfa.ko
 kernel/drivers/media/platform/xilinx/xilinx-cresample.ko
 kernel/drivers/media/platform/xilinx/xilinx-rgb2yuv.ko
 kernel/drivers/media/platform/xilinx/xilinx-scaler.ko
 kernel/drivers/media/platform/xilinx/xilinx-remapper.ko
 kernel/drivers/media/platform/xilinx/xilinx-switch.ko
 kernel/drivers/media/platform/xilinx/xilinx-tpg.ko
 kernel/drivers/media/platform/xilinx/xilinx-vtc.ko
 kernel/drivers/media/v4l2-core/videodev.ko
 kernel/drivers/media/v4l2-core/v4l2-common.ko
 kernel/drivers/media/v4l2-core/v4l2-dv-timings.ko
 kernel/drivers/media/v4l2-core/videobuf2-core.ko
 kernel/drivers/media/v4l2-core/videobuf2-memops.ko
 kernel/drivers/media/v4l2-core/videobuf2-dma-contig.ko
 kernel/drivers/misc/xilinx_trafgen.ko
 kernel/drivers/misc/myir_stlm75x.ko
 kernel/drivers/misc/eeprom/at24.ko
 kernel/drivers/misc/eeprom/at25.ko
 kernel/drivers/mmc/card/mmc_block.ko
 kernel/drivers/mmc/core/mmc_core.ko
 kernel/drivers/mmc/host/sdhci.ko
 kernel/drivers/mmc/host/sdhci-pltfm.ko
 kernel/drivers/mmc/host/sdhci-of-arasan.ko
 kernel/drivers/mtd/mtd.ko
 kernel/drivers/mtd/ofpart.ko
 kernel/drivers/mtd/cmdlinepart.ko
 kernel/drivers/mtd/mtd_blkdevs.ko
 kernel/drivers/mtd/mtdblock.ko
 kernel/drivers/mtd/chips/chipreg.ko
 kernel/drivers/mtd/chips/cfi_probe.ko
 kernel/drivers/mtd/chips/cfi_util.ko
 kernel/drivers/mtd/chips/cfi_cmdset_0002.ko
 kernel/drivers/mtd/chips/gen_probe.ko
 kernel/drivers/mtd/devices/m25p80.ko
 kernel/drivers/mtd/maps/physmap.ko
 kernel/drivers/mtd/maps/physmap_of.ko
 kernel/drivers/mtd/nand/nand.ko
 kernel/drivers/mtd/nand/nand_ecc.ko
 kernel/drivers/mtd/nand/nand_ids.ko
 kernel/drivers/mtd/nand/pl353_nand.ko
 kernel/drivers/net/mii.ko
 kernel/drivers/net/can/can-dev.ko
 kernel/drivers/net/can/xilinx_can.ko
 kernel/drivers/net/ethernet/broadcom/tg3.ko
 kernel/drivers/net/ethernet/cadence/macb.ko
 kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
 kernel/drivers/net/ethernet/realtek/r8169.ko
 kernel/drivers/net/ethernet/xilinx/xilinx_emaclite.ko
 kernel/drivers/net/ethernet/xilinx/xilinx_emacps.ko
 kernel/drivers/net/ethernet/xilinx/xilinx_emac.ko
 kernel/drivers/net/phy/libphy.ko
 kernel/drivers/net/phy/mdio-bitbang.ko
 kernel/drivers/net/phy/at803x.ko
 kernel/drivers/net/ppp/ppp_generic.ko
 kernel/drivers/net/ppp/ppp_async.ko
 kernel/drivers/net/ppp/bsd_comp.ko
 kernel/drivers/net/ppp/ppp_deflate.ko
 kernel/drivers/net/ppp/ppp_synctty.ko
 kernel/drivers/net/slip/slhc.ko
 kernel/drivers/net/wireless/rtlwifi/rtlwifi.ko
 kernel/drivers/net/wireless/rtlwifi/rtl_usb.ko
 kernel/drivers/net/wireless/rtlwifi/rtl8192c/rtl8192c-common.ko
 kernel/drivers/net/wireless/rtlwifi/rtl8192cu/rtl8192cu.ko
 kernel/drivers/of/of_mdio.ko
 kernel/drivers/of/of_pci.ko
 kernel/drivers/of/of_pci_irq.ko
 kernel/drivers/pps/pps_core.ko
 kernel/drivers/ptp/ptp.ko
 kernel/drivers/regulator/fixed.ko
 kernel/drivers/rtc/rtc-pcf8563.ko
 kernel/drivers/scsi/scsi_mod.ko
 kernel/drivers/scsi/sd_mod.ko
 kernel/drivers/scsi/sg.ko
 kernel/drivers/spi/spi-bitbang.ko
 kernel/drivers/spi/spi-cadence.ko
 kernel/drivers/spi/spi-xilinx.ko
 kernel/drivers/spi/spi-zynq-qspi.ko
 kernel/drivers/thermal/thermal_sys.ko
 kernel/drivers/tty/serial/serial_core.ko
 kernel/drivers/tty/serial/xilinx_uartps.ko
 kernel/drivers/uio/uio.ko
 kernel/drivers/uio/uio_pdrv_genirq.ko
 kernel/drivers/uio/uio_xilinx_apm.ko
 kernel/drivers/usb/usb-common.ko
 kernel/drivers/usb/core/usbcore.ko
 kernel/drivers/usb/gadget/udc-core.ko
 kernel/drivers/usb/gadget/zynq_udc.ko
 kernel/drivers/usb/host/ehci-hcd.ko
 kernel/drivers/usb/host/ehci-pci.ko
 kernel/drivers/usb/host/zynq-dr-of.ko
 kernel/drivers/usb/phy/phy-zynq-usb.ko
 kernel/drivers/usb/serial/usbserial.ko
 kernel/drivers/usb/serial/option.ko
 kernel/drivers/usb/serial/usb_wwan.ko
 kernel/drivers/usb/storage/usb-storage.ko
 kernel/drivers/video/console/fbcon.ko
 kernel/drivers/video/console/bitblit.ko
 kernel/drivers/video/console/softcursor.ko
 kernel/drivers/video/fbdev/core/fb.ko
 kernel/drivers/video/fbdev/core/cfbfillrect.ko
 kernel/drivers/video/fbdev/core/cfbcopyarea.ko
 kernel/drivers/video/fbdev/core/cfbimgblt.ko
 kernel/drivers/video/fbdev/core/sysfillrect.ko
 kernel/drivers/video/fbdev/core/syscopyarea.ko
 kernel/drivers/video/fbdev/core/sysimgblt.ko
 kernel/drivers/video/xylon/xylonfb/of/xylonfb_of.ko
 kernel/drivers/watchdog/cadence_wdt.ko
 kernel/drivers/watchdog/of_xilinx_wdt.ko
 kernel/sound/soundcore.ko
 kernel/sound/core/snd.ko
 kernel/sound/core/snd-timer.ko
 kernel/sound/core/snd-pcm.ko
 kernel/sound/core/snd-pcm-dmaengine.ko
 kernel/sound/core/snd-compress.ko
 kernel/sound/soc/snd-soc-core.ko
 kernel/sound/soc/adi/snd-soc-adi-axi-i2s.ko
 kernel/sound/soc/adi/snd-soc-adi-axi-spdif.ko
 kernel/net/can/can.ko
 kernel/net/can/can-raw.ko
 kernel/net/can/can-bcm.ko
 kernel/net/can/can-gw.ko
 kernel/net/ipv4/xfrm4_mode_beet.ko
 kernel/net/ipv4/inet_lro.ko
 kernel/net/ipv4/xfrm4_mode_transport.ko
 kernel/net/ipv4/xfrm4_mode_tunnel.ko
 kernel/net/ipv4/inet_diag.ko
 kernel/net/ipv4/tcp_diag.ko
 kernel/net/ipv4/tcp_cubic.ko
 kernel/net/mac80211/mac80211.ko
 kernel/net/packet/af_packet.ko
 kernel/net/sunrpc/sunrpc.ko
 kernel/net/unix/unix.ko
 kernel/net/wireless/cfg80211.ko
 kernel/lib/bitrev.ko
 kernel/lib/crc-ccitt.ko
 kernel/lib/crc16.ko
 kernel/lib/crc32.ko
 kernel/lib/fonts/font.ko
 kernel/lib/lzo/lzo_compress.ko
 kernel/lib/lzo/lzo_decompress.ko
 kernel/lib/xz/xz_dec.ko
 kernel/lib/zlib_deflate/zlib_deflate.ko
 kernel/lib/zlib_inflate/zlib_inflate.ko

dtb やデバイスドライバの設定方法

Zynq デバイスドライバとデバイスツリーを作る
http://yuki-sato.com/wordpress/2015/01/12/zynq14/

デバイスドライバ udmabuf を使用する1
http://marsee101.blog19.fc2.com/blog-entry-3373.html

ZynqのPLを操作するLinuxドライバ (DTS設定編)
https://formalism.github.io/blog/posts/2014/05/zynqpllinux-dts/

ZynqのPLを操作するLinuxドライバ (ユーザプログラム編)
https://formalism.github.io/blog/posts/2014/05/zynqpllinux/

結構大変だなあ。。。

まとめ

FPGA に独自仕様の PL を組み込みつつ、USB 経由の UART 端末から制御可能な Linux を立ち上げられる SD カードを作成する手順をまとめる:

  1. SD カードにパーティションを切る
    • 先頭に bootable な FAT32 で 32MB くらい
    • 残りを Linux ext4
  2. z-turn DVD のディスクイメージからファイルをコピーする
  3. FAT32 側に入れるファイル
    • BOOT.bin : DVD のまま
    • uEnv.txt : DVD のまま
    • 7z020.bit : DVD の mys-xc7z020-trd というプロジェクトをひな形にした PS + 独自 PL
    • devicetree.dtb : DVD のものを一旦 .dts に直し、ディスプレイ関係を除いた .dtb を作る
      • 必要に応じて自作 IP 用のエントリーを追加する必要あり
    • uImage : DVD のまま
    • uramdisk.image.gz : DVD のまま
  4. ext4 側に入れるファイル
    • まずはすべて DVD のまま
    • 必要に応じて書き換える

独自 PL を組み込んで 7z020.bit を書き換えて、
それに応じた devicetree に沿ってアプリケーションを開発すれば、
問題なく動くはず。

独自 PL を追加したり、それに対応して devicetree を書き換えたりしても、 FAT32 側の書き換えだけで済むのが良い感じ。

あー、とはいえ上記の方法では dtb を作るのに Linux 上の dtc を使っているので、 作業が Windows 上だけで閉じていないのはちょっと嫌。やはり Windows 番の dtc を用意すべきかも。

コメント・質問





Counter: 14243 (from 2010/06/03), today: 5, yesterday: 0