eworker 发表于 2011-3-2 12:11:42

请教LM3S BOOTLOADER代码中“dcd ResetISR - 0x20000000”如何理解?

//*********************************************************
// 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
......

eworker 发表于 2011-3-2 12:28:34

转自网上,全文如下:

揭开BOOT LOAD升级过程的神秘面纱



    在没有接触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                              // Offset 24: Reserved
    dcd   0                              // Offset 28: Reserved
    dcd   UpdateHandler - 0x20000000   // Offset 2C: SVCall handler
    dcd   IntDefaultHandler            // Offset 30: Debug monitor handler
    dcd   0                              // Offset 34: Reserved
    dcd   IntDefaultHandler            // Offset 38: PendSV handler
#if defined(ENET_ENABLE_UPDATE)
    importSysTickIntHandler
    dcd   SysTickIntHandler            // Offset 3C: SysTick handler
#else
    dcd   IntDefaultHandler            // Offset 3C: SysTick handler
#endif
#if defined(UART_ENABLE_UPDATE) && defined(UART_AUTOBAUD)
    importGPIOIntHandler
    dcd   GPIOIntHandler               // Offset 40: GPIO port A handler
#endif
//*********************************************************
// 声明代码段CODE,用于存放代码段
//*********************************************************
    rseg    CODE:CODE(2)
    thumb
//*********************************************************
// 初始化时,把flasn里面的boot loader拷贝到SRAM区,
// 零填充.bss段并从SRAM区向量表开始执行
//*********************************************************
ProcessorInit
    //
    // 把flash 的 boot loader拷贝到SRAM区
    //
    movs    r0, #0x00000000
    ldr   r1, =0x20000000         // SRAM区的起始地址
    ldr   r2, =SFB(.bss)
copy_loop
      ldr   r3, , #4
      str   r3, , #4
      cmp   r1, r2
      blt   copy_loop          // 复制boot loader代码
    //
    // 零填充.bss段
    //
    movs    r0, #0x00000000
    ldr   r2, =SFE(.bss)
zero_loop
      str   r0, , #4
      cmp   r1, r2
      blt   zero_loop

    //
    // 设置中断向量表相对于SRAM区的起始地址的偏移量
    //
    ldr   r0, =0xe000ed08    // 中断向量的起始地址
    ldr   r1, =0x20000000
    str   r1,

    orr   lr, lr, #0x20000000 // 设置向量表偏移寄存器为SRAM底部

    bx      lr               // 跳转到SRAM区执行

//*********************************************************
// 复位中断处理程序
//*********************************************************
    exportResetISR      // 复位中断函数声明
ResetISR

    bl      ProcessorInit   // 调用ProcessorInit汇编代码

    //
    // 看是否有升级信号
    //
    importCheckForceUpdate
    bl      CheckForceUpdate    // 调用升级检测程序
    cbz   r0, CallApplication // 如果检测到没有升级信号.就调用原有的应用程序。
                              // 如果有则继续向下执行

    //
    // 处理器相关配置
    //
#ifdef ENET_ENABLE_UPDATE       // 以太网升级接口配置
    importConfigureEnet
    bl      ConfigureEnet
#elif defined(CAN_ENABLE_UPDATE) // CAN接口升级配置
    importConfigureCAN
    bl      ConfigureCAN
#else
    importConfigureDevice   // 其它接口升级配置如I2C/UART/SSI
    bl      ConfigureDevice
#endif

    //
    //调用升级程序
    //
#ifdef ENET_ENABLE_UPDATE      // 调用以太网升级程序
    importUpdateBOOTP
    b       UpdateBOOTP
#elif defined(CAN_ENABLE_UPDATE) // 调用CAN升级程序
    importUpdaterCAN
    b       UpdaterCAN
#else
    importUpdater            // 其它接口升级程序。开始升级处理了
    b       Updater
#endif

    //
    // 准备调用应用程序
    //
CallApplication                  // 如果没有升级信号就执行这里调应用程序
    ldr   r0, =APP_START_ADDRESS // 应用程序的起始地址加载到R0

    ldr   r1, =0xe000ed08   // 应用程序响量表的地址LM3S系列芯片中断向量是从0Xe000ed08开始的
    str   r0,

    // 从应用程序响量表中读出堆栈指针
    // 堆栈是向量表的一开始位址.LM3S芯片是堆栈的栈顶地址,有些芯片可能是栈底地址,
    // 如果是栈底的话,PC指针就等于SP+堆栈大小+4
    ldr   r1,
    mov   sp, r1

    //
    // 从应用程序响量表中读出PC指针
    //
    ldr   r0,
    bx      r0    // 开始执行应用程序

//*********************************************************
// 升级中断处理程序,这段代码和上面这段代码类似,不加分析。
//*********************************************************
UpdateHandler
    //
    // Initialize the processor.
    //
    bl      ProcessorInit

    //
    // Load the stack pointer from the vector table.
    //
    movs    r0, #0x00000000
    ldr   r0,
    mov   sp, r0

    //
    // Branch to the update handler.
    //
#ifdef ENET_ENABLE_UPDATE
    b       UpdateBOOTP
#elif defined(CAN_ENABLE_UPDATE)
    importAppUpdaterCAN
    b       AppUpdaterCAN
#else
    b       Updater
#endif

//*********************************************************
// 不可屏蔽中断处理程序
//*********************************************************
NmiSR
    b       .   // 死循环
//*********************************************************
// 硬件错误中断处理程序
//*********************************************************
FaultISR
    b       .   // 死循环
//*********************************************************
// 未定义中断处理程序
//*********************************************************
IntDefaultHandler
    b       .   // 死循环
//*********************************************************
// 延时函数
//*********************************************************
    exportDelay
Delay
    subs    r0, #1
    bne   Delay
    bx      lr
//*********************************************************
// 启动文件结束
//*********************************************************
    end

zxy1217 发表于 2011-3-2 12:38:14

好东西 顶个

eworker 发表于 2011-3-2 14:16:27

回复【楼主位】eworker
-----------------------------------------------------------------------

dcd   ResetISR - 0x20000000?

eworker 发表于 2011-3-2 17:13:36

为何要减去0x20000000?

eworker 发表于 2011-3-2 18:41:00

回复【4楼】eworker
为何要减去0x20000000?
-----------------------------------------------------------------------

下班了,顶一下!

touch_avr 发表于 2011-3-3 13:03:13

不是写着,向量表的便宜地址吗?

eworker 发表于 2011-3-3 14:29:34

回复【6楼】touch_avr
不是写着,向量表的便宜地址吗?
-----------------------------------------------------------------------

为何要将中断向量表放到RAM中去?

abo83819 发表于 2011-8-17 15:40:47

mark

NewKing 发表于 2014-2-10 14:20:08

多加学习!

NewKing 发表于 2014-2-10 15:03:34

在看LM4F232,,比这个要复杂些。
页: [1]
查看完整版本: 请教LM3S BOOTLOADER代码中“dcd ResetISR - 0x20000000”如何理解?