歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> 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    0x10

Mode_FIQ           EQU     0x11

Mode_IRQ          EQU     0x12

Mode_SVC         EQU     0x13

Mode_ABT          EQU     0x17

Mode_UND         EQU     0x1B

Mode_SYS         EQU     0x1F

 

I_Bit       EQU    0x80            ; when Ibit is set, IRQ is disabled

F_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     0x00000000

SVC_Stack_Size              EQU    0x00000008

ABT_Stack_Size       EQU     0x00000000

FIQ_Stack_Size        EQU    0x00000000

IRQ_Stack_Size        EQU    0x00000080

USR_Stack_Size       EQU     0x00000400

ISR_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 Address

WTCON_OFS     EQU    0x00      ; Watchdog Timer Control RegisterOffset

WTDAT_OFS      EQU    0x04       ; Watchdog Timer DataRegister    Offset

WTCNT_OFS      EQU    0x08       ; Watchdog Timer CountRegister   Offset

 

WT_SETUP       EQU     0

WTCON_Val      EQU     0x00000000

WTDAT_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 Address

LOCKTIME_OFS   EQU     0x00    ; PLL Lock Time CountRegister   Offset

MPLLCON_OFS    EQU     0x04    ; MPLL ConfigurationRegister    Offset

UPLLCON_OFS    EQU     0x08     ; UPLL ConfigurationRegister    Offset

CLKCON_OFS     EQU     0x0C      ; ClockGenerator Control Reg    Offset

CLKSLOW_OFS    EQU     0x10     ; Clock SlowControl Register    Offset

CLKDIVN_OFS    EQU    0x14        ; Clock Divider ControlRegister Offset

CAMDIVN_OFS    EQU     0x18       ;Camera Clock Divider Register  Offset

 

CLOCK_SETUP    EQU     0

LOCKTIME_Val   EQU     0x0FFF0FFF

MPLLCON_Val    EQU     0x00043011

UPLLCON_Val    EQU     0x00038021

CLKCON_Val     EQU     0x001FFFF0

CLKSLOW_Val    EQU     0x00000004

CLKDIVN_Val    EQU     0x0000000F

CAMDIVN_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 Address

BWSCON_OFS     EQU     0x00     ; Bus Width and WaitStatus Ctrl Offset

BANKCON0_OFS   EQU     0x04    ; Bank 0 ControlRegister        Offset

BANKCON1_OFS   EQU     0x08     ; Bank 1 ControlRegister        Offset

BANKCON2_OFS   EQU     0x0C     ; Bank 2 ControlRegister        Offset

BANKCON3_OFS   EQU     0x10      ; Bank 3Control Register        Offset

BANKCON4_OFS   EQU     0x14      ; Bank 4Control Register        Offset

BANKCON5_OFS   EQU     0x18       ;Bank 5 Control Register        Offset

BANKCON6_OFS   EQU     0x1C       ; Bank 6Control Register        Offset

BANKCON7_OFS   EQU     0x20        ;Bank 7 Control Register        Offset

REFRESH_OFS    EQU    0x24          ; SDRAM RefreshControl Register Offset

BANKSIZE_OFS   EQU     0x28          ; Flexible Bank Size Register    Offset

MRSRB6_OFS     EQU    0x2C           ; Bank 6 ModeRegister           Offset

MRSRB7_OFS     EQU    0x30           ; Bank 7Mode Register          Offset

 

MC_SETUP       EQU     1

BWSCON_Val     EQU     0x22000000

BANKCON0_Val   EQU     0x00000700

BANKCON1_Val   EQU     0x00000700

BANKCON2_Val   EQU     0x00000700

BANKCON3_Val   EQU     0x00000700

BANKCON4_Val   EQU     0x00000700

BANKCON5_Val   EQU     0x00000700

BANKCON6_Val   EQU     0x00018005

BANKCON7_Val   EQU     0x00018005

REFRESH_Val    EQU     0x008404F3

