由于51CTO的博文内容要求不能超过一定数量,好像是把源代码也算在里面了,使得关于startup.s的分析要分成好多篇了。
;------------------------------------
; Enable Instruction Cache
;------------------------------------
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 ; Invalidate Entire I&D Cache
bl System_EnableICache ; Enable I Cache
; Enable Instruction Cache
;------------------------------------
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 ; Invalidate Entire I&D Cache
bl System_EnableICache ; Enable I Cache
上面是进行使能指令
Cache
,
ARM
中的
Cache
分为数据和指令两种。首先使指令
Cache
和数据
Cache
无效(
I&D Cache
)
,
通过设置
CP15
协处理器的
C7
寄存器实现(
CP15
总共有
15
个不同的寄存器,具体定义参看
ARM
体系结构方面的书)。
System_EnableICache
是通过
IMPORT
导入的宏,相当于一个子函数,用来实现使能指令
Cache
。
System_EnableICache
的定义在
PLATFORM\COMMON\SRC\SOC\S3C6410_SEC_V1\OAL
\SYSTEM\s3c6410_system.s
文件中,该部分比较独立,也比较容易,仅仅对
CP15
的
C1
寄存器进行设置即可,如下所示,其中
R1_I
定义
s3c6410.inc
文件中。
;-------------------------
; Enable ICache
;-------------------------
LEAF_ENTRY System_EnableICache
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #R1_I
mcr p15, 0, r0, c1, c0, 0
mov pc, lr
ENTRY_END
; Enable ICache
;-------------------------
LEAF_ENTRY System_EnableICache
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #R1_I
mcr p15, 0, r0, c1, c0, 0
mov pc, lr
ENTRY_END
;------------------------------------
; Peripheral Port Setup
;------------------------------------
ldr r0, =0x70000013 ; Base Addres : 0x70000000, Size : 256 MB (0x13)
mcr p15,0,r0,c15,c2,4
; Peripheral Port Setup
;------------------------------------
ldr r0, =0x70000013 ; Base Addres : 0x70000000, Size : 256 MB (0x13)
mcr p15,0,r0,c15,c2,4
此部分代码用来设置外设端口,从
6410
手册可以得知,外设区域的地址范围是
0x7000000~0x7FFFFFFF
,地址范围为
256M
大小,
CP15
的
C15
是测试配置寄存器(
S3C2410
手册中有,但具体每一位的含义没有找到,所以此处的设置就不是很清楚了,希望知道的可以指导一下
)。
;------------------------------------
; Interrupt Disable
;------------------------------------
ldr r0, =VIC0INTENCLEAR
ldr r1, =0xFFFFFFFF;
str r1, [r0]
ldr r0, =VIC1INTENCLEAR
ldr r1, =0xFFFFFFFF;
str r1, [r0]
; Interrupt Disable
;------------------------------------
ldr r0, =VIC0INTENCLEAR
ldr r1, =0xFFFFFFFF;
str r1, [r0]
ldr r0, =VIC1INTENCLEAR
ldr r1, =0xFFFFFFFF;
str r1, [r0]
此部分用来禁止中断,VIC0INTENCLEAR和VIC1INTENCLEAR是两个寄存器地址,在文件PLATFORM\COMMON\SRC\SOC\S3C6410_SEC_V1\OAL\INC\s3c6410.inc中定义,如下:
VIC0INTENCLEAR EQU (S3C6410_BASE_REG_PA_VIC0 + 0x14)
VIC1INTENCLEAR EQU (S3C6410_BASE_REG_PA_VIC1 + 0x14)
在PLATFORM\COMMON\SRC\SOC\S3C6410_SEC_V1\OAL\INC\s3c6410_base_regs.inc文件中定义了VIC寄存器的基地址,如下:
S3C6410_BASE_REG_PA_VIC0 EQU (0x71200000)
S3C6410_BASE_REG_PA_VIC1 EQU (0x71300000)
VIC0INTENCLEAR EQU (S3C6410_BASE_REG_PA_VIC0 + 0x14)
VIC1INTENCLEAR EQU (S3C6410_BASE_REG_PA_VIC1 + 0x14)
在PLATFORM\COMMON\SRC\SOC\S3C6410_SEC_V1\OAL\INC\s3c6410_base_regs.inc文件中定义了VIC寄存器的基地址,如下:
S3C6410_BASE_REG_PA_VIC0 EQU (0x71200000)
S3C6410_BASE_REG_PA_VIC1 EQU (0x71300000)
;------------------------------------
; Disable WatchDog Timer
;------------------------------------
ldr r0, =WTCON
ldr r1, =0x0
str r1, [r0]
; Disable WatchDog Timer
;------------------------------------
ldr r0, =WTCON
ldr r1, =0x0
str r1, [r0]
此部分用来关闭看门狗,WTCON寄存器地址定义在文件PLATFORM\COMMON\SRC\SOC\S3C6410_SEC_V1\OAL\INC\s3c6410.inc中,可以查阅6410的手册,如下:
WTCON EQU (0x7e004000)
WTCON EQU (0x7e004000)
;------------------------------------
; Expand Memory Port 1 to x32
;------------------------------------
ldr r0, =MEM_SYS_CFG
ldr r1, [r0]
bic r1, r1, #0x80 ; ADDR_EXPAND to "0"
str r1, [r0]
; Expand Memory Port 1 to x32
;------------------------------------
ldr r0, =MEM_SYS_CFG
ldr r1, [r0]
bic r1, r1, #0x80 ; ADDR_EXPAND to "0"
str r1, [r0]
此部分设置扩展存储端口1,MEM_SYS_CFG同样在文件s3c6410.inc中定义(路径省略),如下,先读出MEM_SYS_CFG寄存器的值,清除第7位为0(可以查阅6410手册,不过这部分我还没有太仔细的研究,以后补充),然后再写入寄存器中。
MEM_SYS_CFG EQU (0x7e00f120)
MEM_SYS_CFG EQU (0x7e00f120)
;------------------------------------
; Disable VIC
;------------------------------------
bl System_DisableVIC
; Disable VIC
;------------------------------------
bl System_DisableVIC
此部分关闭向量中断控制器,System_DisableVIC的定义在文件PLATFORM\COMMON\SRC\SOC\S3C6410_SEC_V1\OAL\SYSTEM\s3c6410_system.s中,通过CP15的C1寄存器进行设置,如下所示,R1_VE定义在s3c6410.inc文件中。
;--------------------
; Disable VIC
;--------------------
LEAF_ENTRY System_DisableVIC
mrc p15,0,r0,c1,c0,0
bic r0,r0,#R1_VE
mcr p15,0,r0,c1,c0,0
mov pc, lr
ENTRY_END
; Disable VIC
;--------------------
LEAF_ENTRY System_DisableVIC
mrc p15,0,r0,c1,c0,0
bic r0,r0,#R1_VE
mcr p15,0,r0,c1,c0,0
mov pc, lr
ENTRY_END
;------------------------------------
; Enable IRQ
;------------------------------------
bl System_EnableIRQ
; Enable IRQ
;------------------------------------
bl System_EnableIRQ
此部分用来使能IRQ,System_EnableIRQ的定义在文件s3c6410_system.s(省略路径)中,如下所示,首先获取到CPSR的状态,然后修改进行修改,最后再赋值给CPSR。这里需要说明的是cpsr_cxsf,CPSR被分成了四个区域,“c”代表的是控制位[7:0],“x”代表的扩展为[15:8],“s”代表的是状态位[23:16],“f”代表的是标志位[31:24],四个域也可以单独使用,表示只修改CPSR该域的值。
;--------------------
; Enable IRQ
;--------------------
LEAF_ENTRY System_EnableIRQ
mrs r0,cpsr
bic r0,r0,#I_Bit
msr cpsr_cxsf,r0
mov pc, lr
ENTRY_END
; Enable IRQ
;--------------------
LEAF_ENTRY System_EnableIRQ
mrs r0,cpsr
bic r0,r0,#I_Bit
msr cpsr_cxsf,r0
mov pc, lr
ENTRY_END
;------------------------------------
; Clear DRAM
;------------------------------------
[ CLEAR_DRAM_ON_EBOOT
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 r0, =IMAGE_NK_PA_START ; Start address (Physical 0x5010.0000)
ldr r9, =(DRAM_SIZE-IMAGE_NK_OFFSET) ; 127 MB of RAM (1MB + 127MB)
10
stmia r0!, {r1-r8}
subs r9, r9, #32
bne %B10
]
; Clear DRAM
;------------------------------------
[ CLEAR_DRAM_ON_EBOOT
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 r0, =IMAGE_NK_PA_START ; Start address (Physical 0x5010.0000)
ldr r9, =(DRAM_SIZE-IMAGE_NK_OFFSET) ; 127 MB of RAM (1MB + 127MB)
10
stmia r0!, {r1-r8}
subs r9, r9, #32
bne %B10
]
此部分用来清空DRAM空间,代码用方括号括起来,CLEAR_DRAM_ON_EBOOT宏如果为TRUE,那么下面的代码将被执行,如果为FALSE,则不执行。 CLEAR_DRAM_ON_EBOOT宏在文件s3c6410中被定义,如下:
GBLL CLEAR_DRAM_ON_EBOOT
CLEAR_DRAM_ON_EBOOT SETL {FALSE}
上面的汇编再解释一下,GBLL伪指令用于定义一个全局的逻辑变量,而SETL伪指令用于给一个逻辑变量赋值,所以上面方括号中的代码是不执行的。
但仍然介绍一下里面的代码操作,首先给R1到R8的8个寄存器赋值为0,IMAGE_NK_PA_START在PLATFORM\SMDK6410\SRC\INC\image_cfg.inc文件中定义,如下:
IMAGE_NK_OFFSET EQU (0x00100000)
IMAGE_NK_PA_START EQU(DRAM_BASE_PA_START+IMAGE_NK_OFFSET)
DRAM_BASE_PA_START在上面的介绍中已经给出,是0x50000000,所以R0=0x50100000,是DRAM的起始地址(是否应该是0x50000000或者0x50010000),DRAM_SIZE也在image_cfg.inc文件中定义,如下:
DRAM_SIZE EQU (0x08000000)
所以R9=128M-1M=127M,表明清空的DRAM的大小是127M,stmia指令将R1-R8的8个寄存器的值写入以R0开始的8个对应地址中,之后R9表示的剩余DRAM大小减去32字节(一个寄存器4字节,总共8个),如果R9不为0,则跳转到标号10处,继续清空DRAM。
本文转自jazka 51CTO博客,原文链接:http://blog.51cto.com/jazka/572612,如需转载请自行联系原作者