为基于CC6UL的产品定制DEY系统

本章会介绍如何客制化自己的产品底板和对应的DEY系统定制。

现代的嵌入式处理器通常非常强大,单颗处理器能提供多个各种不同的接口,但同时处理器的引脚又十分有限,也就是处理器核能提供的接口数量能力大于引脚数量。如果某个引脚只能固定配置成某种功能,势必造成资源的浪费。因此通常在处理器中引入IOMUX机制来解决引脚复用功能。 通过IOMUX处理器的引脚可以根据需求配置成不同功能的接口。Digi除了单板机开发套件提供的模板外,还可以利用smart IOMUX工具来加快定制自己的底板功能。当Digi的单板机底板满足不了您的需求,您通过IOMUX配置改变了接口的位置和数量定义时,您就需要进一步根据自己底板的布局和需求深度定制DEY系统。

CC6UL是带片上系统的核心模块,通常您可以根据CC6UL模块所支持的接口和功能设计产品的自定义底板。许多用户会设计不同的底板来满足不同市场或应用的需求。举例来说,您可能在一开始设计一个version 1.0版本的底板,只带有串口和以太网接口。接着您又按客户提出的需求重新设计了一个version 2的版本,添加了一些按钮和LED,并引入一个新的电源管理芯片。您可能还希望用同样的version 2版本的底板来满足高低端市场的要求,一个高配版的用底板ID=1表示,所有元件都贴上。另一个简配版的用ID=2表示,它用同样的底板,但只贴一部分的接口和元件。您还有可能进一步改进板子,修正一些bug并提高稳定性,这就变成version 3的底板,同样有高配和低配(ID=2和ID=2)两种板子。

一些底板上硬件的修改并不影响软件的使用,但另外一些板子硬件上的修改可能需要软件上有相应的变化。因此,如果能将板子的版本信息和用途ID存储在模块的OTP上将会极大方便软件的自动适配。您可以在Uboot或是Linux中添加条件语句代码,让相同的软件可以跑在不同的版本的底板上。

底板的版本号和ID号所在的OTP比特位

在Digi的开发套件/单板机上,采用Bank 4 Word 6 (GP1)来存储底板版本号和ID号。

UBoot中底板的版本号和ID号

Digi的开发板/单板机在出厂时预置好了版本号和ID号,两种CC6UL单板机的Board ID如下:

Board ID 单板机型号 无线 蓝牙
129 CC-WMX6UL-START
135 CC-WMX6UL-SBC

在启动过程中UBoot会显示出版本和ID。

 Board: ConnectCore 6UL SBC, version 3, ID 135 

而对于核心模块出厂没预置底板版本号和ID,上电时就有提示这些信息未定义。

Board: ConnectCore 6UL SBC
   WARNING: Undefined board version!
   WARNING: Undefined board ID!

UBoot在上电启动时,会自动从OTP上读取这类信息生成board_id和board_version两个变量。Digi预编译的DEY和Android启动脚本使用board_id来确认是什么样的底板并选择合适的设备树文件。下面是个启动脚本实例:

if test -n "${board_id}"; then
        setenv fdt_file zImage-imx6ul-ccimx6ulsbc-id${board_id}.dtb
else
        #
        # Set device tree filename depending on the hardware variant
        #
        if test "${module_variant}" = "0x02" || test "${module_variant}" = "0x04"; then
                setenv fdt_file zImage-imx6ul-ccimx6ulsbc-wb.dtb
        elif test "${module_variant}" = "0x03"; then
                setenv fdt_file zImage-imx6ul-ccimx6ulsbc.dtb
        else
                echo "------ Using default fdt_file: $fdt_file"
        fi
fi

该脚本实现的功能是:
如果board_id存在,选择包含该id的设备树文件,如果不存在,选择匹配OTP里定义的该模块类型的设备树,并定模块运行在标准的开发套件底板上。如果模块类型也没定义,选择UBoot环境变量fdt_file定义的默认设备树文件。

在UBoot中烧写OTP及软件中相关用法

烧写底板版本和ID号并不是必须的,另外这是一次性烧写,所以是不可逆的。您可以用board_version和board_id这两个uboot命令来烧写底板版本号和ID号。

相关的详细用法,包括如何利用底板版本号和ID号进行可选的软件行为,请参考官方文档

通常,如果您原样照抄Digi的开发套件或称单板机的开发底板,只做些适量的裁减,并没有硬件的大改动或调整,您是无需订制bsp来匹配自己的底板。DEY的编译选项中,支持的平台包括ccimx6plussbc,ccimx6sbc,ccimx6ulsbc,ccimx6ulstarter这几个开发板。如果您的底板功能和I/O变化不大,您也可以直接在现有的这几个平台做些修改,但更一般的做法是,当你根据开发底板做一些裁减和功能变换,添加或修改了默认的一些接口和功能时,这也意味着您需要添加一个新的机器平台到DEY中。这个过程包括:

  • 为U-Boot添加新的平台支持
  • 添加新的设备树文件到Linux内核中
  • 添加新的机器设备层到DEY的layer中

