嵌入式Linux设备驱动程序开发指南(原书第2版)
上QQ阅读APP看书,第一时间看更新

1.9 为NXP i.MX7D处理器构建嵌入式Linux系统

i.MX7D处理器系列配备了Arm Cortex-A7内核和Cortex-M4内核,最高运行频率可达1.2 GHz。i.MX7D处理器支持多种类型的存储器,包括16/32位DDR3L/LPDDR2/LPDDR3-1066、四路SPI存储器、NAND、eMMC和NOR。通过AVB、PCIe和USB支持包括千兆以太网在内的若干种高速连接。提供并行和串行的显示器和摄像头接口,以及直接连接电泳显示器(EPD)的方式。

可以在下面链接中查到关于这个系列处理器的相关信息:https://www.nxp.com/products/processors-andmicrocontrollers/applications-processors/i.mx-applications-processors/i.mx-7-processors/i.mx-7dualprocessors-heterogeneous-processing-with-dual-arm-cortex-a7-cores-and-cortex-m4-core:i.MX7D。

基于MCIMX7SABRE的开发试验:本试验将使用基于i.MX7D应用处理器的SABRE智能设备开发板。开发板的相关文档可在下面的链接查看:https://www.nxp.com/support/developer-resources/hardware-development-tools/sabre-development-system/sabre-board-for-smart-devices-based-on-the-i.mx-7dual-applicationsprocessors:MCIMX7SABRE。

本书中使用开发板MCIMX7SABRE开发i.MX7D处理器的驱动程序,这些驱动程序也可以很容易地移植到开发板ARROW IMX7 96单板上。这块开发板的相关资料,可在下面的链接查询:https://www.96boards.org/product/imx7-96/。

1.9.1 简介

为了在Linux主机上得到Yocto工程,必须安装下面列出的软件包和工具。一个重要的考虑因素是主机上的硬盘空间要足够大。例如:在运行Ubuntu系统的机器上构建时,最少要为X11后台程序预留50 GB的空间。推荐的空间大小是至少120 GB,这足够存放所有要编译的后台程序了。

下面执行的指令都是在Ubuntu 14.04 64位系统上测试过的。

1.9.2 主机软件包

构建Yocto工程需要安装一些必要的软件包,这些包也记录在Yocto工程的文档中。比较关键的一些主机软件包是:

030-01

Ubuntu 14.04主机需要安装的软件包是:

030-02

1.9.3 设置repo工具

repo工具被开发出来,主要是用来方便对多个Git仓库的管理。相较于从每个仓库逐个下载,repo工具可以用一条命令下载所有的仓库。使用下面的命令来安装这个工具:

1. 建一个目录。下面的命令在你的主目录下创建了一个目录,并命名为bin

031-01

2. 下载工具:

031-02

3. 设置工具的可执行权限:

031-03

4. 把文件夹路径添加到环境变量PATH中,下面这条命令可以添加到你的.bashrc文件中,这样在以后启动的每个shell或者终端中,PATH环境变量都会自动生效。

031-04

1.9.4 Yocto工程的安装和映像构建

NXP Yocto工程的BSP版本目录包含一个“sources”目录,这个目录里包含构建工程的方法文件、一个或者多个构建目录,还有一组设置环境的脚本。

构建工程的方法来自于社区和NXP。把Yocto工程文件下载到“sources”目录。用相应构建方法来建立这个工程。

下面的例子演示了如何从NXP的Yocto工程社区下载BSP配置文件。在这个例子中,这个工程会创建一个名为“fsl-release-bsp”的目录。

031-05

当处理完成的时候,源代码被存放到目录fsl-release-bsp/sources下。你可以反复使用repo sync命令来同步最新代码。在repo初始化的过程里,如果发生错误,请删除.repo目录然后再运行repo初始化命令。

脚本fsl-setup-release.sh简化了i.MX机器的环境设置过程。在使用这个脚本的时候,需要指定要构建机器的名称和要使用的图形后端。脚本会为指定机器和图形后端建立一个目录和配置文件。

对于meta-fsl-bsp-release,i.MX会提供全新的或者更新的机器配置文件以替换meta-fsl-arm机器配置文件。这些文件把脚本fsl-setup-release.sh拷贝到meta-fsl-arm/conf/machine目录里。

在开始构建之前必须先初始化。在这个步骤里,会建立构建目录和本地配置文件。在构建之前的初始化过程中,必须选择一种发布方式。在设置目标机器imx7dsabresd时,要选择构建目录build_imx7dfsl-imx-x11发布方式:

032-01

在做完这些设置后,执行环境将被重定向输出到build_imx7d文件:

032-02

如果你要打开一个新的终端,在构建之前,你必须重新加载fsl-setup-release.sh脚本:

032-03

构建Yocto工程会消耗大量的资源,包括时间和磁盘存储空间,特别是构建多个目录的时候。有些方法可以优化这些问题,例如使用共享的状态缓存(缓存构建时的状态)和共享的下载目录(保存下载包)。可以在local.conf文件里设置路径,这个文件在fsl-release-bsp/build-x11/conf目录下,使用以下命令来添加状态信息:

