; 我们假设在编译镜像文件时设定的ro-base地址为 0xc008000, 镜像文件实际烧入到flash的的起始地址为0
; 一般情况下, 编译镜像文件是设定的地址要和镜像文件实际烧入的地址一致, 程序才可以正确运行
; 如果不一致, 就要在初始化程序中加入特殊的代码, 将镜像文件有实际烧入的地方拷贝到编译文件时所指定的地址
; 下面的这段代码完成的就是这个工作
; ResetEntry 复位入口, 镜像文件头在flash中的实际地址
; BaseOfROM 编译镜像文件时设定的ro-base
IMPORT |Image$$RO$$Base| ; ROM code start
IMPORT |Image$$RO$$Limit| ; RAM data starts after ROM program
IMPORT |Image$$RW$$Base| ; Pre-initialised variables
IMPORT |Image$$ZI$$Base| ; uninitialised variables
IMPORT |Image$$ZI$$Limit| ; End of variable RAM space
BaseOfROM DCD |Image$$RO$$Base|
TopOfROM DCD |Image$$RO$$Limit|
BaseOfBSS DCD |Image$$RW$$Base|
BaseOfZero DCD |Image$$ZI$$Base|
EndOfBSS DCD |Image$$ZI$$Limit|
;********************************************************************************************************
; Copy and paste RWdata/zero initialized data
;********************************************************************************************************
; ADR与LDR区别
; ADR R0, ResetEntry 与 LDR R0, =ResetEntry等效
; LDR R0, ResetEntry 读入的是 ResetEntry 地址处的内容
; ADR为伪指令
ADR R0, ResetEntry ; R0为Flash地址
LDR R1, BaseOfROM ; ro_base地址(编译指定)
CMP R0, R1 ; 判断烧写地址和编译地址是否一致
LDREQ R0, TopOfROM ; 若一致的话跳过该部分, 直接初始化RAM
BEQ InitRamData
;********************************************************************************************************
; 计算拷贝程序在flash中的实际位置
;********************************************************************************************************
LDR R2, =CopyProcBeg ; R2 <=> CopyProcBeg程序编译地址
; 拷贝程序首地址
SUB R1, R2, R1 ; CopyProcBeg相对偏移量
ADD R0, R0, R1 ; R0 <=> CopyProcBeg程序Flash地址
LDR R3, =CopyProcEnd ; R3 <=> CopyProcEnd程序编译地址
;********************************************************************************************************
; 将拷贝程序(CopyProcBeg)复制到RAM中
; R0 <=> CopyProcBeg(Flash地址)
; R2 <=> CopyProcBeg(编译地址)
; R3 <=> CopyProcEnd(编译地址)
;********************************************************************************************************
0 LDMIA R0!, {R4-r7} ; 从Flash读出CopyProcBeg
STMIA R2!, {R4-r7} ; 拷贝到CopyProcBeg编译地址
CMP R2, R3
BCC %B0
;********************************************************************************************************
; 开始用RAM中的拷贝程序复本将所有剩下的代码复制到RAM中
;********************************************************************************************************
LDR R3, TopOfROM ; 调用拷贝来的程序赋值剩余的代码
LDR PC, =CopyProcBeg
;********************************************************************************************************
; 拷贝CopyProcEnd以后的代码
; 本段将代码由实际烧入的地址拷贝到ro-base所指定的位置
; R0 <=> CopyProcEnd(Flash地址)
; R2 <=> CopyProcEnd(编译地址)
; R3 <=> TopOfROM(编译地址), 限制拷贝数量
;********************************************************************************************************
CopyProcBeg
0 LDMIA R0!, {R4-R11}
STMIA R2!, {R4-R11}
CMP R2, R3
BCC %B0
CopyProcEnd
;********************************************************************************************************
; R2 <==> TopOfROM之后的位置, 因为它每次都加32,最后一次加32的时候,不一定正好等于TopOfROM的值
; 所以此时进行如下校正, 之后R0指向Flah中RW区的实际位置
;********************************************************************************************************
SUB R1, R2, R3 ; 计算误差值
SUB R0, R0, R1 ; R0指向了Flash中的RW实际位置
;********************************************************************************************************
; 开始初始化RAM数据
; R0 <=> RW区地址(可能是Flash地址)
;********************************************************************************************************
InitRamData
LDR R2, BaseOfBSS
LDR R3, BaseOfZero
CMP R0, R2 ; 比较指定的加载RW地址是否与运行时的RW地址相同
BEQ %F1 ; 如果R0=R2, 则不需要拷贝, 直接跳转到1
0
CMP R2, R3
LDRCC R1, [R0], #4
STRCC R1, [R2], #4
BCC %B0
1
LDR R3, EndOfBSS
MOV R0, #0
2
CMP R2, R3
STRCC R0, [R2], #4
BCC %B2
【2008-03-05】
文章评论(0条评论)
登录后参与讨论