﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-老狼之家-文章分类-OS</title><link>http://www.cppblog.com/wolf/category/8500.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 27 Aug 2010 01:54:01 GMT</lastBuildDate><pubDate>Fri, 27 Aug 2010 01:54:01 GMT</pubDate><ttl>60</ttl><item><title>vivi嵌入式 bootloader（转）</title><link>http://www.cppblog.com/wolf/articles/63919.html</link><dc:creator>老狼</dc:creator><author>老狼</author><pubDate>Mon, 13 Oct 2008 12:59:00 GMT</pubDate><guid>http://www.cppblog.com/wolf/articles/63919.html</guid><description><![CDATA[

vivi是当前比较流行的，专门针对ARM9处理器而设计的一款Bootloader，它操作简便，同时提供了完备的命令体系。因此，对其进行分析和研究具有一定的实际意义。<br>
<div class="spctrl"></div>　　vivi简介<br>
<div class="spctrl"></div>　　vivi是由韩国Mizi公司开发的一种Bootloader，适合于ARM9处理器，支持S3C2410x处理器，其源代码可以在http://www.mizi.com网站下载。和所有的Bootloader一样，vivi有两种工作模式，即启动加载模式和下载模式。当vivi处于下载模式时， 
它为用户提供一个命令行接口，通过该接口能使用vivi提供的一些命令集。<br>
<div class="spctrl"></div>　　vivi运行过程分析<br>
<div class="spctrl"></div>　　vivi作为一种Bootloader，其运行过程分成两个阶段。第一阶段的代码vivi/arch/s3c2410/head.s中定义，大小不超过10 
KB，它包括从系统上电后在0x00000000地址开始执行的部分。这部分代码运行在Flash中，它包括对S3C2410的一些寄存器、时钟等的初始化并跳转到第二阶段执行。第二阶段的代码在vivi\init\main.c中，主要进行一些开发板初始化、内存映射和内存管理单元初始化等工作，最后会跳转到boot_or_vivi()函数中，接收命令并进行处理。需要注意的是在Flash中执行完内存映射后，会将vivi代码拷贝到SDRAM中执行。如图1所示，给出了vivi的详细的运行过程。<br>
<div class="spctrl"></div>　　大多数Bootloader都分为stage1和stage2两部分，stage2 的代码通常用 C 
语言来实现，以便于实现更复杂的功能并取得更好的代码可读性和可移植性。但是与普通C语言应用程序不同的是，在编译和链接Bootloader 
程序时，不能使用glibc库中的函数。因此，从那里跳转进main()函数，而把main()函数的起始地址作为整个stage2执行映像的入口点也存在两个缺点：无法通过main()函数传递函数参数且无法处理main()函数返回的情况。<br>
<div class="spctrl"></div>　　一种较为巧妙的方法是利用弹簧床的概念，也就是用汇编语言写一段trampoline 
小程序，并将这段程序作为stage2可执行映象的执行入口点，然后在trampoline汇编小程序中用CPU跳转指令跳入main()函数中去执行。当main()函数返回时，CPU执行路径再次回到trampoline程序。简而言之，这种方法的思想就是：用这段 
trampoline小程序来作为main()函数的外部包裹。<br>
<div class="spctrl"></div>　　vivi中的trampoline程序如下：<br>
<div class="spctrl"></div>　　@ get read to call C functions <br>
<div class="spctrl"></div>　　ldr sp, DW_STACK_START @ setup stack pointer<br>
<div class="spctrl"></div>　　mov fp, #0 @ no previous frame, so fp=0<br>
<div class="spctrl"></div>　　mov a2, #0 @ set argv to NULL <br>
<div class="spctrl"></div>　　bl main @ call main <br>
<div class="spctrl"></div>　　mov pc, #FLASH_BASE @ otherwise, reboot；<br>
<div class="spctrl"></div>　　正常情况下，程序能够正常执行完毕，但是如果出错了，就回到最后一条语句重新启动系统。<br>
<div class="spctrl"></div>　　图1　vivi运行过程<br>
<div class="spctrl"></div>　　vivi的移植<br>
<div class="spctrl"></div>　　为了使移植工作更加快捷，本文选择vivi-20030929版本。它不仅提供对ARM-920T内核的支持，而且直接提供了对于S3C2410x的板级支持，这使移植工作量相对减少。<br>
<div class="spctrl"></div>　　vivi中与软件相关的修改<br>
<div class="spctrl"></div>　　vivi作为Linux系统的启动代码，在编译配置时需要用到函数库，包括交叉编译器库和头文件，交叉编译开关选项设置，还包括Linux内核代码中的库和头文件，所以，通常需要修改vivi工程管理文件Makefile。<br>
<div class="spctrl"></div>　　vivi中与硬件相关的初始化<br>
<div class="spctrl"></div>　　与具体运行在哪一个处理器平台上相关的文件都存放在vivi/arch/目录下，本系统使用S3C2410x处理器，对应的目录为s3c2410。<br>
<div class="spctrl"></div>　　其中head.s文件是vivi启动配置代码，加电复位运行的代码就是从这里开始的。由于该文件中对处理器的配置均通过调用外部定义常数或宏来实现，所以针对不同的平台，只要是S3C2410x处理器，几乎不用修改，只要修改外部定义的初始值即可。这部分初始值都在vivi/include/platform/smdk2410.h文件中定义，包括处理器时钟、存储器初始化、通用I/O口初始化以及vivi初始配置等。<br>
<div class="spctrl"></div>　　对不同Flash启动的修改<br>
<div class="spctrl"></div>　　vivi能从Nor Flash或Nand 
Flash启动，因此启动程序以及Linux内核及根文件系统，甚至还包括图形用户界面等就需要存放在Nor Flash或Nand 
Flash中。这样，作为启动程序的vivi还需要根据实际情况来修改存放这些代码的分区。本系统采用64MB Nand Flash、2MB Nor 
Falsh，需要由vivi进行分区才能运行Linux。分区指定的偏移地址就是代码应该存放并执行的地址。<br>
<div class="spctrl"></div>　　内核启动参数设置<br>
<div class="spctrl"></div>　　经过修改后，S3C2410x开发板能从Nand Flash中启动运行Linux，也能从Nor 
Flash中启动，所以相应地也要修改启动命令，如下所示：<br>
<div class="spctrl"></div>　　#ifdef CONFIG_S3C2410_N AND_BOOT<br>
<div class="spctrl"></div>　　char Linux_cmd[] = "noinitrd root=/dev/bon/2 
init=/Linuxrc console=tty0 console=ttyS0 ";<br>
<div class="spctrl"></div>　　#else<br>
<div class="spctrl"></div>　　char Linux_cmd[] = "noinitrd root=/dev/mtdblock/3 
init=/Linuxrc console=tty0 console=ttyS0";<br>
<div class="spctrl"></div>　　#endif<br>
<div class="spctrl"></div>　　修改并实现Flash驱动<br>
<div class="spctrl"></div>　　移植vivi的最后一步是实现Flash驱动，开发者需要根据自己系统中具体Flash芯片的型号及配置，修改驱动程序，使Flash设备能够在嵌入式系统中正常工作。如果使用的是驱动尚未支持的Flash芯片，只需仿照其他型号，将Flash型号加入该驱动程序即可。<br>
<div class="spctrl"></div>　　修改Flash驱动的关键一步是对flash. c文件的修改。flash. c是读、写和删除Flash 
设备的源代码文件。 由于不同开发板中Flash 存储器的种类各不相同，所以修改flash. c 时需参考相应的Flash 芯片手册。它包括如下几个函数：<br>
<div class="spctrl"></div>　　unsigned long flash - init(void )，Flash 初始化；<br>
<div class="spctrl"></div>　　void flash - print - info(flash - info - t 
*info)，打印Flash信息；<br>
<div class="spctrl"></div>　　int flash - erase(flash - info - t*info，ints - 
first，ints -last)，Flash 擦除；<br>
<div class="spctrl"></div>　　volatile static int write-hword(flash - info - 
t*info，ulongdest，ulong data)，Flash 写入；<br>
<div class="spctrl"></div>　　int write - buff(flash - info - t *info，uchar 
*src，ulongaddr，ulong cnt)，从内存复制数据。<br>
<div class="spctrl"></div>　　当做好上述的移植工作后，就能对vivi进行编译了。在编译vivi之前，需要根据开发板进行适当的配置。保存并退出后，执行&#8220;make&#8221;命令开始编译。把编译好的vivi烧到Nor 
Flash中，加电重启开发板就能运行vivi了。<br>
<div class="spctrl"></div>　　结语<br>
<div class="spctrl"></div>　　Bootloader是操作系统和硬件的枢纽，相对于操作系统内核来说，它是一个硬件抽象层。它负责初始化硬件，引导操作系统内核，检测各种参数给操作系统内核使用。一个功能完备的大型Bootloader的工作量，相当于一个小型的操作系统。在嵌入式领域中，操作系统移植的关键在于Bootloader的移植和操作系统内核硬件相关部分的移植。嵌入式Linux操作系统作为开发嵌入式产品的首选，为其选择一款合适的Bootloader能节省开发时间和资金，本文对于使用vivi启动Linux内核具有较好的参考价值。<div>转载：http://baike.baidu.com/view/856252.html?wtp=tt</div><img src ="http://www.cppblog.com/wolf/aggbug/63919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wolf/" target="_blank">老狼</a> 2008-10-13 20:59 <a href="http://www.cppblog.com/wolf/articles/63919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>