;陈锦明 3月10日
;Bootloader的step1,负责简单初始化硬件,屏蔽中断,设置cpu时钟
;为step2准备RAM空间,拷贝搬移step2的代码到RAM,并跳转到main
;应该算是注释够详细的Bootloader了
;参照资料:http://blog.csdn.net/youta_chen/archive/2007/05/07/1599651.aspx
;以及:图书馆405科技阅览室《ARM嵌入式系统典型模块设计》
;还有,当然最主要的参考资料是ARM Manual
;Bootloader的step1,负责简单初始化硬件,屏蔽中断,设置cpu时钟
;为step2准备RAM空间,拷贝搬移step2的代码到RAM,并跳转到main
;应该算是注释够详细的Bootloader了
;参照资料:http://blog.csdn.net/youta_chen/archive/2007/05/07/1599651.aspx
;以及:图书馆405科技阅览室《ARM嵌入式系统典型模块设计》
;还有,当然最主要的参考资料是ARM Manual
 AREA |.text|, CODE, READONLY
EXPORT Bootloader
 
Bootloader
step1
ldr r0, =0x4a000008 ;rINTMSK中断
ldr r1, =0xffffffff ;禁止所有中断
str r1, [r0]
ldr r0, =0x53000000 ;rWTCON 关闭看门狗
ldr r1, =0x0
str r1, [r0]
 
 
;设置CPU的速度和频率
ldr r0, =0x4c000000 ;rLOCKTIME锁定时间计数值寄存器,地址为0x01d8000c
ldr r1, =0xfff ;初始值
str r1, [r0]
 
;设定系统主时钟频率
ldr r0,=UPLLCON
ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)
str r1,[r0];注意,当UPLL设置后,至少需要7个延迟才能让硬件彻底完成设置
nop
nop
nop
nop
nop
nop
nop
;设置 MPLL
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin=16.9344MHz
str r1,[r0]
EXPORT Bootloader
Bootloader
step1
ldr r0, =0x4a000008 ;rINTMSK中断
ldr r1, =0xffffffff ;禁止所有中断
str r1, [r0]
ldr r0, =0x53000000 ;rWTCON 关闭看门狗
ldr r1, =0x0
str r1, [r0]
;设置CPU的速度和频率
ldr r0, =0x4c000000 ;rLOCKTIME锁定时间计数值寄存器,地址为0x01d8000c
ldr r1, =0xfff ;初始值
str r1, [r0]
;设定系统主时钟频率
ldr r0,=UPLLCON
ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)
str r1,[r0];注意,当UPLL设置后,至少需要7个延迟才能让硬件彻底完成设置
nop
nop
nop
nop
nop
nop
nop
;设置 MPLL
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin=16.9344MHz
str r1,[r0]
 str r1, [r0]
ldr r0, =0x4c00000c ;rCLKCON时钟控制寄存器,地址为0x01d80004
ldr r1, =0x7ff8;关闭一些时钟外围设备而保留一些必须的,节省资源
ldr r0, =0x4c00000c ;rCLKCON时钟控制寄存器,地址为0x01d80004
ldr r1, =0x7ff8;关闭一些时钟外围设备而保留一些必须的,节省资源
;初始化堆栈,要对所有不同的模式进行分别初始化,因为对于不同的模式sp寄存器是不同的
mrs r0, cpsr;读取cpsr的状态
bic r0, r0, #MODEMASK ;
orr r1, r0, #UNDEFMODE|NOINT ;UNDEFMODE: 0x1b NOINT: 0xc0, 设为未定义指令终止模式禁止FIQ和IRQ中断
msr cpsr_cxsf, r1
ldr sp, =UndefStack ;0xc7ffb00
orr r1, r0, #ABORTMODE|NOINT
msr cpsr_cxsf, r1 ;数据访问终止模式
ldr sp, =AbortStack ;0xc7ffd00
orr r1, r0, #IRQMODE|NOINT
msr cpsr_cxsf, r1 ;外部中断模式
ldr sp, =IRQStack ;0xc7ffe00
orr r1, r0, #FIQMODE|NOINT
msr cpsr_cxsf, r1 ;快速中断模式
ldr sp, =FIQStack ;0xc7fff00
bic r0, r0, #MODEMASK|NOINT
orr r1, r0, #SVCMODE
msr cpsr_cxsf, r1 ;管理模式
ldr sp, =SVCStack ;0xc7ffb00
mrs r0, cpsr;读取cpsr的状态
bic r0, r0, #MODEMASK ;
orr r1, r0, #UNDEFMODE|NOINT ;UNDEFMODE: 0x1b NOINT: 0xc0, 设为未定义指令终止模式禁止FIQ和IRQ中断
msr cpsr_cxsf, r1
ldr sp, =UndefStack ;0xc7ffb00
orr r1, r0, #ABORTMODE|NOINT
msr cpsr_cxsf, r1 ;数据访问终止模式
ldr sp, =AbortStack ;0xc7ffd00
orr r1, r0, #IRQMODE|NOINT
msr cpsr_cxsf, r1 ;外部中断模式
ldr sp, =IRQStack ;0xc7ffe00
orr r1, r0, #FIQMODE|NOINT
msr cpsr_cxsf, r1 ;快速中断模式
ldr sp, =FIQStack ;0xc7fff00
bic r0, r0, #MODEMASK|NOINT
orr r1, r0, #SVCMODE
msr cpsr_cxsf, r1 ;管理模式
ldr sp, =SVCStack ;0xc7ffb00
 ;RAM初始化
