BootLoader代码解析

BootLoader代码解析
ProcessorInit
;
; Copy the code image from flash to SRAM.
;
movs    r0, #0x0000
movs    r1, #0x0000
movt    r1, #0x2000--->movt把0x2000放到r1的⾼16bit
import  ||Image$$SRAM$$ZI$$Base||--->.BSS段的开始地址
ldr    r2, =||Image$$SRAM$$ZI$$Base||
copy_loop
ldr    r3, [r0], #4
str    r3, [r1], #4
cmp    r1, r2
blt    copy_loop
;
; Zero fill the .bss section.
;
movs    r0, #0x0000
import  ||Image$$SRAM$$ZI$$Limit||
ldr    r2, =||Image$$SRAM$$ZI$$Limit||
zero_loop
str    r0, [r1], #4
cmp    r1, r2
blt    zero_loop
;
; Set the vector table pointer to the beginning of SRAM.
;
movw    r0, #(NVIC_VTABLE & 0xffff)栓剂
movt    r0, #(NVIC_VTABLE >> 16)
movs    r1, #0x0000
movt    r1, #0x2000
str    r1, [r0]
;
; Set the return address to the code just copied into SRAM.
;
//此刻lr寄存器中已经存放了返回地址
// 此操作为lr=lr+SRAM address,所以程序直接返回到SRAM中继续运⾏
orr    lr, lr, #0x20000000
;
; Return to the caller.
;
bx      lr
;******************************************************************************
;
; The reset handler, which gets called when the processor starts.
;
;******************************************************************************
export  Reset_Handler
程序是从这⾥开始的
Reset_Handler
;
; Initialize the processor.
;
//bl指令会把下条指令的地址存放到lr寄存器中
bl      ProcessorInit
/
/程序运⾏到这⾥已经被拷贝到SRAM中了
;
; Call the user-supplied low level hardware initialization function
; if provided.
;
if      :def:_BL_HW_INIT_FN_HOOK
import  $_BL_HW_INIT_FN_HOOK
bl      $_BL_HW_INIT_FN_HOOK
endif
;
; See if an update should be performed.
;
import  CheckForceUpdate
bl      CheckForceUpdate
//r0保存CheckForceUpdate函数的返回值
//如果为0表⽰启动APP程序
cbz    r0, CallApplication
CallApplication
;
; Copy the application's vector table to the target address if necessary.
詹金斯; Note that incorrect boot loader configuration could cause this to
; corrupt the code!  Setting VTABLE_START_ADDRESS to 0x20000000 (the start    ; of SRAM) is safe since this will use the same memory that the boot loader
;
already uses for its vector table.  Great care will have to be taken if
; other addresses are to be used.
;
//把APP的VTABLE拷贝到指定addr
//⼀般来说_APP_START_ADDRESS == _VTABLE_START_ADDRESS==0x1000=4K
//⼀般来说程序的开始是VTABLE表,所以程序开始地址肯定是VTABLE地址
//处理不相等的情况
//把APP开始处得VTABLE拷贝到指定地址
if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
movw    r0, #(_VTABLE_START_ADDRESS & 0xffff)
if (_VTABLE_START_ADDRESS > 0xffff)
movt    r0, #(_VTABLE_START_ADDRESS >> 16)
endif
movw    r1, #(_APP_START_ADDRESS & 0xffff)
if (_APP_START_ADDRESS > 0xffff)
movt    r1, #(_APP_START_ADDRESS >> 16)
endif
;
; Calculate the end address of the vector table assuming that it has the
; maximum possible number of vectors.  We don't know how many the app has    ; populated so this is the safest approach though it may copy some non
; vector data if the app table is smaller than the maximum.蒋丞稷
;
movw    r2, #(70 * 4)
adds    r2, r2, r0
VectorCopyLoop
ldr    r3, [r1], #4
str    r3, [r0], #4
科学情人cmp    r0, r2
blt    VectorCopyLoop
endif
//如果_APP_START_ADDRESS == _VTABLE_START_ADDRESS可以省略拷贝
;
; Set the vector table address to the beginning of the application.
;
//在APP程序开始之前⼀定要配置好VTABLE寄存器
movw    r0, #(_VTABLE_START_ADDRESS & 0xffff)
if (_VTABLE_START_ADDRESS > 0xffff)
movt    r0, #(_VTABLE_START_ADDRESS >> 16)
endif
movw    r1, #(NVIC_VTABLE & 0xffff)
movt    r1, #(NVIC_VTABLE >> 16)
str    r0, [r1]
热效率
;
; Load the stack pointer from the application's vector table.
;
//程序开始处是VTABLE
//VTABLE第⼀个entry是STACK地址
movw    r0, #(_APP_START_ADDRESS & 0xffff)
if (_APP_START_ADDRESS > 0xffff)
movt    r0, #(_APP_START_ADDRESS >> 16)
endif
ldr    sp, [r0]
; Load the initial PC from the application's vector table and branch to    ; the application's entry point.
;
//跳转到APP程序中
//APP和BOOT程序各⾃有⼀个VTABLE表
/
/读取应⽤程序中断向量表次4个字节的内容(即reset后的地址)
ldr    r0, [r0, #4]
bx      r0
************************************************************************
关于配置短接升级:
配置升级时IO⼝的极性
#define FORCED_UPDATE_POLARITY  0
配置IO⼝初始化时的电极
#define FORCED_UPDATE_WPU
所以
1:
如果配置UPDATE 0
则配置IO⼝默认为上拉
端⼝短接时升级
2:
碱式碳酸锌如果配置UPDATE 1
则配置IO⼝默认为下拉
端⼝上拉时升级
在CheckForceUpdate函数中
检查如果FLASH中指定ADDR没有APP程序,则强制进⼊UPDATE模式
pulApp = (unsigned long *)APP_START_ADDRESS;
if((pulApp[0] == 0xffffffff) || ((pulApp[0] & 0xfff00000) != 0x20000000) ||
(pulApp[1] == 0xffffffff) || ((pulApp[1] & 0xfff00001) != 0x00000001))
{
return(1);
}
为什么(pulApp[0] & 0xfff00000) != 0x20000000) 表⽰不像栈指针?堆栈⾄少要建⽴在ram区
为什么(pulApp[1] & 0xfff00001) != 0x00000001)表⽰不像reset向量?向量表第⼆项是复位向量,
也就是初始pc值,pc最后⼀位必须为1 否则会进⼊arm模式产⽣fault;
⽽且Vector⼀开始肯定在FLASH中,FLASH 256K⼤⼩,所以地址最⼤=0x40000。所以&操作后⾼位⼀定为0整个BOOTLOADER⼤致流程:
;
bl      ProcessorInit--->把⾃⼰copy到内存中开始运⾏
bl      CheckForceUpdate--->1: FLASH指定地址中是否有APP ,2: IO⼝是否配置为升级操作
cbz    r0, CallApplication--->如果返回0则启动APP
进⼊UPDATE
EnterBootLoader
bl      ConfigureDevice --->开始配置升级接⼝
b      Updater--->进⼊升级循环操作
CallApplication
进⼊APP
烧写APP后的操作。
发送COMMAND_RUN命令直接从APP_ADDRESS启动程序
发送COMMAND_RESET命令直接RESET MCU
应该采⽤第⼆种⽅式,因为直接从APP_ADDRESS启动程序,但是此时VTABLE寄存器还没有配置。

本文发布于:2024-09-24 23:23:48,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/148006.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:程序   地址   开始   配置
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议