BANKSIZE_Val   EQU     0x00000032

MRSRB6_Val     EQU     0x00000020

MRSRB7_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 BaseAddress

GPB_BASE       EQU     0x56000010      ; GPB BaseAddress

GPC_BASE       EQU     0x56000020      ; GPC BaseAddress

GPD_BASE       EQU     0x56000030      ; GPD BaseAddress

GPE_BASE       EQU     0x56000040      ; GPE BaseAddress

GPF_BASE       EQU     0x56000050      ; GPF BaseAddress

GPG_BASE       EQU     0x56000060      ; GPG BaseAddress

GPH_BASE       EQU     0x56000070      ; GPH BaseAddress

GPJ_BASE       EQU     0x560000D0      ; GPJ BaseAddress

GPCON_OFS      EQU    0x00            ;Control Register Offset

GPDAT_OFS      EQU    0x04            ; DataRegister Offset

GPUP_OFS       EQU    0x08            ;Pull-up Disable Register Offset

 

GP_SETUP       EQU     1

 

;-----------------------------------------------------------------------

;端口A配置

;-----------------------------------------------------------------------

GPA_SETUP      EQU     0

GPACON_Val     EQU     0x000003FF

 

;-----------------------------------------------------------------------

;端口B配置

;-----------------------------------------------------------------------

GPB_SETUP      EQU     0

GPBCON_Val     EQU     0x00000000

GPBUP_Val      EQU     0x00000000

 

;-----------------------------------------------------------------------

;端口C配置

;-----------------------------------------------------------------------

GPC_SETUP      EQU     0

GPCCON_Val     EQU     0x00000000

GPCUP_Val      EQU     0x00000000

 

;-----------------------------------------------------------------------

;端口D配置

;-----------------------------------------------------------------------

GPD_SETUP      EQU     0

GPDCON_Val     EQU     0x00000000

GPDUP_Val      EQU     0x00000000

 

;-----------------------------------------------------------------------

;端口E配置

;-----------------------------------------------------------------------

GPE_SETUP      EQU     0

GPECON_Val     EQU     0x00000000

GPEUP_Val      EQU     0x00000000

 

;-----------------------------------------------------------------------

;端口F配置

;-----------------------------------------------------------------------

GPF_SETUP      EQU     0

GPFCON_Val     EQU     0x00000000

GPFUP_Val      EQU     0x00000000

 

;-----------------------------------------------------------------------

;端口G配置

;-----------------------------------------------------------------------

GPG_SETUP      EQU     0

GPGCON_Val     EQU     0x00000000

GPGUP_Val      EQU     0x00000000

 

;-----------------------------------------------------------------------

;端口H配置

;-----------------------------------------------------------------------

GPH_SETUP      EQU     0

GPHCON_Val     EQU     0x00000000

GPHUP_Val      EQU     0x00000000

 

;-----------------------------------------------------------------------

;端口J配置

;-----------------------------------------------------------------------

GPJ_SETUP      EQU     0

GPJCON_Val     EQU     0x00000000

GPJUP_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_Addr

Undef_Addr     DCD     Undef_Handler ;未定義子程序入口地址賦值給Undef_Addr

SWI_Addr       DCD     SWI_Handler   ;中斷子程序入口地址賦值給SWI_Addr

PAbt_Addr      DCD     PAbt_Handler  ;中止(預存)子程序入口地址賦給PAbt_Addr

DAbt_Addr      DCD     DAbt_Handler  ;中止(數據)子程序入口地址賦給DAbt_Addr

               DCD    0             ;保留地址     

               IF      :DEF:__RTX    ;如果定義了__RTX

IRQ_Addr       DCD     IRQ_Handler_RTX  ;快速中斷子程序入口地址給IRQ_Addr

               ELSE

IRQ_Addr       DCD     IRQ_Handler      ;否則把IRQ_Handler入口地址給IRQ_Addr

               ENDIF

