在没有接触BOOTLOAD之前,看着别人搞这“玩意儿”,觉得是一个很有技术含量的事,当细细的去“品”过后,也就是那么一回事,作技术就是要深专,只要“钻”进去了,在某一时刻就会恍然大悟。今天就将我对BOOTLOAD升级过程的理解和大家分享分享。
BOOTLOAD并不是只有arm中才有的,其它的嵌入式系统甚至PC上都会有bootloader,主要的作用就是引导操作系统。在硬件起动后,硬件设备尚未初始化,直接加载体积较大的系统比较困难,有时甚至无法加载,如系统内核在网络上的情况,所以常常在系统运行前,提供一个体积较小但又具体初始化基本软硬件环境的程序来运行,由它来载入系统并设置系统运行参数,并最终运行系统,这就是bootloader。
它可以分为两大类,一类BOOTLOAD是芯片在出厂时,生产商固化在ROM中的BOOTLOAD;二类BOOTLOAD是用户在设计过程中,根据实际工程的需要设计一小段代码,使新的应用程序从非JATG接口引导到ROM区或RAM区。其实这两类在功能上都差不多。本文讨论二类BOOTLOAD,讨论以Cotex-M3内核的LM3S系列处理器为对象。代码和编译器是基于IAR5.11版本。
我们都知道任何程序都是从复位开始执行起走的,BOOTLOAD也不例外。当芯片复位后(软、硬件复位,掉电复位等),系统产生复位中断,执行复位中断服务程序,复位中断的优先级最高,所以不需要考虑有谁可以打断它(专心做它自己的事)。当然,程序员就可以在复位中断里面打芯片的主意了。BOOTLOAD升级应用程序的点子就是从这里出发的(一发不可收拾“坏透了”),它先把自己的BOOTLOAD复制到RAM区,再零填充.bss段(数据段,主要用于存放那些初始化为0的变量和没有初始的自动变量。位于SRAM区)。然后就让向量表的偏移从RAM的起始地址开始算起,LM3Sxxxx是从0x2000 0000开始偏移,到此,开始在RAM区里执行。
在RAM区里执行时,会对升级信号进行检测,如检测到要升级信号,则开始配置要升级的接口(升级前的准备),准备好了就升级应用程序。如果没有检测到升级信号则执行原有的用户应用程序。我们来看看启动代码分析,就知道是怎么回事了。
//*********************************************************
// 包含配置头文件
//*********************************************************
#include "bl_config.h"
//*********************************************************
// 声明.bbs数据段,此段位于RAM区
//*********************************************************
rseg .bss:DATA(2)
//*********************************************************
// 分配存储堆栈
//*********************************************************
g_pulStack ds8 STACK_SIZE * 4
//*********************************************************
// 声明INTVEC段,此段位于ROM区,用于存放下面这一段向量表
//*********************************************************
rseg INTVEC:CONST(2)
//*********************************************************
// Cortex-M3 处理器的简化向量表,也是必要的,
//*********************************************************
export __vector_table
__vector_table
dcd g_pulStack + (STACK_SIZE * 4) // Offset 00: Initial stack pointer
dcd ResetISR - 0x20000000 // Offset 04: Reset handler
dcd NmiSR // Offset 08: NMI handler
dcd FaultISR // Offset 0C: Hard fault handler
dcd IntDefaultHandler // Offset 10: MPU fault handler
dcd IntDefaultHandler // Offset 14: Bus fault handler
dcd IntDefaultHandler // Offset 18: Usage fault handler
dcd 0 // Offset 1C: Reserved
dcd 0 // Offset 20: Reserved
dcd 0