嵌入式系统实验报告
学 院 测量与通信工程学院
专 业 信号与信息处理
学生姓名 姜 元
学 号 1320600050
指导教师 董静薇
一、 实验目的
?
?
?
?
了解BootLoader的基本概念和框架结构 了解BootLoader引导操作系统的过程 掌握bootloader程序的编译方法 掌握BootLoader程序的使用方法
二、 实验内容
?
?
?
?
?
?
熟悉嵌入式linux环境下的开发工具,包括make、gcc、超级终端等 bootLoader程序的编译和下载 内核和文件系统的编译和下载 实验分析bootLoader程序的实现原理和结构 观察程序运行情况 完成实验手册题2和题5
三、 实验原理
1. BootLoader的功能与结构
1) 嵌入式Linux系统软件结构如图1所示:
图1 嵌入式Linux系统软件结构
2) 什么是BootLoader?
简单地说,BootLoader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
由于硬件结构差别较大,不同的目标板需要不同的BootLoader。
3) BootLoader 的主要功能
? 初始化系统在启动阶段必需的硬件设备;
? 准备后续软件系统(如操作系统)运行所需的软件环境,如复制操作系统内核代码到RAM中等;
- 1 -
?
?
?
? 向内核传递启动参数; [可选] 配置系统各种参数; [可选] 支持各种协议来下载BootLoader、内核、文件系统等; [可选] 在线烧写系统firmware(固件),如启动参数、BootLoader、内核、文件系
统等;
? [可选] 支持在线调试;
? 引导内核启动。
4) 固态存储设备的空间分配
在固态存储设备中的典型空间分配情况如图2所示:
起启动参数始 地 址
Bootloader
图2 固态存储设备中的典型空间分配情况 结
5) 典型BootLoader的启动流程
典型的BootLoader启动流程如图3所示
- 2 -
图3 典型的BootLoader启动流程
6) BootLoader的工作模式
功能完善的BootLoader一般包含2种工作模式:
? 启动加载模式(loading)
从最终用户的角度看,BootLoader的功能就是加载操作系统。
? 下载更新模式(downloading)
主要用于嵌入式系统开发人员。
启动加载模式(loading)
? 这种模式也称为“自主”(Autonomous)模式;
? BootLoader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整
个过程并没有用户的介入;
? BootLoader的正常工作模式,在嵌入式产品发布的时侯,BootLoader 必须工作在该
模式下。
下载更新(Downloading)模式
? 该模式下,目标机上的 BootLoader将通过串口或USB、网络连接等从主机(Host)
下载文件,比如:下载内核映像和根文件系统映像等。
? 下载的文件通常被BootLoader保存到目标机的 RAM 中,然后再被写到目标机上的
FLASH 类固态存储设备中。
? 该模式在第一次安装内核与根文件系统时会被使用;系统更新也会用到。
? 该模式下的 BootLoader通常都会为用户提供一个简单的命令行接口。
此次实验过程中即使用下载模式。
- 3 -
7) BootLoader的典型结构框架
大多数Bootloader的执行分为两个阶段:
a) 第一阶段/也称FlashLoader
--运行于Flash的一段BootLoader代码
特点:
? 代码量小,往往不会超过256B;
? 汇编写成;
? 运行于Flash;
? 由于加载BootLoader后,需要运行BootLoader,因此最后往往是一条跳转语句。
主要操作步骤:
? 硬件设备初始化。
? 为加载BootLoader准备RAM空间。
? 拷贝BootLoader到RAM空间中。
? 设置好堆栈。
? 跳转到BootLoader的C语言入口点。
b) 第二阶段/也称BootLoader
--运行于RAM中的BootLoader主要代码
特点:
BootLoader是操作系统内核运行前的核心程序,它具有如下特点:
? 代码量大;
? 由C语言写成,大多数时候需要嵌入式汇编语言;
? 运行于SDRAM等随机存储器
? 由于它是启动内核前运行的最后一个程序,它必须把控制权交给内核,因此它最后
是一条跳转到系统内核的语句。
主要操作步骤:
? 初始化本阶段要使用到的硬件设备。
? 检测系统内存映射(memory map)。
? 将kernel映像和根文件系统映像从flash上读到RAM空间中。
? 为内核设置启动参数。
? 启动内核。
8) PXA270开发板Flash和SDRAM空间分配
? Defined in xsbase270.h (bootloader源代码中)
? #define LOADER_SRAM_BASE 0x00000000
? #define LOADER_DRAM_BASE 0xA3F00000
? #define LOADER_MAX_SIZE 0x00040000
- 4 -
?
?
?
?
?
?
?
?
?
#define KERNEL_SRAM_BASE 0x00040000 #define KERNEL_DRAM_BASE 0xA0008000 #define KERNEL_MAX_SIZE 0x00140000 #define RAMDISK_SRAM_BASE 0x00180000 #define RAMDISK_DRAM_BASE 0xA1000000 #define RAMDISK_MAX_SIZE 0x00300000 #define ROOTFS_SRAM_BASE 0x00180000 #define ROOTFS_DRAM_BASE 0xA0000000 #define ROOTFS_MAX_SIZE 0x01e80000
2. 嵌入式Linux内核的启动过程
嵌入式LINUX内核的版本控制:
内核版本号格式为:“X . YY . ZZ”,如2.4.18。
--X:主版本号,介于0和9之间,它的变化意味着内核在设计或实现上有重大变化。 --YY:次版本号,介于0和99之间,它一方面表示版本的变迁,一方面表示版本类型,即“发行版”或“开发版”。YY为偶数则表示相对稳定的发行版,而奇数则表示还在开发中的版本,它可能不太稳定,运行中可能会出现较大的问题。
--ZZ:表示内核经过较小修改后的版本。
嵌入式Linux的版本号后面还会加一个后缀,如“rmk4-mx1bsp0.3.6”,该后缀往往表示针对某个开发平台的补丁。几个常用的后缀:
--rmk:表示由Russell King维护的ARM Linux;
--np:表示由Nicolas Pitre维护的基于StrongARM和Xscale的ARM Linux;
--ac:表示由Alan Cox(Alan Cox是仅次于Linus的Linux维护人员,主要负责网络部分和OSS等的维护工作)维护的Linux代码;
--hh:表示由网站发布的ARM Linux代码,主要是基于Xscale的,它包括工具链、内核补丁、嵌入式图形系统等。
嵌入式LINUX的内核源代码结构:
? COPYING
– GPL版权申明。
? CREDITS
– 光荣榜。对Linux做出过重大贡献的人员信息。
? MAINTAINERS
– 维护人员列表,对当前版本的内核各部分都有谁负责;
? ReadMe
– Linux内核安装、编译、配置方法等的简单介绍;
? Makefile
– 第一个Makefile文件。用来组织内核的各模块,记录各模块间的相互联系和
依托关系,编译时使用。
? Rules.make
– 各种Makefile以及make所使用的一些共同规则;
- 5 -
? REPORTING-BUGS
– 有关报告Bug的一些内容;
? Documentation/
– 关于内核源代码的一套非常有用的文档;
? Arch/
所有和体系结构相关的核心代码,每个子目录对应一种CPU体系结构;
– i386 IBM的PC体系结构
– mips SGI的MIPS体系结构
– m68k Motorola的基于C680x0的体系结构
– arm 基于ARM处理器的体系结构
– Sparc sun的sparc处理器体系结构
– 等等
? Include/
– 包括编译核心所需要的大部分头文件。
– 与平台无关的头文件在include/linux子目录下;
– 与ARM CPU相关的头文件在include/asm-arm子目录下;
– include/scsi目录则是有关scsi设备的头文件目录;
? Init/
– 内核的初始化代码, 包括两个重要文件main.c和Version.c,这是研究核心
如何工作的好的起点之一。
? Mm/
– 所有独立于cpu体系结构的内存管理代码,如页式存储管理内存的分配和释
放等;
– 和体系结构相关的内存管理代码则位于arch/*/mm/,例如arch/arm/mm/; ? Kernel/
– 主要的内核代码,此目录下的文件实现了大多数linux系统的内核函数; – 其中最重要的文件为sched.c;
– 和体系结构相关的代码在arch/*/kernel中;
? Drivers/
设备驱动程序;每种驱动程序又各占用一个子目录
– Block: 块设备驱动程序
– Scsi: SCSI设备驱动程序
– Char: 字符设备驱动程序
– net 网卡设备
– sound 音频卡设备
– video 视频卡设备
– cdrom 专用CD-ROM设备(除ATAPI和SCSI之外)
– isdn ISDN设备
– sgi SGI的设备
– acorn Acorn的设备
– pnp 即插即用的支持
– usb 通用串行总线(USB)的支持
– pci PCI总线的支持
– sbus Sun的SPARC SBus的支持
- 6 -
– nubus 苹果的Macintosh Nubus的支持
? Fs/
– 所有的文件系统代码和各种类型的文件操作代码,它的每一个子目录支持一个文件
系统,例如fat和ext2;
? Ipc/
– 包含核心的进程间通信的代码;
? Lib/
– 放置核心的库代码;
? Net/
– 核心与网络相关的代码;
? Modules/
– 模块文件目录,一般为空目录,用于存放编译时产生的模块目标文件;
? Scripts/
– 用于系统配置的命令文件,是一个脚本,用于对核心的配置;
嵌入式LINUX的内核启动过程:
Bootloader运行结束后,程序运行控制权交给操作系统内核,这时进入Linux内核启动阶段,该部分大致可以分为3个阶段:
? 第一阶段
? 主要是进行cpu和体系结构的检查、cpu本身的初始化以及页表的建立等; ? 第二阶段
? 主要是对系统中的一些基础设施进行初始化;
? 第三阶段
? 更高层次的初始化,如根设备和外部设备的初始化。
内核启动第1阶段:
从汇编文件linux/arch/arm/kernle/head-armv.S的ENTRY(stext)点处开始执行,直到start_kernel()函数,主要功能:
? 判断cpu类型
? 判断体系类型
? 创建核心页表
? 初始化处理器,打开MMU、CACHE等
? 跳转到init\main.c中的start_kernel函数处,开始执行c代码
内核启动第1阶段流程如图4所示:
- 7 -
图4 内核启动第1阶段流程
内核启动第2阶段:
从C代码文件linux/init/main.c中的start_kernel函数处开始执行,
??
直到调用kernelthread()产生init线程(位于linux/init/main.c),完成KERNEL的启动过程。
? 系统首先完成一些相关的初始化工作:
? lock_kernel();
? printk(linux_banner); //打印LINUX版本信息等。
? setup_arch(&command_line);//处理器相关的初始化过程
? printk("Kernel command line: %s\n", saved_command_line);
? parse_options(command_line); //解析BootLoader传递过来的内核参数
? trap_init();//设置陷阱门和中断门
? init_IRQ();//初始化系统IRQ
? sched_init(); //进程调度机制的初始化
…….
? console_init(); //控制台设备的初始化
? fork_init(mempages);// 根据系统物理内存的大小计算运行创建线程(包括进
程)的数量。
……
? 最后,在rest_init()中调用kernel_thread()产生产生第一个核心线程init(位于
linux/init/main.c),然后调用cpu_idle(),等待系统调度init线程,从而完成KERNEL的启动过程。
内核启动第3阶段:
内核启动第二阶段完成后,一般会在/sbin、/etc、/bin等目录下查找init程序并执行,init的执行过程如下:
? init从配置文件/etc/inittab中获取所有信息;
- 8 -
? /etc/inittab中会定义一个启动教本,如sysinit、rc、rcS等;
? PXA270开发系统中启动运行脚本文件/etc/rc.d/rc.sysinit,将完成驱动模块的动态加
载、配置网络等工作。
四、 实验步骤
1、阅读“Linux实验上机指导书”中有关bootloader的内容,以及课件相关内容,熟悉bootloader源代码的框架结构;
2、实验箱连线,包括仿真器、串口线、电源等;
3、打开一个Dos窗口,(开始->运行:输入“cmd”命令,然后回车);
4、利用telnet登陆到服务器:在dos窗口中输入218.192.169.240或者218.192.169.241; 用户名和密码同以前的实验。
5、现在你已经登陆到嵌入式linux开发环境服务器,也就是你面对的是一个linux操作系统环境。转换到/home/emb目录下(命令:cd /home/emb )
6、在当前目录下创建一个自己的目录,例如tmptest;命令:mkdir tmptest
7、利用leapftp软件将bootloader源代码(Boot-XSBase270_010005.tar.gz)上传到自己的目录下
8、输入输入tar xzvf Boot-XSBase270_010005.tar.gz,将源代码解压
9、输入“make” 编译bootloader程序,成功的话则生成文件:boot,则就是bootloader的可执行程序,将其下载到本地计算机待用。此时你可以选择根据Linux实验上机指导书的相关内容,编译内核和文件系统。也可以利用leapftp从课件中的实验参考资料的Image目录中直接下载内核(zImage_e24qt)和文件系统(rootfs270qt_24.img)到本地待用。
10、利用FlashWrite将boot文件烧写到Flash
11、打开程序->附件->通讯工具->超级终端,根据电脑的实际接口选择Com1
或com2,端口配置为:Rate:115200;Data Bits:8;Parity:无;Stop Bits:1;Flow Control:无
12、超级终端用于开发板上的嵌入式linux系统的信息界面
13、打开C:\Cisco TFTP Server\TFTPServer.exe软件,用于通过网线烧写内核
和文件系统。
14、此时重启开发板电源,烧写到开发板boot将开始运行,按“空格键”进入
bootloader的下载模式,界面如下:
- 9 -
15、输入“0”,回车,并根据本机的IP地址配置tftp服务器IP地址:(设本机
ip:218.192.169.4)
set myipaddr 218.192.169.5
set destipaddr 218.192.169.4
16、用提供的直连网线连接开发板和pc机,并将要烧写的内核和文件系统复
制到C:\Cisco TFTP Server\tftp目录;
17、超级终端中输入:tftp zImage_e24qt kernel回车,此时开始传输内核镜像
文件,完成后输入:flash kernel回车开始烧写内核;
18、在在超级终端中输入:tftp rootfs270qt_24.img root 回车,此时开始传
输文件系统镜像文件,完成后输入:flash root回车开始烧写文件系统;
此时嵌入式linux 的bootloader、内核、文件系统均已烧写到开发板,重
启开发板电源,开发板的linux系统就可以正常启动了,在系统登陆用户
中输入“root”,系统就登陆到linux 系统了。
19、编写简单应用程序,例如“helloworld.c” ,上传到服务器进行编译
(arm-linux-gcc helloworld.c -o hello),并将可执行文件下载到本机。
20、在超级终端中输入:cd /tmp,然后点击菜单发送->传送文件,选择hello
文件将其下载到cd /tmp目录。
21、运行hello:./hello; 如果没有权限则修改权限:chmod +x hello
五、 程序说明
FlashLoader源代码分析:
PXA270的Flashloader定义在start.S中:
初始化GPIO(定义在fixgpio.S )
bl define_gpio
设置CPU的速度和时钟频率
bl clock_enable
- 10 -
存储控制单元初始化
bl setup_memory
复制bootloader到SDRAM
ldr r0, =0x00//原地址
ldr r1, =__boot_start//运行地址
ldr r2, =__boot_end
1: ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r1, r2
blt 1b
设置网卡基地址
ldr r0, =eth_base
ldr r1, [r0]
设置栈指针
ldr sp, =stack_point-4
跳转到main函数
ldr pc, =main
执行完FlashLoader,CPU控制权移交给BootLoader,开始执行BootLoader的main()函数。
PXA270开发板BootLoader的主要操作为:
? uart_init();//串口初始化
? time_init();//初始化定时器
? config_init();//内存映射配置初始化
? iflash_init();//flash存储器初始化
? eth_init();//网络初始化
– autoboot_mode();//进入自动启动模式
– 进入bootloader 下载模式
? 进入autoboot模式后,先将内核和Ramdisk分别拷贝到0xa000,8000和0xa100,0000 ? 跳转到KERNEL:(do_boot函数)
通过定义void (*kernel)(int zero, int arch);及Kernel = 内核的SDRAM地址,实现跳转。 create_tags();//设置内核的启动参数
kernel(0, 200);//直接跳转到内核开始地址去
六、 程序源代码、注释
(1)阶段1源程序分析
Start.s 源程序如下:
#include <config.h>
- 11 -
#include <hardware.h>
#define eth_base 0x0c00030e
.section .text.start
.global _start
_start :
b start
.section .text
start :
bl define_gpio //初始化GPIO
bl clock_enable //设置CPU的速度和时钟频率
bl setup_memory //@ setup static and dynamic memory存储控制单//元初始化
@ldr r0, =0x0a000000
@ldr r1, =0xfff
@str r1,[r0]
@ copy bootloader to dynamic memory area //复制bootloader到SDRAM
ldr r0, =0x00 //原地址
ldr r1, =__boot_start //运行地址
ldr r2, =__boot_end
1: ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r1, r2
blt 1b
@ clear bss area //设置网卡基地址
mov r3, #0x00
mov r4, #0x00
mov r5, #0x00
mov r6, #0x00
ldr r0, =bss_start
ldr r1, =bss_end
1: stmia r0!, {r3-r6}
cmp r0, r1
blt 1b
ldr r0, =eth_base
ldr r1, [r0]
@ set stack point //设置栈指针
ldr sp, =stack_point-4
@ jump to c code // 跳转到main函数
- 12 -
ldr pc, =main
clock_enable :
#if defined(CONFIG_PXA25x)
ldr r0, =0x0001FFFF
#elif defined(CONFIG_PXA27x)
ldr r0, =0x01FFFFFF
#endif
ldr r1, =CKEN
str r0, [r1]
mov pc, lr
(2)阶段2程序分析
执行完FlashLoader,CPU控制权移交给BootLoader,开始执行BootLoader的main()函数。
uart_init();//串口初始化
time_init();//初始化定时器
config_init();//内存映射配置初始化
iflash_init();//flash存储器初始化
eth_init();//网络初始化
autoboot_mode();//进入自动启动模式
进入bootloader 下载模式
实验中下载到开发板运行的一个“Hello,world!”程序源代码:
#include <stdio.h>
int main()
{
printf(“Hello world!\n”,0);
return 0;
}
七、 总结(心得体会)
这次实验过程中没有接触太多的程序,可能因为程序过于复杂的原因。并且实验本身操作起来比较的复杂,需要用到很多的软件,总之比较麻烦不容易清楚的认识整个实验。
实验中,主要学习了熟悉嵌入式linux环境下的开发工具,包包括make、gcc、超级终端等,还有内核和文件系统的编译和下载。Bootloader这个底层程序完成了上层文件安装的驱动引导作用,让我基本的了解BootLoader的基本概念和框架结构。了解了bootloader的实现原理、结构和运行过程,丰富了自己的见识。
最后,在将hello文件下载到cd /tmp目录之前,要先在服务器上对hello.c文件进行编译,再运用超级终端这个工具把hello.o下载到开发板上去。
- 13 -
郑州航空工业管理学院嵌入式系统实验报告修订版20第赵成张克新编著院姓专学系名业号电子通信工程系20xx年3月制实验一ARM体系结构…
嵌入式系统设计实验报告班级学号姓名成绩指导教师1实验一11实验名称博创UP3000实验台基本结构及使用方法12实验目的1学习嵌入式…
实验报告20xx20xx学年第二学期课程名称ARM嵌入式系统原理与开发实验名称嵌入式Linux交叉开发环境建立与程序开发实验时间指…
嵌入式系统设计实验报告班级学号姓名成绩指导教师20xx061420xx061411刘群峰赵国冬孟昭林1实验一11实验名称博创UP3…
嵌入式系统实验报告学院测量与通信工程学院专业信号与信息处理学生姓名姜元学号1320xx0050指导教师董静薇一实验目的了解Boot…
《嵌入式系统》实验报告姓名:学号:班级:湖南工业大学电气与信息工程学院20xx年x月实验一ARM汇编指令实验1一、实验目的1.初步…
学习嵌入式系统心得说实在话在没有学习之前,以及在学之前通过一些口中得知这是一门很不错,很有意思的一门课。而且目前是十分吃香的一门课…
重庆航天职业技术学院课程作业课程名称嵌入式系统专选班级学号姓名成绩前言嵌入式系统是基于单片机的一种升级版它是以应用为中心以计算机技…
嵌入式系统原理实验总结报告车辆座椅控制系统实验20xx523嵌入式系统原理实验总结报告一技术性总结报告一题目车辆座椅控制系统实验二…
嵌入式系统设计实验报告班级学号姓名成绩指导教师1实验一11实验名称博创UP3000实验台基本结构及使用方法12实验目的1学习嵌入式…
大连理工大学本科实验报告课程名称嵌入式系统实验学院系电子信息与电气工程学部专业自动化班级学号学生姓名20xx年月大连理工大学实验报…