一、BootLoader的移植制作...........................................................................................................21、生成uboot.elf文件............................................................................................................32、system.bit生成.................................................................................................................53、创建fsbl............................................................................................................................84、生成BOOT.BIN..................................................................................................................9二、配置并编译linux内核.........................................................................................................101、修改设备树内容...............................................................................................................102、配置编译linux内核.........................................................................................................12三、Linux设备驱动移植.............................................................................................................141、Linux设备驱动模型.......................................................................................................142、Linux设备驱动移植.......................................................................................................15在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。在一个基于zynq的嵌入式Linux系统中,系统在上电或复位时通常都从地址0x00000000处开始执行,而在这个地址处安排的通常就是系统的BootLoader程序。想要在zynq芯片上顺利启动Linux并且驱动相关模块正常工作,首先需要正确移植BootLoader。作为初始化硬件平台的一段BareMetal代码,Bootloader的移植也并入了我们的工作。所以综合起来说,我们的工作主要分为了三个部分:Bootloader的移植以及Linux内核和设备驱动的移植。在进行移植工作之前,首先要做的是要在宿主机上面搭建好我们目标板的开发平台,以及下载好uboot源代码,Linux内核源代码以及相关驱动源代码。(有的模块的驱动源代码在Linux内核源代码中已经包含进去了,那么就不用单独下载。需要下载的驱动源代码只是针对标准Linux内核中不支持的部件而言。)一、BootLoader的移植制作每一种操作系统都需要有自己的引导程序,最为人们所知的就是Windows的BIOS。缺失了这一部分,系统将无法正常启动。对比与Windows的BIOS,android系统拥有自己的专属的BootLoader,它主要负责初始化系统平台的硬件设备,建立内存空间的映射关系。在它完成初始化工作之后,继续负责把内核镜像和yaffs2格式的文件系统从SD卡载入到RAM中,完成Linux内核和文件系统的加载并设置内核的启动参数,紧接着启动内核。等到内核真正启动了之后,BootLoader就杀死自己,把CPU让出给内核使用。之后内核根据硬件环境做出系统初始化设置,并将CPU转让给yaffs2文件系统运行管理。至此,Linux系统成功的启动起来。下图1为bootloader的启动过程。图1BootLoader启动流程在我们移植的BootLoader中,由于XC7Z020-CLG484-1包含了可编程逻辑(PL)和处理系统(PS)两个部分,所以它的启动过程与一般的BootLoader稍有不同。BootLoader在它的启动过程中需要负责配置可编程逻辑(PL)和处理系统(PS)这两个部分。使用Xilinx官方提供的SDK生成的BOOT.BIN文件包含了fsbl(firststagebootloader)文件、system.bit文件和uboot.elf文件,其中fsbl文件主要用来加载system.bit并且配置处理系统(PS),而system.bit文件起到了配置可编程逻辑(PL)的作用,注意该文件其实并不是必要的,如果在生成BOOT.BIN的过程中缺少该文件,那么PL部分得不到配置,那么我们只是相当于把XC7Z020-CLG484-1当成ARM来使用。之后系统开始加载ssbl(secondstagebootloader)到RAM中,即uboot.elf文件,它主要作用是加载内核镜像到RAM中。如下图所示。1、生成uboot.elf文件Uboot源码的主要目录及其描述上电基本硬件初始化读取loader信息计算loader的二进制checksum检测checksum的正确性检测是否有内核文件扩展功能所需硬件初始化拷贝内核镜像至SDRAM跳转至内核镜像正确有输出错误信息错误进入下载模式无上电基本硬件初始化读取loader信息计算loader的二进制checksum检测checksum的正确性检测是否有内核文件扩展功能所需硬件初始化拷贝内核镜像至SDRAM跳转至内核镜像正确有输出错误信息错误进入下载模式无212BOOT.BINFSBLsystem.bituboot加载system.bit配置PS配置PL加载内核镜像cpu与处理器相关的文件。每个子目录中都包括cpu.c和interrupt.c、start.S、u-boot.lds。cpu.c:初始化CPU、设置指令Cache和数据Cache等interrupt.c:设置系统的各种中断和异常start.S:是U-boot启动时执行的第一个文件,它主要做最早期的系统初始化,代码重定向和设置系统堆栈,为进入U-boot第二阶段的C程序奠定基础。u-boot.lds:链接脚本文件,对于代码的最后组装非常重要。board已经支持的所有开发板相关文件,其中包含SDRAM初始化代码、Flash底层驱动、板级初始化文件。其中的config.mk文件定义了TEXT_BASE,也就是代码在内存的实际地址,非常重要。common与处理器体系结构无关的通用代码,U-boot的命令解析代码/common/command.c、所有命令的上层代码cmd_*.c、U-boot环境变量处理代码env_*.c等都位于该目录下drivers包含几乎所有外围芯片的驱动,网卡、USB、串口、LCD、NandFlash等等include头文件,包括各CPU的寄存器定义,文件系统、网络等等configs子目录下的文件是与目标板相关的配置头文件根据上表可知,在进行uboot移植的过程中需要把相关目录下与目标平台相关的配置文件进行相应的修改,同时集成各种函数库以及驱动程序的支持。我们使用makezynq_zed_config来配置uboot,修改代码的目录列举如下:和处理器相关级别的代码:u-boot/arch/arm/cpu/armv7/start.Su-boot/arch/arm/cpu/armv7/Makefileu-boot/arch/arm/include/asm/hardware.hu-boot/arch/arm/lib/board.cu-boot/arch/arm/lib/Makefileu-boot/arch/arm/config.mk和板级相关的代码:u-boot/board/xilinx/zynq_common/tools/image.cu-boot/board/xilinx/zynq_common/lowlevel_init.Su-boot/board/xilinx/zynq_common/mem_setup.Su-boot/board/xilinx/zynq_common/mmc_boot.cu-boot/board/xilinx/zynq_common/Makefileu-boot/board/xilinx/zynq_common/nand.cu-boot/board/xilinx/zynq_common/nand/Makefileu-boot/spl/Makefileu-boot/boards.cfgu-boot/config.mku-boot/Makefile修改完成上述代码之后,需要在Makefile文件中添加并指定交叉编译器名称和目标平台的类型,比如在我们的XC7Z020-CLG484-1平台下,应该指定为:makeARCH=armCROSS_COMPILE=arm-xilinx-linux-gnueabi-make完成后会在根文件目录下生成uboot文件,我们需要强制将其文件名改为uboot.elf,以便XilinxISE组件里面的SDK能够识别并用于生成BOOT.BIN。2、system.bit生成在现有的Digilent官网提供的基于XC7Z020-CLG484-1能够正常运行的linux设计包ZedBoard_OOB_Design中,已经包含了最重要的系统组件的驱动程序,如串口、网口,USB等接口。针对该设计包,我们需要根据我们的硬件环境进行适当的修改使之能够在我们的平台上运行,例如添加并打开模块所需要的SDIO1通道。由于zynq芯片内部有54个MIO的引脚,这些引脚在满足数量的情况下可以分配给SDIO、SPI或者Ethernet等外部设备,SD/SDIO的控制系统如下图所示。故我们可以使用MIO接口来将SDIO1的通道引出到芯片外部,同时不需要我们自己添加约束文件。SDIO接口控制器控制寄存器MIO-EMIO布线外部设备MIO引脚...PLEMIOSDIO参考时钟InterconnectAHBslaveportInterconnectAHBmasterport中断号{56,79}CPU_1x时钟SDIO{0,1}CPU_1x复位SD/SDIO控制系统图下表展示了SDIO接口与MIO的连接方式。SDIO接口默认控制器输入值MIO引脚引脚号I/OSDIO0时钟信号016,28,40IO~SDIO0