arm-linux移植手记(二)boot loader移植(上)

        arm-linux移植的全过程有些缓慢啊,这么久了才到这里,不过就在这样的空闲中慢慢学习了。其中遇到的些问题,让自己一步步认识,相信后面会越来越快了。回过头来,突然发现没说清楚自己要干什么。其实就是想尝试一下,如果拿到一块板子,没有系统,是怎样把linux内核及其文件系统移植上去的。主要过程,目前个人认为应该是(一)编译环境的搭建,主要就是交叉工具链;(二)boot loader移植;(三)linux内核移植;(四)相关驱动移植;(五)文件系统;最后应该就是相应的应用了吧。针对的板子是mini2440,主机PC使用debian6.0,原厂编译环境主机是在fedora 11下,两个操作系统都在windows xp下虚拟机中。本系列主要是熟悉流程,对内部原因及具体的修改则没有去深入理解,好了,虽然没什么人看,还是言归正传了。
    在此,bootloader主要是移植了u-boot,并使用了前文自己编译的gcc测试通过,可通过板子的nand flash自启动到原yaffs2文件系统,主要参照《u-boot-2010-06在mini2440上的移植》和《mini2440之U-boot移植详细手册-20100419.pdf》,可以说一步一步来的。为了完整还是分上中下来写,上:介绍写基本理论及步骤  中:记录具体的过程   下:记录遇到的问题及解决方法,自己选择的看吧。
    
    基础知识:《嵌入式系统 Boot Loader 技术内幕》
    不好意思的照抄加上点个人感受。其实从我的移植过程看和嵌入式linux系统从软件角度看非常类似啊:
    1.引导加载程序。包括固化在固件(firmware)中的 boot 代码(可选),和 Boot Loader 两大部分。
    2. Linux 内核。特定于嵌入式板子的定制内核以及内核的启动参数。
    3. 文件系统。包括根文件系统和建立于 Flash 内存设备之上文件系统。通常用 ram disk 来作为 root fs。(现在随着flash设备的容量扩大读写速度快,似乎对压缩不再有那么必然的需求了。)
    4. 用户应用程序。特定于用户的应用程序。有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面。常用的嵌入式 GUI 有:MicroWindows 和 MiniGUI 懂。
    引导加载程序是系统加电后运行的第一段软件代码。回忆一下 PC 的体系结构我们可以知道,PC 机中的引导加载程序由 BIOS(其本质就是一段固件程序)和位于硬盘 MBR(主引导记录) 中的 OS Boot Loader(比如,LILO 和 GRUB 等)一起组成。BIOS 在完成硬件检测和资源分配后,将硬盘 MBR 中的 Boot Loader 读到系统的 RAM 中,然后将控制权交给 OS Boot Loader。Boot Loader 的主要运行任务就是将内核映象从硬盘上读到 RAM 中,然后跳转到内核的入口点去运行,也即开始启动操作系统。
    而在嵌入式系统中,通常并没有像 BIOS 那样的固件程序(注,有的嵌入式 CPU 也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由 Boot Loader 来完成。比如在一个基于 ARM7TDMI core 的嵌入式系统中,系统在上电或复位时通常都从地址 0x00000000 处开始执行,而在这个地址处安排的通常就是系统的 Boot Loader 程序。
    Boot Loader的概念:
    简单地说,Boot Loader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
通常,Boot Loader 是严重地依赖于硬件而实现的,特别是在嵌入式世界。因此,在嵌入式世界里建立一个通用的 Boot Loader 几乎是不可能的。尽管如此,我们仍然可以对 Boot Loader 归纳出一些通用的概念来,以指导用户特定的 Boot Loader 设计与实现。
    抄了这么多了,还有很多,都抄上没意思了。还是自己详细去看吧。现在已经有了这个概念,那么分析下吧,boot loader既然是启动的第一段代码,完成硬件的初始化,包括屏蔽中断,设置cpu的速度,ram等,那么肯定不同体系结构的cpu或者说不同型号的cpu可能的设置过程都不一样,以及ram等(这些可以从数据手册上看,步骤值都是有区别的),因此限制了boot loader的通用性,但是从u-boot(一种开源的boot loader)看,它还是支持了很多的cpu体系结构,包括常见的ARM,MIPS,power pc,avr等,因此,只要遵循一定的惯例,再从软件的层次上抽象,还是有其通用性的。因此可以把boot loader分两个层次,底层肯定是和具体硬件相关的,在移植的时候一般要更改,比如针对特定的cpu、ram、flash等的读写,将自己拷贝到ram中,准备上层的运行环境;上层功能丰富,利用底层提供的接口进行操作,同时可以利用串口等于主机交互,进行命令操作等。也不是我想到的仅是点感受,下面继续抄人家的。
    先看boot loader在固态存储设备的典型空间分配结构
     arm-linux移植手记(二)boot loader移植(上)_第1张图片
    从操作系统的角度看,Boot Loader 的总目标就是正确地调用内核来执行。
    另外,由于 Boot Loader 的实现依赖于 CPU 的体系结构,因此大多数 Boot Loader 都分为 stage1 和 stage2 两大部分。依赖于 CPU 体系结构的代码,比如设备初始化代码等,通常都放在 stage1 中,而且通常都用汇编语言来实现,以达到短小精悍的目的。而 stage2 则通常用C语言来实现,这样可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。
    Boot Loader 的 stage1 通常包括以下步骤(以执行的先后顺序):
硬件设备初始化。 
为加载 Boot Loader 的 stage2 准备 RAM 空间。 
拷贝 Boot Loader 的 stage2 到 RAM 空间中。 
设置好堆栈。
跳转到 stage2 的 C 入口点。 
    Boot Loader 的 stage2 通常包括以下步骤(以执行的先后顺序):
初始化本阶段要使用到的硬件设备。 
检测系统内存映射(memory map)。 
将 kernel 映像和根文件系统映像从 flash 上读到 RAM 空间中。 
为内核设置启动参数。 
调用内核。
    具体些:
    在stage1:屏蔽所有的中断,设置 CPU 的速度和时钟频率,RAM 初始化,初始化 LED,关闭 CPU 内部指令/数据 cache,为加载 stage2 准备 RAM 空间,拷贝 stage2 到 RAM 中;
    stage2:初始化本阶段要使用到的硬件设备,包括串口、led等,检测系统的内存映射,加载内核映像和根文件系统映像;
    这样,我们的移植步骤也就出来了:肯定主要是改stage1的了,把针对我们板子的地方修改下,也就是中断的屏蔽,cpu速率,ram以及是从nand flash还是nor flash,根据特定的芯片手册来初始化,具备读写功能;在stage2上完善我们需要使用的命令,以及增加我们要使用的驱动,例如移植u-boot,我想要用网络功能,那么就得有网卡驱动吧。(现在看来选常见的芯片要省我们多少事情啊。。。。!!!!)。
    照抄文章:《嵌入式系统 Boot Loader 技术内幕》  http://www.ibm.com/developerworks/cn/linux/l-btloader/

你可能感兴趣的:(linux,Debian,Flash,嵌入式,任务,linux内核)