了解u-boot之前首先了解下Bootloader,简单说Bootloader就是一段小程序,它在系统上电时开始运行,初始化硬件设备,准备好软件环境,最后调用操作系统内核。
u-boot全称:Universal Boot Loader,即通用Bootloader,遵循GPL条款,开放源码。
支持多种嵌入式操作系统内核:Linux、NetBSD、VxWorks等
支持多个处理器系列:如PowerPC、ARM、x86、MIPS等
u-boot的核心最终目的就是从Flash上读出内核,然后启动内核。如何读出内核,如何启动内核,本系列作一个简要分析。基于JZ2440开发板,S3C2440芯片。
u-boot启动分为两个阶段:
一阶段:
1.硬件设备初始化
2. 加载U-Boot第二阶段代码到SDRAM空间
3. 设置好栈(我后面运行C代码做准备)
4. 跳转到第二阶段C代码入口
二阶段:
1. 初始化本阶段要使用的硬件设备
2. 检测系统内存映射(memory map)
3. 将内核映像(和根文件系统 可选)从Flash上读到RAM空间中
4. 为内核设置启动参数(约定好参数存放地址以及存储格式以便内核去读取)
5. 调用启动内核,内核启动后便于u-boot无关联系了
在分析之前先了解一些概念,了解一下S3C2440从NandFlash和NorFlash启动的区别。
1.嵌入式 Linux 系统软件结构与分布
一般情况下,嵌入式 Linux 系统中的软件主要分为以下几部分:
1) 引导加载程序:其中包括内部 ROM 中的固化启动代码和 BootLoader 两部分。内部固化 ROM 是厂家在芯片生产时候固化的,作用基本上是引导 BootLoader。有的芯片比较复杂,比如 Omap3 在 flash 中没有代码的时候有许多启动方式:USB、 UART 或以太网等等。而 S3C24x0 则很简单,只有 Norboot 和Nandboot。
2) Linux kernel,特定于嵌入式板子的定制内核以及内核的启动参数。内核的启动参数可以是默认的也可以是Bootloader传递给内核的(下图中的 Boot parameters)。
3) 文件系统。 包括根文件系统和建立于 Flash 内存设备之上的文件系统( EXT4、UBI、 CRAMFS等等)。它是提供管理系统的各种配置文件以及系统执行用户应用程序的良好运行环境及载体。
4) 应用程序。 用户自定义的应用程序,存放于文件系统之中。
嵌入式Linux系统典型分区结构如下:
2.SRAM、SDRAM、Nandflash、Norflash的区别:
SRAM:是英文Static RAM的缩写,它是一种具有静止存取功能的内存,不需要刷新电路即能保存它内部存储的数据,速度比SDRAM快,一般用作高速缓冲存储器(Cache)。S3C2440有片内SRAM
SDRAM(Synchronous Dynamic Random Access Memory):同步动态随机存取存储器,同步是指Memory工作需要步时钟,内部的命令的发送与数据的传输都以它为基准;动态是指存储阵列需要不断的刷新来保证数据不丢失;随机是指数据不是线性依次存储,而是由指定地址进行数据读写,简单的说,它就是cpu使用的外部内存,即我们常说的内存条。
Norflash:非易失闪存,是一种外部存储介质,芯片内执行(XIP,eXecute In Place),这样应用程序可以直接在flash闪存内运行,不必再把代码读到系统RAM中,由于它有地址总线,cpu可以直接从norflash中取指,直接从FLASH中运行程序,但是工艺复杂,价格比较贵,容量较小(1~4M),NOR的传输效率很高,cpu可以从Norflash中读取数据,但是写入数据的时候需要指定的命令才能写入,而且每次写入之前都要执行擦除动作,决定了它的运行速度不会太快。
Nandflash:它也是非易失闪存(掉电不丢失)的一种,但是它虽然有数据总线,但是没有地址总线,所以cpu不能直接从NANDFLASH中取指运行,由于它价格便宜,所以常常用来存储大量数据,和我们常说的硬盘类似。
Nandflash价格便宜,可以用来存大量数据u-boot、kernel、rootfs等,而norflash来存储这些价格太昂贵了,Nandflash可读可写,方便开发,所以一般会考虑采用Nandflash启动而不会采用从Norflash启动。
下面将解析S3C2440从nandflash启动和norflash启动两种方式。
一、 Nandflash启动
首先必须把一个正确的bootload烧写到nandflash的最低位置,即从0x000开始烧写。当我们选择从nandflash启动开发板的时候,开发板就会启动连接nandflash的电路结构,当开发板一上电的时候,Nand Flash控制器会自动的把Nand Flash上的前4K数据搬移到CPU的内部RAM中(SRAM),这个内部RAM我们通常称作stepping stone,同时把这段片内SRAM映射到nGCS0片选的空间(即0x00000000),CPU从内部RAM的0x00000000位置开始启动,这个过程不需要程序干涉的。
这个过程就是启动过程的stage1,它将nandflash的前4看内容拷贝到stepping stone中,然后从stepping stone的第一条指令开始执行,这4k内容里面的指令将会完成以下几个动作:
1.硬件设备初始化
2. 加载U-Boot第二阶段代码到SDRAM空间
3. 设置好栈
4. 跳转到第二阶段代码入口
从下图我们可以看到,板子重置以后,内存的映射关系。从图中可以看到以下几点:
1.刚开始bank0~bank5是只能映射SROM的,而bank6和bank7才能够接SDRM,而且每个bank最大接128M的SDRM,所以决定了S3C2440的最大可外接SDRAM是256M;
2.从图中我们可以看到bank6的起始地址是0x3000_0000, 所以我们在执行stage1的第二个动作(加载U-Boot第二阶段代码到SDRAM空间)时,需要将uboot代码放到0x3000_000~0x4000_0000区间内(SDRAM内),才能从SDRAM中正常执行stage2;
3.当没有选择从nandflash启动时,Boot internal SRAM(4k)的起始地址是0x4000_0000, 当选择从nandflash启动时,Boot internal SRAM(4k)的起始地址是0x00, 因为我们的开发板没有外接SROM,所以bank1~bank5都是空闲的,而bank0的位置将被Boot internal SRAM(4k)替代,也就是说bank0的前4k就是stepping stone(起步石),板子上电以后,在nandflash的启动模式下,S3C2440在硬件上会完成下图中的地址映射,并自动将nandflash中的前4k拷贝到stepping stone中,并从stepping stone的开始地址(0x00)获取到第一条指令并执行。
经过上面的分析后,我们可以将上面两图合并成下图所示:
前面说了nandflash启动过程中第一个代码搬移,下面将解析第二个代码搬移,这4k代码首先会设置cpu运行模式,关看门狗,设置时钟,关中断,初始化内存,初始化nandflash,设置堆栈,然后将整个bootload搬运到SDRAM中,并跳转到SDRAM中执行。
基本过程如下图所示:
二、norflash启动
其实理解了nandflash的启动方式,norflash的启动也就好理解多了,首先需要知道的是norflash是可以在片上执行代码(XIP)的,也就是说,我们只需要将bootload烧写到norflash的开始地址,当开发板上电以后,从内存映射图可以知道,nor flash会被映射到0x00000000地址(就是nGCS0,这里就不需要片内SRAM来辅助了,所以片内SRAM的起始地址还是0x40000000,不会改变),然后cpu从0x00000000开始执行(也就是在Norfalsh中执行)整个uboot,直到引导内核启动。
从norflash启动可以省事多了,不仅如此,我们自己编写的裸机程序需要调试,一般也是直接烧写到norflash中进行的,因为只要我们将编译好的可执行文件放到norflash的开始,开发板上电以后就会从norflash的第一条指令开始取指执行,我们后面写裸机程序的调试就是用这种方式进行的。
从norflash启动虽然从开发的角度会很方便(其实也方便不了多少),但是从产品的角度却增加了它的成本,毕竟norflash还是相对较贵的,我们明明只要一块nandflash就足够启动整个开发板了,就没必要在产品中添加一块norflash了,只要代码改改就能省下不少成本,何乐不为。而且nandflash对产品是必不可少的,因为后面还要存放内核和文件系统,起码需要几十兆的空间,用norflash来存储也不现实。
目前说到这里,后面结合代码来具体分析u-boot的功能。