032-04

同时要注意在机器中创建这些目录:

032-05

这些目录需要设置适当的权限。当构建多个目录的时候,共享状态信息缓存会有帮助作用,每一个目录都使用共享缓存信息来最小化构建时间。共享的下载目录能把下载文件时间最小化。如果没有这些设置,Yocto工程默认会创建共享状态缓存目录和下载目录。当你想要进行一次完整的构建时,你需要移除状态缓存目录和临时目录。

032-06

构建新的Linux映像:

032-07

当构建完成的时候,映像文件将生成在指定的目录里。如果你正在使用另一个构建目录和机器配置则此目录是不一样的。

033-01

最后你要把这些映像文件写到SD卡里。下面是使用笔记本电脑自带的SD读卡器时所使用的命令:

033-02

如果你使用的是扩展的USB SD读卡器,请使用下面的命令:

033-03

在这里,/dev/sdX对应的是主机系统分配给SD卡的设备节点。

1.9.5 Yocto之外的工作

你可能觉得在不使用Yocto的情况下开发内核驱动程序和应用程序更方便。Yocto项目SDK试图帮助你完成这些工作。Yocto项目SDK包括以下几个方面:

1. 一个交叉编译工具链。

2. 两个sysroot:

  • 一个属于目标设备:包含适用于目标设备的头文件和库文件。确保生成的映像文件符合目标设备。
  • 一个属于主机设备:包含适用于主机的工具。这些工具可确保在构建目标sysroot时,一切保持一致并按预期工作。

3. 一个环境脚本,设置必要的变量以使它们协同工作。

使用Yocto工程构建一个SDK有以下几种方法:

  • 使用bitbake meta-toolchain。这个方法仍旧需要单独提取并安装目标设备sysroot。
  • 使用bitbake image –c populate_sdk。这个方法比上一个方法有了重大改进,因为它会生成一个工具链安装程序,这个程序包含与目标设备匹配的sysroot。

谨记,在新的终端里使用任何bitbake命令之前,必须先运行安装脚本建立运行环境:

033-04

当bitbake命令运行完毕后,工具链安装程序将被放在tmp/deploy/sdkbuild目录下。工具链安装程序包含匹配目标根文件系统的sysroot。可以用下面的命令来生成:

034-01

在主机上开发应用程序时,为了适合不同的目标体系结构,你需要使用交叉编译工具。这次将使用Yocto SDK,SDK已经提前安装到目录/opt/fsl-imx-x11/4.9.11-1.0.0。在终端上运行如下命令,可以看到SDK目录的具体内容:

034-02

4.9.11-1.0.0文件夹包含导出SDK环境变量的脚本。sysroots文件夹包含SDK工具、库文件、头文件和两个子文件夹,一个是给主机(x86_64)使用的,另一个是给目标设备(cortexa7hf)使用的。你可以通过文件后缀名获得一些关于SDK的信息:

  • cortexa7hf:适配于Crotex-A7带有硬件浮点计算功能的SDK(带有浮点运算单元)。
  • neon:支持neno处理器。
  • linux:支持Linux操作系统。
  • gnueabi:gnu嵌入式应用接口。

在安装SDK之前,你需要先运行环境变量脚本:

034-03

这些脚本将导出下面的几个环境变量:

  • CC:带有目标编译选项的C编译器。
  • CFLAGS:附加的C编译参数,用于C编译器。
  • CXX:C++编译器。
  • CXXFLAGS:附加的C++编译参数,用于CPP编译器。
  • LD:链接器。
  • LDFLAGS:链接参数,用于链接器。
  • GDB:调试器。
  • PATH:SDK二进制文件路径。

可以使用如下的命令看到所有的环境变量:

034-04

编译器现在在当前路径中了:

035-01

$CC提供了目标设备gcc选项:

035-02
  • arch选项armv7ve:适用于armv7ve体系结构的编译。
  • float-abi选项hard:二进制应用的硬件浮点单元的支持(fpu)。
  • fpu选项neno:支持ARM NEO协处理器。
  • sysroot:存放库文件和头文件的地方。

下面写一个简单的例子来验证工具链是否安装正确。打开文本编辑工具gedit,写一个小程序:

035-03

添加如下的代码:

035-04

如果用下面的命令编译它,会显示有错误发生:

035-05

发生错误的原因是设置的编译器支持的ARM处理器不明确,在调用编译器时要设置正确的C编译参数。可以使用C编译器($CC)直接编译app.c文件:

035-06

使用UNIX命令“file”,你可以确定文件类型(参见:man file),并检查文件适用的体系结构和链接方法:

035-07

1.9.6 构建Linux内核

内核的配置和构建是独立于Yocto构建系统的。把内核源文件从Yocto的tmp目录(使用bitbak创建映像文件时产生的目录)拷贝到你自己的内核目录:

