startup.s文件是S3C6410引导程序EBoot的原始入口处,该文件的内容是以汇编形式编写的,本人花了几天的时间对startup.s进行了详细的研究,翻阅了大量的书籍和网络博客。网络上有一些大牛在其博客中对源码已经进行了分析,但本人感觉里面的有些部分对初学者还是不够清楚,谁让人家是大牛呢,直接在一定高度上讲,O(_)O,不过仍然非常感谢这些牛人无私的奉献出那些知识。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

本人是WinCE的入门选手,将沿着自己的菜鸟学习之路,将自己的一些学习心得在这里记录下来,如果能够帮到以后的人,不胜荣幸。如果有什么分析的不正确的地方,欢迎拍砖,大家讨论才能更加进步。

大家都知道startup.s是用来完成硬件的初始化的,具体工作如下:

1、              设置CPU模式,使得可以无限制的访问内存和硬件,一般会设置为管理模式或者系统模式;

2、              关闭所有的CPU中断;

3、              关闭内存管理单元MMUTLB

4、              关闭写缓冲和Cache,使得Write BufferCache无效;

5、              初始化内存控制器;

6、              设置CPUPLL,设置时钟;

7、              创建堆栈;

8、              设置并打开MMU进行地址映射,打开Cache

9、              如果需要,拷贝EbootFlashRAM中;

10、          跳转到C语言的main函数。
InBlock.gif                INCLUDE         kxarm.h
InBlock.gif                INCLUDE         s3c6410.inc
InBlock.gif                INCLUDE         p_w_picpath_cfg.inc
InBlock.gif
InBlock.gif                IMPORT            OALClearUTLB
InBlock.gif                IMPORT            OALFlushICache
InBlock.gif                IMPORT            OALFlushDCache
InBlock.gif
InBlock.gif                IMPORT            System_DisableVIC
InBlock.gif                IMPORT            System_EnableIRQ
InBlock.gif                IMPORT            System_SetSyncMode
InBlock.gif                IMPORT            System_SetAsyncMode
InBlock.gif                IMPORT            System_EnableICache
InBlock.gif
InBlock.gif                EXPORT            StartUp
    首先是函数引用声明, IMPORT 伪指令用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用,这些引用的标号在下面用到时会进行简要介绍, EXPORT 伪指令用于在程序中声明一个全局的标号,该标号可在其他的文件中引用。
InBlock.gif;-------------------------------------------------------------------------------
InBlock.gif;         Definition for MMU table initialization
InBlock.gif;-------------------------------------------------------------------------------
InBlock.gif
InBlock.gifPT_1ST_BASE                 EQU         (DRAM_BASE_PA_START+0x10000)                ; 1st level Page Table Base Address (PHYBASE + 0x10000) save room for interrupt vectors
InBlock.gifPT_1ST_ENTRY_CNB        EQU         (DRAM_BASE_PA_START+0x40E)                    ; Cached Area Page Table Entry (Cache/Unbuffer/RW), PA base = 0x50000000
InBlock.gifPT_1ST_ENTRY_NCNB     EQU         (DRAM_BASE_PA_START+0x402)                    ; Uncached Area Page Table Entry (Uncache/Unbuffer/RW), PA base = 0x50000000
InBlock.gifPTR_1ST_PTE                 EQU         ((DRAM_BASE_PA_START>>16)/4)                ; Ptr to 1st PTE for 0x50000000
InBlock.gifBANK_SHIFT                    EQU         (20)
此部分用来声明一些变量,在 MMU 初始化时使用。 DRAM_BASE_PA_START PLATFORM\SMDK6410\SRC\INC\p_w_picpath_cfg.inc 中定义,这个是 DRAM 的基地址,与硬件相关, S3C2410 0x30000000 S3C6410 0x50000000

PT_1ST_BASE 是一级页表的基地址,一般都选在 DDR 开始地址 + 偏移值( offset )处, WinCe offset=64K Linux 也是,有资料 ARM 的页表基地址必须是 64K 对齐的,貌似在此处比较吻合,但是不知道为什么,有待进一步考证),所以此处在 DRAM_BASE_START 基础上加上了 0x10000 ,正好 64K

PT_1ST_ENTRY_CNB PT_1ST_ENTRY_NCNB 用来设置页表项的对应的虚拟内存页的访问权限和缓冲读写属性,下面用到时再进一步解释。

