Zynq PSのUART0を有効化してPetaLinuxで使う
はじめに
ZynqのPSにはUARTが2つ入っています。
Linuxを使用する際にはこのUART1をブートログとコンソールの入出力に使用してるのですが、残り1つを使っていないのは勿体ないですね。
というわけで、今回PSに残るUART0を使用してみました(PLにUARTを作るのはやったことない…)。
この記事の実行環境は下記のとおりです。
- ホストOS:Windows7 x64
- 仮想化ソフト:VirtualBox 5.0.14
- ゲストOS:Ubuntu 14.04.3 amd64
- ターゲットボード:Zybo
VivadoでUART0を有効化
Zybo/ZedboardにはMIO Pmodという端子にPSのI/O(MIO)が出ています。
ここへUART0を配線し、HDFを作成します。
TODO:後でVivadoの設定がわかる図を張る!!
PetaLinuxのビルド
作成したHDFを元にPetaLinuxプロジェクトを作成、ビルドしたうえ、BOOT.BINとimage.ubを作ってPetaLinuxを起動します(前回手順参照)。
これだけでUARTが使えるんじゃないかと思っていたのですが、ダメでした。
シリアルログが途中で途切れてしまいました…
U-Boot 2015.07 (Feb 15 2016 - 11:35:46 +0900) DRAM: ECC disabled 512 MiB MMC: zynq_sdhci: 0 SF: Detected S25FL256S_64K with page size 256 Bytes, erase size 64 KiB, total 32 MiB *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial Net: Gem.e000b000 U-BOOT for mio_pmod Gem.e000b000 Waiting for PHY auto negotiation to complete.... done BOOTP broadcast 1 DHCP client bound to address 192.168.0.5 (3 ms) Hit any key to stop autoboot: 0 U-Boot-PetaLinux> printenv autoload=no baudrate=115200 boot_img=BOOT.BIN bootcmd=run default_bootcmd bootdelay=4 bootenvsize=0x20000 bootenvstart=0x500000 clobstart=0x01000000 console=console=ttyPS0,115200 cp_kernel2ram=mmcinfo && fatload mmc 0 ${netstart} ${kernel_img} default_bootcmd=run cp_kernel2ram && bootm ${netstart} dnsip=192.168.0.1 dtb_img=system.dtb dtbnetstart=0x02800000 eraseenv=sf probe 0 && sf erase ${bootenvstart} ${bootenvsize} ethact=Gem.e000b000 ethaddr=00:0a:35:00:1e:53 fault=echo ${img} image size is greater than allocated place - partition ${img} is NOT UPDATED gatewayip=192.168.0.1 hostname=mio_pmod install_boot=mmcinfo && fatwrite mmc 0 ${clobstart} ${boot_img} ${filesize} install_jffs2=sf probe 0 && sf erase ${jffs2start} ${jffs2size} && sf write ${clobstart} ${jffs2start} ${filesize} install_kernel=mmcinfo && fatwrite mmc 0 ${clobstart} ${kernel_img} ${filesize} ipaddr=192.168.0.5 jffs2_img=rootfs.jffs2 kernel_img=image.ub load_boot=tftpboot ${clobstart} ${boot_img} load_dtb=tftpboot ${clobstart} ${dtb_img} load_jffs2=tftpboot ${clobstart} ${jffs2_img} load_kernel=tftpboot ${clobstart} ${kernel_img} loadaddr=0x01000000 nc=setenv stdout nc;setenv stdin nc; netboot=tftpboot ${netstart} ${kernel_img} && bootm netmask=255.255.255.0 netstart=0x01000000 psserial0=setenv stdout ttyPS0;setenv stdin ttyPS0 sd_update_dtb=echo Updating dtb from SD; mmcinfo && fatload mmc 0:1 ${clobstart} ${dtb_img} && run install_dtb sd_update_jffs2=echo Updating jffs2 from SD; mmcinfo && fatload mmc 0:1 ${clobstart} ${jffs2_img} && run install_jffs2 sdboot=echo boot Petalinux; mmcinfo && fatload mmc 0 ${netstart} ${kernel_img} && bootm serial=setenv stdout serial;setenv stdin serial serverip=192.168.0.9 test_crc=if imi ${clobstart}; then run test_img; else echo ${img} Bad CRC - ${img} is NOT UPDATED; fi test_img=setenv var "if test ${filesize} -gt ${psize}; then run fault; else run ${installcmd}; fi"; run var; setenv var update_boot=setenv img boot; setenv psize ${bootsize}; setenv installcmd "install_boot"; run load_boot ${installcmd}; setenv img; setenv psize; setenv installcmd update_dtb=setenv img dtb; setenv psize ${dtbsize}; setenv installcmd "install_dtb"; run load_dtb test_img; setenv img; setenv psize; setenv installcmd update_jffs2=setenv img jffs2; setenv psize ${jffs2size}; setenv installcmd "install_jffs2"; run load_jffs2 test_img; setenv img; setenv psize; setenv installcmd update_kernel=setenv img kernel; setenv psize ${kernelsize}; setenv installcmd "install_kernel"; run load_kernel ${installcmd}; setenv img; setenv psize; setenv installcmd Environment size: 2671/131068 bytes U-Boot-PetaLinux> set console console=ttyPS1,115200 U-Boot-PetaLinux> bootcmd Unknown command 'bootcmd' - try 'help' U-Boot-PetaLinux> bootm ## Loading kernel from FIT Image at 01000000 ... Using 'conf@1' configuration Verifying Hash Integrity ... OK Trying 'kernel@1' kernel subimage Description: PetaLinux Kernel Type: Kernel Image Compression: gzip compressed Data Start: 0x010000f0 Data Size: 6378185 Bytes = 6.1 MiB Architecture: ARM OS: Linux Load Address: 0x00008000 Entry Point: 0x00008000 Hash algo: crc32 Hash value: 29f18b43 Verifying Hash Integrity ... crc32+ OK ## Loading fdt from FIT Image at 01000000 ... Using 'conf@1' configuration Trying 'fdt@1' fdt subimage Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Start: 0x016154a0 Data Size: 13352 Bytes = 13 KiB Architecture: ARM Hash algo: crc32 Hash value: 8a9d6513 Verifying Hash Integrity ... crc32+ OK Booting using the fdt blob at 0x16154a0 Uncompressing Kernel Image ... OK Loading Device Tree to 07ff9000, end 07fff427 ... OK Starting kernel ... Booting Linux on physical CPU 0x0 Linux version 4.0.0-xilinx (root@ssd-vm) (gcc version 4.9.2 (Sourcery CodeBench Lite 2015.05-17) ) #4 SMP PREEMPT Mon Feb 15 11:36:08 JST 2016 CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=18c5387d CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache Machine model: mio_pmod bootconsole [earlycon0] enabled cma: Reserved 16 MiB at 0x1f000000 Memory policy: Data cache writealloc PERCPU: Embedded 11 pages/cpu @debcf000 s12672 r8192 d24192 u45056 Built 1 zonelists in Zone order, mobility grouping on. Total pages: 130048 Kernel command line: console=ttyPS0,115200 earlyprintk PID hash table entries: 2048 (order: 1, 8192 bytes) Dentry cache hash table entries: 65536 (order: 6, 262144 bytes) Inode-cache hash table entries: 32768 (order: 5, 131072 bytes) Memory: 493252K/524288K available (4759K kernel code, 223K rwdata, 1708K rodata, 3028K init, 208K bss, 14652K reserved, 16384K cma-reserved, 0K highmem) Virtual kernel memory layout: vector : 0xffff0000 - 0xffff1000 ( 4 kB) fixmap : 0xffc00000 - 0xfff00000 (3072 kB) vmalloc : 0xe0800000 - 0xff000000 ( 488 MB) lowmem : 0xc0000000 - 0xe0000000 ( 512 MB) pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB) modules : 0xbf000000 - 0xbfe00000 ( 14 MB) .text : 0xc0008000 - 0xc0658efc (6468 kB) .init : 0xc0659000 - 0xc094e000 (3028 kB) .data : 0xc094e000 - 0xc0985de0 ( 224 kB) .bss : 0xc0985de0 - 0xc09ba0f4 ( 209 kB) Preemptible hierarchical RCU implementation. Additional per-CPU info printed with stalls. RCU restricting CPUs from NR_CPUS=4 to nr_cpu_ids=2. RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2 NR_IRQS:16 nr_irqs:16 16 L2C: platform modifies aux control register: 0x72360000 -> 0x72760000 L2C: DT/platform modifies aux control register: 0x72360000 -> 0x72760000 L2C-310 erratum 769419 enabled L2C-310 enabling early BRESP for Cortex-A9 L2C-310 full line of zeros enabled for Cortex-A9 L2C-310 ID prefetch enabled, offset 1 lines L2C-310 dynamic clock gating enabled, standby mode enabled L2C-310 cache controller enabled, 8 ways, 512 kB L2C-310: CACHE_ID 0x410000c8, AUX_CTRL 0x76760001 slcr mapped to e0804000 zynq_clock_init: clkc starts at e0804100 Zynq clock init sched_clock: 64 bits at 333MHz, resolution 3ns, wraps every 3298534883328ns timer #0 at e0808000, irq=17 Console: colour dummy device 80x30 Calibrating delay loop... 1332.01 BogoMIPS (lpj=6660096) pid_max: default: 32768 minimum: 301 Mount-cache hash table entries: 1024 (order: 0, 4096 bytes) Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes) CPU: Testing write buffer coherency: ok CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 Setting up static identity map for 0x481788 - 0x4817e0 CPU1: thread -1, cpu 1, socket 0, mpidr 80000001 Brought up 2 CPUs SMP: Total of 2 processors activated (2664.03 BogoMIPS). CPU: All CPU(s) started in SVC mode. devtmpfs: initialized VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 4 pinctrl core: initialized pinctrl subsystem NET: Registered protocol family 16 DMA: preallocated 256 KiB pool for atomic coherent allocations cpuidle: using governor ladder cpuidle: using governor menu hw-breakpoint: found 5 (+1 reserved) breakpoint and 1 watchpoint registers. hw-breakpoint: maximum watchpoint size is 4 bytes. zynq-ocm f800c000.ocmc: ZYNQ OCM pool: 256 KiB @ 0xe0880000 vgaarb: loaded SCSI subsystem initialized usbcore: registered new interface driver usbfs usbcore: registered new interface driver hub usbcore: registered new device driver usb media: Linux media interface: v0.10 Linux video capture interface: v2.00 pps_core: LinuxPPS API ver. 1 registered pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it> PTP clock support registered EDAC MC: Ver: 3.0.0 Advanced Linux Sound Architecture Driver Initialized. Switched to clocksource arm_global_timer NET: Registered protocol family 2 TCP established hash table entries: 4096 (order: 2, 16384 bytes) TCP bind hash table entries: 4096 (order: 3, 32768 bytes) TCP: Hash tables configured (established 4096 bind 4096) TCP: reno registered UDP hash table entries: 256 (order: 1, 8192 bytes) UDP-Lite hash table entries: 256 (order: 1, 8192 bytes) NET: Registered protocol family 1 RPC: Registered named UNIX socket transport module. RPC: Registered udp transport module. RPC: Registered tcp transport module. RPC: Registered tcp NFSv4.1 backchannel transport module. hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7 counters available futex hash table entries: 512 (order: 3, 32768 bytes) jffs2: version 2.2. (NAND) (SUMMARY) c 2001-2006 Red Hat, Inc. io scheduler noop registered io scheduler deadline registered io scheduler cfq registered (default) zynq-pinctrl 700.pinctrl: zynq pinctrl initialized dma-pl330 f8003000.dmac: Loaded driver for PL330 DMAC-241330 dma-pl330 f8003000.dmac: DBUFF-128x8bytes Num_Chans-8 Num_Peri-4 Num_Events-16 e0000000.serial: ttyPS0 at MMIO 0xe0000000 (irq = 144, base_baud = 3125000) is a xuartps console [ttyPS0] enabled bootconsole [earlycon0] disabled <この後何も表示されない>
これでは、そもそもLinuxが死んでいるのか生きているのかさえもよくわかりません。
DeviceTreeの変更
この現象をネットで調べると、Xilinxのフォーラムにデバイスツリーを修正する書き込みを見つけました。
そして、試してみるとログインまでたどり着くことが出来ました!
詳細な手順は以下の通りです。
PetaLinuxプロジェクトの./subsystem/linux/configs/device-treeにあるsystem-conf.dtsiに1行追加します。
#「このファイル変更するべからず。」というコメントは気になりますが進めます。
/* * CAUTION: This file is automatically generated by PetaLinux SDK. * DO NOT modify this file */ /include/ "skeleton.dtsi" /include/ "zynq-7000.dtsi" /include/ "pcw.dtsi" / { model = "mio_pmod"; aliases { serial0 = &uart1; serial1 = &uart0;//<=追加する ethernet0 = &gem0; spi0 = &qspi; }; chosen { bootargs = "console=ttyPS0,115200 earlyprintk"; }; memory { device_type = "memory"; reg = <0x0 0x20000000>; }; }; <略>
serialとUARTの番号を逆に付けていることに注意してください。
初期設定でブートログとコンソールの入出力に使っているのはUART1ですが、PetaLinux上ではttyPS0だと認識しています。
つまり、UART1をttyPS0として使用し、新しく追加するUART0をttyPS1として使用するというわけですね。
#この逆転の修正もできそうですが、このまま進めます。
動作確認
再ビルド・起動するとttyPS0を使ったままなのでログイン画面まで表示されますので、ログインします。
/devを確認すると、ttyPS0とttyPS1が存在します。
Built with PetaLinux v2015.4 (Yocto 1.8) mio_pmod /dev/ttyPS0 mio_pmod login: root Password: login[870]: root login on 'ttyPS0' root@mio_pmod:~# ls /dev console ram10 tty21 tty50 cpu_dma_latency ram11 tty22 tty51 flash ram12 tty23 tty52 full ram13 tty24 tty53 i2c-0 ram14 tty25 tty54 iio:device0 ram15 tty26 tty55 initctl ram2 tty27 tty56 input ram3 tty28 tty57 kmsg ram4 tty29 tty58 loop-control ram5 tty3 tty59 loop0 ram6 tty30 tty6 loop1 ram7 tty31 tty60 loop2 ram8 tty32 tty61 loop3 ram9 tty33 tty62 loop4 random tty34 tty63 loop5 shm tty35 tty7 loop6 snd tty36 tty8 loop7 tty tty37 tty9 mem tty0 tty38 ttyPS0 memory_bandwidth tty1 tty39 ttyPS1 mmcblk0 tty10 tty4 urandom mmcblk0p1 tty11 tty40 vcs mtab tty12 tty41 vcs1 network_latency tty13 tty42 vcsa network_throughput tty14 tty43 vcsa1 null tty15 tty44 vga_arbiter port tty16 tty45 watchdog psaux tty17 tty46 watchdog0 ptmx tty18 tty47 xdevcfg pts tty19 tty48 zero ram0 tty2 tty49 ram1 tty20 tty5 root@mio_pmod:~#
動作確認
では、本当にttyPS1を使用することができるようになったのか確認します。
確認にあたり、今回はechoコマンドを使いました。
PetaLinuxにminicomのようなシリアルコンソールは入っていませんし、テストアプリを作成するのは少し面倒です。
MIO Pmodに出したUART0のGNDとRX、TX端子とUSBシリアル変換基板と接続し、シリアル変換基板をPCに接続します。
TODO:後でシリアル接続のわかる写真を張る!!
PCでシリアルターミナルを開き、PetaLinuxのコンソールで以下を実行します。
root@mio_pmod:~# stty -F /dev/ttyPS1 115200 clocal cread cs8 -cstopb -parenb root@mio_pmod:~# echo 'hoge' > /dev/ttyPS1
すると…
TODO:後で証拠写真を張る!!
PC側のシリアルターミナルに"hoge"と出ました。ちゃんと送信できています!!
また、PC側から文字入力をするとPC側シリアルターミナルに入力が反映されることからZynq側で受信もできていることがわかります(Zynq側で表示が無いような…)。
さいごに
今回はUART0をZyboのMIO Pmodに配線し、PetaLinuxから使用できることを確認しました。
ttyPS*とUART*の番号が逆なのが少し気になりますが、使うことができたのでとりあえずは良しとします。