9. Zynq Linuxからecho 0x0F > /proc/myled でLEDをつけてみる

ここまでで作ったファイルは最初のほうで説明した通り

  • BOOT.bin ・・・FSBLとbitstream(FPGAの設定ファイル)が入っている。これが起動してLinuxを動かし始める
  • devicetree.dtb・・・デバイスツリー。どのアドレスに何があるかなどLinuxにデバイスについて教えるためのもの
  • myled.ko ・・・・今回作るLEDのLinuxにおけるデバイスドライバ
  • uImage・・・Linuxカーネル。今回はこれも0からビルドしてみる
  • uramdisk.image.gz・・・HDDはZYBOにないので、ディスクイメージをRAMに展開する。その時の最初のディスクイメージがこれ。

です。
これらをSDカードに入れます。

SDカード準備

SDカードに余計なファイルがあっても問題ありませんが、気になる人はフォーマットしましょう
Macであればディスクユーティルからフォーマットできます。MS-DOSで全体をEraseします。

Screen Shot 2015-01-11 at 11.09.03

 

SDカードに入れていく

SDカードにはファイルとしてそれぞれ普通に入れればOKです。
ZYBOボードにある最初のブートローダがSDカードのBOOT.binを読んでくれるので心配いりません。
入れるべきファイルと、それぞれが今まで作ってきてどこに作成されたかはこんな感じです

  1. BOOT.bin  zybo_base_system/source/vivado/hw/zybo_bsd/zybo_bsd.sdk/FSBL/bootimage
  2. devicetree.dtb (ubuntuの)digilent/drivers
  3. myled.ko (Ubuntuの)digilent/drivers
  4. uImage (Ubuntuの)digilent/Linux-Digilent-Dev/arch/arm/boot
  5. uramdisk.image.gz (Ubuntuの)digilent

これらを普通にSDカードにファイルとして入れてしまいます。

Screen Shot 2015-01-11 at 14.35.18

 

Linuxを起動する

ZYBOボードにsdカードを刺して、ブート元切り替えをsdカードにします(RGBコネクタのすぐ下のやつね)そして、USBを接続し、パソコンではターミナルソフト(Teratermなど)をつないでおきます。

電源をONにします。すると電源確認LEDとFPGAのコンフィグレーションLED両方共点灯すると思います。また、ターミナルソフトには文字が出るはず。
ちなみにTeratermだと、ボードの電源をいれるたびにCOM6などに接続しないといけないので注意が必要です。速度は115kです。

LEDをつけてみる

LEDをつけるためには

  1. sdカードをマウントする(myled.koをつかうので)
  2. insmodでmyled.koを入れる
  3. echo

の手順が必要です。

[shell]

mount /dev/mmcblk0p1 /mnt/
cd /mnt
insmod myled.ko
echo 0xf > /proc/myled

[/shell]

これでLEDが点灯するはず!

2015-01-12 14.56.15

ちなみに echo 0x5 > /proc/myledとやるとちゃんと変わります
2015-01-12 14.56.30

やったね!
ここまでのシェルはこんな感じでした。

lb86

ちなみにここで僕はよくつまづいたのでトラブルシューティングを書いていきます

トラブルシューティング insmodできない

[shell]
zynq> insmod myled.ko
[  168.884046] myled: no symbol version for module_layout

insmod: can’t insert ‘myled.ko’: invalid module format
[/shell]

こんなエラーが出てinsmod出来ませんでした。
デバイスドライバーにはコンパイルした時のカーネルの情報が載っているのですが、そのカーネルのバージョンと今動かそうとしているバージョンが違うとエラーになります。カーネルのバージョンは

[shell]
uname -r
3.14.0-xilinx-13567-g906a2c9
[/shell]

で、モジュールのバージョンは(これはUbuntuで調べた)

[shell]
modinfo myled.ko
filename: myled.ko
alias: myled
description: myled: MYLED driver (Simple Version)
license: GPL
author: Digilent, Inc.
alias: of:N*T*Cdglnt,myled-1.00.a*
depends:
vermagic: 3.14.0-xilinx-13567-g906a2c9-dirty SMP preempt mod_unload modversions ARMv7 p2v8
[/shell]

でした。
モジュールの方にだけdirtyというバージョンがついてます。
dirtyと言うのはカーネルのgitにcommitしていない変更が入っていると自動的に入るもので( http://blogger.tempus.org/2009/05/linux-kernel-version-dirty.html )、カーネルをコンパイルしてドライバをコンパイルするまでに何か変更されちゃったのでしょうか。。。

強制的に入れようと insmod -f myled.koをしてもダメでした。
結局カーネルを再度コンパイルしたら成功。再コンパイルしたカーネルにはdirtyがついていました。

トラブルシューティング echo 0xf > /proc/myledでLEDがつかない

僕はここまできてledがつきませんでした。
ただ、echoで書いた値はcatで出てきます。なので、アドレスはあっていて、FPGAにあるLEDのIPモジュールのDフリップフロップには値を読み書きはできているようです。どうやらフリップフロップから外部の端子までの接続がおかしいらしい。

vivadoに戻ります。ピンアサインを見てもアドレスを見ても問題なさそうでした。
結局間違っていたのは2箇所で、まず新しく作ったLEDのIPのverilogで
assign led = slv_reg0[3:0];
とするべきところを
assign led = slv_reg3[3:0];
としていました。
これだと echo 0xFFFFFFFF > /proc/myled
としない限りLEDは点灯しません。直してIPを再度作りなおしました

また、プロジェクト内に削除したはずの古い外部led端子が残っていました。xdcファイルで変更したあれです。
プロジェクト内検索で全てledに直しました。

以上2点でBOOT.binを作りなおしたところLED無事点灯!

デバイスドライバを使わない確認方法

ちなみにデバイスドライバを使わないでダイレクトに物理メモリを読み書きする方法があります。

[shell]

devmem 0x43c30000 32 0x00000001

[/shell]

これで0x43c30000という物理アドレスに32bit幅で1という値を書き込めます。
デバイスドライバがうまく入らないけど、LEDがつくかだけを確認したいときには便利です