Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / MDK S3C2440启动代码简单分析

ARM启动代码相当于我们电脑的BIOS,也就是ARM启动时对处理器的一些初始化及嵌入式系统硬件的一些初始化。由于它直接面对处理器内核和硬件控制器进行编程,一般都是用汇编语言。一般包括:中断向量表,初始化存储器系统,初始化堆栈,初始化有特殊要求的断口,设备初始化,变量初始化等。 ;/*****************************************************************************/;/*S3C2440A.S: Startup file for Samsung S3C440A            */;/*****************************************************************************/;/*<<< Use Configuration Wizard in Context Menu >>>         */ ;/*****************************************************************************/;/*This file is part of the uVision/ARM development tools.       */;/*Copyright (c) 2005-2006 Keil Software. All rights reserved.    */;/*This software may only be used under the terms of a valid, current, */;/*end user licence from KEIL for a compatible version of KEIL software */;/*development tools. Nothing else gives you the right to use this software. */;/*****************************************************************************/;下面这些参数是与CPSR状态寄存器有关;这里各个模式的参数是由寄存器CPSR的模式位设置M[4:0]得来的,;比如这里的用户模式,CPSR的M[4:0]设置为10000就是0x10。;Mode_USR      -- 用户模式,正常程序执行模式,用于应用程序;Mode_FIQ        --快速中断模式,一般用于高速数据传输和通道处理。;Mode_IRQ              --外部中断模式,一般用于通用的中断处理。;Mode_SVC      -- 管理模式,供操作系统使用的一种保护模式。;Mode_ABT       -- 数据访问中止模式,用于虚拟存储用存储保护;Mode_UND      -- 未定义指令中止模式,当未定义指令执行时进入此模式。;Mode_SYS       -- 系统模式,用于特权级的操作系统任务。;I_Bit                  --如果I位被置1,则外部中断被禁止(IRQ isdisabled);F_Bit                 -- 如果F位被置1,则快速中断被禁止(FIQ isdisabled);;----------------------------------------------------------------------Mode_USR         EQU    0x10Mode_FIQ           EQU     0x11Mode_IRQ          EQU     0x12Mode_SVC         EQU     0x13Mode_ABT          EQU     0x17Mode_UND         EQU     0x1BMode_SYS         EQU     0x1F I_Bit       EQU    0x80            ; when Ibit is set, IRQ is disabledF_Bit      EQU    0x40            ; when Fbit is set, FIQ is disabled ;----------------------------- Stack Configuration-----------------------------------;下面这些主要是栈配置,系统的栈空间设定;;UND_Stack_Size           -- 未定义模式的栈大小;SVC_Stack_Size             -- 管理模式的栈大小;ABT_Stack_Size            -- 数据访问终止模式的栈大小;FIQ_Stack_Size             -- 快速中断模式的栈大小;IRQ_Stack_Size            -- 中断模式的栈大小;USR_Stack_Size           -- 用户模式的栈大小;ISR_Stack_Size             -- 总堆栈的大小,也就是所有模式下堆栈相加-----------------------------------------------------------------------UND_Stack_Size      EQU     0x00000000SVC_Stack_Size              EQU    0x00000008ABT_Stack_Size       EQU     0x00000000FIQ_Stack_Size        EQU    0x00000000IRQ_Stack_Size        EQU    0x00000080USR_Stack_Size       EQU     0x00000400ISR_Stack_Size        EQU    (UND_Stack_Size + SVC_Stack_Size +ABT_Stack_Size +                                                FIQ_Stack_Size +IRQ_Stack_Size);-----------------------------------------------------------------------;AREA --     是一个伪指令,用于段定义。ARM的汇编程序由段组成,段是相对独立的指令或数据单位,每个段由AREA伪指令定义,并定义段的属性。;STACK      -- AREA指令的一个参数,定义段名称;NOINIT       -- AREA指令的一个参数,指定本数据段仅仅保留了内在单元,而将句初始值写入内存单元,也即将内存单元值初始化为0;READWRITE-- 指定本段为可读可写,数据段默认为READWRITE。;                         READWRITE(读写)、READONLY(只读);ALIGN --    是一个伪指令,指定对齐方式。ALIGN n 指令的对齐值有两种方案,即n 或 2^n,这里采用第二种方案即指定后面的指令8字节对齐。;ATPCS规定数据栈必须为FD类型,并且对数据栈的操作时8字节对齐的;下面这句话意思是:开辟一个堆栈段,段名字为STACK,定义为可读可写,将内存单元初始化为0,;-----------------------------------------------------------------------                AREA    STACK, NOINIT, READWRITE, ALIGN=3;-----------------------------------------------------------------------;SPACE-- 伪指令,用于分配一块内存单元,并用0初始化,与%同义;其指令格式为:;   {lable}  SPACE  expr;lable-- 内存起始地址标号  expr -- 所要分配的内存字节数  ;-----------------------------------------------------------------------Stack_Mem      SPACE   USR_Stack_Size    ;堆栈内存起始地址标号__initial_sp   SPACE   ISR_Stack_Size    ;汇编代码的地址标号 Stack_Top   ;堆栈段内容结束,在这里放个标号,用来获得堆栈顶部地址 Heap_Size      EQU     0x00000000    ;定义堆大小设置               ;开辟一个名字为HEAP可读可写,不初始化内存单的内存单元。               AREA    HEAP, NOINIT, READWRITE, ALIGN=3__heap_base    ;堆的基址Heap_Mem       SPACE   Heap_Size    ;堆内存起始地址标号__heap_limit   ;堆结束 ;----------------------------内存初始化定义-----------------------------;在一些应用系统中除了扩展Flash,RAM挂接在外部存储器接口上外,可能还有其它;的外设挂接在外部存储器接口上,不同外设的操作时序什么的都是不一样的,所以;在使用这些外设之前必须初始化连接这些外设存储器接口。这里因为没扩展,所以;只定义一个片上内存基地址。;----------------------------------------------------------------------- IRAM_BASE      EQU     0x40000000    ;片上SRAM的基地址,即内存基地址 ;-------------------------看门狗初始化定义------------------------------;看门狗在防止程序跑飞,进入无限死循环时起着重要作用。有些应用可能用不上;看门狗功能,也可能有些应用会用到外部看门狗。在这个时候内部看门狗必须禁;止,所以有时候会在初始化时将内部看门狗禁止,当以后应用用到时再开启它。;看门狗定时器包括三个寄存器:;WTCON-- 看门狗控制寄存器,设定看门狗定时器模式;WTDAT-- 看门狗数据寄存器,用于设定超时宽度;WTCNT-- 看门狗计数寄存器,里面存放的是看门狗定时器当前值;;WT_BASE  -- 看门狗定时器基地址;WTCON_OFS-- 看门狗控制寄存器偏移地址,相对于基址;WTDAT_OFS-- 看门狗数据寄存器偏移地址,相对于基址;WTCNT_OFS-- 看门狗计数寄存器偏移地址,相对于基址;WT_SETUP -- 看门狗设置;WTCON_Val-- 看门狗控制寄存器设置,关闭看门狗;WTDAT_Val-- 看门狗数据寄存器设置,初始值即为0x8000;----------------------------------------------------------------------- WT_BASE        EQU     0x53000000      ; WatchdogTimer Base AddressWTCON_OFS     EQU    0x00      ; Watchdog Timer Control RegisterOffsetWTDAT_OFS      EQU    0x04       ; Watchdog Timer DataRegister    OffsetWTCNT_OFS      EQU    0x08       ; Watchdog Timer CountRegister   Offset WT_SETUP       EQU     0WTCON_Val      EQU     0x00000000WTDAT_Val      EQU     0x00008000  ;----------------------------时钟与电源管理定义-------------------------;S3C2440A中的时钟控制逻辑可以产生必须的时钟信号,包括CPU的FCLK,AHB总线的;HCLK以及APB总线外设的PCLK3C2440A内部有两个锁相环(PLL):一个提供FCLK,;HCLK及PCLK,另一个专用于USB模块(48MHz).;;CLOCK_BASE  -- 时钟基地址;LOCKTIME_OFS-- 锁相环锁定时间计数寄存器偏移地址,相对于基址;MPLLCON_OFS -- MPLL配置寄存器偏移地址,相对于基址,主时钟源PLL;UPLLCON_OFS -- UPLL配置寄存器偏移地址,相对于基址,USB时钟源PLL;CLKCON_OFS  -- 时钟控制寄存器偏移地址,相对于基址;CLKSLOW_OFS -- 时钟减慢控制寄存器偏移地址,相对于基址;CLKDIVN_OFS -- 时钟分频器控制寄存器偏移地址,相对于基址;CAMDIVN_OFS -- 摄像头时钟分频器控制寄存器偏移地址,相对于基址,UPLL提供;;CLOCK_SETUP -- 时钟设置;LOCKTIME_Val-- PLL锁定时间计数器值;MPLLCON_Val -- MPLL配置寄存器值;UPLLCON_Val -- UPLL配置寄存器值;CLKCON_Val  -- 时钟配置寄存器值;CLKSLOW_Val -- 时钟减慢控制寄存器值;CLKDIVN_Val -- 时钟分频控制寄存器值;CAMDIVN_Val -- 摄像头分频控制寄存器值;-----------------------------------------------------------------------CLOCK_BASE     EQU     0x4C000000      ; ClockBase AddressLOCKTIME_OFS   EQU     0x00    ; PLL Lock Time CountRegister   OffsetMPLLCON_OFS    EQU     0x04    ; MPLL ConfigurationRegister    OffsetUPLLCON_OFS    EQU     0x08     ; UPLL ConfigurationRegister    OffsetCLKCON_OFS     EQU     0x0C      ; ClockGenerator Control Reg    OffsetCLKSLOW_OFS    EQU     0x10     ; Clock SlowControl Register    OffsetCLKDIVN_OFS    EQU    0x14        ; Clock Divider ControlRegister OffsetCAMDIVN_OFS    EQU     0x18       ;Camera Clock Divider Register  Offset CLOCK_SETUP    EQU     0LOCKTIME_Val   EQU     0x0FFF0FFFMPLLCON_Val    EQU     0x00043011UPLLCON_Val    EQU     0x00038021CLKCON_Val     EQU     0x001FFFF0CLKSLOW_Val    EQU     0x00000004CLKDIVN_Val    EQU     0x0000000FCAMDIVN_Val    EQU     0x00000000 ;--------------------存储控制器设置定义---------------------------------;下面这些都是一些关于存储控制器的地址宏定义;;MC_BASE     -- 存储控制器基地址;BWSCON_OFS  -- 总线宽度和等待控制寄存器偏移地址;BANKCON0_OFS-- BANK1控制寄存器偏移地址;  .;  .;BANKCON7_OFS-- BANK7控制寄存器偏移地址;REFRESH_OFS -- DRAM/SDRAM刷新控制寄存器偏移地址;BANKSIZE_OFS-- 可调的bank大小寄存器偏移地址;MRSRB6_OFS  -- bank6模式控制寄存器偏移地址;MRSRB7_OFS  -- bank7模式控制寄存器偏移地址;;MC_SETUP    -- 存储器控制寄存器设置;BWSCON_Val  -- 写入总线宽度和等待控制寄存值;BANKCON0_Val-- 写入Blank0的值;  .;  .;BANKCON7_Val-- 写入BANK7 的值;REFRESH_Val -- 写入DRAM/SDRAM刷新控制寄存的值;BANKSIZE_Val-- 写入可调的bank大小寄存的值;MRSRB6_Val  -- 写入bank6模式控制寄存器的值;MRSRB7_Val  -- 写入bank7模式控制寄存器的值;-----------------------------------------------------------------------MC_BASE        EQU     0x48000000      ; MemoryController Base AddressBWSCON_OFS     EQU     0x00     ; Bus Width and WaitStatus Ctrl OffsetBANKCON0_OFS   EQU     0x04    ; Bank 0 ControlRegister        OffsetBANKCON1_OFS   EQU     0x08     ; Bank 1 ControlRegister        OffsetBANKCON2_OFS   EQU     0x0C     ; Bank 2 ControlRegister        OffsetBANKCON3_OFS   EQU     0x10      ; Bank 3Control Register        OffsetBANKCON4_OFS   EQU     0x14      ; Bank 4Control Register        OffsetBANKCON5_OFS   EQU     0x18       ;Bank 5 Control Register        OffsetBANKCON6_OFS   EQU     0x1C       ; Bank 6Control Register        OffsetBANKCON7_OFS   EQU     0x20        ;Bank 7 Control Register        OffsetREFRESH_OFS    EQU    0x24          ; SDRAM RefreshControl Register OffsetBANKSIZE_OFS   EQU     0x28          ; Flexible Bank Size Register    OffsetMRSRB6_OFS     EQU    0x2C           ; Bank 6 ModeRegister           OffsetMRSRB7_OFS     EQU    0x30           ; Bank 7Mode Register          Offset MC_SETUP       EQU     1BWSCON_Val     EQU     0x22000000BANKCON0_Val   EQU     0x00000700BANKCON1_Val   EQU     0x00000700BANKCON2_Val   EQU     0x00000700BANKCON3_Val   EQU     0x00000700BANKCON4_Val   EQU     0x00000700BANKCON5_Val   EQU     0x00000700BANKCON6_Val   EQU     0x00018005BANKCON7_Val   EQU     0x00018005REFRESH_Val    EQU     0x008404F3BANKSIZE_Val   EQU     0x00000032MRSRB6_Val     EQU     0x00000020MRSRB7_Val     EQU     0x00000020 ;---------------------I/O端口宏定义--------------------------------------;GPA_BASE  -- 端口A基地址;  .;GPJ_BASE  -- 端口J基地址;GPCON_OFS -- 端口配置寄存器偏移地址;GPDAT_OFS -- 端口数据寄存器偏移地址;GPUP_OFS  -- 端口上拉寄存器偏移地址;GP_SETUP  -- 端口设置;GPA_SETUP -- 端口A配置;GPACON_Val-- 写入端口A配置寄存器的值;     .;     .;GPJ_SETUP -- 端口J配置;GPJCON_Val-- 写入端口J配置寄存器的值;GPJUP_Val -- 写入端口J上拉寄存器的值;-----------------------------------------------------------------------GPA_BASE       EQU     0x56000000      ; GPA BaseAddressGPB_BASE       EQU     0x56000010      ; GPB BaseAddressGPC_BASE       EQU     0x56000020      ; GPC BaseAddressGPD_BASE       EQU     0x56000030      ; GPD BaseAddressGPE_BASE       EQU     0x56000040      ; GPE BaseAddressGPF_BASE       EQU     0x56000050      ; GPF BaseAddressGPG_BASE       EQU     0x56000060      ; GPG BaseAddressGPH_BASE       EQU     0x56000070      ; GPH BaseAddressGPJ_BASE       EQU     0x560000D0      ; GPJ BaseAddressGPCON_OFS      EQU    0x00            ;Control Register OffsetGPDAT_OFS      EQU    0x04            ; DataRegister OffsetGPUP_OFS       EQU    0x08            ;Pull-up Disable Register Offset GP_SETUP       EQU     1 ;-----------------------------------------------------------------------;端口A配置;-----------------------------------------------------------------------GPA_SETUP      EQU     0GPACON_Val     EQU     0x000003FF ;-----------------------------------------------------------------------;端口B配置;-----------------------------------------------------------------------GPB_SETUP      EQU     0GPBCON_Val     EQU     0x00000000GPBUP_Val      EQU     0x00000000  ;-----------------------------------------------------------------------;端口C配置;-----------------------------------------------------------------------GPC_SETUP      EQU     0GPCCON_Val     EQU     0x00000000GPCUP_Val      EQU     0x00000000 ;-----------------------------------------------------------------------;端口D配置;-----------------------------------------------------------------------GPD_SETUP      EQU     0GPDCON_Val     EQU     0x00000000GPDUP_Val      EQU     0x00000000 ;-----------------------------------------------------------------------;端口E配置;-----------------------------------------------------------------------GPE_SETUP      EQU     0GPECON_Val     EQU     0x00000000GPEUP_Val      EQU     0x00000000 ;-----------------------------------------------------------------------;端口F配置;-----------------------------------------------------------------------GPF_SETUP      EQU     0GPFCON_Val     EQU     0x00000000GPFUP_Val      EQU     0x00000000 ;-----------------------------------------------------------------------;端口G配置;-----------------------------------------------------------------------GPG_SETUP      EQU     0GPGCON_Val     EQU     0x00000000GPGUP_Val      EQU     0x00000000 ;-----------------------------------------------------------------------;端口H配置;-----------------------------------------------------------------------GPH_SETUP      EQU     0GPHCON_Val     EQU     0x00000000GPHUP_Val      EQU     0x00000000  ;-----------------------------------------------------------------------;端口J配置;-----------------------------------------------------------------------GPJ_SETUP      EQU     0GPJCON_Val     EQU     0x00000000GPJUP_Val      EQU     0x00000000 ;-----------------------------------------------------------------------;PRESERVE8-- 伪指令,指示当前文件请求堆栈为8字节对齐。; 汇编程序数据8字节对齐,c和汇编有8位对齐的要求.;-----------------------------------------------------------------------               PRESERVE8 ;-----------------------------------------------------------------------;存储区设定和程序入口点;启动代码必须连接到第一个地址才能运行;下面这句话的意思是:;       声明一个名为RESET的代码段,属性为只读;-----------------------------------------------------------------------               AREA    RESET, CODE, READONLY               ARM    ;ARM模式运行程序;-----------------------------------------------------------------------              ;IMPORT-- 相当于C语言中的关键字extern;       指当前的符号在其他源文件中定义的,在本源文件中可能引用该符号.;EXPORT-- 相当于C语言中的关键字global;         声明一个符号可以被其它文件引用.相当于声明了一个全局变量;下面这几句话是的意思是:;   如果定义了_EVAL这个变量,引用RO输出区的字节长度与RW输出区的字节长度;注意:;ARM连接器定义了一些包含$$的符号。这些符号及其他所有包含$$的名称都是ARM的;保留字。这些符号被用于指定域的基地址,输出段的基地址和输入段的基地址及其;大小。我们可以自己的汇编语言程序中引用这些符号地址,把它们用作可重定位的;地址,也可能在C或C++代码中使用extern关键字来引用它们。这个可以查看uVision;Help的Region-relatedsymbols这一节。;-----------------------------------------------------------------------               IF      :LNOT::DEF:__EVAL     ;逻辑判断是否定义了_EVAL这个变量               IMPORT  ||Image$$ER_ROM1$$RO$$Length||               IMPORT  ||Image$$RW_RAM1$$RW$$Length||               ENDIF ;-----------------------------------------------------------------------;   异常向量,映射到地址0,必须使用绝对寻址方式,子程序用无限循环方式;实现可以被修改。;-----------------------------------------------------------------------Vectors        LDR     PC, Reset_Addr ;将复位地址装载到程序指针,即复位                      LDR     PC, Undef_Addr ;未定义指令               LDR     PC, SWI_Addr   ;软件中断               LDR     PC, PAbt_Addr  ;中止(预取)               LDR     PC, DAbt_Addr  ;中止(数据)               IF     :DEF:__EVAL    ;如果定义了__EVAL变量                 DCD   0x4000         ;分配2k空间               ELSE                  ;否则分配空间大小为RO输出区的字节                                                          ;长度与RW输出区的字节长度之和                 DCD   ||Image$$ER_ROM1$$RO$$Length||+                       ||Image$$RW_RAM1$$RW$$Length||               ENDIF               LDR     PC, IRQ_Addr   ;外部中断               LDR     PC, FIQ_Addr   ;快速中断                IF      :DEF:__RTX     ;如果定义了__RTX               IMPORT  SWI_Handler    ;则定义中断子程序               IMPORT  IRQ_Handler_RTX ;定义快速中断子程序               ENDIF;-----------------------------------------------------------------------;下面这几句的任务是把各个子程序的入口地址分配给相应的地址变量;-----------------------------------------------------------------------Reset_Addr     DCD     Reset_Handler ;复位子程序入口地址赋值给Reset_AddrUndef_Addr     DCD     Undef_Handler ;未定义子程序入口地址赋值给Undef_Addr SWI_Addr       DCD     SWI_Handler   ;中断子程序入口地址赋值给SWI_AddrPAbt_Addr      DCD     PAbt_Handler  ;中止(预存)子程序入口地址赋给PAbt_AddrDAbt_Addr      DCD     DAbt_Handler  ;中止(数据)子程序入口地址赋给DAbt_Addr               DCD    0             ;保留地址                    IF      :DEF:__RTX    ;如果定义了__RTXIRQ_Addr       DCD     IRQ_Handler_RTX  ;快速中断子程序入口地址给IRQ_Addr               ELSEIRQ_Addr       DCD     IRQ_Handler      ;否则把IRQ_Handler入口地址给IRQ_Addr               ENDIFFIQ_Addr       DCD     FIQ_Handler      ;快速中断入口地址给FIQ_Addr ;-----------------------------------------------------------------------;这些子程序都是用无限循环方式实现的可以被修改。;----------------------------------------------------------------------- Undef_Handler                                      B       Undef_Handler    ;跳转到Undef_Handler,还是在这个地方               IF      :DEF:__RTX      ;如果定义了DEF:__RTX,在此等待中断               ELSESWI_Handler                                       B       SWI_Handler     ;否则跳转到软件中断               ENDIFPAbt_Handler                                       B       PAbt_Handler     ;中止(预存)子程DAbt_Handler                                       B       DAbt_Handler     ;中止(数据)子程;-----------------------------------------------------------------------;外部中断子程序;    如果函数标有PROC与ENDP,但没有FRAMEPUSH 或FRAME POP,则堆栈作用量;假定为0.这意味着无需手动添加FRAMEPUSH 0或FRAMEPOP 0;-----------------------------------------------------------------------                                  IRQ_Handler                                                                PROC               EXPORT  IRQ_Handler  [WEAK] ;声明一个全局变量,并且其它                                                               ;同名符优先于本符号被引用               B       .   ;跳转到当前地址即在此等待“.”代表当前指令地址               ENDPFIQ_Handler                               ;快速中断子程序                 B       FIQ_Handler ;-----------------------------------------------------------------------;复位子程序;-----------------------------------------------------------------------               EXPORT  Reset_Handler     ; 声明一个全局变量Reset_Handler   ;-----------------------------------------------------------------------;配置看门狗;前面已经初始化WT_SETUP == 0,要想执行下面的程序需将WT_SETUP置1;-----------------------------------------------------------------------               IF      WT_SETUP != 0               LDR     R0, =WT_BASE    ;加载看门狗基址               LDR     R1, =WTCON_Val  ;加载看门狗控制寄存器数据               LDR     R2, =WTDAT_Val  ;加载看门狗数据寄存器数据               STR     R2, [R0,#WTCNT_OFS]  ;将WTDAT_Val配置给看门狗                                                                 ;计数寄存器               STR     R2, [R0, #WTDAT_OFS]  ;将WTDAT_Val配置给看门狗                                                                 ;数据寄存器               STR     R1, [R0, #WTCON_OFS]  ;将WTCON_Val配置给看门狗                                                                 ;控制寄存器               ENDIF               ;-----------------------------------------------------------------------;配置时钟;如果逻辑上没有定义NO_CLOCK_SETUP并且CLOCK_SETUP != 0执行下面程序;-----------------------------------------------------------------------                                                           IF     (:LNOT:(:DEF:NO_CLOCK_SETUP)):LAND:(CLOCK_SETUP != 0)               LDR     R0,     =CLOCK_BASE    ;加载时钟基址               LDR     R1,     =LOCKTIME_Val  ;加载PLL锁定时间计数值               STR     R1, [R0, #LOCKTIME_OFS] ;并将该值配置到PLL锁定时间计数器               MOV     R1,     #CLKDIVN_Val                 STR     R1, [R0, #CLKDIVN_OFS]  ;配置时钟分频器               LDR     R1,      =CAMDIVN_Val               STR    R1, [R0, #CAMDIVN_OFS]  ;配置摄像头分频控制寄存器               LDR     R1,      =MPLLCON_Val               STR     R1, [R0, #MPLLCON_OFS]  ;配置MPLL配置寄存器               LDR     R1,      =UPLLCON_Val               STR     R1, [R0, #UPLLCON_OFS]  ;配置UPLL配置寄存器               MOV     R1,      #CLKSLOW_Val               STR     R1, [R0, #CLKSLOW_OFS]  ;配置时钟减慢控制寄存器               LDR     R1,      =CLKCON_Val               STR     R1, [R0, #CLKCON_OFS]   ;配置时钟配控制寄存器               ENDIF ;-----------------------------------------------------------------------;存储器设定;如果没有定义NO_MC_SETUP且CLOCK_SETUP!= 0则执行下面的程序;-----------------------------------------------------------------------               IF      (:LNOT:(:DEF:NO_MC_SETUP)):LAND:(CLOCK_SETUP!= 0)               LDR     R0,      =MC_BASE  ;加载存储控制器基址               LDR     R1,      =BWSCON_Val               STR     R1, [R0, #BWSCON_OFS]   ;配置总线宽度和等待控制寄存器               LDR     R1,      =BANKCON0_Val               STR     R1, [R0, #BANKCON0_OFS] ;配置BLANK0控制寄存器               LDR     R1,      =BANKCON1_Val               STR     R1, [R0, #BANKCON1_OFS] ;配置BLANK1控制寄存器               LDR     R1,      =BANKCON2_Val               STR    R1, [R0, #BANKCON2_OFS] ;配置BLANK2控制寄存器               LDR     R1,      =BANKCON3_Val               STR     R1, [R0, #BANKCON3_OFS] ;配置BLANK3控制寄存器               LDR     R1,      =BANKCON4_Val               STR     R1, [R0, #BANKCON4_OFS] ;配置BLANK4控制寄存器               LDR     R1,      =BANKCON5_Val               STR     R1, [R0, #BANKCON5_OFS] ;配置BLANK5控制寄存器               LDR     R1,      =BANKCON6_Val               STR     R1, [R0, #BANKCON6_OFS] ;配置BLANK6控制寄存器               LDR     R1,      =BANKCON7_Val               STR     R1, [R0, #BANKCON7_OFS] ;配置BLANK7控制寄存器               LDR     R1,      =REFRESH_Val               STR     R1, [R0, #REFRESH_OFS]  ;配置DRAM/SDRAM刷新控制寄存器               MOV     R1,      #BANKSIZE_Val               STR     R1, [R0, #BANKSIZE_OFS] ;配置可调的bank大小寄存器               MOV     R1,      #MRSRB6_Val               STR     R1, [R0, #MRSRB6_OFS]   ;配置bank6模式控制寄存器               MOV     R1,      #MRSRB7_Val               STR     R1, [R0, #MRSRB7_OFS]   ;配置bank7模式控制寄存器               ENDIF                           ;-----------------------------------------------------------------------;IO端口配置;如果没有定义NO_GP_SETUP并且GP_SETUP!= 0则执行下面的程序;-----------------------------------------------------------------------                          IF      (:LNOT:(:DEF:NO_GP_SETUP)):LAND:(GP_SETUP !=0)                IF      GPA_SETUP != 0               LDR     R0, =GPA_BASE      ;配置端口A功能               LDR    R1, =GPACON_Val    ;A口有25个口,做IO时只能做输出口               STR     R1, [R0, #GPCON_OFS]                 ENDIF                IF      GPB_SETUP != 0               LDR     R0, =GPB_BASE      ;配置端口B功能               LDR     R1, =GPBCON_Val               STR     R1, [R0, #GPCON_OFS]               LDR     R1, =GPBUP_Val     ;配置端口B上拉寄存器               STR     R1, [R0, #GPUP_OFS]               ENDIF                IF      GPC_SETUP != 0               LDR     R0, =GPC_BASE      ;配置端口C功能               LDR     R1, =GPCCON_Val               STR     R1, [R0, #GPCON_OFS]               LDR     R1, =GPCUP_Val     ;??置端口C上拉寄存器               STR     R1, [R0, #GPUP_OFS]               ENDIF                IF      GPD_SETUP != 0               LDR     R0, =GPD_BASE      ;配置端口D功能               LDR     R1, =GPDCON_Val               STR     R1, [R0, #GPCON_OFS]               LDR     R1, =GPDUP_Val     ;配置端口D上位寄存器               STR     R1, [R0, #GPUP_OFS]               ENDIF                IF      GPE_SETUP != 0               LDR     R0, =GPE_BASE               LDR     R1, =GPECON_Val   ;配置端口E功能               STR     R1, [R0, #GPCON_OFS]               LDR     R1, =GPEUP_Val    ;配置端口E上位寄存器               STR     R1, [R0, #GPUP_OFS]               ENDIF                IF      GPF_SETUP != 0               LDR     R0, =GPF_BASE               LDR     R1, =GPFCON_Val   ;配置端口F功能               STR     R1, [R0, #GPCON_OFS]               LDR     R1, =GPFUP_Val    ;配置端口F上位寄存器               STR     R1, [R0, #GPUP_OFS]               ENDIF                IF      GPG_SETUP != 0               LDR     R0, =GPG_BASE               LDR     R1, =GPGCON_Val   ;配置端口G功能               STR     R1, [R0, #GPCON_OFS]               LDR    R1, =GPGUP_Val    ;配置端口G上位寄存器               STR     R1, [R0, #GPUP_OFS]               ENDIF                IF      GPH_SETUP != 0               LDR     R0, =GPH_BASE               LDR     R1, =GPHCON_Val   ;配置端口H功               STR     R1, [R0, #GPCON_OFS]               LDR     R1, =GPHUP_Val    ;配置端口H上位寄存器               STR     R1, [R0, #GPUP_OFS]               ENDIF                IF      GPJ_SETUP != 0               LDR     R0, =GPJ_BASE               LDR     R1, =GPJCON_Val   ;配置端口J功               STR     R1, [R0, #GPCON_OFS]               LDR     R1, =GPJUP_Val    ;配置端口J上位寄存               STR     R1, [R0, #GPUP_OFS]               ENDIF                             ENDIF               ;-----------------------------------------------------------------------;拷贝异常向量到内部RAM;如果定义了RAM_INTVEC就执行下面一段程序;-----------------------------------------------------------------------               IF      :DEF:RAM_INTVEC               ADR     R8,  Vectors    ; 读取向量源地址               LDR     R9, =IRAM_BASE  ; 读取片上SRAM的基地址               LDMIA   R8!, {R0-R7}    ; 批量加载异常向量               STMIA   R9!, {R0-R7}    ; 批量存储向量               LDMIA   R8!, {R0-R7}    ; 加载程序入口地址(LoadHandler Addresses )               STMIA   R9!, {R0-R7}    ; 存储程序入口地址(StoreHandler Addresses)               ENDIF ;-----------------------------------------------------------------------;配置相应模式栈的大小(SetupStack for each mode );下面这一段主要是设置各个异常模式的堆栈,注意在设置的时候需要禁止IRQ和FIQ.;这段代码也是系统复位后执行的第一段代码。执行完这段代码后系统处于系统模;式,并且IRQ和FIQ都是禁止的。;-----------------------------------------------------------------------                  LDR     R0, =Stack_Top  ;加载栈顶指针地址 ;-----------------------------------------------------------------------;进入未定义模式,并设定其栈指针;-----------------------------------------------------------------------               ;将(Mode_UND| I_Bit | F_Bit)赋值给CPSR_c即CPSR[7:0]               MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit               MOV     SP, R0    ;栈顶指针地址赋值给SP指针               SUB     R0, R0, #UND_Stack_Size  ;分其栈指针                                    ;-----------------------------------------------------------------------;进入异常中断模式,并设定其栈指针;下面这三句话与上面原理一样;-----------------------------------------------------------------------               MSR     CPSR_c,#Mode_ABT:OR:I_Bit:OR:F_Bit               MOV     SP, R0               SUB     R0, R0, #ABT_Stack_Size ;-----------------------------------------------------------------------;进入FIQ模式,并设定其栈指针;下面这三句话与上面原理一样;-----------------------------------------------------------------------               MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit               MOV     SP, R0               SUB     R0, R0, #FIQ_Stack_Size ;-----------------------------------------------------------------------;进入IRQ模式,并设定其栈指针;下面这三句话与上面原理一样;-----------------------------------------------------------------------               MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit               MOV     SP, R0               SUB     R0, R0, #IRQ_Stack_Size ;-----------------------------------------------------------------------;进入Supervisor模式,并设定其栈指针;下面这三句话与上面原理一样;-----------------------------------------------------------------------               MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit               MOV     SP, R0               SUB     R0, R0, #SVC_Stack_Size ;-----------------------------------------------------------------------;进入用户模式,并设定其栈指针;下面这三句话与上面原理一样;-----------------------------------------------------------------------; Enter User Mode and set its Stack Pointer               MSR     CPSR_c, #Mode_USR               MOV     SP, R0       &