036-01

你也可以从NXP的内核仓库下载内核源代码:

036-02

在编译内核之前,最好确保内核源码是干净的并且没有遗留之前构建产生的文件:

  • clean:移除构建产生的大部分文件,但是保留config文件和支持构建外部模块的文件。
  • mrproer:移除所有构建产生的文件、config文件和各种备份文件。
  • distclean:在mrproper的基础上再移除编辑器备份文件和补丁文件。
036-03

通常最容易的办法是从使用默认配置开始,这样可以根据你的需要来定制内核。imx_v7_defconfig位于arch/arm/configs目录下,以它为例:

036-04

当你想定制内核配置的时候,最简单的办法就是使用内核内建的配置系统。最常用的一种配置系统就是menuconfig工具。使用一个没有配置environment-setup-cortexa7hf-neon-poky-linux-gnueabi的终端,使用命令“cd /”在menuconfig中搜索:

036-05

配置驱动程序开发过程中需要的以下内核设置:

036-06

保存配置并从menuconfig退出。

一旦内核配置完毕,就可以编译生成可引导内核映像以及所选择的动态内核模块。默认情况下U-Boot系统使用的内核映像类型是zImage。在编译内核前,请确保在终端里已经使用environment-setup-cortexa7hf-neon-poky-linux-gnueabi脚本建立了编译环境:

037-01

从Linux内核3.8版开始,每一个ARM单板的内核要求对应唯一的设备树二进制文件。因此需要为目标设备构建和安装正确的dtb文件。所有的设备树文件都存放在arch/arm/boot/dts/目录下。为了构建单个设备树文件,找到所使用单板对应的dts文件的名称,将.dts扩展名替换为.dtb。编译后的设备树文件放置在arch/arm/boot/dts/目录下。运行下面的命令编译并构建设备树文件:

037-02

构建所有的设备树文件:

037-03

默认情况下,大多数的驱动文件没有被集成到Linux内核映像中(例如zImage)。这些驱动被构建为动态模块,存放于内核树中,文件后缀为.ko(内核对象)。这些.ko文件就是内核的动态模块。一旦内核文件被改动,通常推荐的做法是重构内核模块并安装它们。否则内核模块将不能被加载和运行。构建内核模块的命令如下:

037-04

使用下面的命令,单步编译内核映像、模块和所有的设备树文件。

038-01

内核映像、内核模块和设备树文件被编译后,就可以安装了。对于内核映像,可以通过把zImage文件复制到系统读取内核映像的位置来安装。将设备树二进制文件复制到内核映像被复制到的文件夹下。你将从TFTP服务器读取内核映像和设备树文件:

038-02

在为处理器i.MX7D和SAMA5D2开发驱动程序的过程中,你将在主机上使用TFTP和NFS服务器,SD卡中只需要存储U-Boot引导加载器。引导加载器将从TFTP服务器上获取Linux内核映像文件,内核将从NFS服务器上挂载根文件系统。无论是更改内核还是根文件系统,都无须烧写SD卡。

1.9.7 安装TFTP服务器

如果你还没有运行过TFTP服务器,请按照下面的步骤在Ubuntu 14.04主机上安装和配置TFTP服务器:

038-03

tftpd-hpa配置文件安装在/etc/default/tftpd-hpa目录下。它默认使用/var/lib/tftpboot作为TFTP的根目录。为了让所有的用户都能访问这个目录,使用下面的命令修改目录的权限:

038-04

使用netstat –a | grep tftp检查TFTP服务器的状态。如果没有结果,很可能是服务器没有启动。为了安全起见,可以使用如下命令停止服务后再重新启动服务:sudo service tftpd-hpa stopsudo service tftpd-hpa start

1.9.8 安装NFS服务器

如果你还没有运行过NFS服务器,请使用下面的步骤在Ubuntu 14.04主机上安装和配置NFS服务器:

038-05

/nfsroot将被作为NFS服务器的根目录,因此目标根文件系统将从Yocto构建目录里解压出来:

038-06

接下来将NFS服务器配置到/nfsroot文件夹。编辑/etc/exports文件并加入下面这句代码:

039-01

然后重启NFS服务器使最新的配置生效:

039-02

为了安装内核模块,可以使用与make命令类似的命令,但是需要添加一些参数来说明模块安装的路径。这个命令将在此安装路径下创建一系列的文件和文件夹,例如lib/modules/<kernel version>,这个目录下包含适用于当前内核的驱动模块。这个路径应该是目标文件系统的根目录。

039-03

1.9.9 设置U-Boot环境变量

给MCIMX7SABRE单板上电。在你的主机系统中运行并配置minicom来观察系统启动过程。配置如下:波特率115200,8位数据,1位停止位,无奇偶校验位。确保硬件和软件流控制被禁用。按任意键停止U-Boot启动过程。

要执行网络引导,请在U-Boot提示符下设置如下环境变量:

039-04

重启你的单板;它现在就可以从网络启动了。