lpc2300启动代码分析

发布者:dadigt最新更新时间:2016-11-16 来源: eefocus关键字:lpc2300  启动代码 手机看文章 扫描二维码
随时随地手机看文章

;/*****************************************************************************/
;/* LPC2300.S: Startup file for Philips LPC2300 device series                 */
;/*****************************************************************************/
;/* <<< Use Configuration Wizard in Context Menu >>>                          */
;/*****************************************************************************/
;/* This file is part of the uVision/ARM development tools.                   */
;/* Copyright (c) 2007 Keil - An ARM Company. 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. */
;/*****************************************************************************/


;/*
; *  The LPC2300.S code is executed after CPU Reset. This file may be 
; *  translated with the following SET symbols. In uVision these SET 
; *  symbols are entered under Options - ASM - Define.
; *
; *  REMAP: when set the startup code initializes the register MEMMAP 
; *  which overwrites the settings of the CPU configuration pins. The 
; *  startup and interrupt vectors are remapped from:
; *     0x00000000  default setting (not remapped)
; *     0x40000000  when RAM_MODE is used
; *
; *  RAM_MODE: when set the device is configured for code execution
; *  from on-chip RAM starting at address 0x40000000. 
; */
;/*
;  启动代码是在CPU复位后执行的
;  重映象:启动代码初始化寄存器,设置好CPU的端脚,中断向量
;  默认的地址 :0x00000000,不需要重新映象
;  当程序在RAM中运行时,地址位0x40000000
;
;
;*/

; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs

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 I bit is set, IRQ is disabled
F_Bit           EQU     0x40            ; when F bit is set, FIQ is disabled

;堆栈大小设置(字节)
;// Stack Configuration (Stack Sizes in Bytes)
;//   Undefined Mode      <0x0-0xFFFFFFFF:8>
;//   Supervisor Mode     <0x0-0xFFFFFFFF:8>
;//   Abort Mode          <0x0-0xFFFFFFFF:8>
;//   Fast Interrupt Mode <0x0-0xFFFFFFFF:8>
;//   Interrupt Mode      <0x0-0xFFFFFFFF:8>
;//   User/System Mode    <0x0-0xFFFFFFFF:8>
;//

;定义各种模式堆栈的空间大小
UND_Stack_Size  EQU     0x00000000   ;定义未定义模式堆栈大小
SVC_Stack_Size  EQU     0x00000008   ;定义管理模式堆栈大小
ABT_Stack_Size  EQU     0x00000000   ;定义中止模式堆栈大小
FIQ_Stack_Size  EQU     0x00000000   ;定义快速中断模式堆栈大小
IRQ_Stack_Size  EQU     0x00000100   ;定义普通中断模式堆栈大小
USR_Stack_Size  EQU     0x00000400   ;定义用户模式堆栈大小

; 将所有的堆栈大小进行相加,得到总堆栈大小
ISR_Stack_Size  EQU     (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
                         FIQ_Stack_Size + IRQ_Stack_Size)

;开辟一个名为STACK的段,定义为可写可读,字节对齐

                AREA    STACK, NOINIT, READWRITE, ALIGN=3

;定义堆栈的空间,用户的在上面,ISR(中断处理)的在下面

Stack_Mem       SPACE   USR_Stack_Size    ;申请堆栈内存空间

__initial_sp    SPACE   ISR_Stack_Size    ;申请堆栈内存空间


Stack_Top     ;在这里放个标号,用来获得堆栈顶部地址
;// Heap Configuration
;//     Heap Size (in Bytes) <0x0-0xFFFFFFFF>
;//

Heap_Size       EQU     0x00000000                      ;(Heap)堆是C语言动态分配内存使用,是编译器自己设定,如果没

                                                                             ;有Printf ,New,Malloc之类的函数可以不设置

;开辟一个名为HEAP的段,定义为可写可读,字节对齐

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base      ;指定堆的开头
Heap_Mem        SPACE   Heap_Size
__heap_limit       ;指定堆的结尾