通常地,您可以直接使用Digi核心板自带的u-boot。我们建议您采用和Digi的开发板一样的控制芯片(比如以太网和USB的PHY等),避免对u-boot进行开发。使用Digi原生自带的UBoot,您仍可以通过uboot的脚本来实现对板子进行一些定制行为。如果您确实需要进行一些代码级的定制开发,请参考下面内容。

u-boot开发定制参考

u-boot开发定制参考

您可以从github上访问Digi核心模块的Uboot,或是在DEY的项目的session下,用bitbake -c devshell virtual/bootloader这个命令,调出核心板虚拟机的shell来查看相关代码。

平台的BSP代码

BSP目录位于board/digi/目录下,包括了三个子目录:

  • ccimx6ul:核心模块通用的BSP代码ccimx6ul,像DDR,eMMC或NAND,PMIC,以太网等,核心模块这部分通常不用作改动。
  • ccimx6ulstarter,Starter kit单板机的目录,包括像以太网的PHY,电源控制等功能。
  • ccimx6ulsbc,CCimx6SBC PRO单板机目录,包括像以太网的PHY,电源控制等功能。

通常地,你只需要修改单板机相应的BSP代码来匹配您的硬件,这些包括

  • 以太网的PHY,如果你用了和SBC不一样的PHY芯片
  • PMIC电压,如是使用了不同的LDO电压
  • GPIO,IOMUX等

平台的头文件

头文件位于include/configs/,从目录下的文件名可以看出它,它包括核心模块的通用配置和Digi嵌入式产品的通用配置以及单板机上的配置。通常地,您也只需要更改单板机上的配置(ccimx6ulsbc.h或 ccimx6ulstarter.h)来匹配您自己的底板硬件。

为u-boot添加一个新机器平台支持

当你理解了u-boot平台代码的架构后,你就可以通过复制Digi的参考平台来定制自己的平台。有两种方法修改定制,一种是用bitbake -c devshell virtual/bootloader来调出虚拟机,在虚拟机内部去修改并重新编译,通常快速测试可以用这种方法。

点击查看示例

点击查看示例

……略

这个方法优点是,只要你有bitbake生成过镜像,就能很快调出devshell来改动,但它有个缺点是,它是在bitbake编译目录下,如果做一次clean或是升级后再次编译,就有可能丢失改动,所以说它是是一个临时的,快速验证改动的方法。

另一方式就是用git的方法直接进行版本管理和控制。您可以将自己的改动放置在github上,如果希望代码保密,也可以使用Eccee git或是自建本地的git库。

  1. git clone一个uboot到本地
  2. make <platform>_defconfig来生成make的配置文件,然后就可以直接make出uboot的镜像。
  3. 修改代码,重复上述开发过程
  4. 你也可以托管到github或私有的Eccee git仓库
  5. 如果需要整合到DEY中一起编译,可以修改DEY u-boot的recipe来指向你fork的分支,或是解压分支生成的patch到并添加到自定义的Yocto layer。参考在DEY的layer中添加自定义机器。

点击查看一个u-boot开发并托管到版本库的完整过程

点击查看一个u-boot开发并托管到版本库的完整过程

  • 您先要安装SDK,如果您之前没有安装过的话,uboot需要用SDK来交叉编译。到官方ftp去下载任一个版本。
  • 从github上下载uboot源码
 
  make -p ~/dey-workspace/uboot/cc6        在dey-workspace下创建uboot子目录和平台子目录,比如cc6或cc6ul或是你的板子名称等,并进入到该目录 
  cd ~/dey-workspace/uboot/cc6
  git clone https://github.com/digi-embedded/u-boot.git
  
  • 登录到gitlab.eccee.com,并创建一个新的私有项目,比如my-uboot
  • 先做一次初始同步
git remote rename origin old-origin
git remote add origin http://gitlab.eccee.com:11022/digirobin/my-uboot.git
可以先用git config --list查看一下当前的user.name和user.email是否你在Eccee git上的注册用户,如果不是,请用改过来。
git push -u origin --all
git push -u origin --tags
  • 修改代码,编译,验证,不断提交,每次提交请添加好注释,更多git的操作技巧请参考git常用操作
  • 正常的编译流程
make <platform>_defconfig     这里platform可以到configs目录下查找,一般是ccimx6sbc,ccimx6ulsbc,ccimx6ulstarter等
make


