Bootloader的操作模式
大多数 Boot Loader 都包含两种不同的操作模式:"启动加载"模式和"下载"模式,这种区别仅对于开发人员才有意义。但从最终用户的角度看,Boot Loader 的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。
启动加载(Boot loading)模式:这种模式也称为"自主"(Autonomous)模式。也即 Boot Loader 从目标机上的某个固态存储设备上将操作系统加载到 RAM 中运行,整个过程并没有用户的介入。这种模式是 Boot Loader 的正常工作模式,因此在嵌入式产品发布的时侯,Boot Loader 显然必须工作在这种模式下。
下载(Downloading)模式:在这种模式下,目标机上的 Boot Loader 将通过串口连接或网络连接等通信手段从主机(Host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被 Boot Loader 保存到目标机的 RAM 中,然后再被 Boot Loader 写到目标机上的FLASH 类固态存储设备中。Boot Loader 的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用 Boot Loader 的这种工作模式。工作于这种模式下的 Boot Loader 通常都会向它的终端用户提供一个简单的命令行接口。
像 Blob 或 U-Boot 等这样功能强大的 Boot Loader 通常同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行切换。比如,Blob 在启动时处于正常的启动加载模式,但是它会延时 10 秒等待终端用户按下任意键而将 blob 切换到下载模式。如果在 10 秒内没有用户按键,则 blob 继续启动 Linux 内核。
Boot Loader 所支持的 CPU 和嵌入式板
每种不同的 CPU 体系结构都有不同的 Boot Loader。有些 Boot Loader 也支持多种体系结构的 CPU,比如 U-Boot 就同时支持 ARM 体系结构和MIPS 体系结构。除了依赖于 CPU 的体系结构外,Boot Loader 实际上也依赖于具体的嵌入式板级设备的配置。这也就是说,对于两块不同的嵌入式板而言,即使它们是基于同一种 CPU 而构建的,要想让运行在一块板子上的 Boot Loader 程序也能运行在另一块板子上,通常也都需要修改 Boot Loader 的源程序。Boot Loader 的安装媒介
系统加电或复位后,所有的 CPU 通常都从某个由 CPU 制造商预先安排的地址上取指令。比如,基于 ARM7TDMI core 的 CPU 在复位时通常都从地址 0x00000000 取它的第一条指令。而基于 CPU 构建的嵌入式系统通常都有某种类型的固态存储设备(比如:ROM、EEPROM 或 FLASH 等)被映射到这个预先安排的地址上。因此在系统加电后,CPU 将首先执行 Boot Loader 程序。
下图就是一个同时装有 Boot Loader、内核的启动参数、内核映像和根文件系统映像的固态存储设备的典型空间分配结构图。
图 固态存储设备的典型空间分配结构
Boot loader程序流程
系统上电复位后, 在完成各种初始化配置后首先判断0x500地址单元中值是否为0xFF, 如果是,则说明系统从未下载过用户程序, 系统会一直运行Boot loader程序等待PC 机发送下载命令; 如果0x500中的值不是0xFF, 则说明系统中已经下载过用户程序了, 这时候根据0x500中的值来设置定时器T imer2的初值并开始计时, 如果UART2 在指定的自举周期内未接收到PC 机发来的下载命令(说明系统不需要下载程序), 系统会自动跳出Boo tloader程序而去运行已有的用户代码, 如果UART2在自举周期内接收到了下载命令, Boo tloader程序会进入循环状态等待PC机发送数据。如图所示。
图 程序流程图。
如前文所述, PC 机发送的数据是从. hex 文件中提取的, PC机首先发送扩展地址部分, 下位机接收保存后会继续等待接收32个指令字( 96字节)并保存到RAM 中, 然后根据接收到的地址擦除FLASH 存储器中的1行, 擦除FLASH 是通过调用汇编函数E raseMem来进行的, 函数原型如下:
mov# 0x4041, NVMCON ; 使NVMCON 寄存器为擦除FLASH模式
mov # 0x55, W 0
movW0, NVMKEY
mov # 0xAA, W0
movW 0, NVMKEY ; 将0x55、0xAA 写入密钥寄存器
bsetNVMCON, #WR ; 开始擦除
nop
nop
return
擦除FLASH存储器的一行后需要把接收到的32个指令字写入到FLASH 存储器写锁存器中, 这一过程可以通过函数W riteLatch 实现, 函数原型如下:
movW0, TBLPAG ; 写表寄存器
tb lw tlW3, [W1]
tb lw thW2, [W1] ; 写入锁存器
return
这一步完成之后就可以将接收到的32个指令字写入FLASH 存储器了, 其方法与擦除FLASH 类似, 写完一行后向PC 机发送应答。待FLASH 存储器全部写完之后, PC 机会发送表示结束下载的命令, 下位机接收后退出Boo tloader程序, 进入新的用户程序继续运行, 从而完成整个在线自编程过程。