;包括正确地设置系统内存控制器的功能寄存器以及各内存库控制器等共13个需要初始设置的寄存器?
ldr r0, =SMRDATA ;取得这13个寄存器的初始设置段地址
ldmia r0, {r1-r13} ;将13个初始值推入r1-r13中
ldr r0, =0x48000000 ;将r0指向rBWSCON, 地址为0x48000000,
stmia r0, {r1-r13} ;将初始值填入这13个寄存器
;从SMRDATA标号开始的一段连续的地址中存放了这13个寄存器的初始化数据。
;包括正确地设置系统内存控制器的功能寄存器以及各内存库控制器等共13个需要初始设置的寄存器?
ldr r0, =SMRDATA ;取得这13个寄存器的初始设置段地址
ldmia r0, {r1-r13} ;将13个初始值推入r1-r13中
ldr r0, =0x48000000 ;将r0指向rBWSCON, 地址为0x48000000,
stmia r0, {r1-r13} ;将初始值填入这13个寄存器
;从SMRDATA标号开始的一段连续的地址中存放了这13个寄存器的初始化数据。
;为stage2准备RAM空间
;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|
0
ldr r2, BaseOfBSS ;数据段基地址
ldr r3, BaseOfZero ;未初始化的数据段基地址0
cmp r2, r3 ;比较r2,r3的值
ldrcc r1, [r0], #4 ;r2 strcc r1, [r2], #4 r2 bcc %B0 ;跳回标号0处执行,直到r2=r3
mov r0, #0 ;将0装入r0
1
cmp r2, r3 ;比较r2和r3,此时r2值为BaseOfZero
strcc r0, [r2], #4 ;r2 bcc %B1 ;跳回标号1处执行,直到r2=r3
 
;拷贝stage2到RAM
adr r0, MAIN
ldr r2, BaseOfROM
ldr r3, TopOfROM   
;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|
0
ldr r2, BaseOfBSS ;数据段基地址
ldr r3, BaseOfZero ;未初始化的数据段基地址0
cmp r2, r3 ;比较r2,r3的值
ldrcc r1, [r0], #4 ;r2
mov r0, #0 ;将0装入r0
1
cmp r2, r3 ;比较r2和r3,此时r2值为BaseOfZero
strcc r0, [r2], #4 ;r2
;拷贝stage2到RAM
adr r0, MAIN
ldr r2, BaseOfROM
ldr r3, TopOfROM
;这是一个取ROM上的数据,然后不断向RAM搬移的过程 
0
ldmia r0!, {r4-r7}
stmia r2!, {r4-r7}
cmp r2, r3
bcc %B0;无符号数小于
0
ldmia r0!, {r4-r7}
stmia r2!, {r4-r7}
cmp r2, r3
bcc %B0;无符号数小于
;因为是三个寄存器一组,所以,很可能r2的值会在一次操作后比r3大
;此时,r0正好也相差了那么多,所以从r0中减去这些差,就正好了
sub r2, r2, r3 ; r2 超出r3
sub r0, r0, r2 ;确保取得RW区精确起始地址
;初始化SDRAM,将RW段拷贝到SDRAM
ldr r2, BaseOfBSS
ldr r3, BaseOfZero
0
cmp r2, r3
ldrcc r1, [r0], #4
strcc r1, [r2], #4
bcc %B0
;对SDRAM ZI段清零
mov r0, #0
ldr r3, EndOfBSS
;此时,r0正好也相差了那么多,所以从r0中减去这些差,就正好了
sub r2, r2, r3 ; r2 超出r3
sub r0, r0, r2 ;确保取得RW区精确起始地址
;初始化SDRAM,将RW段拷贝到SDRAM
ldr r2, BaseOfBSS
ldr r3, BaseOfZero
0
cmp r2, r3
ldrcc r1, [r0], #4
strcc r1, [r2], #4
bcc %B0
;对SDRAM ZI段清零
mov r0, #0
ldr r3, EndOfBSS
1
cmp r2, r3
strcc r0, [r2], #4
bcc %B1
cmp r2, r3
strcc r0, [r2], #4
bcc %B1
Lable
bl Main ;从汇编进入C语言代码空间
b Lable
bl Main ;从汇编进入C语言代码空间
b Lable
 END
  |