- 追加された行はこのように表示されます。
- 削除された行は
このように表示されます。
!Embedded Linux Hands-on Tutorial -- ZedBoard
Linux + Zynqに慣れるべく,2013年と2年前の資料だけど,[Embedded Linux Hands-on Tutorial -- ZedBoard|http://www.digilentinc.com/Data/Documents/Product%20Documentation/ZedBoard_ELHoT.zip] をやってみる.
ISEは14.4.
14.7でやろうとしたら,PSのIPコアのバージョンがあがっているためか,そのままではBitStreamが生成できなかった.
OSはCentOS 6.2を用意.
今日びCnetOS 6.2のリポジトリはそうそうないので,
baseurl=http://vault.centos.org/6.2/os/$basearch/
とかを使う.(cf. http://d.hatena.ne.jp/tmatsuu/20120324/1332578375)
x86_64版でインストールするけど,CodeSaurcyの都合で32bit実行/開発環境も必要.
sudo yum install compat-libstdc++-33-3.2.3-69.el6.i686
sudo yum install glibc-devel.i686 glibc-devel
とかした上でISEをインストールする必要があるので注意.
!準備
::設計イメージのダウンロードと展開
wget http://www.digilentinc.com/Data/Products/ZEDBOARD/ZedBoard_Linux_Design.zip
unzip ZedBoard_Linux_Design.zip
::XPSで開く
source /opt/Xilinx/14.4/ISE_DS/settings64.sh
xps ZedBoard_Linux_Design/hw/xps_proj/system.xmp &
!HWの変更と合成
::PSのGPIOコアからLEDをはずす
+ I/O Peripheralsをクリック
+ Zynq PS MIO Configurationsダイアログが開く → EMIO GPIOの幅を60から52に変更 (8 LEDピンの削除)
+ Portsタブを開いてポートの設定
++ processing_system7_0の(IO_IF) GPIO_0を選択
++ ポートをNo Connectionに
++ ポートをExternal Portsに.名前のprefixの_pinを削除(既存のUCFとできるだけあわせるため)
::Create and Import Peripheral Wizardでmyledを作る
* コア名はmyled.
* AXI4-Lite
* software resetとinclude data phase timerはオフ
* レジスタの数は1つ
* user_logicは(私の場合)VHDLのままでいい
::myledの追加と編集
* add IP.パラメタはデフォルトのまま
* ソースコードを修正.Browse HDL Sources...でHDLコードに,View MPDでmpdファイルに簡単にアクセスできる
** user_logic.vhdの修正
101 LED : out std_logic_vector(7 downto 0);
148 LED <= slv_reg0(7 downto 0);
** myled.vhdの修正
141 LED : out std_logic_vector(7 downto 0);
306 LED => LED,
** myled_v2_1_0.mpdの修正
40 PORT LED = "", DIR = O, VEC = [7:0]
* Project -> Rescan User RepositriesでIPコアをリスキャン
* Portsタブでmyled_0を開くと追加したLEDな出力ポートができているので外部出力ピンに
* UCFでピン割り当てを変更
** ProjectタブのUCF File: data/system.ucf からアクセスできる
** 80行目付近からのOn-board LED'sのprocessing_system7_0_GPIO<>をmyled_0_LED_pin<>に変更.
** 以降のペリフェラルに対するprocessing_sytem7_0_GPIO<>のインデックスを8減らす
::Bitファイルの生成
* Hardware->Genearete Bitstream
!U-BOOT作る
:: U-Bootのコンパイルの準備
gitで取得するかBranchのアーカイブかを利用する.
git clone https://github.com/Digilent/u-boot-digilent
ドキュメントに沿ったバージョンのものをダウンロードしてみた.
wget https://github.com/Digilent/u-boot-digilent/archive/v2012.04-digilent-13.01.zip
展開して,もぐる
unzip v2012.04-digilent-13.01.zip
cd u-boot-digilent-2012.04-digilent-13.01
:: U-Bootのコンパイルのための設定
* IPアドレスの設定.include/configs/zynq_zed.h を編集.
/* Default environment */
#define CONFIG_IPADDR 10.0.0.1
#define CONFIG_SERVERIP 10.0.0.3
:: ビルド
次のようにしてビルド.
make CROSS_COMPILE=arm-xilinx-linux-gnueabi- zynq_zed_config
make CROSS_COMPILE=arm-xilinx-linux-gnueabi-
できあがったものをコピー.
cp u-boot ../ZedBoard_Linux_Design/boot_image/u-boot.elf
!FSBLを作ってBOOT.BINを作る
::BOOT.BINを作る(準備)
(閉じていれば)xpsでxmpを再び開く.
xps ZedBoard_Linux_Design/hw/xps_proj/system.xmp &
Project→Export Hardware Design to SDKでExportしつつSDK起動.
ワークスペースは,
ZedBoard_Linux_Design/hw/xps_proj/SDK/SDK_Export
にある.
File⇒New⇒Project...でXilinxのApplication Projectの作成を開始.
キモは,
Project Name: FSBL
Hardware Plat: xps_proj_hw_platform
OS Platform: standalone
くらいか.Available Templatesでは,Zynq FSBLを選択.
::main.cの修正
ZedBoardでは,FSBLで,USB-ResetピンのトグルによってUSB PHYチップをリセットする必要があるらしい.
main.cのFsbHandOff()の呼び出しの前(472行目)に次のコードを追加.
472
473 /* Reset the USB */
474 {
475 fsbl_printf(DEBUG_GENERAL, "Reset USB...\r\n");
476
477 /* Set data dir */
478 *(unsigned int *)0xe000a284 = 0x00000001;
479
480 /* Set OEN */
481 *(unsigned int *)0xe000a288 = 0x00000001;
482 Xil_DCacheFlush();
483 /* For REVB Set data value low for reset, then back high */
484 #ifdef ZED_REV_A
485 *(unsigned int *)0xe000a048 = 0x00000001;
486 Xil_DCacheFlush();
487 *(unsigned int *)0xe000a048 = 0x00000000;
488 Xil_DCacheFlush();
489 #else
490 *(unsigned int *)0xe000a048 = 0x00000000;
491 Xil_DCacheFlush();
492 *(unsigned int *)0xe000a048 = 0x00000001;
493 Xil_DCacheFlush();
494 #endif
495 }
デフォルトで自動Buildだけど,念の為にCleanしてBuild.
::BOOT.BINを作る
Xilinx Tools⇒Create Zynq Boot Imageでツールを起動.
FSLB elfには,
ZedBoard_Linux_Design/hw/xps_proj/SDK/SDK_Export/FSBL/Debug/FSBL.elf
を選択.
List of partitions int the boot imageは,FSBL.elf,system.bit,u-boot.elf の順.
ZedBoard_Linux_Design/hw/xps_proj/SDK/SDK_Export/FSBL/Debug/FSBL.elf
ZedBoard_Linux_Design/hw/xps_proj/SDK/SDK_Export/xps_proj_hw_platform/system.bit
ZedBoard_Linux_Design/boot_image/u-boot.elf
出力先のフォルダは,
ZedBoard_Linux_Design/boot_image/
にする.
できあがったu-boot.binをBOOT.BINにリネーム.
!Linuxカーネルのコンパイル
::Linuxカーネルのコンパイルの準備
gitのメインブランチかタグを切られたものを持ってくる.
u-bootのときと同じように,v3.6-digilent-13.01とタグを切られたものを持ってくることにする.
https://github.com/Digilent/linux-digilent/archive/v3.6-digilent-13.01.zip
wgetで取得したら拡張子がつかなかったので末尾に.zipをつけて,unzipで展開してもぐる.
::コンフィグ
まずはデフォルトコンフィギュレーション
make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- digilent_zed_defconfig
で,menuconfig
make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- menuconfig
ちなみに,ncurses-develがなかったのでyumでインストール...
ドキュメントではPmodOLED1をビルトイン・ドライバからローダブルモジュールに変更している
具体的には Device Driver→PMOD Support と辿って,PmodOLED1の'*'を'M'に変更.
::ビルド
Exitをつづけて終了したらビルド
make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi-
ビルドが終わったらarch/arm/boot/zImageができている
!デバイスツリーを作る
カーネルソースの下で,
./scripts/dtc/dtc -I dts -O dtb -o ../devicetree.dtb arch/arm/boot/dts/digilent-zed.dts
を実行
!SDカードにセットアップ
::SDカードを用意
先頭1GBをvfat,残りをext4にする.
* fdiskでパーティション作る
* vfatとext4で,それぞれフォーマット.たとえば,
suudo mkfs -t vfat -n ZED_BOOT /dev/sdb1
sudo mkfs -t ext4 -L ROOT_FS /dev/sdb2
::ルートファイルシステムの用意
* Linaroをダウンロード.
wget http://releases.linaro.org/12.09/ubuntu/precise-images/ubuntu-desktop/linaro-precise-ubuntu-desktop-20120923-436.tar.gz
* 展開
mkdir -p /tmp/linaro
sudo cp linaro-precise-ubuntu-desktop-20120923-436.tar.gz /tmp/linaro
cd /tmp/linaro
sudo tar zxf fs.tar.gz
* ext4領域をマウント
mkdir -p /tmp/sd_ext4
sudo mount /dev/sdb2 /tmp/sd_ext4
* 展開した一式をコピー.ドキュメントではrsync使ってる
cd binary/boot/filesystem.dir/
sudo rsync -a ./ /tmp/sd_ext4
sudo sync; sudo sync; sudo sync; # 念のため
* unmountして取り出す
sudo umount /tmp/sd_ext4
::BOOT.BIN,dtc,zImageをコピー
vfat領域に
* BOOT.BIN
* devicetree.dtb
* zImage
をコピーする.
!ZedBoardで起動してみる
HDMIケーブルつなぐとGUIがあがってくるのがわかる.
apt-get install openssh-server
とかするとsshdがインストールできる.
sshでログインできるようにrootのパスワードを適当に設定.
!myled用のドライバを作る
::準備
カーネルソースにアクセスしやすいようにシンボリックリンクを用意
ln -s linux-digilent-3.6-digilent-13.01 linux-digilent
作業用のディレクトリを用意して移動
mkdir drivers
cd drivers
::必要なファイルを書いてmake
Makefileを書く
obj-m := myled.o
all:
make -C ../linux-digilent/ M=$(PWD) modules
clean:
make -C ../linux-digilent/ M=$(PWD) clean
{{ref myled.c}}を書いて,make.
make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi-
!デバイスツリーを更新
myledのアドレスをxpsで確認.今回は0x7e400000-0x7e40ffffの64KBの空間だった.
サンプルをコピー
cp ../linux-digilent/arch/arm/boot/dts/digilent-zed.dts .
一番最後にエントリを追加.
myled {
compatible = "dglnt,myled-1.00.a";
reg = <0x7e400000 0x10000>;
};
編集したらデバイスツリーを作りなおす
../linux-digilent/scripts/dtc/dtc -I dts -O dtb -o devicetree.dtb digilent-zed.dts
::システムに反映
scpでmyled.koとdevicetree.dtbをコピー.
ブートパーティションはマウントされてないので,マウントしてコピー
mount /dev/mmcblk0p1 /mnt/
cp /root/devicetree.dtb /mnt/
で,リブート.
再起動したら,/proc/myledができている.
insmod myled.ko
echo 0x0F > /proc/myled
echo 0xF0 > /proc/myled
とかして楽しむ
!ユーザアプリを書く
作業用ディレクトリをつくって,もぐる
mkdir user_app
cd user_app
{{ref led_blink.c}}を書く.Makefileも用意.ドキュメントのMakefileは何か変な感じだったので注意.
また,クロスコンパイル環境とターゲットでライブラリがちぐはぐなので-staticが必要だった.
CC = arm-xilinx-linux-gnueabi-gcc
CFLAGS = -g -static
all : led_blink
led_blink : led_blink.c
${CC} ${CFLAGS} -o $@ $^
clean :
rm -rfv *.o
rm -rfv led_blink
.PHONY : clean
Linaroの場合,ホストコンパイラもあるので,ソースをコンパイルしてもOK.