由于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
   上面是进行使能指令 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
 
;------------------------------------
;         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]
    此部分用来禁止中断,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)
;------------------------------------    
;                 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)
;------------------------------------    
;                 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)
;------------------------------------    
;                 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
 
;------------------------------------    
;                 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
 
;------------------------------------    
;                 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\p_w_picpath_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也在p_w_picpath_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。