菜鸟学习S3C2440bootloader第三话

来源:互联网 发布:java输出汉字 编辑:程序博客网 时间:2024/04/28 10:12

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;       When EINT0 is pressed,  Clear SDRAM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; check if EIN0 button is pressed

 

       ldr   r0,=GPFCON

       ldr   r1,=0x0

       str   r1,[r0]

       ldr   r0,=GPFUP

       ldr   r1,=0xff

       str   r1,[r0]

 

       ldr   r1,=GPFDAT

       ldr   r0,[r1]

       bic   r0,r0,#(0x1e<<1)  ; bit clear

       tst    r0,#0x1

       bne %F1

 

; Clear SDRAM Start

 

       ldr   r0,=GPFCON

       ldr   r1,=0x55aa

       str   r1,[r0]

;      ldr   r0,=GPFUP

;      ldr   r1,=0xff

;      str   r1,[r0]

       ldr   r0,=GPFDAT

       ldr   r1,=0x0

       str   r1,[r0]     ;LED=****

 

       mov r1,#0

       mov r2,#0

       mov r3,#0

       mov r4,#0

       mov r5,#0

       mov r6,#0

       mov r7,#0

       mov r8,#0

      

       ldr   r9,=0x4000000   ;64MB

       ldr   r0,=0x30000000

0    

       stmia       r0!,{r1-r8}

       subs r9,r9,#32

       bne  %B0

 

;Clear SDRAM End

 

1

 

       ;Initialize stacks

       bl     InitStacks

接下来是这段比较长的代码,总体的作用就是,如果 EINT0 产生(这中断就是我们按键产生的), 就清除SDRAM。分析之前先搞清一个知识点,这段代码里面有一个bne %B0,还有一个bne    %F1,这两句代码是什么意思呢?%B代表向前搜索,%F代表向后搜索,“0”“1”只是标号而已。也就是不等于则向前后者向后跳转到标号0或者标号1的位置。

       ldr   r0,=GPFCON

       ldr   r1,=0x0

       str   r1,[r0]

GPF0-GPF7都被设置成了input

       ldr   r0,=GPFUP

       ldr   r1,=0xff

       str   r1,[r0]

GPF0-GPF7都被禁止上拉。

       ldr   r1,=GPFDAT

       ldr   r0,[r1]

       bic   r0,r0,#(0x1e<<1)  ; bit clear

       tst    r0,#0x1

       bne %F1

这段代码则是检测EINT0的输入。有输入则清空SDRAM,没输入就直接向下跳到标号1处。再来看bic指令。举个例子,BIC  R1,R2,R3则是将R3的反码和R2逻辑与,结果保存到R1。这里为什么是0x1e,我也不是很理解。反正0x1e倒是可以。一会到CSDN去发帖。弄清楚了,再补充进来。tst       r0,#0x1这段指令就是测试最低位是否为0.

; Clear SDRAM Start

 

       ldr   r0,=GPFCON

       ldr   r1,=0x55aa

       str   r1,[r0]

;      ldr   r0,=GPFUP

;      ldr   r1,=0xff

;      str   r1,[r0]

       ldr   r0,=GPFDAT

       ldr   r1,=0x0

       str   r1,[r0]     ;LED=****

 

       mov r1,#0

       mov r2,#0

       mov r3,#0

       mov r4,#0

       mov r5,#0

       mov r6,#0

       mov r7,#0

       mov r8,#0

      

       ldr   r9,=0x4000000   ;64MB

       ldr   r0,=0x30000000

0    

       stmia       r0!,{r1-r8}

       subs r9,r9,#32

       bne  %B0

 

;Clear SDRAM End

这段代码则是清空SDRAM

       ldr   r0,=GPFCON

       ldr   r1,=0x55aa

       str   r1,[r0]

GPF0-GPF3设置为中断EINT0-EINT3GPF4-GPF7设置为输出。

;      ldr   r0,=GPFUP

;      ldr   r1,=0xff

;      str   r1,[r0]

全部禁止上拉。

       ldr   r0,=GPFDAT

       ldr   r1,=0x0

       str   r1,[r0]

GPFDAT全部置0.GPF4-GPF7输出低电平。

       mov r1,#0

       mov r2,#0

       mov r3,#0

       mov r4,#0

       mov r5,#0

       mov r6,#0

       mov r7,#0

       mov r8,#0

r1-r8寄存器内容设置为0,用来做清空SDRAM用的。

       ldr   r9,=0x4000000   ;64MB

       ldr   r0,=0x30000000

0    

       stmia       r0!,{r1-r8}

       subs r9,r9,#32

       bne  %B0

r9中装入的值是SDRAM的容量大小,r0中装入的值是SDRAM的首地址。

0    

       stmia       r0!,{r1-r8}

       subs r9,r9,#32

       bne  %B0

这段代码用来循环清零,直到SDRAM全部清空为止。

1

       ;Initialize stacks

       bl     InitStacks

当然如果在代码前段,没有按下按键的话,就直接跳到标号1处的这段代码,跳转到初始化堆栈的地方了。事实上,基本不会在此处按下按键,所以清空SDRAM的代码基本不会执行。

       接着向下看:

       mrs  r0,cpsr

       bic   r0,r0,#MODEMASK

       orr   r1,r0,#UNDEFMODE|NOINT

       msr  cpsr_cxsf,r1          ;UndefMode

       ldr   sp,=UndefStack            ; UndefStack=0x33FF_5C00

 

       orr   r1,r0,#ABORTMODE|NOINT

       msr  cpsr_cxsf,r1          ;AbortMode

       ldr   sp,=AbortStack             ; AbortStack=0x33FF_6000

 

       orr   r1,r0,#IRQMODE|NOINT

       msr  cpsr_cxsf,r1          ;IRQMode

       ldr   sp,=IRQStack        ; IRQStack=0x33FF_7000

 

       orr   r1,r0,#FIQMODE|NOINT

       msr  cpsr_cxsf,r1          ;FIQMode

       ldr   sp,=FIQStack        ; FIQStack=0x33FF_8000

 

       bic   r0,r0,#MODEMASK|NOINT

       orr   r1,r0,#SVCMODE

       msr  cpsr_cxsf,r1          ;SVCMode

       ldr   sp,=SVCStack              ; SVCStack=0x33FF_5800

这段代码则是分别初始化各种模式的堆栈。以初始化未定义模式堆栈为例。先将CPSR读取到r0,然后利用bic指令,将控制模式的低5位清零。之后设置(或上)为未定义模式,禁止中断,将结果保存到r1,然后将r1保存到CPSR。接着ldr       sp,=UndefStack     设置堆栈。堆栈的地址值,为UndefStack宏,具体是多少查看宏定义即可。程序注释中也已经标注了。

需要知道orr  r1,r0,#UNDEFMODE|NOINT,这条指令执行之后,r0寄存器中的值是无变化的,所以以后初始化其他堆栈的时候,可以接着拿r0来用。初始化其他模式堆栈,与此相同,不再赘述。     

mov pc,lr  程序跳转回去。

先到这。下次接着来分析。

 

 

 

 

原创粉丝点击