570 likes | 730 Views
嵌入式 Linux 移植. 广东省嵌入式软件公共技术中心 2007 年 7 月 14 日. 课程介绍. 主要介绍 嵌入式系统发展 嵌入式系统结构 嵌入式软件开发 Bootloader 设计. 现今,嵌入式开发分类. 基于单片机开发; 基于专用集成电路的板级系统设计;根据需求利用现有的 IC(CPU 、 RAM 、 flash) 等设计电路板, 在板中移植操作系统,开发应用程序。 片上系统( System On Chip,SOC );在单芯片上集成数字信号处理器、微控制器、存储器、接口电路等模块,即芯片设计;讲求软硬件协调开发。. 二 嵌入式系统结构.
E N D
嵌入式Linux移植 广东省嵌入式软件公共技术中心 2007年7月14日
课程介绍 • 主要介绍 • 嵌入式系统发展 • 嵌入式系统结构 • 嵌入式软件开发 • Bootloader设计
现今,嵌入式开发分类 • 基于单片机开发; • 基于专用集成电路的板级系统设计;根据需求利用现有的IC(CPU、RAM、flash)等设计电路板, 在板中移植操作系统,开发应用程序。 • 片上系统(System On Chip,SOC);在单芯片上集成数字信号处理器、微控制器、存储器、接口电路等模块,即芯片设计;讲求软硬件协调开发。
二 嵌入式系统结构 • 嵌入式系统一般包括硬件和软件两部分 • 这里的硬件是以一个高性能的处理器(通常是32位处理器)为基础; • 软件是以一个多任务操作系统为基础的综合平台 • 这样一个软、硬件平台是单片机无法比拟的,可称之为“嵌入式系统”。
(1)嵌入式硬件平台 片上系统 时钟 SDRAM 控制器 SDRAM 处理器核 复位 外部总线 控制器 Flash 中断 控制器 其他外设
(2)嵌入式系统软件 • 嵌入式软件可以分为两大类: • 系统软件:控制和管理嵌入式系统资源,一般是内核。 • 应用软件:在系统软件之上,如GUI(图形界面),网络服务器软件等。
(2)嵌入式软件结构 应用程序 动态库 系统调用 内核子程序(进程调度、 内存管理、文件系统、 网络、进程间通信) 嵌入式软件 内核软件 BSP包(驱动程序) 硬件平台
嵌入式软件开发 • 嵌入式应用开发过程 一个嵌入式应用项目的开发过程是一个硬件和软件设计的综合过程,是一个系统设计过程,主要经历以下步骤: • 硬件设计与实现 • 引导加载程序的设计 • 操作系统的移植(主要是驱动程序移植) • 应用程序的设计 • 系统调试,样机交付 • 其中,引导加载程序,操作系统移植,应用程序设计是软件设计,具有自己的特点。
嵌入式软件开发的特点 • 需要交叉编译 • 硬件平台处理器较慢,内存和外存容量小等等; • 把软件开发放在高性能的PC机上进行; • PC机上CPU指令集与嵌入式CPU的指令集是不同的,因此,在PC机上开发嵌入式软件需要交叉编译。 • 需要移植 • 由于嵌入式系统是一个软硬件定制的系统,硬件平台各不相同,软件设计需要根据不同的硬件设备来添加或修改相应的代码,这就是移植。
基于linux的嵌入式软件设计 在一个硬件平台上设计一个基于linux的软件系统,需要的工作可以分为以下三部分: • Bootloader设计 • Linux内核的定制移植,驱动程序的开发 • 应用程序的设计
根据GEC2410开发板,构建嵌入式linux系统 • 接下来,我们以gec2410开发板为硬件平台,介绍构建一个嵌入式linux系统的原理和过程。 • 系统软件有以下部分组成 • Bootloader为u-boot • Linux内核的版本为2.6.14 • 应用程序由busybox、bash等构成
一 Bootloader 介绍 • 引导加载程序BootLoader 是系统加电后运行的第一段代码。 • PC 中的引导程序一般由BIOS 和位于硬盘MBR中的OS bootloader(例如LILO 或者GRUB)一起组成。 • 然而嵌入式系统中通常没有像BIOS那样的固件程序,因此整个系统的加载启动任务就完全由bootloader 来完成。 • 在一个基于ARM920T core 的嵌入式系统中,系统在上电或复位时都从地址0x00000000开始执行,而在这个地址处安排的通常就是系统的BootLoader 程序。
一 Bootloader 介绍 • 首先,bootloader是在特定硬件平台运行的程序; • 严重依赖于硬件平台,需要移植。 • 是系统上电之后,第一个运行的程序; • 系统在上电或复位时通常都从地址 0x0 处开始执行,而在这个地址处安排的通常就是系统的 Boot Loader 程序。 • bootloader程序的设计目标是启动嵌入式操作系统。 • 嵌入式操作系统的启动需要一定的条件,这些条件由bootloader来满足。 • Bootloader一般具有对存储器和网络接口操作的功能;如擦除、读写Flash,通过USB、串口下载文件等。
Bootloader的存储位置 bootloader 文件系统 内核映象 参数 如上图,bootloader一般放在Flash的底端,这是因为系统复位后执行的第一条指令的地址一般对应于Flash的底端。
Bootloader的结构 • Bootloader 的启动过程一般分为两个阶段:stage1和stage2。 • Stage1的代码: • 依赖于CPU体系结构,例如系统初始化代码等 • 一般用汇编语言来实现, • 达到短小精悍的目的 • Stage2 的代码: • 用C语言实现 • 可以实现更复杂的功能 • 具有更好的可读性和可移植性
Bootloader的stage1通常要完成以下工作 • 硬件设备初始化 • 为加载bootloader本身准备内存空间 • 复制bootloader本身到内存 • 设置好堆栈 • 跳转到stage2的C入口点。 Flash不算内存?
Bootloader的stage2通常要完成以下工作 • 初始化本阶段要使用到的硬件设备; • 进入一个无限循环,等待用户的输入; • 当bootloader接受到要启动系统的信息的时候,作出以下动作; • 将 内核 映像和根文件系统映像从 flash 上读到 RAM 空间中; • 为内核设置启动参数; • 调用内核; • 这样bootloader的使命结束,系统的控制权交给操作系统。
BootLoader 操作模式 • 大多数bootloader 都包含两种不同的操作模式:“启动加载”模式和“下载”模式: • 启动加载模式: • 这种模式也称为“自主”模式,即bootloader 从目标机上的某个固体存储设备上将操作系统加载到RAM 中运行; • 整个过程没有用户的介入; • 当以嵌入式产品发布的时候,bootloader 必须工作在这种模式下。 • 下载模式: • 在这种模式,bootloader从开发机(PC)上下载文件到目标机的RAM中,然后直接运行; • 这种模式适用于软件开发阶段;
“Bootloader”与“Monitor”的区别 • “bootloader”只是负责引导系统; • “Monitor”除了引导系统之外,还提供了更多的命令行接口,可以进行: • 调试 • 读写内存 • 烧写Flash • 配置环境变量等 • “Monitor”在嵌入式系统开发过程中可以提供很好的调试功能,开发完成之后,完全可以设置成一个“bootloader”。所以,在习惯上把它们统称为“bootloader”。
实例分析 BootLoader 实验
U-boot的介绍 • Uboot是德国DENX软件工程小组开发的、支持多种嵌入式CPU的bootloader程序。 • 可引导的嵌入式操作系统: UBoot不仅仅支持嵌入式Linux系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式操作系统。 • 支持的处理器: UBoot支持PowerPC、MIPS、 x86、ARM、NIOS、XScale等诸多常用系列的处理器。 • 特点: 功能多、灵活性强、开发积极、开放源代码、属于“monitor”
U-boot的介绍 • uboot的获得: • 从下面地址下载uboot的源代码。 http://sourceforge.net/projects/uboot • 邮件列表: http://lists.sourceforge.net/lists/listinfo/u-boot-users/
U-boot的源码结构 • uboot的目录结构 • 顶层有18个子目录,分别存放和管理不同的源代码。这些目录分三类: • 与处理器体系结构或者开发板硬件直接相关 • 存放通用的函数或者驱动程序的目录 • 存放uboot的应用程序、工具、文档的目录
U-boot的源码结构 • uboot的目录结构 • board:存放与开发板有关的文件。每一个开发板都以一个子目录出现在当前目录中。如smdk2410 • common:实现uboot支持的命令,每一条命令都对应一个文件。例如bootm命令 -> cmd_bootm.c。 • cpu:与特定CPU架构相关目录,每一款Uboot下支持的CPU在该目录下对应一个子目录,比如有子目录arm920t等。 • doc:文档目录。Uboot有非常完善的文档,推荐大家参考阅读。 • drivers:Uboot支持的设备驱动程序都放在该目录,比如各种网卡、串口和USB等。
U-boot的源码结构 • uboot的目录结构 • fs: 支持的文件系统,Uboot现在支持cramfs、fat、fdos、jffs2和registerfs。 • lib_xxxx: 与体系结构相关的库文件。如与ARM相关的库放在lib_arm中。 • net:与网络协议栈相关的代码,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的实现。 • tools:生成Uboot的工具,如:mkimage, crc等等
问题 • 问题:u-boot支持多种体系结构的CPU,那么怎么在配置编译u-boot的时候选择自己的平台呢?
U-boot的配置编译 • U-Boot 的源码是通过 GCC 和 Makefile 组织编译的。 • 首先顶层 Makefile 设置开发板的定义; • 然后递归地调用各级子目录下的 Makefile; • 最后把编译生成的目标文件链接成U-Boot 映像。
U-boot的配置编译 • 顶层目录下的 Makefile • 负责U-Boot整体配置编译。 • 每一种开发板在 Makefile 都需要有板子配置的定义。 • 执行配置U-Boot的命令make smdk2410_config,则通过./mkconfig脚本生成include/config.mk 的配置文件。实际上是定义了ARCH、CPU、BOARD、SOC这些变量 • ARCH = arm • CPU = arm920t • BOARD = smdk2410 • SOC = s3c24x0
U-boot的配置编译 • 顶层目录下的 Makefile • Makefile文件开始的部分包含了这些变量的定义和输出。 # load ARCH, BOARD, and CPU configuration include include/config.mk export ARCH CPU BOARD VENDOR SOC
U-boot的配置编译 • 顶层目录下的 Makefile • 硬件平台依赖的目录文件就是根据这些定义来确定。SMDK2410平台相关目录如下。 • board/smdk2410/ • cpu/arm920t/ • cpu/arm920t/s3c24x0/ • lib_arm/ • include/asm-arm/ • include/configs/smdk2410.h
U-boot的配置编译 • 顶层目录下的 Makefile • Makefile文件还定义uboot映象编译的依赖关系。 ALL = u-boot.srec u-boot.bin System.map all: $(ALL) u-boot.hex: u-boot $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ u-boot.srec: u-boot $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ u-boot.bin: u-boot $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ …… Makefile缺省的编译目标是all,包括: u-boot.srec u-boot.bin System.map
U-boot的配置编译 • 开发板配置头文件 • 编译之前,可通过修改头文件include/configs/<board_name>.h,为开发板定义配置选项或者参数。例如smdk2410板的头文件是smdk2410.h。 • 这个头文件主要定义了两类变量 • 一类是选项,前缀是CONFIG_,用来选择处理器、设备接口、命令、属性等。 #define CONFIG_DRIVER_CS8900 1 • 另一类是参数,前缀是 CFG_,用来定义总线频率、串口波特率、Flash 地址等参数。 #define PHYS_FLASH_1 0x00000000 #define CFG_FLASH_BASE PHYS_FLASH_1
U-boot的配置编译 • U-boot编译分2步 • 第1步配置,例如:make smdk2410_config; • 第2步编译,执行make,得到U-Boot各种格式的映像文件和符号表。 • System.map U-Boot映像的符号表 • u-boot.bin U-Boot映像原始的二进制格式 • u-boot U-Boot 映像的 ELF 格式 • u-boot.srec U-Boot 映像是motorola的S-Record 格式 • 其中u-boot.bin可以按照绝对地址烧写到flash芯片中去。
U-boot的移植 • 什么叫做移植? • 当一个软件的运行环境发生变化时,软件跟硬件平台密切相关的代码需要经过修改,才能在新的平台上运行,这就是移植的工作。
U-boot的移植 • 为什么选择U-boot作为系统的bootloader? • U-boot 源码在不断地更新,支持的开发板越来越多; • U-boot 源码被反复应用、测试和维护,具有很好的稳定性; • U-boot 较新的版本已经支持smdk2410开发板,移植的工作量少,可以缩短移植周期,提高开发效率,降低开发成本。
U-boot的移植 • 下面就以GEC2410开发板为例介绍移植的过程,硬件环境如下: • CPU: S3C2410 • SDRAM: HY57V561620 • Nand flash: K9F1208U0B(64MB) • 以太网芯片:CS8900A (10M/100MB)
U-boot的移植过程 (1)在顶层Makefile中为开发板添加新的配置选项,例如,参考“smdk2410_config”选项,添加如下: gec2410_config : unconfig @./mkconfig $(@:_config=) arm arm920t gec2410 NULL s3c24x0 • 各项的意思如下: arm: CPU的架构(ARCH) arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。 gec2410: 开发板的型号(BOARD),对应于board/gec2410目录。 NULL: 开发者/或经销商(vender)。 s3c24x0: 片上系统(SOC)。
U-boot的移植过程 (2)在board目录中建立gec2410子目录,用于存放与开发板相关的代码,这里以smdk2410为例: #cp -rf board/smdk2410 board/gec2410 #cd board/gec2410 #mv smdk2410.c gec2410.c • 修改board/gec2410/Makefile 将: OBJS := smdk2410.o flash.o 改为: OBJS := gec2410.o flash.o
U-boot的移植过程 (3)为gec2410开发板添加新的配置文件,存放在include/configs/中。 #cp include/configs/smdk2410.h include/configs/gec2410.h (4)指定交叉编译工具的路径,并配置开发板 #export PATH=/usr/local/arm/2.95.3/bin:$PATH #make gec2410_config (5)编译u_boot #make all 执行make命令,测试编译能否成功
U-boot的移植过程 (6)添加驱动或者功能选项 • 当测试编译能够通过的时候,还要实现u_boot的以太网接口,Flash擦除、读写等的功能; • 这些功能由于不同的开发板采用不同的芯片,因此需要修改源码。
U-boot的移植过程 • 添加网络功能 • 修改include/configs/gec2410.h文件中对命令的支持参数CONFIG_COMMANDS,添加需要的网络命令。 #define CONFIG_COMMANDS 添加 CFG_CMD_NET CFG_CMD_PING • 若要添加这些命令宏之外的新命令,则可参考书中的方法
U-boot的移植过程 • 支持从nand flash启动 • 首先,我们来了解一下s3c2410的nand flash特性: • S3C2410的Nand Flash支持由两部分组成: • Nand Flash控制器(集成在S3C2410 CPU); • Nand Flash存储芯片(K9F1208U0B)两大部分组成。 • 对Nand Flash存储芯片进行操作, 必须通过Nand Flash控制器的专用寄存器才能完成; • Nand Flash相当于一个外设,而不位于它的内存地址区; • 所以,不能对Nand Flash进行总线操作。
U-boot的移植过程 • 为了支持NAND flash起动,S3C2410内建了内部的4k的SRAM缓存“Steppingstone”。 • 当选择从nand flash启动的时候,Nand flash最初的4k字节将被读入“Steppingstone”然后开始执行起动代码。 • 通常要求起动代码在前4k代码中把他本身从Nand flash中的拷到SDRAM中以便执行主代码。
U-boot的移植过程 • U_boot为了支持从nand flash启动,必须在启动时把自己拷贝到SDRAM中,这个搬运的工作需要我们自己实现。 • 具体就是在“cpu/arm920t/start.S”中添加搬运代码
U-boot的移植过程 • 支持nand flash的读写命令 • 对nand flash操作的命令的实现在“common/cmd_nand.c”文件中; • 移植的主要工作是在文件中添加: • nand flash专用寄存器地址的宏定义 • nand flash 操作的一些命令等
U-boot的移植过程 (7)调试u_boot源码,直到u_boot能在开发板上正常运行起来。 • 调试的过程可能很艰难,这就要求我们对U_BOOT的相当熟悉; • 可以用source insight建立一个u_boot的工程项目,深入分析u_boot的启动代码; • 在调试的过程中还可以使用一些调试技巧,比如: • 当遇到串口没有打印信息的时候,我们可以借助LED灯的亮灭来提示程序执行到那里。 • 当遇到nand flash 芯片不能初始化的时候,可以在代码中插入一句“printf(“I am here\n”)”语句,检查程序的执行。
实验 • u-boot的配置编译
U-boot的引导 • 一旦u-boot被正确安装都目标板之后,接着可以使用串行线连接目标板,并且用终端程序连接目标板,然后用u-boot引导。 • 下面是GEC2410开发板在引导期间的输出: U-Boot 1.1.4 (Jul 16 2007 - 16:26:51) U-Boot code: 33F80000 -> 33F9C5D4 BSS: -> 33FA06BC RAM Configuration: Bank #0: 30000000 64 MB Flash: 512 kB nand flash : 64 MB *** Warning - bad CRC or NAND, using default environment In: serial Out: serial Err: serial GEC2410#
U-boot的引导 • 正如所见,u-boot先是打印出版本信息; • 然后提供与硬件有关的细节; • 最后u-boot提供了一个命令提示符“GEC2410#”; • 用户可以在提示符下输入相应的命令,执行相应的操作。