Linux内核对特定硬件的支持是通过设备树文件实现的。设备树文件是描述硬件平台的文本文件,它是Linux内核源码树的一部分,但被单独编译成二进制文件。u-boot在启动过程会加载设备树到内存,并传递给内核。内核根据设备树中的硬件描述加载对应的设备驱动从而实现对特定硬件的支持。 CC6UL的设备树文件详细位置和参考: https://www.digi.com/resources/documentation/digidocs/90002285/reference/bsp/r_device_tree_files.htm

为您的底板创建设备树文件

你可以复制现有的设备树文件来加以修改定制,也可以从头创建一个设备树文件。

  • 复制cc6UL SBC的设备树
    1. 从github上dey项目中fork linux源码
    2. 复制参考设备树文件,您可以用这个作为参考
    3. 定制你的平台设备树,包括确保defconfig和设备树文件匹配你的需求
    4. 可修改dey的linux recipe来指向您的分支,或解压生成的patch到本地并添加到你的自定义layer,参考在DEY层中添加新的机器平台
  • 全新构建CC6UL设备树

在arch/arm/boot/dts/下创建一个新的设备树源码文件,比如命名为imx6ul-custom.dts,确保它包含以下内容:i.mx6ul的设备树头文件和和CC6UL模块类型的设备树头文件,用model定义平台名称,compatible参数设置为“digi,ccimx6ul”, “fsl,imx6ul”。例如:

imx6ul-custom.dts 
/dts-v1/;
 
/* i.MX6UL CPU */
#include "imx6ul.dtsi"
/* ConnectCore 6UL module */
#include "imx6ul-ccimx6ul-wb.dtsi"
/ {                                                                                
        model = "My Company's ConnectCore 6UL based platform";               
        compatible = " mycc6ulboard, digi,ccimx6ul", "fsl,imx6ul";        
        digi,machine,name = " custom";                                     
};                 

启用ConnectCore 6UL相关接口

在设备树头文件中,大部分的接口是设置成关闭的(disabled), 对于每个您相用的接口,您需要:

  • 设置状态属性为okey来开启它
  • 配置IOMUX来匹配您底板上使用的引脚,参考Pin multiplexing (IOMUX)
  • 如果需要,配置其它额外参数来匹配您的硬件设计

从CC6UL单板机中复制硬件相关配置

如果您的底板是参考Digi单板机,您可以从相应的设备树复制接口和IOMUX配置。

添加自定义的相关硬件配置

你的底板可能包含额外的硬件组件,如果Linux内核中已有相关驱动,检查内核文档中的设备树绑定情况(Documentation/devicetree/bindings/)。

编译您平台的设备树

如果您希望编译您新创建的平台设备树文件,请在设备树的Makefile中添加imx6ul-custom设备树:

        arch/arm/boot/dts/Makefile 
        imx6ul-9x9-evk-ldo.dtb \
        imx6ul-ccimx6ulsbc.dtb \
        imx6ul-ccimx6ulsbc-id135.dtb \
        imx6ul-ccimx6ulsbc-wb.dtb \
+       imx6ul-custom.dtb \
        imx6ul-ccimx6ulstarter.dtb \
        imx6ul-ccimx6ulstarter-id129.dtb \
        imx6ul-ccimx6ulstarter-wb.dtb \

最后一步是在DEY中创建自定义层,定义新机器平台,并指向刚刚创建的u-boot的内核分支。您可以参考meta-custom这个例子。

要使用它,拷贝到DEY安装目录下,在新建项目时用:

source /usr/local/dey-2.2/mkproject.sh -m meta-custom -p custom

注意,您必须拷贝Linux内核默认配置文件到meta-custom层,因为Yocto并不使用包含在内核树中的那个配置文件,关于Linux默认内核配置,请参考: Kernel development workflows。设备树文件也没在这一层中,DEY使用内核源码树中的设备树来编译。

上面假定您用patch的方式本地修改meta-custom,在下面这个中,修改的u-boot和内核分支在github上:
U-Boot recipes实例

recipes-bsp/u-boot/u-boot-dey_2015.04.bbappend 
FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}-${PV}:"                           
                                                                                
UBOOT_GIT_URI = "git://github.com/<username>/u-boot.git;protocol=http"              
SRCBRANCH_custom = "2.2-r3/custom"                                         
                                                                                
COMPATIBLE_MACHINE = "(custom)"  

Linux Recipes实例

recipes-kernel/linux/linux-dey_4.9.bbappend 
FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}-${PV}:"                              
                                                                                   
LINUX_GIT_URI = "git://github.com/<username>/linux-dey.git;protocol=http"              
SRCBRANCH = "2.2-r3/custom"                                                   
                                                                                   
COMPATIBLE_MACHINE = "(custom)"