; System Control Block (SCB) Module Definitions
SCB_BASE        EQU     0xE01FC000      ; SCB Base Address
PLLCON_OFS      EQU     0x80            ; PLL Control Offset
PLLCFG_OFS      EQU     0x84            ; PLL Configuration Offset
PLLSTAT_OFS     EQU     0x88            ; PLL Status Offset
PLLFEED_OFS     EQU     0x8C            ; PLL Feed Offset
CCLKCFG_OFS     EQU     0x104           ; CPU Clock Divider Reg Offset
USBCLKCFG_OFS   EQU     0x108           ; USB Clock Divider Reg Offset
CLKSRCSEL_OFS   EQU     0x10C           ; Clock Source Select Reg Offset
SCS_OFS         EQU     0x1A0           ; System Control and Status Reg Offset
PCLKSEL0_OFS    EQU     0x1A8           ; Peripheral Clock Select Reg 0 Offset
PCLKSEL1_OFS    EQU     0x1AC           ; Peripheral Clock Select Reg 1 Offset

; Constants
OSCRANGE        EQU     (1<<4)          ; Oscillator Range Select
OSCEN           EQU     (1<<5)          ; Main oscillator Enable
OSCSTAT         EQU     (1<<6)          ; Main Oscillator Status
PLLCON_PLLE     EQU     (1<<0)          ; PLL Enable
PLLCON_PLLC     EQU     (1<<1)          ; PLL Connect
PLLSTAT_M       EQU     (0x7FFF<<0)     ; PLL M Value
PLLSTAT_N       EQU     (0xFF<<16)      ; PLL N Value
PLLSTAT_PLOCK   EQU     (1<<26)         ; PLL Lock Status

;时钟的建立
;// Clock Setup
;//   System Controls and Status Register (SCS)     ;系统控制和状态寄存器
;//         OSCRANGE: Main Oscillator Range Select   ;主晶振的范围选择
;//                     <0=>  1 MHz to 20 MHz
;//                     <1=> 15 MHz to 24 MHz
;//            OSCEN: Main Oscillator Enable      ;主晶振使能
;//    

;//  

;时钟源选择
;//
;//   Clock Source Select Register (CLKSRCSEL)     ;PLL时钟源选择
;//        CLKSRC: PLL Clock Source Selection
;//                     <0=> Internal RC oscillator      ;内部RC
;//                     <1=> Main oscillator    ;主晶振
;//                     <1=> RTC oscillator        ;实时时钟晶振
;//  

;PLL的配置
;//
;//   PLL Configuration Register (PLLCFG)
;//                     PLL_clk = (2* M * PLL_clk_src) / N
;//         MSEL: PLL Multiplier Selection  ;PLL倍频
;//                     <1-32768><#-1>
;//                     M Value
;//        NSEL: PLL Divider Selection    ;PLL分频
;//                     <1-256><#-1>
;//                     N Value
;//  

;CPU时钟配置
;//
;//   CPU Clock Configuration Register (CCLKCFG)
;//       CCLKSEL: Divide Value for CPU Clock from PLL   ;系统的频率,由PLL分频得到
;//                     <1-256><#-1>
;//  

;USB时钟配置
;//
;//   USB Clock Configuration Register (USBCLKCFG)
;//        USBSEL: Divide Value for USB Clock from PLL    ;USB的频率,由PLL分频得到
;//                     <1-16><#-1>
;//  

;外设时钟选择
;//
;//   Peripheral Clock Selection Register 0 (PCLKSEL0)
;//           PCLK_WDT: Peripheral Clock Selection for WDT   ;WDT的外设时钟
;//                     <0=> Pclk = Cclk / 4        ;系统时钟/4
;//                     <1=> Pclk = Cclk         ;系统时钟
;//                     <2=> Pclk = Cclk / 2        ;系统时钟/2
;//                     <3=> Pclk = Hclk / 8        ;AHB总线时钟/2

