用户选择使用Digi嵌入式核心模块作为主控单元,是为了充分利用Digi的DEY简单易用的特点,以及各种验证过的BSP和软硬件功能模块。在开发过程中,用户可以仅维护少数几个自己改动过的配置文件,设备树文件等,利用这些文件就可以直接配合已有的或全新安装的DEY开发环境编译出自己定制的系统。利用这种方式开发对初学者非常有利,不论DEY或上游软件如何更新变化,只要大版本一致,都可以在任意时刻快速复原之前的开发成果。
本文以一个cc6ul项目为例,针对Yocto的初学者,希望以最接近传统开发方式来进行项目开发和维护。在熟练掌握本文的方法后,还可以meta-custom来代替相关的文件和操作。这是熟练掌握Yocto开发方式之后的事,在此之前,先用本文的方法来开发和维护自己的工作。
根据项目需求设计第一版硬件,只需配合该硬件设计更改编译相关的设备树文件。硬件电路设计时,请注意参考cc6ul官方硬件参考手册,特别注意cc6ul硬件设计指南:
用到uart2,uart3设计为两线RS232接口,uart4为485接口,uart5
SPI1接MC33996
I2C1,CAN1,CAN2
了解Digi Embedded Yocto的基本知识并搭好DEY开发环境,编译出最基本的镜像dey-image-qt和core-image-base,请参考本wiki上的DEY系统开发教程
熟悉单板机设备树,DEY2.6的设备树源文件在github上的位置:
https://github.com/digi-embedded/linux/tree/v4.14/dey-2.6/maint/arch/arm/boot/dts
我们可以先在github上浏览它,并确定将来需要变更的地方,做好笔记,然后复制单板板级设备树并重新定义一个名字,并编译测试它。Digi的单板机有SBC EXPRESS(ID 129)和 SBC PRO (ID 135)两种,我们可以打开它们对应的HRM来查看对应的板载接口和资源分配。对应的设备树文件在:arch/arm/boot/dts/imx6ul-ccimx6ulsbc-(board_ID).dts。
以单板机设备树为模板,修改为自己底板的设备树,并建立和维护相关工作的版本控制。 以arch/arm/boot/dts/imx6ul-ccimx6ulsbc-id135.dts为例,我们可以在这个板级文件基础上更改设备树以匹配我们的硬件平台。复制一份并重新命名为i.mx6ul-ccimx6ulsbc-id201.dts。
为了更好的维护自己的工作,采用git的方式来维护自己的开发工作。
请先注册一个git服务帐户,以ECCEE的git为例,到http://gitlab.eccee.com:11080/申请一个帐户,然后把相关帐户信息配置到开发电脑中。你还需要生成ssh-key并配置到帐户中,参考利用Eccee的免费gitlab进行版本控制和管理工作
git config --global user.name "my-username" git config --global user.email "my-email"
先在Ecceegit上新建好一个项目,比如命名为tdmkv1,然后在DEY的项目文件夹下,初始化git项目,并新建一个README.rd,输入下面相关备注信息:
git init git remote add ecceegit ssh://git@gitlab.eccee.com:11022/<myusername>/myproject.git #请用你项目的git地址替掉上面URL nano README.rd ****This is custom board DEY project of dey-2.6************ 2019-11-1 V1 board release, board ID 201
接着添加README.rd,local.conf和i.mx6ul-ccimx6ulsbc-id201.dts到git中,先将这几个文件commit,并提交到git服务器上。为了能编译自定义ID的板子设备树,我们还需要添加tmp/work-shared/ccimx6ulsbc/kernel-source/arch/arm/boot/dts/Makefile到git,并添加id201这个dts文件到Makefile对应位置中。
接下来就可以慢慢修改和调试相关文件了。
git add README.rd git add conf/local.conf cp tmp/work-shared/ccimx6ulsbc/kernel-source/arch/arm/boot/dts/imx6ul-ccimx6ulsbc-id135.dts tmp/work-shared/ccimx6ulsbc/kernel-source/arch/arm/boot/dts/imx6ul-ccimx6ulsbc-id201.dts git add tmp/work-shared/ccimx6ulsbc/kernel-source/arch/arm/boot/dts/imx6ul-ccimx6ulsbc-id201.dts git add tmp/work-shared/ccimx6ulsbc/kernel-source/arch/arm/boot/dts/Makefile nano tmp/work-shared/ccimx6ulsbc/kernel-source/arch/arm/boot/dts/Makefile 添加id201这个设备树文件在id136那一行下,然后保存 git commit -a 注意这是第一次提交,远程库没任何版本,我们先用本地master分支提交并设置到远程库上 git push -u ecceegit master 这里-u也可以用--set-upstream,这样远程库的主版本建立好后,下次提交只需直接git push了。
由于tmp下的目录比较长,我们又经常需要nano,cat或ls来查看相关的文件或文件夹,掌握一些linux小技巧很重要。比如用“history |grep work”之类的快速来找到之前打过的命令,减少一些出错机率。对于git命令,常用的还有“git status|more “,来查看哪些文件是否有变动,而忽略那些我们不需要管理的文件。
从搜索串口UART开始,默认已经有uart2和uart5,uart3是注释掉的状态,先将对应的注释取消。因为我们只需要两线的uart,所以uart-has-rtscts;这一句在对应的串口下都要注释掉。还需加一个uart4:
&uart4 { status = "okay"; };
串口对应的设备树源码修改就完成了。
uart3作为485接口的设备树修改目标:uart3的RTS作为485的方向使能脚。
因为uart3的RTS和CAN1复用,为了用作485的使能脚,需禁掉can1。在id201设备树中搜索uart3相关项,做如下修改:
1、注释掉can1 //&can1 { // status = "okay"; //};
2、启用uart3的485接口RTS使能。 参考BSP中的串口/485接口说明: 注意,RTS是请求发送的意思,在i.mx6ul的串口中,CTS线是输出引脚,用于控制发送请求(RTS功能线),因此应该使用CTS线来连接方向脚,输出高电平时(DE为高),表示请求发送,当CTS为低时(/RE为低),接收有效。
pinctrl-0 = <&pinctrl_uart3_4wires>; uart-has-rtscts; linux,rs485-enabled-at-boot-time; rs485-rts-active-high; rs485-rx-during-tx; rs485-rts-delay = <1 1>; status = "okay";
其它接口待续。。 请用git commit 和git push ecceegit来保存您的工作
在uart2中 pinctrl-0 = <&pinctrl_uart2_2wires>;
如果不用uart的CTS作为RTS使能控制,而是指定gpio,至少需要下面两行
uart3中用下面改法: &uart3 { pinctrl-0 = <&pinctrl_uart3_2wires>; linux,rs485-enabled-at-boot-time; cts-gpios = <&gpio1 2>; rts-gpios; rs485-rts-active-high; rs485-rx-during-tx; rs485-rts-delay = <1 1>; status = "okay"; };
如果您不小心没用(-C)重新编译了内核或整个镜像,或是用cleanall,即
bitbake -c cleanall virtual/kernel
该命令会清空tmp/work-shared/ccimx6ulsbc/kernel-source下的文件(包括自定义的id设备树文件和Makefile,所以还要用
git reset –hard
回退到上一次commit之后和改动前的状态(把删除的设备树文件和Makefile恢复)。
设备树的编译方法 bitbake -c devshell virtual/kernel 然后在devshell里编译自定义板子的设备树文件 make dtbs exit 编译结果在:tmp/work/ccimx6ulsbc-dey-linux-gnueabi/linux-dey/4.14-r0/build/arch/arm/boot/dts/
cd 项目文件夹 git clone --no-checkout ssh://git@my-project-url tempgit mv tempgit/.git . rmdir tempgit git reset –hard HEAD bitbake -c devshell virtual/kernel ####在devshell内,直接运行设备树编译命令#### >make dtbs >exit
退出后,就可以在tmp/work/ccimx6ulsbc-dey-linux-gnueabi/linux-dey/4.14-r0/build/arch/arm/boot/dts/目录下找到自定义板子的设备树
如果你有bitbake dey-image-qt,则就已经编译出linux-kernel,但是bitbake -c cleanall dey-image-qt并不会删除编译的linux-kernel。如果想清除已经编译的linux-kernel,需要用bitbake -c cleanall virtual/kernel,只有这个命令会清空我们git版本维护的东西,因此当我们不小心清除时,需要用bitbake -c compile virtual/kernel来重新编译出相关的内核,然后再用git pull, bitbbake -C compile virtual/kernel来编译出我们自己修改的内核和设备树文件等。
测试设备树,您无需每次都重刷固件,设备树只需拷贝到内核分区,然后在启动时注意启用的是它即可。flas系统启动时,会打印加载的设备树文件名,它是由启动脚本和模块上的参数共同决定的。我们在测试设备树时,可以绕过该脚本,直接用dboot linux nand命令来启动系统,这时会采用uboot参数fdt_file定义的设备树文件。但您的内核必须有你要测试的设备树文件。比如我们想测试my-device-tree.dtb,可以先拷到u盘或是用网络传到linux文件系统上
进入系统后,加载linux分区,一些固件会自动加载linux分区为只读文件系统,可用mount命令查看。 ls /mnt 如果没有linux文件夹,可以创建一个再加载linux分区,如果已经存在,说明已经加载了linux内核分区。 mkdir -p /mnt/linux mount -t ubifs /dev/ubi0_0 /mnt/linux 如果系统已经加载过,一般是只读分区,用下面命令修改为可读写分区: mount -o remount,rw /dev/ubi0_0 /mnt/linux 拷入my-device-tree.dtb,如果你从sd卡拷入,要先加载sd卡 mkdir -p /media/tfcard mount -t vfat /dev/mmcblk1p1 /media/tfcard cp /media/tfcard/my-device-tree.dtb /mnt/linux 然后reset,即可 启动时停在uboot界面,用setenv设置fdt_file参数 setenv fdt_file my-device-tree.dtb dboot linux nand
如果上面这个设备树文件名想多次测试,可以在bootcmd里改相应的设备树文件名
setenv fdt_file my-device-tree.dtb setenv bootcmd dboot linux nand saveenv reset
DEY在编译过程中,会下载Linux源码树和软件包到downloads目录下,在编译系统的过程中,它还用到两个目录work和work-shared,其中work就是编译内核时的工作目录,它会用到linux的源码树,这个是在tmp/work/<平台>-dey-linux-gnueabi/<内核版本号>/git,而实际上这个git是链接,指向work-shared/<平台>/kernel-source。
如果我们已经编译了一个镜像,那么编译的结果是在tmp/work/<平台>-dey-linux-gnueabi/<内核版本号>/build下。当我们 注意编译结果除了在tmp/work/ccimx6ulsbc-dey-linux-gnueabi/linux-dey/4.14-r0/相关目录下,也会更新tmp/deploy/images/ccimx6ulsbc下的设备树和内核二进制文件,但不会更新内核文件系统固件。
要修改内核选项:
bitbake -c menuconfig virtual/kernel 在出来的图形化配置窗口勾选所需的选项,然后按默认文件名保存(.config),并退出,注意bitbake并不直接引用该配置文件,而是使用defconfig配置文件,在build的父目录中有默认的defconfig,我们需要在build目录中生成一个新的defconfig,它的优先权比默认的高 bitbake -c savedefconfig virtual/kernel 上述命令会在build目录内生成defconfig,这样再编译出来的内核,就带有更改好的内核选项配置文件。
要查看对应的内核选项开关是否起作用,进入linux用下面命令
zcat /proc/config.gz | grep DP83848 上面这个命令查询DP83848在当前运行内核的配置情况
如果需要编译到镜像,请先用bitbake -c cleanall core-image-base(或dey-image-qt)来删除旧镜像,然后再bitbake core-image-base生成新的内核镜像即可。
请将tmp/work/ccimx6ulsbc-dey-linux-gnueabi/linux-dey/4.14-r0/build/defconfig也添加到版本管理中
git add tmp/work/ccimx6ulsbc-dey-linux-gnueabi/linux-dey/4.14-r0/build/defconfig git commit -a git push
其实您无需更改启动脚本boot.scr就可以测试自己的内核,只需将bootcmd命令改为直接绕过boot.scr启动,这样就可以更改并利用fdt_file参数来加载设备树。不过您仍先设置一个内核已经有的设备树,在可以在进入linux系统后,加载内核分区,将对应的设备树拷入到内核分区中,再重新启动即可。
第一次启动,先用默认镜像中的imx6ul-ccimx6ulsbc-id135.dtb setenv fdt_file imx6ul-ccimx6ulsbc-id135.dtb dboot linux nand 进入系统后,加载linux分区,一些固件会自动加载linux分区为只读文件系统,可用mount命令查看。 ls /mnt 如果没有linux文件夹,可以创建一个再加载linux分区,如果已经存在,说明已经加载了linux内核分区。 mkdir -p /mnt/linux mount -t ubifs /dev/ubi0_0 /mnt/linux 如果系统已经加载过,一般是只读分区,用下面命令修改为可读写分区: mount -o remount,rw /dev/ubi0_0 /mnt/linux 拷入imx6ul-ccimx6ulsbc-id201.dtb,如果你从sd卡拷入,要先加载sd卡 mkdir -p /media/tfcard mount -t vfat /dev/mmcblk1p1 /media/tfcard cp /media/tfcard/imx6ul-ccimx6ulsbc-id201.dtb /mnt/linux 然后reset,即可
当您集成好设备树到内核固件后,可更改启动脚本boot.scr,以便系统启动时可以加载自己的设备树。
启动脚本和卡刷脚本源码,默认在dey安装目录meta-digi/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ulsbc/ 下,有两个文件 boot.txt和install_linux_fw_sd.txt ,经bitbake编译出来后,后缀会变成.scr
当编译镜像后,这两个文件会被拷在tmp/work/ccimx6ulsbc-dey-linux-gnueabi/u-boot-dey/2017.03-r0/目录下,因此我们可以添加到git中
git add tmp/work/ccimx6ulsbc-dey-linux-gnueabi/u-boot-dey/2017.03-r0/boot.txt git add tmp/work/ccimx6ulsbc-dey-linux-gnueabi/u-boot-dey/2017.03-r0/install_linux_fw_sd.txt #手工修改boot.txt nano tmp/work/ccimx6ulsbc-dey-linux-gnueabi/u-boot-dey/2017.03-r0/boot.txt #将第一个else if语句中的内容全注释掉,然后加上下面这句 setenv fdt_file imx6ul-ccimx6ulsbc-id201.dtb #按ctrl+o保存后,ctrl+s退出 git commit -a git push ecceegit 用bitbake编译的方法是: bitbake -C compile virtual/bootloader 编译的结果在: tmp/work/ccimx6ulsbc-dey-linux-gnueabi/u-boot-dey/2017.03-r0/deploy-u-boot-dey目录下
如果我们使用的不是dey-image-qt,而是core-image-base,可以修改卡刷脚本install_linux_fw_sd.txt
nano tmp/work/ccimx6ulsbc-dey-linux-gnueabi/u-boot-dey/2017.03-r0/install_linux_fw_sd.txt #在脚本开头,将定义镜像的文件名由dey-image-qt-x11开头变成core-image-base开头。 #保存,退出 git commit -a git push
这个脚本在DEY2.6-r3下测试已经是用bitbake -C compile virtual/bootloader编译,结果同样在tmp/work/ccimx6ulsbc-dey-linux-gnueabi/u-boot-dey/2017.03-r0/deploy-u-boot-dey目录下。事实上,tmp/deploy/images/下uboot相关的脚本和uboot也是在这个命令后更新的。
文件系统裁剪定制后,原本的Linux分区可能不够用,我们除了可以在uboot编辑分区大小外,还可以用卡刷脚本自动定义所需的分区,update分区对DEY来说并非必须,所以我们可以增大rootfs,改小update,来满足分区大小的需求。在install_linux_fw_sd.txt中增加mtdparts一行:
... setenv bootcmd " env default -a; setenv mtdparts mtdparts=gpmi-nand:3m(bootloader),1m(environment),1m(safe),12m(linux),14m(recovery),150m(rootfs),-(update); saveenv; echo \"\"; echo \"\"; echo \">> Installing Linux kernel and device tree files\"; echo \"\"; ...
然后重编译uboot,得到新的卡刷脚本,并应用到卡刷包中,就可以实现卡刷前自动改分区大小。
上面我们用git的方式建立了源码版本管理项目,通常我们还可以在ecceegit上建立一个发布版本,比如项目名称为tdmkv1_release,然后在项目文件夹中新建一个release项目 mkdir release #创建一个shell脚本来打包各种release的文件 nano copyrelease.sh
cp ../tmp/work/ccimx6ulsbc-dey-linux-gnueabi/linux-dey/4.14-r0/build/arch/arm/boot/dts/imx6ul-ccimx6ulsbc-id201.dtb ./ cp ../tmp/work/ccimx6ulsbc-dey-linux-gnueabi/u-boot-dey/2017.03-r0/deploy-u-boot-dey/boot.scr ./ cp ../tmp/work/ccimx6ulsbc-dey-linux-gnueabi/u-boot-dey/2017.03-r0/deploy-u-boot-dey/install_linux_fw_sd.scr ./ cp ../tmp/deploy/images/ccimx6ulsbc/core-image-base-ccimx6ulsbc.ubifs ./ cp ../tmp/deploy/images/ccimx6ulsbc/core-image-base-ccimx6ulsbc.boot.ubifs ./ cp ../tmp/deploy/images/ccimx6ulsbc/core-image-base-ccimx6ulsbc.recovery.ubifs ./ cp ../tmp/deploy/images/ccimx6ulsbc/u-boot.imx ./ sleep 5 zip my_sd_installer.zip ./* -x copyrelease.sh
保存后,记得更改为可执行权限,然后运行,就可以自动把想要发布的镜像或脚本复制到release目录中
chmode a+x copyrelease.sh ./copyrelease.sh
然后在release目录内初始化git项目
git init git remote add ecceegit ssh://git@gitlab.eccee.com:11022/<myusername>/tdmkv1_release.git nano README.rd ####README.rd内容,主要记录发布信息#### Release Note: 20191114 initial release ---core-image-base images added ---imx6ul-ccimx6ulsbc-id201.dtb added ---boot.scr change to boot into id201 if board_id does exist ---install_linux_fw_sd change to use core-image-base #### git add * git commit -a 注意这是第一次提交,远程库版本为空,我们要用本地源去设置远程库版本 git push --set-upstream ecceegit master
注意本文我们学习了在ecceegit上新建源码项目和发布项目,对于设备树等需要自行管理版本控制的文件,重大修改请及时git commit -a并git push上去。当某个版本测试得差不多时,请用git tag打上标签,例如:
git tag -a v0.1 -m "basic IO function work" git push ecceegit --tags
同样地,定期管理发布的内容,并打上版本号,添加注释以示区别,形成良好的产品版本管理习惯。