PTR_1ST_PTE BANK_SHIFT 下面用到时,自然就明白什么用处了。
InBlock.gif;------------------------------------------------------------------------------
InBlock.gif;
InBlock.gif;         Macro for LED on SMDK Board (GPN[15:12])
InBlock.gif;
InBlock.gif;         LED_ON for physical address domain
InBlock.gif;         VLED_ON for virtual address domain
InBlock.gif;
InBlock.gif;------------------------------------------------------------------------------
InBlock.gif
InBlock.gif        MACRO
InBlock.gif
InBlock.gif                LED_ON         $data
InBlock.gif
InBlock.gif                ldr                    r10, =GPNPUD
InBlock.gif                ldr                    r11, [r10]
InBlock.gif                bic                    r11, r11, #0xFF000000         ; Pull-Up-Down Disable
InBlock.gif                str                    r11, [r10]
InBlock.gif
InBlock.gif                ldr                    r10, =GPNDAT
InBlock.gif                ldr                    r11, [r10]
InBlock.gif                bic                    r11, r11, #0xF000
InBlock.gif                ldr                    r12, =$data
InBlock.gif                mov                    r12, r12, lsl #12         ; [15:12]
InBlock.gif                orr                    r11, r11, r12
InBlock.gif                str                    r11, [r10]
InBlock.gif
InBlock.gif                ldr                    r10, =GPNCON
InBlock.gif                ldr                    r11, [r10]
InBlock.gif                bic                    r11, r11, #0xFF000000
InBlock.gif                orr                    r11, r11, #0x55000000         ; GPN[15:12] Output .
InBlock.gif                str                    r11, [r10]
InBlock.gif
InBlock.gif        MEND
InBlock.gif
InBlock.gif
InBlock.gif        MACRO
InBlock.gif
InBlock.gif                VLED_ON         $data
InBlock.gif
InBlock.gif                ldr                    r10, =vGPNPUD
InBlock.gif                ldr                    r11, [r10]
InBlock.gif                bic                    r11, r11, #0xFF000000         ; Pull-Up-Down Disable
InBlock.gif                str                    r11, [r10]
InBlock.gif
InBlock.gif                ldr                    r10, =vGPNDAT
InBlock.gif                ldr                    r11, [r10]
InBlock.gif                bic                    r11, r11, #0xF000
InBlock.gif                ldr                    r12, =$data
InBlock.gif                mov                    r12, r12, lsl #12         ; [15:12]
InBlock.gif                orr                    r11, r11, r12
InBlock.gif                str                    r11, [r10]
InBlock.gif
InBlock.gif                ldr                    r10, =vGPNCON
InBlock.gif                ldr                    r11, [r10]
InBlock.gif                bic                    r11, r11, #0xFF000000
InBlock.gif                orr                    r11, r11, #0x55000000         ; GPN[15:12] Output .
InBlock.gif                str                    r11, [r10]
InBlock.gif
InBlock.gif        MEND
    这部分是用来点亮 LED 灯的,在 Eboot 中可有可无,不过在这里也顺便分析一下。这里 LED 灯是接在 GPN 的管脚上,由 GPNPUD GPNDAT GPNCON 三个寄存器控制,具体功能参看一下手册吧,这三个寄存器的定义在 PLATFORM\COMMON\SRC\SOC\S3C6410_SEC_V1\OAL\INC\s3c6410.inc 文件中。此处用 MACRO MEND 来定义了一段代码的宏, $data 是宏的参数。
InBlock.gif;------------------------------------------------------------------------------
InBlock.gif;
InBlock.gif;         StartUp Entry
InBlock.gif;
InBlock.gif;         Main entry point for CPU initialization.
InBlock.gif;
InBlock.gif;------------------------------------------------------------------------------
InBlock.gif        LEAF_ENTRY            StartUp
InBlock.gif
InBlock.gif                b                    ResetHandler
InBlock.gif                b                    .                                        ; HandlerUndef
InBlock.gif                b                    .                                        ; HandlerSWI
InBlock.gif                b                    .                                        ; HandlerPabort
InBlock.gif                b                    .                                        ; HandlerDabort
InBlock.gif                b                    .                                        ; HandlerReserved
InBlock.gif                b                    .                                        ; HandlerIRQ
InBlock.gif                b                    .                                        ; HandlerFIQ
    上面是 startup.s 的入口部分,由 LEAF_ENTRY 宏进行标示,进入到程序段 StartUp 中,由 ENTRY_END 标示程序段的结束。首先就跳转到 ResetHandler 处执行,这也是复位以后的位置,下面的跳转语句不应该进入(不过不知道为什么还要写?)。
InBlock.gifResetHandler
InBlock.gif
InBlock.gif                LED_ON 0x1
    这条语句就是应用上面定义的 LED_ON 宏,点亮 LED 指示灯。