📄 bootloader.s
字号:
;** 函数名称: ChipRemapInterRam ChipRemapExtRam
;** 功能描述: 向量复制到指定的存储区
;**
;** 参 数: None
;**
;** 返 回 值: None
;**
;** 作 者: 罗辉联
;** 日 期: 2006年6月10日
;**-------------------------------------------------------------------------------------------------------
;** 修 改 人:
;** 日 期:
;**------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
EXPORT REMAP_InterRam
REMAP_InterRam
MOV R10, LR ;//函数返回地址保存在R10中
MOV R8, #REMAP_INTER_RAM_BASE ;//映射后内部RAM的地址0x0
ADD R9, PC,#-(8+.-InitVectors) ;//读值处(相对)
LDMIA R9!, {R0-R7} ;//读8个异常向量
STMIA R8!, {R0-R7} ;//写到目标地址
LDMIA R9!, {R0-R7} ;//读8个异常处理函数地址
STMIA R8!, {R0-R7} ;//函数地址写到目标地址
MOV PC, R10 ;//程序返回
EXPORT REMAP_ExtRam
REMAP_ExtRam
MOV R10, LR ;//函数返回地址保存在R10中
MOV R8, #REMAP_EXT_RAM_BASE ;//映射后内部RAM的地址0x0
ADD R9, PC,#-(8+.-InitVectors) ;//读值处(相对)
LDMIA R9!, {R0-R7} ;//读8个异常向量
STMIA R8!, {R0-R7} ;//写到目标地址
LDMIA R9!, {R0-R7} ;//读8个异常处理函数地址
STMIA R8!, {R0-R7} ;//函数地址写到目标地址
MOV PC, R10 ;//程序返回
;//*******************************************************************************************************
;//
;// REMAP 选项定义
;//
;// 根据STARM的映射规则,定义不同的映射编译开关
;//
;//
;//*******************************************************************************************************
; GBLL remapping ;//如果进入MAIN前需要映射存储器,定义此逻辑变量
; GBLL remap_ram ;//如果需要将内部RAM映射到0x0000,定义此逻辑变量
; GBLL remap_flash ;//如果需要将内部FLASH映射到0x0000,定义此逻辑变量
; GBLL remap_ext ;//如果需要将外部存储器映射到0x0000,定义此逻辑变量
;/*********************************************************************************************************
;** 函数名称: INT_Initialize
;** 功能描述: 复位入口
;**
;** 参 数: 无
;**
;** 返 回 值: 无
;**
;** 作 者: 罗辉联
;** 日 期: 2006年5月30日
;**-------------------------------------------------------------------------------------------------------
;** 修 改 人:
;** 日 期:
;**------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
EXPORT INT_Initialize
INT_Initialize
ENTRY ;//程序入口点
;{
LDR PC, =NextInst
NextInst
NOP ;//等待OSC稳定,此时使用XTAL的频率
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
; 保证处理器处于管理模式
MRS a1,CPSR ;//获得当前的CPSR
BIC a1,a1,#MODE_MASK ;//清除当前的工作模式位
ORR a1,a1,#SVC_MODE ;//设置管理模式位
ORR a1,a1,#NoInt ;//保证IRQ/FIQ处于禁止状态
MSR CPSR_cxsf,a1 ;//设置新的CPSR
BL ChipResetInit ;//ARM芯片复位初始化,在ChipReset.s中定义
IF :DEF: remapping ;//重映射选择
IF :DEF: remap_flash
MOV r0, #REMAP_INTER_FLASH
ENDIF
IF :DEF: remap_ram
MOV r0, #REMAP_INTER_RAM
ENDIF
IF :DEF: remap_ext
MOV r0, #REMAP_EXT_MEMORY
ENDIF
LDR r1, =CPM_BASE_ADDR
LDRH r2, [r1, #BOOTCR_OFF_ADDR] ;//读取BOOTCR值
BIC r2, r2, #0x03 ;//复位BOOTCR的低两位
ORR r2, r2, r0
STRH r2, [r1, #BOOTCR_OFF_ADDR] ;//写映射类型值
ENDIF
;初始化各种数据(主要是全局变量),把已初始化的数据从ROM中复制到RAM中,并在RAM中建立ZI数据段,包含那些未初始化的数据
LDR a1, =|Image$$RO$$Limit| ;//引入RO数据段的起始地址
LDR a2, =|Image$$RW$$Base| ;//引入RW数据段的起始地址
LDR a4, =|Image$$ZI$$Base| ;//引入ZI数据段的起始地址
CMP a1, a2 ;//需要从ROM复数据制到RAM吗
BEQ BSS_Clear ;//处理ZI数据段还是复制数据
;将初始化的数据从ROM复制到RAM中
ROM_copy_loop
CMP a2, a4 ;//需要需要复制数据吗
LDRCC a3, [a1], #4 ;//从ROM获得需要复制的数据
STRCC a3, [a2], #4 ;//将复制的数据存储在RAM区
BCC ROM_copy_loop ;//继续复制数据
;初始化ZI数据段
BSS_Clear
LDR a2, =|Image$$ZI$$Limit| ;//引入ZI数据段的结束地址
MOV a3, #0 ;//设置清除初始值
BSS_RAM_Clear_Loop
CMP a4, a2 ;//比较ZI数据段(BBS)的开始地址和结束地址是否相等?
STRCC a3, [a4], #4 ;//清除一个字
BCC BSS_RAM_Clear_Loop ;//判断是否清除完毕
;建立各种数据栈,其起始地址紧接在ZI数据段(BBS)的尾部,所以在建立各种数据栈之前,应该初始化好ZI数据段(BBS
BSS_End_Ptr
DCD |Image$$ZI$$Limit|
;建立系统模式下的数据栈-------堆栈的首地址来自于ZI(初始化为零的数据段)段的结束地址之后
LDR a1,[pc, #BSS_End_Ptr-.-8] ;// 获得ZI数据段(BSS)结束的地址
MOV a2,#SYS_STACK_SIZE ;// 获得系统堆栈大小(1024byte)
SUB a2,a2,#4 ;// Subtract one word for first addr
ADD a3,a1,a2 ;// 设置系统堆栈区间
BIC a3,a3,#3 ;// 保证堆栈字对齐
;确定系统堆栈的界限
MOV v7,a1 ;// Setup initial stack limit
LDR a4,[pc, #System_Limit-.-8] ;//获得系统堆栈最高地址
STR v7,[a4, #0] ;// Save stack limit
MOV sp,a3 ;// Setup initial stack pointer
LDR a4,[pc, #System_Stack-.-8] ;// 获得系统堆栈地址
STR sp,[a4, #0] ;// 保存System_Stack堆栈指针
;建立IRQ模式下的数据栈
MOV a2,#IRQ_STACK_SIZE ;// 获得 IRQ 堆栈大小(512byte)
ADD a3,a3,a2 ;// 分配 IRQ 堆栈区域
BIC a3,a3,#3 ;// 保证字对齐
MRS a1,CPSR ;// 获得当前 CPSR 的值
BIC a1,a1,#MODE_MASK ;// 清除当前的工作模式位
ORR a1,a1,#IRQ_MODE ;// 设置中断模式位
MSR CPSR_cxsf,a1 ;// 写入 IRQ 模式位值
MOV sp,a3 ;// 设置中断模式堆栈
;建立FIQ模式下的数据栈
MOV a2,#FIQ_STACK_SIZE ;// 获得 FIQ 堆栈大小(512byte)
ADD a3,a3,a2 ;// 分配 FIQ 堆栈区域
BIC a3,a3,#3 ;// 保证字对齐
MRS a1,CPSR ;// 获得当前 CPSR 的值
BIC a1,a1,#MODE_MASK ;// 清除当前的工作模式位
ORR a1,a1,#FIQ_MODE ;// 设置快速中断模式位
MSR CPSR_cxsf,a1 ;// 写入 FIQ 模式位值
MOV sp,a3 ;// 设置快速中断模式堆栈
;建立ABORT模式下的数据栈
MRS a1,CPSR ;//获得当前 CPSR 的值
BIC a1,a1,#MODE_MASK ;//获得当前 CPSR 的值
ORR a1,a1,#ABT_MODE ;//设置 Abort 模式位
MSR CPSR_cxsf,a1 ;//写入 Abort 模式位值
LDR sp,Exception_Stack ;//设置 Abort 模式堆栈
;建立UNDEF模式下的数据栈
MRS a1,CPSR
BIC a1,a1,#MODE_MASK
ORR a1,a1,#UNF_MODE
MSR CPSR_cxsf,a1
LDR sp,Exception_Stack
;返回到管理模式
MRS a1,CPSR ;// 获得当前 CPSR 的值
BIC a1,a1,#MODE_MASK ;// 清除当前的工作模式位
ORR a1,a1,#SVC_MODE ;// 设置管理模式位
MSR CPSR_cxsf,a1 ;// 所有中断堆栈设置完成,返回到管理模式
;/*-------------------------------------------------------------------------------------------------------
;** 建立定时器高级中断服务所需的数据栈
;** 初始化定时器高级中断服务中需要用到的变量----方便管理定时器高级中断服务程序
;**------------------------------------------------------------------------------------------------------*/
; TMD_HISR_Stack_Ptr = (VOID *) a3;
; TMD_HISR_Stack_Size = TIMER_SIZE;
; TMD_HISR_Priority = TIMER_PRIORITY;
;设置定时器高级中断服务(HISR)堆栈指针 TMD_HISR_Stack_Ptr = (VOID *) a3;
LDR a4,[pc,#HISR_Stack_Ptr-.-8] ;//获得定时器高级中断服务(HISR)的堆栈指针
ADD a3,a3,#4 ;//向后移动一个字的空间
STR a3,[a4, #0]
;设置定时器高级中断服务(HISR)堆栈大小 TMD_HISR_Stack_Size = TIMER_SIZE;
MOV a2,#TIMER_SIZE ;//获得定时器高级中断服务(HISR)的stack size
BIC a2,a2,#3 ;//保证字对齐
ADD a3,a3,a2 ;//从可获取的内存中为定时器高级中断服务程序分配堆栈空间
LDR a4,[pc,#HISR_Stack_Size-.-8]
STR a2,[a4, #0] ;//保存堆栈指针
;设置定时器高级中断服务的优先级(初始化时设为最低) TMD_HISR_Priority = TIMER_PRIORITY;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -