按照gooogleman老兄的建议,从优龙2440板子的bootloader学起。首先先将程序运行起来,step执行,搞清楚每步做了什么,为什么这么做。将整体的流程学习一遍。等1个月,2个月,无论多长时间,当自己真正掌握后,再将整体的代码加上注释,做成PDF文档。分给后来者,去帮助像我现在这样水平的小小鸟。
OK,第一话开始:
程序入口点:
程序最开始跳到2440init.s文件,执行如下代码:b ResetHandler 跳转到复位异常处理程序。
ResetHandler
ldr r0,=WTCON ;watch dog disable
ldr r1,=0x0
str r1,[r0]
(将看门狗定时器清零,查看datasheet,WTCON的第0位是看门狗定时器复位输出信号开关。为0,则程序关闭了S3C2440A的看门狗复位功能。)
ldr r0,=INTMSK
ldr r1,=0xffffffff ;all interrupt disable
str r1,[r0]
(将中断屏蔽寄存器全部置1,将对应的中断全部关闭。)
ldr r0,=INTSUBMSK
ldr r1,=0x7fff ;all sub interrupt disable `
str r1,[r0]
(将子中断屏蔽寄存器全不置1,将子中断屏蔽寄存器对应的中断全部关闭。)
ldr r0,=LOCKTIME
ldr r1,=0xffffff
str r1,[r0]
(LOCKTIME是锁定时间计数寄存器,分别设定了UPLL 对于UCLK 的锁定时间计数值和
MPLL对于FCLK、HCLK、PCLK的锁定时间计数值。具体查看datasheet第7章时钟部分。)
[ PLL_ON_START
; Added for confirm clock divide. for 2440.
; Setting value Fclk:Hclk:Pclk
ldr r0,=CLKDIVN
ldr r1,=CLKDIV_VAL ; 0=1:1:1, 1=1:1:2, 2=1:2:2, 3=1:2:4, 4=1:4:4, 5=1:4:8, 6=1:3:3, 7=1:3:6.
str r1,[r0]
(这里先明确一下,在ADS下的bootloader代码常看到
[
|
]
他们其实就相当于c语言里面的
Ifdef
Else
Endif)
(CLKDIVN是时钟分频器控制寄存器,设置的值为CLKDIV_VAL宏。我这里设置的是CLKDIV_VAL EQU 5 ;1:4:8)
继续执行:
[ CLKDIV_VAL>1 ; means Fclk:Hclk is not 1:1.
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000;R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
|
mrc p15,0,r0,c1,c0,0
bic r0,r0,#0xc0000000;R1_iA:OR:R1_nF
mcr p15,0,r0,c1,c0,0
]
由于我这里CLKDIV_VAL的值为5,所以执行
mrc p15,0,r0,c1,c0,0 <1>
orr r0,r0,#0xc0000000;R1_nF:OR:R1_iA <2>
mcr p15,0,r0,c1,c0,0 <3>
<1> mrc是协处理器命令。用于读取协处理器中的寄存器的数据到ARM处理器的寄存器里面。这句话的意思应该是读协处理器中的寄存器数据到ARM处理器的r0里面。应该是ARM访问MMU,一般cp15就是MMU。这三条指令的目的是将MMU的30,31位置1。
功能如下:31位(iA bit)Function:Asynchronous clock select (选择异步时钟)
30位(nF bit)Function: notFastBus select
未完待续。。。。。