前面的几篇文章里简单的记录了一下使用buildroot构建RIoTBoard系统镜像的过程,因想使用imx6 solo的VPU,但是buildroot默认使用的kernal版本是liunx-fslc,需要使用linux-imx的kernal才能使用GPU, VPU 以及 IPU,Yocto构建系统的时候可以灵活的选择kernal版本,而且FSL Community 每个版本BSP Release Notes 中的教程也是使用Yocto来构建,所以决定来踩下Yocto的坑。
linux-fslc: Linux kernel based on mainline kernel used by FSL Community BSP in order to provide support for some backported features and fixes, or because it was applied in linux-next and takes some time to become part of a stable version, or because it is not applicable for upstreaming.
linux-imx: Linux Kernel provided and supported by Freescale with focus on i.MX Family Reference Boards. It includes support for many IPs such as GPU, VPU and IPU.
1 Yocto 下载
Yocto构建的时候需要使用repo来下载source code,所以需要先安装repo,安装方法FSL Community Release Notes或者网上有详细的说明,此处不再赘述。
repo环境搭建好以后就可以下载code了:
mkdir imx-yocto-bsp
cd imx-yocto-bsp
repo init -u https://source.codeaurora.org/external/imx/imx-manifest -b imx-linux-sumo -m imx-4.14.98-2.0.0_ga.xml --depth=1
git config --global url."https://github.com".insteadOf git://github.com
repo sync -c --no-repo-verify --no-tags --no-clone-bundle -j 4
repo init 时–depth=1参数指定只拉取最近一版code, repo sync时也选择不下载tag等,这样fetch速度会快一些
2 编译
编译方面i.MX提供了fsl-setup-release.sh脚步,可简化i.MX机器的设置, 使用该脚本时,需要指定要为其构建的特定机器的名称以及图形 backend,fsl-setup-release.sh脚本的语法如下所示:
DISTRO=<distro name> MACHINE=<machine name> source fsl-setup-release.sh -b <build dir>
(1)DISTRO是发行版,用于配置构建的环境,下面是DISTRO可使用的配置:
fsl-imx-x11 - X11
fsl-imx-wayland - Wayland weston
fsl-imx-xwayland - Wayland and X11
fsl-imx-fb - Frame Buffer
(2)MACHINE是指向meta-freescale和meta-fsl-bsp-release中conf/machine中配置文件的机器名称,下面列出的是可以选择的i.MX机器配置文件:
imx6qpsabreauto
imx6qpsabresd
imx6ulevk
imx6ulz14x14evk
imx6ull14x14evk
imx6ull9x9evk
imx6dlsabreauto
imx6dlsabresd
imx6qsabreauto
imx6qsabresd
imx6slevk
imx6solosabreauto
imx6solosabresd
imx6sxsabresd
imx6sxsabreauto
imx6sllevk
imx7dsabresd
imx7ulpevk
imx8qmmek
imx8qxpmek
imx8mqevk
imx8mmevk
(3)-b 指定由fsl-setup-release.sh脚本创建的构建目录的名称。
RIoTBoard按照以下形式执行fsl-setup-release.sh脚本,脚本执行后会自动跳转到build目录:
DISTRO=fsl-imx-xwayland MACHINE=imx6dl-riotboard source fsl-setup-release.sh -b build
imx6dl-riotboard的kernal 和uboot 版本是linux-fslc-imx 和u-boot-fslc ,需要修改配置文件将其改为linux–imx和u-boot-imx,首先修改source/meta-freescale-3rdparty/conf/machine/imx6dl-riotboard.conf文件,修改后文件如下:
include conf/machine/include/imx-base.inc
include conf/machine/include/tune-cortexa9.inc
MACHINEOVERRIDES =. "mx6:mx6dl:"
UBOOT_MACHINE = "riotboard_defconfig"
PREFERRED_PROVIDER_virtual/kernel ?= "linux-imx"
KERNEL_DEVICETREE = "imx6dl-riotboard.dtb"
SERIAL_CONSOLE = "115200 ttymxc1"
MACHINE_ESSENTIAL_EXTRA_RDEPENDS += " \
kernel-image \
kernel-devicetree \
u-boot-imx \
"
WKS_FILES = "imx-uboot.wks"
然后修改source//meta-fsl-bsp-release/imx/meta-bsp/conf/machine/include/imx-base.inc文件,主要修改了两处,第一处将PREFERRED_PROVIDER_u-boot 改为u-boot-imx:
# Set specific make target and binary suffix
PREFERRED_PROVIDER_u-boot ??= "u-boot-imx"
PREFERRED_PROVIDER_virtual/bootloader ??= "u-boot-imx"
第二处修改imx6的默认kernal version:
# Handle default kernel
IMX_DEFAULT_KERNEL = "linux-imx"
IMX_DEFAULT_KERNEL_mxs = "linux-fslc"
IMX_DEFAULT_KERNEL_mx5 = "linux-fslc"
IMX_DEFAULT_KERNEL_mx6 = "linux-fslc-imx"
#IMX_DEFAULT_KERNEL_mx6 = "Linux-imx"
IMX_DEFAULT_KERNEL_mx7 = "linux-fslc-imx"
IMX_DEFAULT_KERNEL_mx6ul = "linux-fslc-imx"
IMX_DEFAULT_KERNEL_mx6ull = "linux-fslc-imx"
IMX_DEFAULT_KERNEL_mx6ulz = "linux-imx"
IMX_DEFAULT_KERNEL_mx8 = "linux-imx"
IMX_DEFAULT_KERNEL_mx7ulp = "linux-imx"
IMX_DEFAULT_KERNEL_mx6sll = "linux-imx"
修改完成后就可以编译了,Yocto提供了多种镜像,具体如下:
先选择core-image-base,-k表示发生错误时不退出,继续构建其他。
bitbake -k core-image-base
遇到的编译错误:
tmp/work/imx6dl_riotboard-poky-linux-gnueabi/u-boot-imx/2018.03-r0/git/arch/arm/mach-imx/cpu.c:354: undefined reference to `ldo_mode_set'
查看cpu.c中源码:
#if defined(CONFIG_LDO_BYPASS_CHECK)
ldo_mode_set(check_ldo_bypass());
#endif
ldo_mode_set用CONFIG_LDO_BYPASS_CHECK 宏包着,解决方案是在tmp/work/imx6dl_riotboard-poky-linux-gnueabi/u-boot-imx/2018.03-r0/git/include/configs/embestmx6boards.h中取消这个宏定义:
#undef CONFIG_LDO_BYPASS_CHECK
取消宏定义后再次编译OK,构建成功后会在build/tmp/deploy/images/imx6dl-riotboard目录生成u-boot.imx,rootfs.sdcard等文件:
zhy@zhy-ThinkPad-E480:~/code/rIoTboard/yocoto/imx-4.14/build/tmp/deploy/images/imx6dl-riotboard$ ls -l
total 185748
-rw-r--r-- 2 zhy zhy 96468992 10月 6 15:22 core-image-base-imx6dl-riotboard-20221006070905.rootfs.ext4
-rw-r--r-- 2 zhy zhy 11763 10月 6 15:22 core-image-base-imx6dl-riotboard-20221006070905.rootfs.manifest
-rw-r--r-- 1 zhy zhy 113246208 10月 6 15:22 core-image-base-imx6dl-riotboard-20221006070905.rootfs.sdcard
-rw-r--r-- 1 zhy zhy 140568 10月 6 15:22 core-image-base-imx6dl-riotboard-20221006070905.testdata.json
lrwxrwxrwx 2 zhy zhy 59 10月 6 15:22 core-image-base-imx6dl-riotboard.ext4 -> core-image-base-imx6dl-riotboard-20221006070905.rootfs.ext4
lrwxrwxrwx 2 zhy zhy 63 10月 6 15:22 core-image-base-imx6dl-riotboard.manifest -> core-image-base-imx6dl-riotboard-20221006070905.rootfs.manifest
lrwxrwxrwx 2 zhy zhy 64 10月 6 15:22 core-image-base-imx6dl-riotboard.sdcard.gz -> core-image-base-imx6dl-riotboard-20221006070905.rootfs.sdcard.gz
lrwxrwxrwx 1 zhy zhy 61 10月 6 15:22 core-image-base-imx6dl-riotboard.testdata.json -> core-image-base-imx6dl-riotboard-20221006070905.testdata.json
lrwxrwxrwx 1 zhy zhy 64 10月 5 21:04 core-image-minimal-imx6dl-riotboard.testdata.json -> core-image-minimal-imx6dl-riotboard-20221005130318.testdata.json
lrwxrwxrwx 2 zhy zhy 54 10月 6 15:20 imx6dl-riotboard.dtb -> zImage--4.14.98-r0-imx6dl-riotboard-20221006070905.dtb
-rw-rw-r-- 2 zhy zhy 848905 10月 6 15:20 modules--4.14.98-r0-imx6dl-riotboard-20221006070905.tgz
lrwxrwxrwx 2 zhy zhy 55 10月 6 15:20 modules-imx6dl-riotboard.tgz -> modules--4.14.98-r0-imx6dl-riotboard-20221006070905.tgz
lrwxrwxrwx 2 zhy zhy 38 10月 6 15:09 u-boot.imx -> u-boot-imx6dl-riotboard-2018.03-r0.imx
-rw-r--r-- 2 zhy zhy 470016 10月 6 15:09 u-boot-imx6dl-riotboard-2018.03-r0.imx
lrwxrwxrwx 2 zhy zhy 38 10月 6 15:09 u-boot-imx6dl-riotboard.imx -> u-boot-imx6dl-riotboard-2018.03-r0.imx
lrwxrwxrwx 2 zhy zhy 54 10月 6 15:20 zImage -> zImage--4.14.98-r0-imx6dl-riotboard-20221006070905.bin
-rw-r--r-- 2 zhy zhy 7267792 10月 6 15:20 zImage--4.14.98-r0-imx6dl-riotboard-20221006070905.bin
-rw-r--r-- 2 zhy zhy 43224 10月 6 15:20 zImage--4.14.98-r0-imx6dl-riotboard-20221006070905.dtb
lrwxrwxrwx 2 zhy zhy 54 10月 6 15:20 zImage-imx6dl-riotboard.bin -> zImage--4.14.98-r0-imx6dl-riotboard-20221006070905.bin
lrwxrwxrwx 2 zhy zhy 54 10月 6 15:20 zImage-imx6dl-riotboard.dtb -> zImage--4.14.98-r0-imx6dl-riotboard-20221006070905.dtb
3 系统烧写测试
我选择的是将image烧写到TF 卡中,只需要将core-image-base-imx6dl-riotboard-20221006070905.rootfs.sdcard.gz解压并通过dd命令烧写即可:
gzip -d core-image-base-imx6dl-riotboard-20221006070905.rootfs.sdcard.gz
sudo dd if=core-image-base-imx6dl-riotboard-20221006070905.rootfs.sdcard of=/dev/mmcblk0 bs=1M
这个命令执行完成后/dev/mmcblk0被分成/dev/mmcblk0p1 /dev/mmcblk0p2两个分区,可以把这个两个分区挂载一下看看里面存放的内容:
sudo mount /dev/mmcblk0p1 sd-part/
mmcblk0p1里面存放了dtb和kernal
zhy@zhy-ThinkPad-E480:~/code/rIoTboard/yocoto/imx-4.14/build/tmp/deploy/images/imx6dl-riotboard/sd-part$ ls
imx6dl-riotboard.dtb zImage
mmcblk0p2 存放的是rootfs,
sudo mount /dev/mmcblk0p2 sd-part/
sd-part$ ls
bin boot dev etc home lib lost+found media mnt proc run sbin sys tmp usr var
mmcblk0p2的/boot 目录下同样存在dtb和kernal
sd-part/boot$ ls
devicetree-zImage-imx6dl-riotboard.dtb imx6dl-riotboard.dtb u-boot.imx u-boot-imx6dl-riotboard-2018.03-r0.imx zImage zImage-4.14.98-imx_4.14.98_2.0.0_ga+g5d6cbeafb80c
将TF卡插到开发板上,启动模式设置为TF 卡启动,上电后发现kernal无法启动:
U-Boot 2018.03-imx_v2018.03_4.14.98_2.0.0_ga+g87a19df5e4 (Oct 06 2022 - 07:09:15 +0000)
CPU: Freescale i.MX6SOLO rev1.2 996 MHz (running at 792 MHz)
CPU: Commercial temperature grade (0C to 95C) at 38C
...................
Device 0: device type unknown
... is now current device
** Bad device usb 0 **
** Bad device usb 0 **
FEC Waiting for PHY auto negotiation to complete......... TIMEOUT !
Could not initialize PHY FEC
BOOTP broadcast 1
uboot下查看bootcmd和bootargs,发现bootcmd不对,而且没有设置bootargs
=> print bootcmd
bootcmd=run finduuid; run distro_bootcmd
=> print bootargs
## Error: "bootargs" not defined
先设置bootargs,因rootfs在/dev/mmcblk0p2,所以设置root=/dev/mmcblk0p2:
setenv bootargs console=ttymxc1,115200 nosmp video=mxcfb0:dev=hdmi,1280x720M@60,bpp=32 video=mxcfb1:off fbmem=10M vmalloc=400M rootwait root=/dev/mmcblk0p2
saveenv
bootcmd用来启动kernal ,所以先查看看MMC下是否存在该镜像和设备树,查看emmc 设备
=> mmc list
FSL_SDHC: 0
FSL_SDHC: 1 (SD)
FSL_SDHC: 2 (eMMC)
镜像烧写在了SD卡中,所以应该选择mmc 1,之前说过SD卡被分成两个分区,第一个分区是fat32格式,第二个分区是ext4格式,uboot下分别看一下mmc 1两个分区的存储内容:
=> fatls mmc 1:1
7267792 zImage
43224 imx6dl-riotboard.dtb
2 file(s), 0 dir(s)
=> ext4ls mmc 2:1
<DIR> 4096 .
<DIR> 4096 ..
<DIR> 16384 lost+found
<DIR> 4096 bin
<DIR> 4096 boot
<DIR> 4096 clips
<DIR> 4096 dev
<DIR> 4096 etc
<DIR> 4096 home
<DIR> 4096 lib
<DIR> 4096 media
<DIR> 4096 mnt
<DIR> 4096 opt
<DIR> 4096 proc
<DIR> 4096 root
<DIR> 4096 run
<DIR> 4096 sbin
<DIR> 4096 selinux
4692 session.vim
<DIR> 4096 srv
<DIR> 4096 sys
<DIR> 4096 tmp
<DIR> 4096 unit_tests
<DIR> 4096 usr
<DIR> 4096 var
16427 viminfo
=> ext4ls mmc 1:2 /boot
<DIR> 1024 .
<DIR> 1024 ..
<SYM> 20 devicetree-zImage-imx6dl-riotboard.dtb
43224 imx6dl-riotboard.dtb
470016 u-boot-imx6dl-riotboard-2018.03-r0.imx
7267792 zImage-4.14.98-imx_4.14.98_2.0.0_ga+g5d6cbeafb80c
<SYM> 49 zImage
<SYM> 38 u-boot.imx
可以看到和在PC上挂载以后看到的内容一样,我选择加载mmc 1:2 /boot目录下的kernal 和dtb来启动,bootcmd设置如下:
setenv bootcmd 'mmc dev 1;ext4load mmc 1:2 10800000 /boot/zImage;ext4load mmc 1:2 16800000 /boot/devicetree-zImage-imx6dl-riotboard.dtb;bootz 10800000 - 16800000'
saveenv
boot
这样kernal可以启动:
=> boot
switch to partitions #0, OK
mmc1 is current device
7267792 bytes read in 464 ms (14.9 MiB/s)
43224 bytes read in 101 ms (417 KiB/s)
Kernel image @ 0x10800000 [ 0x000000 - 0x6ee5d0 ]
## Flattened Device Tree blob at 16800000
Booting using the fdt blob at 0x16800000
Loading Device Tree to 1fff2000, end 1ffff8d7 ... OK
Starting kernel ...
Booting Linux on physical CPU 0x0
Linux version 4.14.98-imx_4.14.98_2.0.0_ga+g5d6cbeafb80c (oe-user@oe-host) (gcc version 7.3.0 (GCC)) #1 SMP PREEMPT Thu Oct 6 07:09:40 UTC 2022
CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c53c7d
但是会卡在Waiting for root device /dev/root=/dev/mmcblk0p2…这里,网上搜索资料发现应该是rootfs 挂载不上的问题:
Waiting for root device /dev/root=/dev/mmcblk0p2...
imx-sdma 20ec000.sdma: external firmware not found, using ROM firmware
查看kernal 启动log, 发现TF 卡被挂载到了mmcblk2(使用的TF卡的大小是32G):
mmc1: SDHCI controller on 2194000.usdhc [2194000.usdhc] using ADMA
sdhci-esdhc-imx 2198000.usdhc: Got CD GPIO
sdhci-esdhc-imx 2198000.usdhc: Got WP GPIO
mmc2: SDHCI controller on 2198000.usdhc [2198000.usdhc] using ADMA
mmc2: new high speed SDHC card at address aaaa
mmcblk2: mmc2:aaaa SD32G 29.7 GiB
mmc3: SDHCI controller on 219c000.usdhc [219c000.usdhc] using ADMA
mmcblk2: p1 p2
mxc_vpu 2040000.vpu_fsl: VPU initialized
重新设置bootargs:
setenv bootargs console=ttymxc1,115200 nosmp video=mxcfb0:dev=hdmi,1280x720M@60,bpp=32 video=mxcfb1:off fbmem=10M vmalloc=400M rootwait root=/dev/mmcblk2p2
saveenv
这样rootfs 挂载成功,可以正常进入console。
#0: imx6-riotboard-sgtl5000
EXT4-fs (mmcblk2p2): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext4 filesystem) readonly on device 179:2.
devtmpfs: mounted
使用root登陆后可以看到/dev目录下已成功创建mxc_vpu设备:
FSLC Wayland with XWayland 2.5 imx6dl-riotboard ttymxc1
imx6dl-riotboard login: root
root@imx6dl-riotboard:~# ls
root@imx6dl-riotboard:~# cd /dev/
root@imx6dl-riotboard:/dev# ls
autofs ram0 tty38
block ram1 tty39
bus ram10 tty4
char ram11 tty40
console ram12 tty41
cpu_dma_latency ram13 tty42
disk ram14 tty43
dri ram15 tty44
fb0 ram2 tty45
fb1 ram3 tty46
fd ram4 tty47
full ram5 tty48
fuse ram6 tty49
gpiochip0 ram7 tty5
gpiochip1 ram8 tty50
gpiochip2 ram9 tty51
gpiochip3 random tty52
gpiochip4 rtc tty53
gpiochip5 rtc0 tty54
gpiochip6 shm tty55
hwrng snd tty56
i2c-0 stderr tty57
i2c-1 stdin tty58
i2c-3 stdout tty59
initctl tty tty6
kmsg tty0 tty60
log tty1 tty61
loop-control tty10 tty62
loop0 tty11 tty63
loop1 tty12 tty7
loop2 tty13 tty8
loop3 tty14 tty9
loop4 tty15 ttymxc0
loop5 tty16 ttymxc1
loop6 tty17 ttymxc2
loop7 tty18 ttymxc3
mem tty19 ttymxc4
memory_bandwidth tty2 ubi_ctrl
mmcblk2 tty20 urandom
mmcblk2p1 tty21 vcs
mmcblk2p2 tty22 vcs1
mmcblk3 tty23 vcs2
mmcblk3boot0 tty24 vcs3
mmcblk3boot1 tty25 vcs4
mmcblk3p1 tty26 vcs5
mmcblk3rpmb tty27 vcs6
mxc_asrc tty28 vcsa
mxc_hdmi tty29 vcsa1
mxc_ipu tty3 vcsa2
mxc_vpu tty30 vcsa3
network_latency tty31 vcsa4
network_throughput tty32 vcsa5
null tty33 vcsa6
pps0 tty34 watchdog
ptmx tty35 watchdog0
ptp0 tty36 zero
后来测试的时候发现HDMI 口接上显示器后kernal无法启动,不接显示器就可以正常启动,后来在谷歌上找到了解决方法(参考链接:https://bugzilla.yoctoproject.org/show_bug.cgi?id=6703),在uboot下输入以下命令即可:
setenv panel Hannstar-XGA