ZYBOの追加のUART0をpeta linuxから使う
はじめに
ZYBOのUART1はUSB側につながっていて、パソコンと接続すれば簡単にシリアル通信ができるようになっています。しかし、パソコンではなく外部の機器とシリアル通信をしたかったため、使われていないUART0を有効にしました。
試行錯誤した結果を残しておきます。
petalinuxをビルドするために開発環境はlinuxを使いました。
環境の都合でCentOSでやりましたが、特に理由がなければArchLinuxやUbuntuなど一般的なものをお勧めします。
ZYBOのUARTの種類
最初にUARTの種類について確認します。
ZYBOのUARTにはいくつか種類があります。
①PS側に実装されているUART (UART0, UART1)
最初からPS側にUARTが2つついています。
UART1は標準で有効で、USBに変換され UART/JTAG USB portに接続されています。なので、パソコンにUSBでつなぐだけで簡単に使えます。Linuxからは/dev/ttyPS0として認識されます。
UART0は存在はしていますが、使用するためにはPLをいじったりdtsをいじったりなど軽く設定が必要です。今回はこのUART0を有効にしてLinuxで/dev/ttyPS1として認識させるまでの説明をします。
②PL側にIPを張り付けて作るUART(いくつでも追加可能)
標準で用意されているUARTは上記の2つだけですが、PL側にUartliteやUART16550を張り付けることによっていくらでもUARTポートを増やすことができます。こちらの方法は今回は使いませんでした。3ポート以上必要な場合にはこれを使うことになります。
いくつか種類がありますが、これらの中から必要に応じて使うことになります。
それではUART0をLinuxで使うために設定を始めていきましょう。
UART0を外部に出す(vivadoでの操作)
標準では外部に接続されていないUART0をMIOの任意のポートに接続します。
MIOは外部に接続できるピンヘッダのPmodの一つです。しかし、他のPmod(JAからJE)がPL側に接続されているのに対して、MIO(JF)はPS側に接続されているという違いがあります。このため、MIOはPS側から簡単に使うことができます。
vivadoでの手順は以下のようになります。プロジェクトの作成などは省略します。
①Create Block Design
②Add IPからZYNQ7 Processing Systemを追加してRun Block Automationを実行。
③ZYNQのブロックをダブルクリックしてRe-customize IPを開く。
④左のPage NavigatorのMIO Configrationを選択。
⑤UART0にチェックを入れて、任意のMIOポートを指定(画像ではMIO10とMIO11を指定)。OKを押して閉じる。
(Ethernetにつなぐ場合には、ここでPeripheral I/O PinsタブでEthernet0->MDIOでMDIOを選択する必要があるようです。参考: hiro99ma blog: [zybo]PetaLinux (9) )
⑥ZYNQブロックの右側のFCLK_CLK0を左側のM_AXI_GP0_ACLKに接続。
⑦保存してHDLラッパを作成して、Generate Bitstreamまで実行。
⑧File -> Export -> Export Hardware...を選択し、Include bitstreamのチェックを入れて出力。
ハードウェアは
<プロジェクトルート>/プロジェクト名.sdk/
の下に出力されます。
ここまででvivadoでの操作は終了です。
これでUART0が外部ポートに接続されました。
petalinuxのビルド
UART0をベアメタルアプリケーションから使うこともできますが、今回はpeta linuxから使用します。
まずは普通にpetalinuxをビルドします。
環境はCentOS + zshを使いました。CentOSでのビルドはあまりお勧めしません。
手順は以下のようになります。
①petalinuxプロジェクトの作成
$ petalinux-create -t project --template zynq -n project_name
project_nameは適宜置き換えてください。
②ハードウェアのインポートとコンフィギュレーション
$ cd project_name
$ petalinux-config --get-hw-description=path_to_hw
$ petalinux-config -c rootfs
path_to_hwは先ほどvivadoで出力したハードウェアがあるディレクトリ名に置き換えてください。
設定画面は特に何もなければそのままExitしてください。
③ビルド
$ petalinux-build
ビルドを行います。時間がかかります。
これでビルドは完了です。
これで通常のpetalinuxは起動しますが、今回はdtsを編集して/dev/ttyPS1として認識させます。
デバイスツリーの編集
UART0を/dev/ttyPS1として認識させるために、デバイスツリーを編集します。正攻法ではない気しかしません。
今回ビルドしたdtbは
<プロジェクトフォルダ>/image/linux/system.dtb
にあります。
これをdtcで.dtsに戻して編集したのちに.dtbに戻します。
手順は下記のようになります。
①フォルダに移動
$ cd image/linux/
②dtsに変換する。
$ dtc -I dtb -O dts -o system.dts system.dtb
これでsystem.dtsというファイルが生成されます。
これを編集します。
③dtsに追記する。
system.dtsの上のほうにあるaliasesに追記します。
aliases {
serial0 = "/amba/serial@e0001000";
serial1 = "/amba/serial@e0000000"; // <==これを追記
ethernet0 = "/amba/ethernet@e000b000";
spi0 = "/amba/spi@e000d000";
};
下のほうにあるserial@0000000に追記します。下記のようになるように編集してください。
serial@e0000000 {
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
status = "okay";
clocks = <0x1 0x17 0x1 0x28>;
clock-names = "uart_clk", "pclk";
reg = <0xe0000000 0x1000>;
interrupts = <0x0 0x1b 0x4>;
device_type = "serial";
port-number = <0x1>;
};
④dtbに変換する。
$ dtc -I dts -O dtb -o system.dtb system.dts
これでデバイスツリーの編集は完了しました。
起動
以上ですべての設定手順は終了です。
最後にpackageを実行してJTAG経由で起動します。
$ petalinux-package --prebuilt --force
$ cp images/linux/design_1_wrapper.bit pre-built/linux/implementation/download.bit
$ petalinux-boot --jtag --prebuilt 3
jtag経由(USB経由)でpetalinuxをダウンロードして起動します。
もし、jtag経由ではなくSDカードから起動する場合には、次のように実行します。
$ petalinux-package --boot --fsbl images/linux/zynq-fsbl.elf \
--fpga images/linux/design_1_wrapper.bit -u-boot --force
あとは、BOOT.binとimage.ubをSDカードにコピーします。
jtagでもsdでも、しばらく待つと/dev/ttyUSB?として認識されるUART0のシリアルコンソールからログインできます。
$ sudo screen /dev/ttyUSB0 115200
/dev/ttyUSB0は適宜自分の環境に置き換えてください。
petalinuxはユーザー名root/パスワードrootでログインできます。
ログインしたのちに/dev/ttyPS0と/dev/ttyPS1があることを確認してください。
/dev/ttyPS1に書き込むと接続したMIOポートから9600でシリアルが出力されます。
$ for i in {0..1000}; do echo "hello $i" > /dev/ttyPS1; done
さいごに
今回はUART0をpetalinuxで使用する方法を確認しました。
わからないことがありましたらご質問ください。