;//        PCLK_TIMER0: Peripheral Clock Selection for TIMER0    ;TIMER0时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//        PCLK_TIMER1: Peripheral Clock Selection for TIMER1   ;TIMER0时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//         PCLK_UART0: Peripheral Clock Selection for UART0    ;UART0时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//         PCLK_UART1: Peripheral Clock Selection for UART1    ;UART1时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//        PCLK_PWM0: Peripheral Clock Selection for PWM0    ;PWM0时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//        PCLK_PWM1: Peripheral Clock Selection for PWM1    ;PWM1时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//        PCLK_I2C0: Peripheral Clock Selection for I2C0    ;I2C0时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//         PCLK_SPI: Peripheral Clock Selection for SPI     ;SPI时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//         PCLK_RTC: Peripheral Clock Selection for RTC     ;RTC 时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//        PCLK_SSP1: Peripheral Clock Selection for SSP1    ;SSP1时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//         PCLK_DAC: Peripheral Clock Selection for DAC      ;DAC时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//         PCLK_ADC: Peripheral Clock Selection for ADC      ;ADC时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//        PCLK_CAN1: Peripheral Clock Selection for CAN1  ;CAN总线1时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 6
;//        PCLK_CAN2: Peripheral Clock Selection for CAN2     ;CAN总线2时钟选择
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 6
;//         PCLK_ACF: Peripheral Clock Selection for ACF     ;高级通讯时钟选择
;//                     <0=> Pclk = Cclk / 4          ;在这为以太网
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 6
;//  

;外设时钟选择
;//
;//   Peripheral Clock Selection Register 1 (PCLKSEL1)
;//       PCLK_BAT_RAM: Peripheral Clock Selection for the Battery Supported RAM  ;电池RAM
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//          PCLK_GPIO: Peripheral Clock Selection for GPIOs    ;GPIO 时钟
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//           PCLK_PCB: Peripheral Clock Selection for Pin Connect Block   ;引脚连接模块时钟
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//          PCLK_I2C1: Peripheral Clock Selection for I2C1      ;I2C1时钟
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8             ;SSP1时钟
;//        PCLK_SSP0: Peripheral Clock Selection for SSP0
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//     PCLK_TIMER2: Peripheral Clock Selection for TIMER2    ;TIMER2时钟
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//     PCLK_TIMER3: Peripheral Clock Selection for TIMER3        ;TIMER3时钟
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//       PCLK_UART2: Peripheral Clock Selection for UART2    ;UART2时钟
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//       PCLK_UART3: Peripheral Clock Selection for UART3       ;UART3时钟
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8          ;I2C2时钟
;//        PCLK_I2C2: Peripheral Clock Selection for I2C2
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//         PCLK_I2S: Peripheral Clock Selection for I2S      ;I2S(数字音频设备)时钟
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//         PCLK_MCI: Peripheral Clock Selection for MCI     ;MCI(媒体控制接口)时钟
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//     PCLK_SYSCON: Peripheral Clock Selection for System Control Block ;系统控制模块时钟
;//                     <0=> Pclk = Cclk / 4
;//                     <1=> Pclk = Cclk
;//                     <2=> Pclk = Cclk / 2
;//                     <3=> Pclk = Hclk / 8
;//  

;//
CLOCK_SETUP     EQU     1
SCS_Val         EQU     0x00000020     ;使用外部晶振
CLKSRCSEL_Val   EQU     0x00000001     ;选择主晶振的PLL输出
;Fcco(电流控制振荡器)的范围为275MHZ~550MHZ
;Fin 的范围为32k~50MHZ
;Fcco=(2*M*Fin)/N
;M,N在写入寄存器的时候减1

;Fcco=(2*12*12M)/1=288M,LPC2378的FCCO范围:275MHZ~550MHZ
PLLCFG_Val      EQU     0x0000000B

;Fcclk=PLL/CCLKSEL=288M/4=72MHZ
CCLKCFG_Val     EQU     0x00000003   ;CCLKCFG的值必须为0或者奇数,否则会引起器件的不正确操作

;USB时钟=PLL/USBSEL=288/6=48MHZ
USBCLKCFG_Val   EQU     0x00000005

;外设时钟=CCLK/4=72MHZ/4=18MHZ
PCLKSEL0_Val    EQU     0x00000000
PCLKSEL1_Val    EQU     0x00000000

;内存加速模块
; Memory Accelerator Module (MAM) definitions
MAM_BASE        EQU     0xE01FC000      ; MAM Base Address
MAMCR_OFS       EQU     0x00            ; MAM Control Offset
MAMTIM_OFS      EQU     0x04            ; MAM Timing Offset

