Petalinux のカスタマイズ の履歴(No.7)
更新概要†
電気回路/zynq/Petalinux のビルド の続きです。
z-turn ボード用に Petalinux から起動 SD カードを作ったのですが、
- シリアルポート番号の問題でメインコンソールが正常起動しない
- BOOT.bin と image.ub だけ、という構成は部分的な差し替えが難しいので改善したい
- その他諸々
いろいろ不満があるので解決しようと思います。
解決した結果の手順をまとめたものはこのページの最後にあります >> 全体のまとめ
フォルダ構成†
~/z-turn/
- petalinux/ : petalinux SDK のルートフォルダ
- zturn-v2016.4/ : プロジェクトのルートフォルダ
- design_1_wrapper_hw_platform_1/ : vivado から export したフォルダ
主にプロジェクトのルートフォルダである ~/z-turn/zturn-v2016.4/ で作業します。
環境設定スクリプト†
- petalinux-setup というコマンドで petalinux 環境を整えられるようにした
- petalinux のコマンドは LANG=C でないと動かないので、 忘れずに LANG=C するために alias を設定した
LANG:console $ alias petalinux-setup='source ~/z-turn/petalinux/settings.sh' $ petalinux-setup PetaLinux environment set to '/home/osamu/z-turn/petalinux' WARNING: /bin/sh is not bash! bash is PetaLinux recommended shell. Please set your default shell to bash. INFO: Checking free disk space INFO: Checking installed tools INFO: Checking installed development libraries INFO: Checking network and other services $ set | grep PETA PETALINUX=/home/osamu/z-turn/petalinux PETALINUX_VER=2016.4 $ petalinux-^t petalinux-boot petalinux-config petalinux-package petalinux-util petalinux-build petalinux-create petalinux-setup $ petalinux-^c $ cat >> ~/.bashrc # 自動実行スクリプトに登録する alias petalinux-setup='export LANG=C; source ~/z-turn/petalinux/settings.sh' alias petalinux-boot='LANG=C petalinux-boot' alias petalinux-build='LANG=C petalinux-build' alias petalinux-config='LANG=C petalinux-config' alias petalinux-create='LANG=C petalinux-create' alias petalinux-package='LANG=C petalinux-package' alias petalinux-util='LANG=C petalinux-util' ^D
パッケージング方法の変更†
Petalinux のデフォルト設定では、
- BOOT.BIN
- fsbl.elf = First Stage Boot Loader
- u-boot.bin = 初期ロジック設定?
- u-boot.elf = Second Stage Boot Loader
- design.bit = ロジック設定
- image.ub
- system.dtb = デバイスツリー設定
- uImage = カーネル
- rootfs = ルートファイルシステム
の2つのファイルに起動に必要なすべてのファイルをまとめるようになっています。
BOOT.BIN はまあこれでもいいとして、 image.ub については中の dtb, uImage, rootfs をすべて別々にしておいた方が、 個別にビルドできて便利です。
ということで、設定を変更してみます。
petalinux-config & build†
- fsbl は vivado で作ったものを使えばいいようなので、 petalinux では生成しない
- dtb を SD カードから読ませる
- rootfs を SD カードから読ませる
- console=ttyPS1
としました。
LANG:console
$ petalinux-setup
$ petalinux-config
Linux Components Selection --->
[Uncheck] First Stage Bootloader
Auto Config Settings --->
[Uncheck] fsbl autoconfig
Subsystem AUTO Hardware Settings --->
Advanced bootable images storage Settings --->
dtb image settings --->
image storage media --->
primary sd
Kernel Bootargs --->
[Uncheck] generate boot args automatically
user set kernel bootargs = console=ttyPS1,115200 root=/dev/mmcblk0p2 rw earlyprintk
Image Packing Configuration --->
Root filesystem type = SD Card
$ petalinux-build
$ petalinux-package --boot --fsbl ../design_1_wrapper_hw_platform_1/fsbl.elf --fpga images/linux/design_1_wrapper.bit --u-boot --force
$ rm BOOT.BIN # なぜかカレントフォルダにもできてしまうので
$ ls -l images/linux/
-rw-rw-r-- 1 4545920 BOOT.BIN
-rw-r--r-- 1 2077787 System.map.linux
-rw-r--r-- 1 4045676 design_1_wrapper.bit
-rw-r--r-- 1 9055012 image.ub
-rw-r--r-- 1 67108864 rootfs.ext3
-rw-r--r-- 1 67108864 rootfs.ext4
-rw-r--r-- 1 5280887 rootfs.ext4.gz
-rw-r--r-- 1 13702 system.dtb
-rwxr-xr-x 1 396096 u-boot.bin
-rwxr-xr-x 1 2507500 u-boot.elf
-rw-r--r-- 1 11615732 vmlinux
-rw-r--r-- 1 3827624 zImage
$ sudo fdisk /dev/sdf
コマンド (m でヘルプ): p
Disk /dev/sdf: 7.4 GiB, 7962886144 bytes, 15552512 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xd720fb16
デバイス 起動 Start 最後から セクタ Size Id タイプ
/dev/sdf1 * 2048 133119 131072 64M e W95 FAT16 (LBA)
コマンド (m でヘルプ): d
Selected partition 1
Partition 1 has been deleted.
コマンド (m でヘルプ): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
パーティション番号 (1-4, default 1):
First sector (2048-15552511, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-15552511, default 15552511): +128M
Created a new partition 1 of type 'Linux' and of size 128 MiB.
コマンド (m でヘルプ): t
Selected partition 1
Partition type (type L to list all types): b
Changed type of partition 'Linux' to 'W95 FAT32'.
コマンド (m でヘルプ): n
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p): p
パーティション番号 (2-4, default 2):
First sector (264192-15552511, default 264192):
Last sector, +sectors or +size{K,M,G,T,P} (264192-15552511, default 15552511):
Created a new partition 2 of type 'Linux' and of size 7.3 GiB.
コマンド (m でヘルプ): p
Disk /dev/sdf: 7.4 GiB, 7962886144 bytes, 15552512 sectors
Geometry: 74 heads, 1 sectors/track, 1023 cylinders
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xd720fb16
デバイス 起動 Start 最後から セクタ Size Id タイプ
/dev/sdf1 2048 264191 262144 128M b W95 FAT32
/dev/sdf2 264192 15552511 15288320 7.3G 83 Linux
コマンド (m でヘルプ): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
$ sudo mkfs.vfat -F32 /dev/sdf1
mkfs.fat 3.0.28 (2015-05-16)
$ sudo mkfs.ext4 /dev/sdf2
mke2fs 1.42.13 (17-May-2015)
Creating filesystem with 1911040 4k blocks and 478608 inodes
Filesystem UUID: 71a66d67-ba3e-4ee2-bc7a-33a87f8611b9
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
$ sudo mkdir /mnt/sdcard1
$ sudo mkdir /mnt/sdcard2
$ sudo mount /dev/sdf1 /mnt/sdcard1
$ sudo cp images/linux/BOOT.BIN /mnt/sdcard1
$ sudo cp images/linux/image.ub /mnt/sdcard1
$ sudo cp images/linux/system.dtb /mnt/sdcard1
$ sudo umount /mnt/sdcard1
$ sudo mount /dev/sdf2 /mnt/sdcard2
$ sudo tar fxz images/linux/rootfs.tar.gz -C /mnt/sdcard2
$ sudo umount /mnt/sdcard2
起動してみる†
オプションで bootargs を設定したおかげで、起動時に手動で入力しなくても ttyPS1 への出力を読めるようになっている。
ちゃんと SD カードをルートとしてマウントしており、起動直後は
LANG:console $ df Filesystem 1K-blocks Used Available Use% Mounted on /dev/root 7392892 29248 6965052 0% / devtmpfs 64 0 64 0% /dev tmpfs 515880 32 515848 0% /run tmpfs 515880 40 515840 0% /var/volatile tmpfs 64 0 64 0% /dev /dev/mmcblk0p1 129039 13298 115741 10% /run/media/mmcblk0p1 /dev/mmcblk0p2 7392892 29248 6965052 0% /run/media/mmcblk0p2
のようになっていた。
これで、
- mmcblk0p1
- BOOT.BIN
- image.ub
- system.dtb
- mmcblk0p2
- /
という構成にできた。
image.ub をやめたい†
image.ub は U-Boot fitImage だそうで、
http://mizupc8.bio.mie-u.ac.jp/pukiwiki/index.php?LinkStation%2FTeraStation%2F%E7%8E%84%E7%AE%B1%2FPPC%2FKURO-BOX%2FT4%2FU-Boot%2FFIT
によれば、
- FIT - Flattened uImage Tree
- dtb のような構造を持っており、
- .its - image tree source
- .itb - image tree blob
- .dtb - device tree blob
its というファイルから作られるっぽい。
kernel と ramdisk を一度にメモリに上げるには良いけれど、 今はもうカーネルしか入っていないと思われるので、 uImage をそのまま読んでくれた方がカーネルのリコンパイル時などに手間が省ける。
LANG:console
$ find -name "*.its"
./build/tmp/deploy/images/plnx_arm/fitimage.its
./build/tmp/work/plnx_arm-xilinx-linux-gnueabi/petalinux-user-image/1.0-r0/petalinux-user-image-1.0/fit-image.its
$ cat ./build/tmp/deploy/images/plnx_arm/fitimage.its
...
images {
kernel@0 {
description = "Linux Kernel";
data = /incbin/("/home/osamu/z-turn/zturn-v2016.4/build/tmp/deploy/images/plnx_arm/zImage");
...
load = <0x8000>;
entry = <0x8000>;
...
fdt@0 {
description = "Flattened Device Tree blob";
data = /incbin/("/home/osamu/z-turn/zturn-v2016.4/build/tmp/deploy/images/plnx_arm/plnx_arm-system.dtb");
...
ramdisk@0 {
description = "ramdisk";
data = /incbin/("/home/osamu/z-turn/zturn-v2016.4/build/tmp/deploy/images/plnx_arm/petalinux-user-image-plnx_arm.cpio.gz");
...
configurations {
default = "conf@1";
conf@1 {
description = "Boot Linux kernel with FDT blob + ramdisk";
kernel = "kernel@0";
fdt = "fdt@0";
ramdisk = "ramdisk@0";
hash@1 {
algo = "sha1";
};
};
conf@2 {
description = "Boot Linux kernel with FDT blob";
kernel = "kernel@0";
fdt = "fdt@0";
hash@1 {
algo = "sha1";
};
};
...
あれ? ramdisk と dtb も含まれてる?
確かにファイルサイズも、zImage + rootfs くらいになってる。。。
3827624 zImage 13726 system.dtb 5211912 rootfs.cpio.gz ======================== 9054900 image.ub
petalinux-config -c u-boot†
これは多分 u-boot の設定に違いない?ということで、
LANG:console
$ petalinux-config -c u-boot
Boot Images --->
[uncheck] Support Flattened Image Tree
Boot media --->
[check] Support for booting from SD/EMMC
Networking support --->
[uncheck] Random ethaddr if unset
[uncheck] Control TFTP timeout and count through environment
Device Drivers --->
[uncheck] Ethernet PHY (physical media interface) support
$ petalinux-config
u-boot Configuration --->
U-boot config --->
other
WARNING: /home/osamu/z-turn/petalinux/components/yocto/source/arm/layers/meta-xilinx/recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb.do_compile is tainted from a forced run
$ petalinux-build
WARNING: /home/osamu/z-turn/petalinux/components/yocto/source/arm/layers/meta-xilinx/recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb.do_compile is tainted from a forced run
$ petalinux-package --boot --fsbl ../design_1_wrapper_hw_platform_1/fsbl.elf --fpga images/linux/design_1_wrapper.bit --u-boot --force
$ ls -l images/linux/
-rw-rw-r-- 1 osamu osamu 4515888 2月 23 16:31 BOOT.BIN
-rw-r--r-- 1 osamu osamu 2077787 2月 23 16:21 System.map.linux
-rw-r--r-- 1 osamu osamu 4045676 2月 23 15:59 design_1_wrapper.bit
-rw-r--r-- 1 osamu osamu 9054896 2月 23 16:23 image.ub
-rw-r--r-- 1 osamu osamu 67108864 2月 23 16:22 rootfs.ext3
-rw-r--r-- 1 osamu osamu 67108864 2月 23 16:22 rootfs.ext4
-rw-r--r-- 1 osamu osamu 5280834 2月 23 16:22 rootfs.ext4.gz
-rw-r--r-- 1 osamu osamu 13726 2月 23 16:21 system.dtb
-rwxr-xr-x 1 osamu osamu 366064 2月 23 16:22 u-boot.bin
-rwxr-xr-x 1 osamu osamu 2368752 2月 23 16:22 u-boot.elf
-rw-r--r-- 1 osamu osamu 11615732 2月 23 16:21 vmlinux
-rw-r--r-- 1 osamu osamu 3827616 2月 23 16:21 zImage
-rw-r--r-- 1 osamu osamu 396001 2月 23 16:31 zynq_fsbl.elf
まず、u-boot の設定を自分でして、その後 petalinux-config すると WARNING が出るのは、上書きされてるってことなのかどうか???
個別の config を動かした後は petalinux-config しちゃだめなのかも?
でもじゃあどうしろと・・・
あと、U-Boot の設定で FIT support を off にしたのに image.ub が作成されている。
fsbl の生成も off にしたつもりだったのに生成されている。
zImage も作成されているのでこれを置けば良いのかどうか?
ブートパーティションの中身を BOOT.BIN と zImage, system.dtb だけにしてみたところ、
LANG:console reading uEnv.txt ** Unable to read file uEnv.txt ** Copying Linux from SD to RAM... reading uImage ** Unable to read file uImage **
違ったみたい。
uImage を生成†
LANG:console $ petalinux-package --image -c kernel --format uImage $ touch uEnv.txt # 空のファイル
としてこれらをコピーしたところ、
(なぜかカーネルを再コンパイルしてるみたいでものすごく時間がかかる orz)
LANG:console reading devicetree.dtb ** Unable to read file devicetree.dtb **
ありゃ。
uEnv.txt の設定†
LANG:console echo "devicetree_image=system.dtb" > image/linux/uEnv.txt
としたら dtb はちゃんと読まれたのだけれど、
今度は、ramdisk を読めないと言われた。
LANG:console
reading uEnv.txt
28 bytes read in 8 ms (2.9 KiB/s)
Importing environment from SD ...
Hit any key to stop autoboot: 0
Device: sdhci@e0100000
Manufacturer ID: 13
OEM: 4b47
Name: SD08G
Tran Speed: 50000000
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 7.4 GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes
reading uEnv.txt
28 bytes read in 8 ms (2.9 KiB/s)
Loaded environment from uEnv.txt
Importing environment from SD ...
Copying Linux from SD to RAM...
reading uImage
3827680 bytes read in 256 ms (14.3 MiB/s)
reading system.dtb
13726 bytes read in 17 ms (788.1 KiB/s)
reading uramdisk.image.gz
** Unable to read file uramdisk.image.gz **
Zynq> printenv
baudrate=115200
bitstream_image=system.bit.bin
boot_image=BOOT.bin
boot_size=0xF00000
bootcmd=run $modeboot
bootdelay=4
bootenv=uEnv.txt
devicetree_image=system.dtb
devicetree_load_address=0x2000000
devicetree_size=0x20000
ethaddr=00:0a:35:00:01:22
fdt_high=0x20000000
fdtcontroladdr=3ffa8ed0
fileaddr=2000000
filesize=359e
importbootenv=echo Importing environment from SD ...; env import -t ${loadbootenv_addr} $filesize
initrd_high=0x20000000
jtagboot=echo TFTPing Linux to RAM... && tftpboot ${kernel_load_address} ${kernel_image} && tftpboot ${devicetree_load_address} ${devicetree_image} && tftpboot ${ramdisk_load_address} ${ramdisk_image} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
kernel_image=uImage
kernel_load_address=0x2080000
kernel_size=0x500000
loadbit_addr=0x100000
loadbootenv=load mmc 0 ${loadbootenv_addr} ${bootenv}
loadbootenv_addr=0x2000000
mmc_loadbit=echo Loading bitstream from SD/MMC/eMMC to RAM.. && mmcinfo && load mmc 0 ${loadbit_addr} ${bitstream_image} && fpga load 0 ${loadbit_addr} ${filesize}
modeboot=sdboot
nandboot=echo Copying Linux from NAND flash to RAM... && nand read ${kernel_load_address} 0x100000 ${kernel_size} && nand read ${devicetree_load_address} 0x600000 ${devicetree_size} && echo Copying ramdisk... && nand read ${ramdisk_load_address} 0x620000 ${ramdisk_size} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
norboot=echo Copying Linux from NOR flash to RAM... && cp.b 0xE2100000 ${kernel_load_address} ${kernel_size} && cp.b 0xE2600000 ${devicetree_load_address} ${devicetree_size} && echo Copying ramdisk... && cp.b 0xE2620000 ${ramdisk_load_address} ${ramdisk_size} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
preboot=if test $modeboot = sdboot && env run sd_uEnvtxt_existence_test; then if env run loadbootenv; then env run importbootenv; fi; fi;
qspiboot=echo Copying Linux from QSPI flash to RAM... && sf probe 0 0 0 && sf read ${kernel_load_address} 0x100000 ${kernel_size} && sf read ${devicetree_load_address} 0x600000 ${devicetree_size} && echo Copying ramdisk... && sf read ${ramdisk_load_address} 0x620000 ${ramdisk_size} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
ramdisk_image=uramdisk.image.gz
ramdisk_load_address=0x4000000
ramdisk_size=0x5E0000
rsa_jtagboot=echo TFTPing Image to RAM... && tftpboot 0x100000 ${boot_image} && zynqrsa 0x100000 && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
rsa_nandboot=echo Copying Image from NAND flash to RAM... && nand read 0x100000 0x0 ${boot_size} && zynqrsa 0x100000 && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
rsa_norboot=echo Copying Image from NOR flash to RAM... && cp.b 0xE2100000 0x100000 ${boot_size} && zynqrsa 0x100000 && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
rsa_qspiboot=echo Copying Image from QSPI flash to RAM... && sf probe 0 0 0 && sf read 0x100000 0x0 ${boot_size} && zynqrsa 0x100000 && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
rsa_sdboot=echo Copying Image from SD to RAM... && load mmc 0 0x100000 ${boot_image} && zynqrsa 0x100000 && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
sd_uEnvtxt_existence_test=test -e mmc 0 /uEnv.txt
sdboot=if mmcinfo; then run uenvboot; echo Copying Linux from SD to RAM... && load mmc 0 ${kernel_load_address} ${kernel_image} && load mmc 0 ${devicetree_load_address} ${devicetree_image} && load mmc 0 ${ramdisk_load_address} ${ramdisk_image} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; fi
stderr=serial@e0001000
stdin=serial@e0001000
stdout=serial@e0001000
uenvboot=if run loadbootenv; then echo Loaded environment from ${bootenv}; run importbootenv; fi; if test -n $uenvcmd; then echo Running uenvcmd ...; run uenvcmd; fi
usbboot=if usb start; then run uenvboot; echo Copying Linux from USB to RAM... && load usb 0 ${kernel_load_address} ${kernel_image} && load usb 0 ${devicetree_load_address} ${devicetree_image} && load usb 0 ${ramdisk_load_address} ${ramdisk_image} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; fi
Environment size: 4395/131068 bytes
起動方法を細かく指定しないとダメみたい?
printenv の結果から見ると、
LANG:sh
bootcmd=run $modeboot
modeboot=sdboot
sdboot=if mmcinfo; then \
run uenvboot; \
echo Copying Linux from SD to RAM... &&
load mmc 0 ${kernel_load_address} ${kernel_image} &&
load mmc 0 ${devicetree_load_address} ${devicetree_image} &&
load mmc 0 ${ramdisk_load_address} ${ramdisk_image} &&
bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; \
fi
uenvboot=if run loadbootenv; then \
echo Loaded environment from ${bootenv}; \
run importbootenv; \
fi; \
if test -n $uenvcmd; then \
echo Running uenvcmd ...; \
run uenvcmd; \
fi
loadbootenv= \
load mmc 0 ${loadbootenv_addr} ${bootenv}
importbootenv= \
echo Importing environment from SD ...; \
env import -t ${loadbootenv_addr} $filesize
これを z-turn に付いてきた SD Card の uEnv.txt と比べる。
bootargs=console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0
load_image=fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image}
uenvcmd=run mmc_loadbit_fat && echo Copying Linux from SD to RAM... && mmcinfo && run load_image && bootm ${kernel_load_address} - ${devicetree_load_address}
z-turn の SD Card で起動したときの環境変数は、
LANG:console
zynq-uboot> printenv
baudrate=115200
bitstream_image=system.bit.bin
boot_image=BOOT.bin
boot_size=0x080000
bootcmd=run $modeboot
bootdelay=3
bootenv=uEnv.txt
devicetree_image=devicetree.dtb
devicetree_load_address=0x2000000
devicetree_size=0x010000
ethact=Gem.e000b000
ethaddr=00:0a:35:00:01:22
fdt_high=0x20000000
importbootenv=echo Importing environment from SD ...; env import -t ${loadbootenv_addr} $filesize
initrd_high=0x20000000
ipaddr=192.168.1.55
jtagboot=echo TFTPing Linux to RAM... && tftpboot ${kernel_load_address} ${kernel_image} && tftpboot ${devicetree_load_address} ${devicetree_image} && tftpboot ${ramdisk_load_address} ${ramdisk_image} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
kernel_image=uImage
kernel_load_address=0x2080000
kernel_size=0x480000
loadbit_addr=0x100000
loadbootenv=fatload mmc 0 ${loadbootenv_addr} ${bootenv}
loadbootenv_addr=0x2000000
mmc_loadbit_fat=echo Loading bitstream from SD/MMC/eMMC to RAM.. && get_bitstream_name && mmcinfo && fatload mmc 0 ${loadbit_addr} ${bitstream_image} && fpga loadb 0 ${loadbit_addr} ${filesize}
modeboot=sdboot
nandboot=echo Copying Linux from NAND flash to RAM... && nand read ${kernel_load_address} 0x100000 ${kernel_size} && nand read ${devicetree_load_address} 0x600000 ${devicetree_size} && echo Copying ramdisk... && nand read ${ramdisk_load_address} 0x620000 ${ramdisk_size} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
norboot=echo Copying Linux from NOR flash to RAM... && cp.b 0xE2100000 ${kernel_load_address} ${kernel_size} && cp.b 0xE2600000 ${devicetree_load_address} ${devicetree_size} && echo Copying ramdisk... && cp.b 0xE2620000 ${ramdisk_load_address} ${ramdisk_size} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
qboot_addr=0x000000
qbootenv_addr=0x080000
qbootenv_size=0x020000
qdevtree_addr=0x980000
qkernel_addr=0x500000
qramdisk_addr=0x990000
qspiboot=echo Copying Linux from QSPI flash to RAM... && sf probe 0 0 0 && qspi_get_bitsize 0x0A0000 && sf read ${loadbit_addr} 0x0A0004 ${bitsize} && fpga loadb 0 ${loadbit_addr} ${bitsize} && sf read ${kernel_load_address} ${qkernel_addr} ${kernel_size} && sf read ${devicetree_load_address} ${qdevtree_addr} ${devicetree_size} && echo Copying ramdisk... && sf read ${ramdisk_load_address} ${qramdisk_addr} ${ramdisk_size} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
qspiupdate=echo Update qspi images from sd card... && echo - Init mmc... && mmc rescan && echo - Init qspi flash... && sf probe 0 0 0 && echo - Write boot.bin... && fatload mmc 0 0x200000 boot.bin && sf erase ${qboot_addr} ${boot_size} && sf erase ${qbootenv_addr} ${qbootenv_size} && sf write 0x200000 0 ${filesize} && get_bitstream_name && echo - Write ${bitstream_image}... && fatload mmc 0 0x200000 ${bitstream_image} && sf erase 0x0A0000 0x460000 && mw.l 0x100000 ${filesize} && sf write 0x100000 0x0A0000 4 && sf write 0x200000 0x0A0004 ${filesize} && echo - Write uImage... && fatload mmc 0 0x200000 uImage && sf erase ${qkernel_addr} ${kernel_size} && sf write 0x200000 ${qkernel_addr} ${filesize} && echo - Write device tree... && fatload mmc 0 0x200000 devicetree.dtb && sf erase ${qdevtree_addr} ${devicetree_size} && sf write 0x200000 ${qdevtree_addr} ${filesize} && echo - Write Ramdisk... && fatload mmc 0 0x200000 uramdisk.image.gz && sf erase ${qramdisk_addr} ${ramdisk_size} && sf write 0x200000 ${qramdisk_addr} ${filesize} && echo - Done.
ramdisk_image=uramdisk.image.gz
ramdisk_load_address=0x4000000
ramdisk_size=0x600000
rsa_jtagboot=echo TFTPing Image to RAM... && tftpboot 0x100000 ${boot_image} && zynqrsa 0x100000 && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
rsa_nandboot=echo Copying Image from NAND flash to RAM... && nand read 0x100000 0x0 ${boot_size} && zynqrsa 0x100000 && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
rsa_norboot=echo Copying Image from NOR flash to RAM... && cp.b 0xE2100000 0x100000 ${boot_size} && zynqrsa 0x100000 && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
rsa_qspiboot=echo Copying Image from QSPI flash to RAM... && sf probe 0 0 0 && sf read 0x100000 0x0 ${boot_size} && zynqrsa 0x100000 && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
rsa_sdboot=echo Copying Image from SD to RAM... && fatload mmc 0 0x100000 ${boot_image} && zynqrsa 0x100000 && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
sdboot=if mmcinfo; then run uenvboot; get_bitstream_name && echo - load ${bitname} to PL... && fatload mmc 0 0x200000 ${bitname} && fpga loadb 0 0x200000 ${filesize} && echo Copying Linux from SD to RAM... && fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image} && fatload mmc 0 ${ramdisk_load_address} ${ramdisk_image} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; fi
serverip=192.168.1.13
stderr=serial
stdin=serial
stdout=serial
uenvboot=if run loadbootenv; then echo Loaded environment from ${bootenv}; run importbootenv; fi; if test -n $uenvcmd; then echo Running uenvcmd ...; run uenvcmd; fi
usbboot=if usb start; then run uenvboot; echo Copying Linux from USB to RAM... && fatload usb 0 ${kernel_load_address} ${kernel_image} && fatload usb 0 ${devicetree_load_address} ${devicetree_image} && fatload usb 0 ${ramdisk_load_address} ${ramdisk_image} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; fi
Environment size: 5720/131068 bytes
こちらでは u-boot コンソールを抜けた後に uEnv.txt が読まれる。 どうしてだろう?
とりあえず置いておいて、
LANG:sh
bootcmd=run $modeboot
modeboot=sdboot
sdboot= \
if mmcinfo; then \
run uenvboot; \
get_bitstream_name && \
echo - load ${bitname} to PL... && \
fatload mmc 0 0x200000 ${bitname} && \
fpga loadb 0 0x200000 ${filesize} && \
echo Copying Linux from SD to RAM... && \
fatload mmc 0 ${kernel_load_address} ${kernel_image} && \
fatload mmc 0 ${devicetree_load_address} ${devicetree_image} && \
fatload mmc 0 ${ramdisk_load_address} ${ramdisk_image} && \
bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; \
fi
uenvboot= \
if run loadbootenv; then \
echo Loaded environment from ${bootenv}; \
run importbootenv; \
fi; \
if test -n $uenvcmd; then \
echo Running uenvcmd ...; \
run uenvcmd; \
fi
loadbootenv= \
fatload mmc 0 ${loadbootenv_addr} ${bootenv}
importbootenv= \
echo Importing environment from SD ...; \
env import -t ${loadbootenv_addr} $filesize
# 以下は uEnv.txt 内
uenvcmd= \
run mmc_loadbit_fat && \
echo Copying Linux from SD to RAM... && \
mmcinfo && \
run load_image && \
bootm ${kernel_load_address} - ${devicetree_load_address}
load_image= \
fatload mmc 0 ${kernel_load_address} ${kernel_image} && \
fatload mmc 0 ${devicetree_load_address} ${devicetree_image}
# 以下再び uEnv.txt 外
mmc_loadbit_fat= \
echo Loading bitstream from SD/MMC/eMMC to RAM.. && \
get_bitstream_name && \
mmcinfo && \
fatload mmc 0 ${loadbit_addr} ${bitstream_image} && \
fpga loadb 0 ${loadbit_addr} ${filesize}
なので、
LANG:sh
get_bitstream_name && \
echo - load ${bitname} to PL... && \
fatload mmc 0 0x200000 ${bitname} && \
fpga loadb 0 0x200000 ${filesize} && \
の部分が追加されている以外、uEnv.txt が呼ばれるまでのところに違いは無い。
uEnv.txt は importbootenv で取り込まれて、uenvcmd が起動されるので、 uenvcmd 内で bootm を呼んでそれ以降の処理(ramdisk の読み込みを含む)を キャンセルしてしまえば良いみたい。そして、ramdisk を使わない場合、 bootm の ramdisk アドレスには - を渡せばいいみたい。
上記の理解を確かめるために u-boot のコマンドラインで
LANG:console
Zynq> get_bitstream_name
Unknown command 'get_bitstream_name' - try 'help'
Zynq> setenv bootargs console=ttyPS1,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 devtmpfs.mount=0
Zynq> bootm ${kernel_load_address} - ${devicetree_load_address}
としたところ、Linux が起動した。
これは、すでに uImage と system.dtb がメモリに読み込まれていたため。
uenvcmd を自分で書く場合には、上記と同様にこれらの読み込みも必要になる。
u-boot のコマンドラインで get_bitstream_name が失敗するのはなぜだろう?
今の設定では bitstream が BOOT.BIN に含まれてしまっているのだけれど、 実際には VFAT 上に単独ファイルとして置きたいところ。z-turn 付属の SD カードではそのようになっている。
試しに、design_1_wrapper_0.bit を design1.bit として SD カードに入れ、
LANG:console
Zynq> fatload mmc 0 0x200000 design1.bit
reading design1.bit
4045676 bytes read in 275 ms (14 MiB/s)
Zynq> fpga loadb 0 0x200000 ${filesize}
design filename = "design_1_wrapper;UserID=0XFFFFFFFF;Version=2014.4"
part number = "7z020clg400"
date = "2015/08/11"
time = "17:59:43"
bytes in bitstream = 4045564
zynq_align_dma_buffer: Align buffer at 200070 to 200000(swap 1)
としたところ、正しくプログラムできることがわかった。
あれ?いやいや、Linux が立ち上がったっぽいけど sshd が起動しておらず、 コンソールも ttyPS0 を見に行ってしまっているらしく繋がらないので、 本当に起動しているか確認できてない感じ。
inittab の設定†
LANG:console $ sudo mount /dev/sdf2 /mnt/sdcard2 $ sudo jed /mnt/sdcard2/etc/inittab # /etc/inittab: init(8) configuration. # $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $ # The default runlevel. id:5:initdefault: # Boot-time system configuration/initialization script. # This is run first except when booting in emergency (-b) mode. si::sysinit:/etc/init.d/rcS # What to do in single-user mode. ~~:S:wait:/sbin/sulogin # /etc/init.d executes the S and K scripts upon change # of runlevel. # # Runlevel 0 is halt. # Runlevel 1 is single-user. # Runlevels 2-5 are multi-user. # Runlevel 6 is reboot. l0:0:wait:/etc/init.d/rc 0 l1:1:wait:/etc/init.d/rc 1 l2:2:wait:/etc/init.d/rc 2 l3:3:wait:/etc/init.d/rc 3 l4:4:wait:/etc/init.d/rc 4 l5:5:wait:/etc/init.d/rc 5 l6:6:wait:/etc/init.d/rc 6 # Normally not reached, but fallthrough in case of emergency. z6:6:respawn:/sbin/sulogin - PS0:12345:respawn:/bin/start_getty 115200 ttyPS0 + PS1:12345:respawn:/bin/start_getty 115200 ttyPS1 # /sbin/getty invocations for the runlevels. # # The "id" field MUST be the same as the last # characters of the device (after "tty"). # # Format: # <id>:<runlevels>:<action>:<process> # - 1:12345:respawn:/sbin/getty 38400 tty1 + #1:12345:respawn:/sbin/getty 38400 tty1 $ sudo umount /dev/sdf2
としたところ、無事ターミナルが起動した。
改めて uEnv.txt†
ファイル名をなるべくデフォルトに合わせることにして、
- ビットストリームを system.bit.bin
- デバイスツリーを devicetree.dtb
と名前を変えれば、uEnv.txt は
LANG:sh
bootargs=console=ttyPS1,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 devtmpfs.mount=0
uenvcmd=run mmc_loadbit_fat && echo Copying Linux from SD to RAM... && mmcinfo && run load_image && bootm ${kernel_load_address} - ${devicetree_load_address}
load_image=fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image}
mmc_loadbit_fat=echo Loading ${bitstream_image} to PL... && mmcinfo && fatload mmc 0 ${loadbit_addr} ${bitstream_image} && fpga loadb 0 ${loadbit_addr} ${filesize}
でいいみたい。
BOOT.BIN から .bit ファイルを取り除く†
起動時に
In FsblHookBeforeBitstreamDload function
でかなり待たされるのも気になる。
というか、今の形だと fsbl 内でビットストリームをダウンロードしちゃってる。
LANG:console $ petalinux-package --boot --fsbl ../design_1_wrapper_hw_platform_1/fsbl.elf --u-boot --force
として、BOOT.BIN に .bit ファイルを入れないようにしたところ、 待ち時間も無く u-boot が起動して、上記の fatload & fpga loadb でプログラムできることがわかった。
ここまでのまとめ†
最終的な SD カードの構成と、 それぞれの生成方法をまとめる。
- /dev/mmcblk0p1
- BOOT.BIN : petalinux-package --boot --fsbl ../design_1_wrapper_hw_platform_1/fsbl.elf --u-boot --force
- fsbl.elf : vivado で作成
- u-boot.elf : petalinux-build -c u-boot
- uEnv.txt : テキストエディタで作成
- system.bit.bin : vivado で作成
- devicetree.dtb : テキストエディタで作成
- uImage : petalinux-package --image -c kernel --format uImage
- BOOT.BIN : petalinux-package --boot --fsbl ../design_1_wrapper_hw_platform_1/fsbl.elf --u-boot --force
- /dev/mmcblk0p2
- / : Debian
- /lib/modules/4.6.0-xilinx/ : カーネルソースから作成
カーネルをソースから make†
カーネルの設定を変えるには、標準的には
LANG:console $ petalinux-config -c kernel
でいけるのだけれど、これだと一々ものすごく時間がかかるので、
(petalinux-project-dir)/build/tmp/work-shared/plnx_arm/kernel-source/
を使って手動でビルドしたいところ。
上記ディレクトリで make すると、.config が無いと言われる。
で、探してみると
(petalinux-project-dir)/build/tmp/work-shared/plnx_arm/kernel-build-artifacts/
に .config やら何やらがある。どうやって使うのだろう???
試しに上記 kernel-source/* と kernel-build-artifacts/.config とを kernel-source/ にコピーして、
LANG:console
$ cp -R build/tmp/work-shared/plnx_arm/kernel-source/ .
$ cp build/tmp/work-shared/plnx_arm/kernel-build-artifacts/.config kernel-source/
$ cd kernel-source/
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
CHK include/config/kernel.release
CHK include/generated/uapi/linux/version.h
CHK include/generated/utsrelease.h
make[1]: 'include/generated/mach-types.h' は更新済みです.
CHK include/generated/bounds.h
CHK include/generated/timeconst.h
/bin/sh: 1: bc: not found
Kbuild:66: ターゲット 'include/generated/timeconst.h' のレシピで失敗しました
make[1]: *** [include/generated/timeconst.h] エラー 127
Makefile:1002: ターゲット 'prepare0' のレシピで失敗しました
make: *** [prepare0] エラー 2
$ sudo apt-get install bc
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- UIMAGE_LOADADDR=0x8000 uImage
CC drivers/char/xilinx_devcfg.o
In file included from include/linux/printk.h:6:0,
from include/linux/kernel.h:13,
from include/linux/list.h:8,
from include/linux/kobject.h:20,
from include/linux/cdev.h:4,
from drivers/char/xilinx_devcfg.c:12:
drivers/char/xilinx_devcfg.c: In function 'xdevcfg_write':
include/linux/kern_levels.h:4:18: warning: too many arguments for format [-Wformat-extra-args]
#define KERN_SOH "\001" /* ASCII Start Of Header */
^
include/linux/kern_levels.h:10:18: note: in expansion of macro 'KERN_SOH'
#define KERN_ERR KERN_SOH "3" /* error conditions */
^
include/linux/printk.h:252:9: note: in expansion of macro 'KERN_ERR'
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
^
drivers/char/xilinx_devcfg.c:423:5: note: in expansion of macro 'pr_err'
pr_err("Bitstream does not match the device\n",
^
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
$
ビルドできた。kernel-source/arch/arm/boot/uImage を SD カードにコピーしたところ、 ちゃんと起動することを確認。
以降は、
LANG:console $ make ARCH=arm menuconfig $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- UIMAGE_LOADADDR=0x8000 uImage $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules $ sudo make ARCH=arm INSTALL_MOD_PATH=/mnt/sdcard2 modules_install $ sudo make ARCH=arm INSTALL_MOD_PATH=/mnt/sdcard2 firmware_install
で設定&ビルド&インストールできる。
ルートファイルシステムのカスタマイズ†
上のようにして作った SD カードで起動した場合、
LANG:console $ uname -a Linux plnx_arm 4.6.0-xilinx #1 SMP PREEMPT Thu Feb 23 17:42:19 JST 2017 armv7l GNU/Linux $ ls -F /lib/modules/4.6.0-xilinx/ kernel/ modules.builtin.bin modules.order modules.alias modules.dep modules.softdep modules.alias.bin modules.dep.bin modules.symbols modules.builtin modules.devname modules.symbols.bin $ ls /lib/firmware ls: /lib/firmware: No such file or directory
となりました。
LANG:console $ petalinux-config -c rootfs
とするとこのファイルシステムに含めるパッケージを選択できるようだけれど 一々ここまで戻らないとパッケージを追加できないのは困るのと、 そもそも個人的に使い慣れた Debian にした方がいろいろはかどりそうなのとで、 まるっと入れ替えてしまうことに。
やり方は 電気回路/z-turn/Linuxの設定 を参照。
全体のまとめ†
もう一度はじめから、全手順を確認してみます。
LANG:console
$ cd ~/z-turn
$ mv zturn-v2016.4 zturn-v2016.4_backup
$ petalinux-setup
$ petalinux-create -t project --template zynq -n zturn-v2016.4
$ cd zturn-v2016.4
$ git init
$ cat <<EOT > .gitignore
> .petalinux
> /build
> /images
> /components
> /BOOT.BIN
> *~
> EOT
$ petalinux-config --get-hw-description=../design_1_wrapper_hw_platform_1/
Linux Components Selection --->
[Uncheck] First Stage Bootloaer
Auto Config Settings --->
[Uncheck] fsbl autoconfig
Yocto Settings --->
Parallel thread execution --->
BB_NUMBER_THREADS = 4
PARALLEL_MAKE = 4
$ petalinux-config -c u-boot
Boot images --->
[Uncheck] Support Flattened Image Tree
Boot media --->
[Check] Support for booting from SD/EMMC
Networking support --->
[Uncheck] all
Device Drivers --->
[Uncheck] Ethernet PHY support
$ mkdir -p images/linux/
$ petalinux-package --image -c kernel --format uImage
WARNING: /home/osamu/z-turn/petalinux/components/yocto/source/arm/layers/meta-xilinx/recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb.do_compile is tainted from a forced run
NOTE: Tasks Summary: Attempted 1793 tasks of which 1378 didn't need to be rerun and all succeeded.
Summary: There was 1 WARNING message shown.
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
File "/home/osamu/z-turn/petalinux/components/yocto/source/arm/buildtools/sysroots/x86_64-petalinux-linux/usr/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
func(*targs, **kargs)
File "/home/osamu/z-turn/petalinux/components/yocto/source/arm/layers/poky/bitbake/lib/bb/ui/knotty.py", line 226, in finish
self.termios.tcsetattr(fd, self.termios.TCSADRAIN, self.stdinbackup)
error: (5, 'Input/output error')
Error in sys.exitfunc:
Traceback (most recent call last):
File "/home/osamu/z-turn/petalinux/components/yocto/source/arm/buildtools/sysroots/x86_64-petalinux-linux/usr/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
func(*targs, **kargs)
File "/home/osamu/z-turn/petalinux/components/yocto/source/arm/layers/poky/bitbake/lib/bb/ui/knotty.py", line 226, in finish
self.termios.tcsetattr(fd, self.termios.TCSADRAIN, self.stdinbackup)
termios.error: (5, 'Input/output error')
$ ls images/linux
uImage
$ ls build/tmp/deploy/images/plnx_arm/
modules-plnx_arm.tgz
plnx_arm-system.dtb
plnx_arm-system.dts
u-boot.bin
u-boot.elf
uImage
...
$ cp build/tmp/deploy/images/plnx_arm/u-boot.elf images/linux/
$ petalinux-package --boot --fsbl ../design_1_wrapper_hw_platform_1/fsbl.elf --u-boot --force
$ rm BOOT.BIN
$ cp build/tmp/deploy/images/plnx_arm/plnx_arm-system.dtb images/linux/devicetree.dtb
$ cp ../design_1_wrapper_hw_platform_1/design_1_wrapper.bit images/linux/system.bit.bin
$ cat > images/linux/uEnv.txt
bootargs=console=ttyPS1,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 devtmpfs.mount=0
uenvcmd=run mmc_loadbit_fat && echo Copying Linux from SD to RAM... && mmcinfo && run load_image && bootm ${kernel_load_address} - ${devicetree_load_address}
load_image=fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image}
mmc_loadbit_fat=echo Loading ${bitstream_image} to PL... && mmcinfo && fatload mmc 0 ${loadbit_addr} ${bitstream_image} && fpga loadb 0 ${loadbit_addr} ${filesize}
^D
$ ls images/linux
BOOT.BIN devicetree.dtb system.bit.bin u-boot.elf uEnv.txt uImage zynq_fsbl.elf
$ cp -R build/tmp/work-shared/plnx_arm/kernel-source/ .
$ cp build/tmp/work-shared/plnx_arm/kernel-build-artifacts/.config kernel-source/
$ petalinux-build -c u-boot $ ls images/linux/ BOOT.BIN devicetree.dtb rootfs.tar.gz u-boot.bin uImage System.map.linux rootfs.cpio system.bit.bin u-boot.elf vmlinux design_1_wrapper.bit rootfs.cpio.gz system.dtb uEnv.txt zynq_fsbl.elf
- u-boot の confiture をしないと image.ub を読みに行ってしまいます
- mkdir -p images/linux/ をしないと uImage などがコピーできないというエラーが出ます