=====利用git托管服务开发DEY过程===== 用户选择使用Digi嵌入式核心模块作为主控单元,是为了充分利用Digi的DEY简单易用的特点,以及各种验证过的BSP和软硬件功能模块。在开发过程中,用户可以仅维护少数几个自己改动过的配置文件,设备树文件等,利用这些文件就可以直接配合已有的或全新安装的DEY开发环境编译出自己定制的系统。利用这种方式开发对初学者非常有利,不论DEY或上游软件如何更新变化,只要大版本一致,都可以在任意时刻快速复原之前的开发成果。 本文以一个cc6ul项目为例,针对Yocto的初学者,希望以最接近传统开发方式来进行项目开发和维护。在熟练掌握本文的方法后,还可以meta-custom来代替相关的文件和操作。这是熟练掌握Yocto开发方式之后的事,在此之前,先用本文的方法来开发和维护自己的工作。 ====一、用到的相关硬件接口资源==== 根据项目需求设计第一版硬件,只需配合该硬件设计更改编译相关的设备树文件。硬件电路设计时,请注意参考[[http://cms.digi.com/resources/documentation/digidocs/embedded/dey/2.6/cc6ul/hw_index.html|cc6ul官方硬件参考手册]],特别注意[[http://cms.digi.com/resources/documentation/digidocs/embedded/dey/2.6/cc6ul/hw_r_design-guidelines|cc6ul硬件设计指南]]: * 串口 用到uart2,uart3设计为两线RS232接口,uart4为485接口,uart5 * SPI SPI1接MC33996 * 其它 I2C1,CAN1,CAN2 ====二、熟悉刷机和uboot进行固件升级的相关操作==== 请参考[[digi:arm-embedded:cc6ul:cc6ul-get-started|CC6UL上手指南]]和[[digi:arm-embedded:linux:dey:固件更新|固件升级]]教程,学会卡刷和TFTP刷固件等操作 ====三、搭好DEY开发环境并编译出默认镜像==== 了解[[digi:arm-embedded:linux:dey|Digi Embedded Yocto]]的基本知识并搭好DEY开发环境,编译出最基本的镜像dey-image-qt和core-image-base,请参考本wiki上的[[digi:arm-embedded:linux:dey:system-development|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帐户 请先注册一个git服务帐户,以ECCEE的git为例,到http://gitlab.eccee.com:11080/申请一个帐户,然后把相关帐户信息配置到开发电脑中。你还需要生成ssh-key并配置到帐户中,参考[[digi:arm-embedded:linux:howto:ecceegit|利用Eccee的免费gitlab进行版本控制和管理工作]] git config --global user.name "my-username" git config --global user.email "my-email" * 初始化git项目tdmk-dey-2.6 先在Ecceegit上新建好一个项目,比如命名为tdmkv1,然后在DEY的项目文件夹下,初始化git项目,并新建一个README.rd,输入下面相关备注信息: git init git remote add ecceegit ssh://git@gitlab.eccee.com:11022//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 ",来查看哪些文件是否有变动,而忽略那些我们不需要管理的文件。 ====五、进行设备树源码的修改工作==== * [[#version1|第一版]] * [[#version2|第二版]] * 串口相关的设备树源码调整 从搜索串口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使能。 参考[[https://www.digi.com/resources/documentation/digidocs/embedded/dey/2.6/cc6ul/bsp_r_uart_6ul#rs-485-support|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"; * SPI 其它接口待续。。 请用git commit 和git push ecceegit来保存您的工作 第二版资源简述:这一版中uart3用作485,方向控制用GPIO1 2\\ 首先,把can的注释去掉,并把uart2,3都改成两线。 在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"; }; ====六、编译和测试设备树==== * [[#existing-project|已有DEY项目]] * [[#new-project|新建DEY项目]] 为了编译自定义的设备树,您需要进入devshell来运行make dtbs。一些人喜欢在DEY默认的设备树上更改,比如直接改id135的设备树,然后用bitbake -C compile virtual/kernel来编译它。注意-C是大写,这种方法编译并不会生成自定义的设备树,它只能编译本来就有的设备树。 但要注意的是,如果您用小写的-c并使用bitbake编译镜像,因为每一次编译镜像或是内核,会用DEY默认安装版本重新生成内核相关文件(也包括设备树以及相关的Makefile)。为了保留自己的变更,如果需要重新编译内核或系统原有但改动过的设备树,请使用\\ bitbake -C compile virtual/kernel \\ 命令,\\ 如果您不小心没用(-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/ 新建DEY项目,并bitbake出基本镜像后,我们可以用git clone把自己的相关改动放到项目文件夹中。然后进行编译。注意使用非空项目文件夹,需要用--no-checkout参数\\ 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,得到新的卡刷脚本,并应用到卡刷包中,就可以实现卡刷前自动改分区大小。 早期的DEY版本可以用SDK中的mkimage来单独编译它,但它使用了不同的脚本环境,因此做个脚本来完成相关环境变量切换和编译,注意,您需要先安装对应版本的DEY的SDK,然后在脚本中用该SDK中的mkimage来编译卡刷脚本,下面以cc6ul的dey-2.6r2为例: >nano installer_compiler.sh #以下为脚本内容: #!/bin/bash source /opt/dey/2.6-r2/environment-setup-cortexa7t2hf-neon-dey-linux-enugabi mkimage -T script -n "DEY firmware install script" -C none -d ./release/install_linux_fw_sd.txt install_linux_fw_sd.scr source dey-setup-environment #保存并退出 >chmod a+x installer_compiler.sh >.installer_compiler.sh #将该脚本添加到git中 git add installer_compiler.sh git commit -a git push ====管理发布版本==== 上面我们用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//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 同样地,定期管理发布的内容,并打上版本号,添加注释以示区别,形成良好的产品版本管理习惯。