;内存加速模块控制
;// MAM Setup
;//      MAM Control
;//               <0=> Disabled        ;全部禁止
;//               <1=> Partially Enabled  ;部分使能
;//               <2=> Fully Enabled   ;全部使能
;//               Mode      ;保留
;//      MAM Timing
;//               <0=> Reserved  <1=> 1   <2=> 2   <3=> 3
;//               <4=> 4         <5=> 5   <6=> 6   <7=> 7
;//               Fetch Cycles
;//

MAM_SETUP       EQU     1      ; MAM 设置程序判断标志
MAMCR_Val       EQU     0x00000002    ; MAM全部使能
MAMTIM_Val      EQU     0x00000004    ; MAM,4个CPU时钟访问一次内存


; Area Definition and Entry Point
;  Startup Code must be linked first at Address at which it expects to run.

;程序入口点,每个ARM必须至少要有一个入口

                AREA    RESET, CODE, READONLY  
                ARM


; Exception Vectors
;  Mapped to Address 0.
;  Absolute addressing mode must be used.
;  Dummy Handlers are implemented as infinite loops which can be modified.

;配置各中断向量
Vectors         LDR     PC, Reset_Addr           ;//引入复位地址
                LDR     PC, Undef_Addr    ;//引入未定义地址
                LDR     PC, SWI_Addr    ;//引入软件中断地址
                LDR     PC, PAbt_Addr    ;//引入中止(预取指)地址
                LDR     PC, DAbt_Addr    ;//引入中止(数据)地址

                NOP                            ; Reserved Vector

                LDR     PC, IRQ_Addr    ;//引入中断地址
                LDR     PC, [PC, #-0x0120]      ;Vector from VicVectAddr
                LDR     PC, FIQ_Addr    ;//引入快速中断地址

Reset_Addr      DCD     Reset_Handler
Undef_Addr      DCD     Undef_Handler
SWI_Addr        DCD     SWI_Handler
PAbt_Addr       DCD     PAbt_Handler
DAbt_Addr       DCD     DAbt_Handler
                DCD     0                      ; Reserved Address 
IRQ_Addr        DCD     IRQ_Handler
FIQ_Addr        DCD     FIQ_Handler

Undef_Handler   B       Undef_Handler   ;B为跳转指令,跳转到某个地方
SWI_Handler     B       SWI_Handler
PAbt_Handler    B       PAbt_Handler
DAbt_Handler    B       DAbt_Handler
IRQ_Handler     B       IRQ_Handler
FIQ_Handler     B       FIQ_Handler


; Reset Handler

                EXPORT  Reset_Handler     ;导出定义一个全局函数名变量
Reset_Handler  


;设置时钟
; Setup Clock
                IF      CLOCK_SETUP != 0
                LDR     R0, =SCB_BASE
    ;使PLL配置寄存器有效
                MOV     R1, #0xAA
                MOV     R2, #0x55
;配置使能PLL
;  Configure and Enable PLL        
                LDR     R3, =SCS_Val          ; Enable main oscillator
                STR     R3, [R0, #SCS_OFS]    ;SCS<=SCS_Val ,主晶振使能,使用外部引脚的晶振 

                IF      (SCS_Val:AND:OSCEN) != 0  ;晶振是否已经稳定,继续判断
OSC_Loop        LDR     R3, [R0, #SCS_OFS]    ; Wait for main osc stabiliz  等待主晶振稳定
                ANDS    R3, R3, #OSCSTAT
                BEQ     OSC_Loop      ;
                ENDIF
             
                LDR     R3, =CLKSRCSEL_Val    ; Select PLL source clock
                STR     R3, [R0, #CLKSRCSEL_OFS]   ; CLKSRCSEL<=0x00000001 ,选择主晶振作为PLL时钟源

                LDR     R3, =PLLCFG_Val    ; PLLCFG <=0x0000000B,M,N赋值
                STR     R3, [R0, #PLLCFG_OFS]

                STR     R1, [R0, #PLLFEED_OFS]  ; PLLFEED <=0xAA
                STR     R2, [R0, #PLLFEED_OFS]  ; PLLFEED <=0x55

                MOV     R3, #PLLCON_PLLE   ; PLLCON  <= 1<<0,PLL使能
                STR     R3, [R0, #PLLCON_OFS]

                STR     R1, [R0, #PLLFEED_OFS]  ; PLLFEED <=0xAA
                STR     R2, [R0, #PLLFEED_OFS]  ; PLLFEED <=0x55

;等待PLL锁存
;  Wait until PLL Locked
PLL_Loop        LDR     R3, [R0, #PLLSTAT_OFS]  ;;读PLLSTAT
                ANDS    R3, R3, #PLLSTAT_PLOCK    ;是否PLL已经锁定
                BEQ     PLL_Loop

M_N_Lock        LDR     R3, [R0, #PLLSTAT_OFS]     ;读PLLSTAT的状态
                LDR     R4, =(PLLSTAT_M:OR:PLLSTAT_N) ;读M,N的值
                AND     R3, R3, R4              ;R3=R3&&R4,M,N和锁存状态

                LDR     R4, =PLLCFG_Val       ;R4<=M,N的值
                EORS    R3, R3, R4        ;M,N的设定值是否与读出值相等
                BNE     M_N_Lock

;设置CPU时钟
;  Setup CPU clock divider
                MOV     R3, #CCLKCFG_Val    ;CPU时钟为PLL时钟/5
                STR     R3, [R0, #CCLKCFG_OFS]

;设置USB时钟
;  Setup USB clock divider
                LDR     R3, =USBCLKCFG_Val     ;USB时钟为PLL时钟/6
                STR     R3, [R0, #USBCLKCFG_OFS]

;设置外设时钟
;  Setup Peripheral Clock
                LDR     R3, =PCLKSEL0_Val        ;外设时钟=CPU时钟/4=57.6MHZ/4=14.4MHZ
                STR     R3, [R0, #PCLKSEL0_OFS]
                LDR     R3, =PCLKSEL1_Val
                STR     R3, [R0, #PCLKSEL1_OFS]

;开启PLL时钟
;  Switch to PLL Clock
                MOV     R3, #(PLLCON_PLLE:OR:PLLCON_PLLC)  ;PLL使能并连接
                STR     R3, [R0, #PLLCON_OFS]

                STR     R1, [R0, #PLLFEED_OFS]               ;PLLFEED <=0xAA
                STR     R2, [R0, #PLLFEED_OFS]      ;PLLFEED <=0x55
                ENDIF   ; CLOCK_SETUP

;设置MAM 存储器加速模块
; Setup MAM
                IF      MAM_SETUP != 0
                LDR     R0, =MAM_BASE
                MOV     R1, #MAMTIM_Val             ;4个CPU时钟访问依次内存
                STR     R1, [R0, #MAMTIM_OFS]

                MOV     R1, #MAMCR_Val       ;内存加速全部使能
                STR     R1, [R0, #MAMCR_OFS] 
                ENDIF   ; MAM_SETUP

;内存映射(当中断向量是在内存)
; Memory Mapping (when Interrupt Vectors are in RAM)
MEMMAP          EQU     0xE01FC040      ; Memory Mapping Control
                IF      :DEF:REMAP
                LDR     R0, =MEMMAP
                IF      :DEF:RAM_MODE
                MOV     R1, #2
                ELSE
                MOV     R1, #1
                ENDIF
                STR     R1, [R0]
                ENDIF

; 初始化中断堆栈系统
; Initialise Interrupt System
;  ...


;设置每一个工作模式堆栈
; Setup Stack for each mode

                LDR     R0, =Stack_Top                              ;R0设置为堆栈的首地址

; 进入未定义模式,并设置堆栈指针
;  Enter Undefined Instruction Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #UND_Stack_Size             ;每设置完一种模式的堆栈,就减去,得到下一堆栈的首地址

;进入中止模式,并设置堆栈指针
;  Enter Abort Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #ABT_Stack_Size

;进入快速中断模式,并设置堆栈指针
;  Enter FIQ Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #FIQ_Stack_Size

;进入普通中断模式,并设置堆栈指针
;  Enter IRQ Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #IRQ_Stack_Size

;进入管理(特权)模式,并设置堆栈指针
;  Enter Supervisor Mode and set its Stack Pointer
                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
                IF      :DEF:__MICROLIB

                EXPORT __initial_sp

                ELSE

                MOV     SP, R0
                SUB     SL, SP, #USR_Stack_Size

                ENDIF

 ;进入C代码, __main前的下划线不要去,进入C代码库的初始化函数,再进入用户的函数
; Enter the C code

                IMPORT  __main
                LDR     R0, =__main
                BX      R0


                IF      :DEF:__MICROLIB

                EXPORT  __heap_base
                EXPORT  __heap_limit

                ELSE

;用户设置堆栈程序(C外部接口:用于动态申请内存使用)
; User Initial Stack & Heap
                AREA    |.text|, CODE, READONLY

                IMPORT  __use_two_region_memory
                EXPORT  __user_initial_stackheap
__user_initial_stackheap

                LDR     R0, =  Heap_Mem
                LDR     R1, =(Stack_Mem + USR_Stack_Size)
                LDR     R2, = (Heap_Mem +      Heap_Size)
                LDR     R3, = Stack_Mem
                BX      LR
                ENDIF


                END


关键字:lpc2300  启动代码 引用地址:lpc2300启动代码分析

上一篇:GPRS和ARM相配合的软件无线升级系统设计
下一篇:s3c2410 LCD驱动学习心得

推荐阅读最新更新时间:2024-03-16 15:20

分析ARM启动代码和中断处理过程
之前有分析过44b0下的这个启动代码,差别不是非常大,今天再重新看了一遍。启动代码与 Bootloader不同,主要是指进入C语言之前的汇编代码,网上都称为是bootloader的stage1,一般通用的内容包括: 1. 定义程序入口点 2. 设置异常向量表 3. 初始化存储系统 4. 初始化用户程序的执行环境 5. 初始化堆栈指针寄存器,改变处理器的模式 6. 设置FIQ/IRQ中断处理程序入口 7. 进入C程序 1)编译器选择 GBLL THUMBCODE 因为处理器分为16位 32位两种工作状态,程序的编译器也是分16位和32两种编译方式,所以这段程序用于根据处理器工作状态确定编译器编译方式,程序不难理解,主
[单片机]
STM32启动代码分析
启动代码文件名是STM32F10X.S,它的作用先总结下,然后再分析。启动代码作用一般是:1)堆和栈的初始化;2)向量表定义;3)地址重映射及中断向量表的转移;4)设置系统时钟频率;5)中断寄存器的初始化;6)进入C应用程序。 (1)按启动代码的次序,先看堆和栈的初始化: Stack_Size EQU 0x00000200 ;定义Stack_Size为0x00000200 AREA STACK, NOINIT, READWRITE, ALIGN=3 ;定义栈,可初始为0,8字节对齐 Stack_Mem
[单片机]
STM32 启动代码 __main 与用户主程序 main() 的区别
1、__main 作用 __main函数是C/C++运行时库的一个函数,嵌入式系统在进入应用主程序之前必须有一个初始化的过程,使用__main标号引导系统时必须将应用程序的入口定义为main()。 在初始化的过程中,__main函数的作用主要有两点: 1) 完成对映像文件的初始化操作 a、映像文件 链接器把多个目标文件链接成一个映像文件。 b、加载地址和执行地址 映像文件可以有两种地址:加载地址和执行地址。 加载地址是映像文件在存储器中的存储地址;执行地址就是映像文件运行时的地址。 c、加载域和执行域 文件加载的存储区叫加载域,文件运行的存储区叫执行域。 d、从加载地址到执行地址 在结构比较简单的系统中,加载地址就是执行地
[单片机]
STM32 <font color='red'>启动</font><font color='red'>代码</font> __main 与用户主程序 main() 的区别
ARM的启动代码(3):异常向量
ARM的启动代码是非常重要的代码,直接关系到系统的稳定性和可靠性(这里主要讨论arm7, arm9;cortex系列的会在后续的文章中讨论)。上次我们通过两则文章讨论了ARM启动代码的过程, ARM的启动代码(1):介绍 ARM的启动代码(2):AT91SAM9260启动详解 这次我们聊聊ARM的代码的具体编写。那么什么样的代码会涉及到这些问题呢? 1.Bootloader或者位于启动序列上进行加载其他应用程序的程序; 2.单独的二进制镜像,直接可以在ARM处理器上直接执行。 这两种代码都需要对 ARM 的启动过程有深入理解。说深入理解,其实只有一条,闹闹记住,ARM7,ARM9的异常向量表从地址0开始。这是铁打不能改
[单片机]
STM32启动代码概述
一般嵌入式开发流程就是先建立一个工程,再编写源文件,然后进行编译,把所有的 *.s文件和 *.c文件编译成一个 *.o文件,再对目标文件进行链接和定位,编译成功后会生成一个 *.hex文件和调试文件,接下来要进行调试,如果成功的话,就可以将它固化到 flash 里面去。 启动代码是用来初始化电路以及用来为高级语言写的软件作好运行前准备的一小段汇编语言,是任何处理器上电复位时的程序运行入口点。 比如,刚上电的过程中,PC机会对系统的一个运行频率进行锁定在一个固定的值,这个设计频率的过程就是在汇编源代码中进行的,也就是在启动代码中进行的。与此同时,设置完后,程序开始运行,注意,程序是在内存中运行的。这个时候,就需要把一些源文件
[单片机]
STM32<font color='red'>启动</font><font color='red'>代码</font>概述
快速学Arm(24)--lpc2300系统时钟3
接着上一篇我们再来介绍一下2300系统时钟中的时钟分频器.由于PLL的输出频率在275MHz到550MHz之间,而LPC2300系列ARM最高只能工作在72MHz,所以PLL输出的频率必须经过分频后才能提供给CPU内核和外设使用. 时钟分频作用. 1.将Fcco分频提供给CPU和USB使用. 2.将处理器时钟(Fcclk)分频,以便外设在合适的速度下工作. LPC2300系列ARM时钟分频器含有三类寄存器,其结构如下图所示: 1.CPU时钟配置寄存器:通过设置CPU时钟配置寄存器可以使Fcco分频到CPU所能正常运行的频率范围.其分频值只能是0或奇数.(寄存器:CCLKCFG,CCLKSEL) 2.USB时钟配置
[单片机]
快速学Arm(24)--<font color='red'>lpc2300</font>系统时钟3
周立功lpc21xx/lpc22xx系列ARM7启动代码分析
网上已经有人做了一个周立功lpc2000(ARM7TDMI)启动代码分析的文章, 我本来想做一个s3c2410(ARM920T)的启动代码分析的, 但是看来了一下2410的启动代码,发现有些东西还不是理解的很清楚, 我ARM9的经验比较少. 所以还是做一个ARM7的启动代码分析吧, 网上那一份相比,我这个主要关注startup.s文件.网上那个startup.s几乎是一笔带过的. 红色标记的是源码. SVC_STACK_LEGTH EQU 0 FIQ_STACK_LEGTH EQU 0 IRQ_STACK_LEGTH EQU 256 ABT_STACK_LEGTH
[单片机]
周立功lpc21xx/lpc22xx系列ARM7<font color='red'>启动</font><font color='red'>代码</font>分析
cortex-m3启动代码详解
1.1 启动代码内容 1) 硬件初始化:最起码的是要初始化堆栈指针。 2) C语言环境 :在main函数调用之前要完成对一些变量的初始化。 3) 应用初始化: 这主要取决于你的应用。比如设置系统的晶振、时钟。 1.2 图解M3启动过程 1)程序开始运行,系统启动代码首先要完成硬件初始化,比如说对堆栈的初始化。图中显示初始化堆栈指针为之前 预先定义好堆栈区域的末尾(M3内核堆栈时向下生长)。 2)初始化变量初始值为0全局变量和静态变量 3)初始化变量初始值为非0的变量,链接器将存储在ROM的初始值复制到相应的RAM中。 4)初始化应用(可选) 5)最后调用主函数 6)附录 关于C语言中变量的存储
[单片机]
cortex-m3<font color='red'>启动</font><font color='red'>代码</font>详解
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多每日新闻
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved