ZYBOの追加のUART0をpeta linuxから使う

はじめに

ZYBOのUART1はUSB側につながっていて、パソコンと接続すれば簡単にシリアル通信ができるようになっています。しかし、パソコンではなく外部の機器とシリアル通信をしたかったため、使われていないUART0を有効にしました。

試行錯誤した結果を残しておきます。

 

petalinuxをビルドするために開発環境はlinuxを使いました。

環境の都合でCentOSでやりましたが、特に理由がなければArchLinuxやUbuntuなど一般的なものをお勧めします。

 

ZYBOのUARTの種類

最初にUARTの種類について確認します。

ZYBOのUARTにはいくつか種類があります。

①PS側に実装されているUART (UART0, UART1)

f:id:tokunn:20171130134909p:plain

最初からPS側にUARTが2つついています。

UART1は標準で有効で、USBに変換され UART/JTAG USB portに接続されています。なので、パソコンにUSBでつなぐだけで簡単に使えます。Linuxからは/dev/ttyPS0として認識されます。

 

UART0は存在はしていますが、使用するためにはPLをいじったりdtsをいじったりなど軽く設定が必要です。今回はこのUART0を有効にしてLinuxで/dev/ttyPS1として認識させるまでの説明をします。

②PL側にIPを張り付けて作るUART(いくつでも追加可能)

f:id:tokunn:20171130134917p:plain

標準で用意されているUARTは上記の2つだけですが、PL側にUartliteやUART16550を張り付けることによっていくらでもUARTポートを増やすことができます。こちらの方法は今回は使いませんでした。3ポート以上必要な場合にはこれを使うことになります。

 

いくつか種類がありますが、これらの中から必要に応じて使うことになります。

それではUART0をLinuxで使うために設定を始めていきましょう。

 

UART0を外部に出す(vivadoでの操作)

f:id:tokunn:20171130134914p:plain

標準では外部に接続されていない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を実行。

f:id:tokunn:20171130141210p:plain

③ZYNQのブロックをダブルクリックしてRe-customize IPを開く。

f:id:tokunn:20171130141357p:plain

④左のPage NavigatorのMIO Configrationを選択。

⑤UART0にチェックを入れて、任意のMIOポートを指定(画像ではMIO10とMIO11を指定)。OKを押して閉じる。

f:id:tokunn:20171130141614p:plain

Ethernetにつなぐ場合には、ここでPeripheral I/O PinsタブでEthernet0->MDIOでMDIOを選択する必要があるようです。参考: hiro99ma blog: [zybo]PetaLinux (9) 

⑥ZYNQブロックの右側のFCLK_CLK0を左側のM_AXI_GP0_ACLKに接続。

f:id:tokunn:20171130141738p:plain

⑦保存して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で使用する方法を確認しました。

わからないことがありましたらご質問ください。

twitter.com