FIQ_Addr       DCD     FIQ_Handler      ;快速中斷入口地址給FIQ_Addr

 

;-----------------------------------------------------------------------

;這些子程序都是用無限循環方式實現的可以被修改。

;-----------------------------------------------------------------------

 

Undef_Handler  

                                    B       Undef_Handler    ;跳轉到Undef_Handler,還是在這個地方

               IF      :DEF:__RTX      ;如果定義了DEF:__RTX,在此等待中斷

               ELSE

SWI_Handler   

                                    B       SWI_Handler     ;否則跳轉到軟件中斷

               ENDIF

PAbt_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       .   ;跳轉到當前地址即在此等待“.”代表當前指令地址

               ENDP

FIQ_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

               SUB     SL, SP, #USR_Stack_Size

 

;-----------------------------------------------------------------------

;進入用戶模式

;-----------------------------------------------------------------------

               MSR     CPSR_c, #Mode_USR

               IF      :DEF:__MICROLIB  ;如果定義了__MICROLIB

 

               EXPORT __initial_sp      ;那麼就聲明__initial_sp

 

               ELSE

 

               MOV     SP,R0           ;否則就設定用戶模式棧指針

               SUB     SL, SP, #USR_Stack_Size

 

               ENDIF

 

;-----------------------------------------------------------------------

;些處開始正式進入C代碼區

;反匯編以後C程序中的main函數名就變成了__main

;-----------------------------------------------------------------------

               IMPORT  __main      ;聲明__main 函數

               LDR     R0, =__main ;加載__main 函數入口地址

               BX     R0          ;跳轉到__main處

 

 

               IF      :DEF:__MICROLIB  ;如果定義了__MICROLIB

 

               EXPORT  __heap_base      ;則聲明__heap_base

               EXPORT  __heap_limit     ;聲明__heap_limit

 

               ELSE

;-----------------------------------------------------------------------

;用戶初始化堆與棧,用於動態申請內存使用

;__use_two_region_memory這是MDK的庫函

;__user_initial_stackheap也是一個庫函數,它的返回值有

;          * 堆基址(heapbase)  --> R0

;          * 棧基址(stackbase) --> R1 一般為棧的最高地址

;          * 堆頂(heaplimit)   --> R2

;          * 棧頂(stacklimit)  --> R3

;

;-----------------------------------------------------------------------

               AREA    |.text|, CODE, READONLY

 

               IMPORT  __use_two_region_memory

               EXPORT  __user_initial_stackheap

__user_initial_stackheap

 

               LDR     R0, = Heap_Mem  ;堆內存起始地址-->R0

               LDR     R1, =(Stack_Mem + USR_Stack_Size) ;棧起始地址-->R1

               LDR     R2, = (Heap_Mem +      Heap_Size);堆頂-->R2

               LDR     R3, = Stack_Mem  ;棧頂地址 -->R3

               BX     LR              ;子程序返回

               ENDIF

 

               END

//////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\//////////////////////////\\\\\\\\\\

:LEN:X    返回字符串X的長度(字符數)
:CHR:M    將0~255之間的整數轉換為一個字符
:STR:X    將一個數字表達式或邏輯表達式轉換為一個字符串.對於數字表達式,STR運算符將其轉換為一個以十六進制組成的字符串;對於邏輯表達式,STR運算符將其轉換為字符串T或F.
X:LEFT:Y  返回某個字符串左端的一個子串.X為源字符串,Y表示返回的個數
X:RIGHT:Y 與LEFT對應
X:CC:Y    將Y連接到X的後面
:BASE:X   返回基於寄存器的表達式中寄存器的編號
:INDEX:X  返回基於寄存器的表達式中相對於其基址寄存器的偏移量
?X        返回定義符號X的代碼行所生成的可執行代碼的字節數
:DEF:X    如果符號X已定義,則結果為真,否則為假 

Copyright © Linux教程網 All Rights Reserved