1.07k likes | 1.31k Views
嵌入式系统讲义 第 6 章 嵌入式系统软件移植与 Linux 下程序开发. 周国运 2007.9. 本章主要内容. 1 、 Bootloader 及 vivi 移植 2 、嵌入式 Linux 内核及移植 3 、基于 Linux 的应用程序开发 4 、基于 Linux 的驱动程序开发 5 、驱动程序开发实例. 6.1 Bootloader 及 vivi 移植. 本节内容 1 、 Bootloader 简介 2 、 Bootloader 工作模式 3 、 Bootloader 启动过程 4 、 vivi Bootloader 源代码分析
E N D
嵌入式系统讲义第6章 嵌入式系统软件移植与Linux下程序开发 周国运 2007.9
本章主要内容 1、Bootloader及vivi移植 2、嵌入式Linux内核及移植 3、基于Linux的应用程序开发 4、基于Linux的驱动程序开发 5、驱动程序开发实例
6.1 Bootloader 及vivi移植 本节内容 1、Bootloader简介 2、Bootloader工作模式 3、Bootloader启动过程 4、vivi Bootloader源代码分析 5、vivi Bootloader接口命令 6、vivi 源代码修改移植
嵌入式系统软件开发流程 建立交叉编译环境 Bootloader的/移植/配置/编译 kernel的移植/配置/编译 根文件系统Cramfs的实现 用户应用程序开发
6.1.1 Bootloader简介 Bootloader,为引导加载程序,是嵌入式系统加电后运行的第一段代码,相当于PC机的BIOS。 Bootloader的位置:通常固化在硬件上的某个固态存储设备上,加电后自启动。 Bootloader功能:初始化硬件设备、建立内存空间的映射图,将系统的软、硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
Bootloader的地址:在嵌入式系统中,系统在上电或复位时从地址0x0000,0000处开始执行,在这个地址处安排的就是Bootloader。Bootloader的地址:在嵌入式系统中,系统在上电或复位时从地址0x0000,0000处开始执行,在这个地址处安排的就是Bootloader。 Bootloader是严重地依赖于硬件而实现的。每种不同体系结构的处理器都有不同的Bootloader。不过Bootloader的发展也趋于支持多种体系结构,如现在比较成熟的vivi、RedBoot和U-Boot等。
几种发布的Bootloader 1、vivi vivi是韩国Mizi公司开发的Bootloader,适用于ARM9处理器。 2、RedBoot RedBoot即红帽(Red Hat)嵌入式调试引导程序,是一种用于嵌入式系统的独立开放源代码引导/装载器。 3、U-Boot U-Boot(Universal Bootloader)由德国DENX小组开发,是一款目前功能较为强大的开源Bootloader程序,它支持多种处理器平台,包括ARM、PowerPC、MIPS等。
6.1.2 Bootloader操作模式 大多数Bootloader都有两种不同的操作模式:“启动加载”模式和“下载”模式。其区别对于开发人员才有意义。 从最终用户的角度看,Bootloader的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载模式的区别。
1、启动加载(Bootloading)模式 启动加载模式称为“自举”(Autonomous)模式。即Bootloader从目标机上的某个固态存储设备上将操作系统加载到 RAM 中运行,整个过程并没有用户的介入。 启动加载模式是 Bootloader的正常工作模式,在嵌入式产品发布的时侯,Bootloader必须工作在这种模式下。
2、下载(Downloading)模式 下载方式:在这种模式下,目标机上的Bootloader将通过串口连接或网络连接等通信手段从主机下载文件。 下载内容及存储:主要是下载内核映像和根文件系统映像等。从主机下载的文件通常首先被Bootloader保存到目标机的RAM中,然后再被 Bootloader写到目标机上的FLASH 类固态存储设备中。
下载模式应用场合:Bootloader的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用到这种工作模式。下载模式应用场合:Bootloader的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用到这种工作模式。 用户应用接口:工作于这种模式下的Bootloader通常都会向它的终端用户提供一个简单的命令行接口。 如在RedBoot下,将出现“RedBoot>”提示符;在vivi Bootloader 下出现“vivi>”提示符。
RedBoot的Bootloader 像RedBoot或U-Boot等功能强大的Bootloader通常都可同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行切换。 比如,RedBoot在启动时处于正常的启动加载模式,但是它会延时3秒等待终端用户按下任意键而将RedBoot切换到下载模式。如在等待时间内没有接收到用户按键,则继续启动 Linux 内核。
6.1.3 Bootloader启动过程 Bootloader的启动可以分为两个阶段 1、第一阶段 阶段1主要包含依赖于CPU体系结构及硬件设备的初始化等。通常都用汇编语言来实现。这个阶段的任务有5: (1)、基本的硬件设备初始化 这是 Bootloader 一开始就执行的操作,其目的是为阶段2 的执行、以及随后kernel 的执行准备好一些基本的硬件环境。
它通常包括以下工作:屏蔽所有的中断、设置 CPU 的速度和时钟频率、关闭处理器内部指令/数据cache等。
(2)、为阶段2代码准备RAM空间 为了获得更快的执行速度,通常把 阶段2 的代码加载到 RAM 空间中来执行。 准备RAM空间考虑的因素:阶段2代码大小、堆栈、页大小(4KB的倍数)、安排位置等。 总的空间有1MB足够,安排在RAM的顶端较恰当。
(3)、拷贝阶段2代码到RAM空间 (4)、设置好堆栈 堆栈指针sp设置在1MB 的 RAM 空间的最顶端(堆栈向下生长)。 (5)、跳转到阶段2的C程序入口点 在上述一切都就绪后,就可以跳转到 Bootloader 的 stage2 去执行了。
2、第二阶段 阶段2通常用C语言来实现,以便实现更复杂的功能,也使程序有更好的可读性和可移植性。这个阶段的主要任务有5: (1)、初始化本阶段要使用到的硬件 至少初始化一个串口,以便和终端用户进行 I/O 输出信息等。
(2)、检测系统内存映射(memory map) 所谓内存映射,就是指在整个物理地址空间中有哪些地址范围被分配用来作为系统的 RAM 单元。为后面使用RAM、运行程序做好准备。 (3)、将kernel和根文件系统映像从flash读到RAM空间
(4)、为kernel设置启动参数 这是在调用内核之前应该做的准备工作。Linux 2.4.x 以后的内核都期望以标记列表(tagged list)的形式来传递启动参数。 启动参数标记列表方法:以ATAG_CORE标记开始,以ATAG_NONE标记结束。 在嵌入式 Linux 系统中,通常需要由 Boot Loader 设置的启动参数有:ATAG_CORE、ATAG_MEM(内存映射)、ATAG_NONE等。
(5)、调用内核 Bootloader调用Linux kernel的方法是直接跳转到内核的第一条指令处。在跳转时必须满足下列条件: 1)、CPU寄存器的设置:R0为0;R1为机器类型ID;R2为启动参数,标记列表在RAM中的起始基地址。 (机器类型参见 linux/arch/arm/tools/mach-types目录) 2)、CPU模式: CPU必须设置为SVC模式,必须禁止中断(IRQs和FIQs)。 3)、 MMU 和 Cache的设置:MMU 必须关闭;指令 Cache 可以打开也可以关闭; 数据 Cache 必须关闭。
6.1.4 vivi Bootloader源码分析 vivi是韩国Mizi公司开发的Bootloader,适用于ARM9处理器。 vivi有两种工作模式,在启动时可以选择。在vivi启动时,通过串行口发出如下信息: Press Return to start the Linux now, any other key for vivi 按回车键启动Linux OS,按其它键进入vivi命令接口模式,可以使用vivi提供的命令进行一些操作。
一、vivi源代码目录结构 vivi源代码包含的目录有:arch、Documentation、drivers、init、include、lib、scripts、test、util等10目录,共300多个文件。各个目录内容如下: 1、arch(architecture)目录 它下面的文件为与CPU硬件相关的初始化代码,此目录包含了所用vivi支持的CPU。一般只包含S3C2410x的文件。
2、Documentation目录 其下文件为vivi使用指南。 3、drivers目录 存放的为MTD(数据存储媒质)设备读写控制文件和串行口操作文件,对串行口支持xmodem和ymodem协议。 4、include目录 存放所有的头文件,包括S3C2410微处理器的和S3C2410开发板的头文件。
5、init目录 该目录下是系统初始化文件main.c、version.c,后者是vivi版本信息,main.c为vivi整个初始化的结构。 6、lib目录 该目录下是公共应用及接口代码,如时钟功能文件time.c,堆栈初始化文件heap.c等文件。 7、scripts目录 该目录存放的是系统配置需要的脚本文件,如menuconfig和configue文件。
8、CVS目录 所有的目录下面都有一个CVS目录,存放的是该目录的路径和它的子目录。
二、vivi源代码文件与功能结构 vivi源代码文件: 1、vivi/arch/s3c2410/head.s 2、一段过度,实现循环调用,main返回后重新复位 LDR SP, DW_STACK_START MOV FP, #0 MOV A2, #0 BL MAIN MOV PC, #FLASH_BASE 3、vivi/init/main.c
6.1.5 vivi Bootloader接口命令 vivi有两种工作模式,一种是 “启动加载”模式,另一种是命令行模式。利用串行口与主机的连接,可以进行命令行操作。 vivi启动后,通过串行口发出如下信息: Press Return to start the Linux now, any other key for vivi 按下除了“Enter”之外的键,便可进入命令行模式。 vivi的接口命令有5条。
1、load---下载文件命令 功能:将二进制文件下载到Flash或RAM 格式:load <media_type> [<partname>|<addr> <size>] <x|y|z> media_type:存储器类型,Flash或RAM partname:分区名称 addr size:下载的地址及占用空间大小 x|y|z:文件的传输协议。x表示采用xmodem协议,y表示采用ymodem协议,z表示采用zmodem协议。目前vivi仅支持xmodem协议。
例1:vivi>load flash kernel x 表示下载压缩的内核映像文件zImage到flash存储器的内核分区中,采用xmodem传输协议。 例2:vivi>load flash 0x80000 0xc0000 x
2、part---MTD分区操作命令 操作命令:显示、增加、删除、复位、保存MTD分区等。 各个命令格式: part show:显示分区信息 part del <partname>:删除指定的分区 part reset:恢复分区的默认值 part save:在flash中保存分区和参数值
增加新的分区 part add <partname> <offset> <size> <flag>: partname:新分区名称 offset:新分区的偏移地址 size:新分区的大小 flag:新分区的类型,可以是JFFS2、LOCKED、BONFS
3、param ---设置或查看分区参数命令 • 查看分区参数: param show • 设置启动等待按键延迟: param set boot_delay n(μs) • 设置通信初始化超时: param set xmodem_initial_timeout m (μs)
4、boot---引导内核命令 格式: boot [media_type] [<partname>|<addr> < size>] media_type:存储器类型,flash或RAM partname:内核所在分区名称 addr:内核所在器件的偏移地址 size:内核的大小 若 boot (无参数),则从kernel内核对应的分区中(kernel)读取内核映像启动。
例如: 1、vivi>boot nand 0x80000 内核在nand flash中,偏移地址为0x80000,大小为缺省值0xc0000 2、vivi>boot nor 0x80000
5、flash---flash存储器管理命令 擦除flash数据格式: flash erase [<partname>|<offset> <size>] 说明: 对flash只有擦除命令。 例如: flash erase 0x80000 0xc0000
vivi接口命令 第三讲到此
6.1.6 vivi源码的修改移植 vivi的移植方法步骤: • 对vivi进行修改移植 • 对vivi进行配置 • 对vivi进行编译 • 下载、运行vivi 一、对vivi进行修改移植 设Linux系统的目录结构为
设Linux系统的目录结构为: cygwin friendly-arm crosstool kernel vivi …
1、修改vivi/Makefile (1)修改交叉编译库和头文件 1)修改编译器路径: 将: CROSS_COMPILE= /opt/host/armv4l/bin/armv4l-unknown-linux- 修改为: CROSS_COMPILE= arm-linux-gcc的路径 如: CROSS_COMPILE =/friendly-arm/ crosstool/arm-linux/ gcc-2.95.3-glibc-2.2.3/bin/arm-linux-
2)修改编译器库文件路径: 将: ARM_GCC_LIBS= /opt/host/armv4l/bin/gcc-lib/ armv4l-unknown-linux/2.95.2 修改为: ARM_GCC_LIBS=符合本机的路径 如: ARM_GCC_LIBS= /friendly-arm/ crosstool/arm-linux/gcc-2.95.3-glibc-2.2.3/lib/ gcc-lib/arm-linux/2.95.3
3)增加交叉编译时头文件的搜索路径: LIBC_INCLUDE_DIR= 本机的include的路径 如: LIBC_INCLUDE_DIR = /friendly-arm/ crosstool/arm-linux/ gcc-2.95.3-glibc-2.2.3/include
(2)Linux内核包含文件 修改Linux头文件所在路径 将:LINUX_INCLUDE_DIR= /opt/host/armv4l/include 改为: LINUX_INCLUDE_DIR=符合本机的 如: LINUX_INCLUDE_DIR= /friendly-arm/kernel/include
2、修改vivi中与硬件相关的部分 只需要修改: /friendly-arm/vivi/include/platform/ 下面的文件smdk2410.h即可。 文件smdk2410.h的内容是针对开发板的硬件配置的,主要有:时钟设置、存储器初始化、通用I/O口初始化、UART初始化、vivi初始配置等。 根据自己的目标板的实际情况进行设置即可。
3、支持Nor Flash启动的修改 (vivi/arch/s3c2410/smdk.c) (1) Nor flash分区 对于一个嵌入式系统,可能会采用Nor flash、Nand flash、SDRAM等多种介质构成存储器系统, Nor flash(如1、2MB)用于存放、运行bootloader,Nand flash用于存放操作系统、其它系统软件、应用程序和各种文件, SDRAM用于运行程序和存放数据。 如果系统有Nor flash存储器(一般没有),则需要做相应修改。
修改方法:在vivi/arch/s3c2410/smdk.c中的分区代码,添加上Nor flash分区: #ifdef CONFIG_S3C2410_AMD_BOOT mtd_partition_t default_mtd_partitions[] = { { name: "vivi", offset: 0, size: 0x00020000, flag: 0 },
{ name: "param", offset: 0x00020000, size: 0x00010000, flag: 0 }, { name: "kernel", offset: 0x00030000, size: 0x000C0000, flag: 0 },
{ name: "root", offset: 0x00100000, size: 0x00140000, flag: MF_BONFS } }; #endif