×
单片机 > 单片机程序设计 > 详情

ARM启动代码注释

发布时间:2020-06-05 发布时间:
|
\\\\\\\\\\\\\

下边是完整的工程

运行平台:mini2440

启动代码ourdev_444408.rar(文件大小:61K) (原文件名:MicroOS.rar)  
;--------------------------------------------------------------------- 
;startup.s 
;系统启动代码 
;起始时间 : 2009.5.7 ----->2009.5.11 
;--------------------------------------------------------------------- 



;--------------------------------------------------------------------- 
GET ./Include/s3c2440.inc ;寄存器地址信息 
GET ./Include/memcfg.inc ;内存控制器配置信息 

;处理器模式 
USERMODE EQU  0x10 
FIQMODE EQU  0x11 
IRQMODE EQU  0x12 
SVCMODE EQU  0x13 
ABORTMODE EQU  0x17 
UNDEFMODE EQU  0x1b 
SYSMODE EQU 0x1f 
;相关掩码 
MODEMASK     EQU  0x1f 
NOINT EQU  0xc0 

;各个处理器模式下堆栈设置 
_STACK_BASEADDRESS EQU 0x33ff8000 ;BANK6 64MB顶部 
UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~ 
SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~ 
UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~ 
AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~ 
IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~ 
FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~ 

;导入操作系统入口函数 
IMPORT OSEntry 

;导入外部C语言编写的异常与中断处理函数 
IMPORT vectorUNDEF 
IMPORT vectorSWI 
IMPORT vectorPABT 
IMPORT vectorDABT 
IMPORT vectorIRQ 
IMPORT vectorFIQ 

;导入镜像装载域段起始地址 
IMPORT  |Image$$RO$$Limit|  ; End of ROM code (=start of ROM data) 
IMPORT  |Image$$RW$$Base|   ; Base of RAM to initialise 
IMPORT  |Image$$ZI$$Base|   ; Base and limit of area 
IMPORT  |Image$$ZI$$Limit|  ; to zero initialise 
;-------------------------------------------------------------------- 


;------------------------------------------------------ 
AREA startup, CODE, READONLY 

ENTRY 

;系统向量表 

 b vectorRESET ;复位向量 
 b vectorUNDEF ;未定义指令 
 b vectorSWI ;软中断 
 b vectorPABT ;预取指终止 
 b vectorDABT ;数据终止 
 b . ;系统保留 
 b vectorIRQ ;外部中断 
 b vectorFIQ ;快速中断 
;------------------------------------------------------- 

;-------------------------------------------------------------------------- 
;复位向量 
;复位向量是ARM处理器上电后第一个被执行的异常 
;此时系统处理管理(SVC)模式 

vectorRESET 

;复位向量有以下六件事要做 

;第一步 : 关闭看门狗定时器屏蔽所有中断 
;第二步 : 配置系统时钟 
;第三步 : 配置内存控制器 
;第四步 : 配置每种处理器模式下堆栈指针 
;第五步 : 初始化镜像运行域 
;第六步 : 跳转到操作系统入口 


;------------------------------------------ 
;第一步 : 关闭看门狗定时器 
;具体内容请参看s3c2440a数据手册的第18章 
ldr r0, =WTCON 
ldr  r1, =0x0 
str  r1, [r0, #0x0] 

;屏蔽所有中断 
ldr r0, =INTMSK 
ldr r1, =0xffffffff 
str r1, [r0] 
;------------------------------------------ 



;------------------------------------------ 
;第二步 : 配置系统时钟 
;具体内容请看手册第7章 

;先减少锁相环锁定时间,s3c2440a要求PLL 
;锁定时间>300us,在上电时s3c2440a预设值 
;mpll为晶体频率,我用的晶体频率为12MHz 
;300us*12M = 3600设置LOCKTIME = 0xfff 
;足够了 
ldr r0, =LOCKTIME 
ldr r1, =0xfff0fff0 ;高16为对应UPLL 
;低16为对应MPLL 
str r1, [r0, #0x0] 

;根据器件手册我们还有以下几个事要做 
;step1.配置UPLL 
;step2.配置MPLL 
;注:手册要求先配置UPLL后MPLL 
; 且之间要间隔7NOP 
; 详请看手册第7-21. 
;step3.配置分频系数 

;step1: 
ldr r0, =UPLLCON 
ldr r1, =((56<<12) + (2<<4) + 2) 
ldr r1, [r0] 

;按手册要求插入7个NOP 
nop 
nop 
nop 
nop 
nop 
nop 
nop 

;step2: 
ldr r0, =MPLLCON 
ldr r1, =((127<<12) + (2<<4) + 1) 
ldr r1, [r0] 

;step3: 
ldr r0, =CLKDIVN 
ldr r1, =((0<<3) + (2 < ldr r1, [r0] 
;------------------------------------------ 



;------------------------------------------ 
;第三步 : 配置内存控制器 
;内存控制内的寄存器器地址是连续分布的 
;从0x4800_0000 -- 0x4800_0030,所以可以 
;通过一个循环依次填入各个寄存器的内容 

ldr r0, =SMRDATA ;装入配置值的地址 
ldr r1, =BWSCON ;装入起始寄存器地址 
add r2, r0, #0x34 ;计算结束地址 

;下面是用于向内存控制器 
;装入配置信息的循环 

ldr r3, [r0], #4 ;装入配置值到r3,后变址 
str r3, [r1], #4  ;把r3内包含的配置值写入 
;内存控制器的寄存器 
cmp r2, r0 ;结束否? 
bne %B0 ;没结束则继续 
;------------------------------------------ 



;------------------------------------------ 
;第四步 : 配置每种处理器模式下堆栈指针 
;方法与原则: 
;1: 通过CPSR寄存器切换处理器模式 
;2: 对CPSR的操作方式为 读-修改-写回 
;3: 绝对不要跳到用户模式,跳过去容易 
; 回来就难了 
;4: 切到新处理器模式后要屏蔽IRQ和FIQ 
; 防止在未设置好堆栈前进入中断处理 
; 程序,但是在启动代码的最先我们已 
; 经屏蔽了所有的32个中断源,所以感 
; 觉是否屏蔽都可以 

;step1: 先把程序状态寄存器读到r0 
mrs r0, cpsr 

;step2: 清除处理器模式位(最前面5位) 
bic r0, r0, #MODEMASK 

;step3: 设置未定义状态下的堆栈指针 
orr r1, r0, #UNDEFMODE|NOINT 
msr cpsr_cxsf, r1 ;UndefMode 
ldr sp, =UndefStack ;UndefStack=0x33FF_5C00 

;step4: 设置终止状态下的堆栈指针 
orr r1, r0, #ABORTMODE|NOINT 
msr cpsr_cxsf, r1 ;AbortMode 
ldr sp, =AbortStack ;AbortStack=0x33FF_6000 

;step5: 设置中断模式下的堆栈指针 
orr r1, r0, #IRQMODE|NOINT 
msr cpsr_cxsf, r1 ;IRQMode 
ldr sp, =IRQStack ;IRQStack=0x33FF_7000 

;step6: 设置快速中断模式下的堆栈指针 
orr r1, r0, #FIQMODE|NOINT 
msr cpsr_cxsf, r1 ;FIQMode 
ldr sp, =FIQStack ;FIQStack=0x33FF_8000 

;step7: 设置管理模式下的堆栈指针 
orr r1, r0, #SVCMODE|NOINT 
msr cpsr_cxsf, r1 ;SVCMode 
ldr sp, =SVCStack ;SVCStack=0x33FF_5800 

;step8: 因为管理模式与用户模式共用 
; 堆栈指针,所以借着系统模式 
; 来设置用户模式的堆栈指针 
orr r1, r0, #SYSMODE|NOINT 
msr cpsr_cxsf, r1 ;SYSMode 
ldr sp, =UserStack ;SVCStack & USERMode=0x33ff4800 

;现在处理器处于系统模式 
;------------------------------------------ 
    
    
    
;------------------------------------------ 
;第五步 : 初始化镜像运行域 
;复制RW段和ZI段到SDRAM指定地址 

LDR     r0, =|Image$$RO$$Limit| ; 装入RO段结束地址 
LDR     r1, =|Image$$RW$$Base|  ; 装入RW段起始地址 
LDR     r3, =|Image$$ZI$$Base|  ; 装入ZI段起始地址 


;|Image$$RO$$Limit| == |Image$$RW$$Base| ? 跳过RW段复制 : 复制RW段 
CMP     r0, r1      
BEQ     %F2 

;复制RW段 
1        
CMP     r1, r3   
LDRCC   r2, [r0], #4      
STRCC   r2, [r1], #4 
BCC     %B1 
2        
LDR     r1, =|Image$$ZI$$Limit|  
MOV     r2, #0 

;构造ZI段 
3        
CMP     r3, r1      
STRCC   r2, [r3], #4 
BCC     %B3 

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



;------------------------------------------ 
;第六步 : 跳转到操作系统入口 

b OSEntry ;不要使用main,因为如果使用main 
;ads还会调用_main()初始化RW和ZI 
;段,但是那里的数据和本程序不同 

b . 

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

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



SMRDATA DATA 

;这里是内存控制器的配置数据 
;配置数据需要根据你使用的存储器修改 
;在第三步时会将以下数据写入 
;内存控制器的相关寄存器中 
;共13个寄存器的配置值 

DCD (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) 
DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))   ;GCS0 
DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))   ;GCS1 
DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))   ;GCS2 
DCD ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))   ;GCS3 
DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))   ;GCS4 
DCD ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))   ;GCS5 
DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))    ;GCS6 
DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))    ;GCS7 
DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) 
DCD 0x32     ;SCLK power saving mode, BANKSIZE 128M/128M 
DCD 0x30     ;MRSR6 CL=3clk 
DCD 0x30     ;MRSR7 CL=3clk 

ALIGN ;数据边界对齐 

END 


我在写一个arm920T的微型OS,主要是想借着写OS的过程学习ARM的底层编程,然后跳到Linux。启动代码是固件的一部分,最经学校要搞个设计,不知OS什么时候能写好,反正搞定后立即发帖。 

                                  

;*

;* 文件名称 : 2410INIT.S 

;* 文件功能 : S3C2410 启动代码,配置存储器,ISR,堆栈,初始化C向量地址

;* 补充说明 :

;*-------------------------------------------- 最新版本信息 -------------------------------------------------

;* 修改作者 : ARM开发小组

;* 修改日期 : 2004/00/00

;* 版本声明 : V0.1

;*-------------------------------------------- 历史版本信息 -------------------------------------------------

;* 文件作者 : kwtark(samsung)

;* 创建日期 : 2002/02/25

;* 版本声明 : ver 0.0

;             2002/03/20: purnnamu: Add some functions for testing STOP,POWER_OFF mode

;             2002/04/10: SJS:sub interrupt disable 0x3ff -> 0x7ff

;*-----------------------------------------------------------------------------------------------------------

;*************************************************************************************************************

;*/

 GET 2410addr.s                   ;定义了2410各各寄存器的地址

 GET memcfg.s                     ;定义了2410各内存bank的带宽值和访问参数

BIT_SELFREFRESH EQU (1<<22)       ;定义了几个常数 _STACK_BASEADDRESS  EQU   0x33ff8000     堆栈基地址

                                  ;               _ISR_STARTADDRESS   EQU   0x33ffff00     中断向量表基地址

;Pre-defined constants            处理器模式预定义常量

USERMODE    EQU  0x10

FIQMODE     EQU  0x11

IRQMODE     EQU  0x12

SVCMODE     EQU  0x13

ABORTMODE   EQU  0x17

UNDEFMODE   EQU  0x1b

MODEMASK    EQU  0x1f

NOINT       EQU  0xc0             ;屏蔽中断位

 

;/*************定义处理器各模式下堆栈地址常量*******************/

UserStack   EQU (_STACK_BASEADDRESS-0x3800)      ;0x33ff4800 ~

SVCStack    EQU (_STACK_BASEADDRESS-0x2800)      ;0x33ff5800 ~

UndefStack  EQU (_STACK_BASEADDRESS-0x2400)      ;0x33ff5c00 ~

AbortStack  EQU (_STACK_BASEADDRESS-0x2000)      ;0x33ff6000 ~

IRQStack    EQU (_STACK_BASEADDRESS-0x1000)      ;0x33ff7000 ~

FIQStack    EQU (_STACK_BASEADDRESS-0x0)       ;0x33ff8000 ~

 

;/* Check if tasm.exe(armasm -16 ...@ADS 1.0) is used.   ADS编译器的检查 */

 GBLL    THUMBCODE

 [ {CONFIG} = 16

THUMBCODE SETL  {TRUE}

     CODE32

     |  

THUMBCODE SETL  {FALSE}

 ]

     MACRO

 MOV_PC_LR

 [ THUMBCODE

            bx lr

     |

            mov pc,lr

 ]

    MEND

 

     MACRO

 MOVEQ_PC_LR

 [ THUMBCODE

         bxeq lr

     |

         moveq pc,lr

 ]

    MEND

 

;/*******************************************************************************************************/

;                          正式代码的开始,首先是分配中断向表    

;/******************************************************************************************************/

     MACRO               ;先定义了一个负责处理中断宏

$HandlerLabel HANDLER $HandleLabel

$HandlerLabel

 sub sp,sp,#4                ;减少sp,保存跳转地址

 stmfd sp!,{r0}              ;PUSH the work register to stack(lr does't push because it return to original address)

 ldr     r0,=$HandleLabel    ;load the address of HandleXXX to r0

 ldr     r0,[r0]             ;load the contents(service routine start address) of HandleXXX

 str     r0,[sp,#4]          ;store the contents(ISR) of HandleXXX to stack

 ldmfd   sp!,{r0,pc}         ;POP the work register and pc(jump to ISR)

    MEND

 

 IMPORT  |Image$$RO$$Limit|  ;End of ROM code (=start of ROM data)

 IMPORT  |Image$$RW$$Base|   ;Base of RAM to initialise

 IMPORT  |Image$$ZI$$Base|   ;Base and limit of area

 IMPORT  |Image$$ZI$$Limit|  ;to zero initialise

 

 IMPORT  Main            ;The main entry of mon program 

                             ;指示编译器的符号不是在本源文件中定义的,而是在其他源文件中

                             ;定义的,在本源文件中可能引用该符号

    AREA    Init,CODE,READONLY               ;声明一个代码段,名为:Init

 ENTRY                                       ;程序的入口点

 ;//1)The code, which converts to Big-endian, should be in little endian code.

 ;//2)The following little endian code will be compiled in Big-Endian mode.

 ;//  The code byte order should be changed as the memory bus width.

 ;//3)The pseudo instruction,DCD can't be used here because the linker generates error.

 ASSERT :DEF:ENDIAN_CHANGE                   ;//断言已经定义大端模式

 [ ENDIAN_CHANGE

     ASSERT  :DEF:ENTRY_BUS_WIDTH

     [ ENTRY_BUS_WIDTH=32

  b ChangeBigEndian       ;DCD 0xea000007

     ]

    

     [ ENTRY_BUS_WIDTH=16

  andeq r14,r7,r0,lsl #20   ;DCD 0x0007ea00

     ]

    

     [ ENTRY_BUS_WIDTH=8

  streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea

     ]

 |

     b ResetHandler 

 ]

 b HandlerUndef      ;handler for Undefined mode

 b HandlerSWI        ;handler for SWI interrupt

 b HandlerPabort      ;handler for PAbort

 b HandlerDabort       ;handler for DAbort

 b .               ;reserved

 b HandlerIRQ        ;handler for IRQ interrupt

 b HandlerFIQ        ;handler for FIQ interrupt

;//@0x20

 b EnterPWDN

ChangeBigEndian

;//@0x24

 [ ENTRY_BUS_WIDTH=32

     DCD 0xee110f10 ;0xee110f10 => mrc p15,0,r0,c1,c0,0

     DCD 0xe3800080 ;0xe3800080 => orr r0,r0,#0x80;      //Big-endian

     DCD 0xee010f10 ;0xee010f10 => mcr p15,0,r0,c1,c0,0

 ]

 [ ENTRY_BUS_WIDTH=16

     DCD 0x0f10ee11     ;分配一段字的内存单元,并用指令的数据初始化

     DCD 0x0080e380 

     DCD 0x0f10ee01 

 ]

 [ ENTRY_BUS_WIDTH=8

     DCD 0x100f11ee 

     DCD 0x800080e3 

     DCD 0x100f01ee 

     ]

 DCD 0xffffffff         ;swinv 0xffffff is similar with NOP and run well in both endian mode.

 DCD 0xffffffff

 DCD 0xffffffff

 DCD 0xffffffff

 DCD 0xffffffff

 b ResetHandler

 

;//Function for entering power down mode

;// 1. SDRAM should be in self-refresh mode.

;// 2. All interrupt should be maksked for SDRAM/DRAM self-refresh.

;// 3. LCD controller should be disabled for SDRAM/DRAM self-refresh.

;// 4. The I-cache may have to be turned on.

;// 5. The location of the following code may have not to be changed.

;//void EnterPWDN(int CLKCON);

EnterPWDN   

 mov r2,r0          ;r2=rCLKCON

 tst r0,#0x8         ;POWER_OFF mode?

 bne ENTER_POWER_OFF

ENTER_STOP 

 ldr r0,=REFRESH  

 ldr r3,[r0]          ;r3=rREFRESH 

 mov r1, r3

 orr r1, r1, #BIT_SELFREFRESH

 str r1, [r0]         ;Enable SDRAM self-refresh

 mov r1,#16           ;wait until self-refresh is issued. may not be needed.

0 subs r1,r1,#1

 bne %B0

 ldr r0,=CLKCON       ;enter STOP mode.

 str r2,[r0]   

 mov r1,#32

0 subs r1,r1,#1       ;1) wait until the STOP mode is in effect.

 bne %B0            ;2) Or wait here until the CPU&Peripherals will be turned-off

                 ;   Entering POWER_OFF mode, only the reset by wake-up is available.

 ldr r0,=REFRESH        ;exit from SDRAM self refresh mode.

 str r3,[r0]

 

 MOV_PC_LR

ENTER_POWER_OFF 

 ;//NOTE.

 ;//1) rGSTATUS3 should have the return address after wake-up from POWER_OFF mode.

 

 ldr r0,=REFRESH  

 ldr r1,[r0]        ;r1=rREFRESH 

 orr r1, r1, #BIT_SELFREFRESH

 str r1, [r0]       ;Enable SDRAM self-refresh

 mov r1,#16           ;Wait until self-refresh is issued,which may not be needed.

0 subs r1,r1,#1

 bne %B0

 ldr  r1,=MISCCR

 ldr r0,[r1]

 orr r0,r0,#(7<<17)     ;Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE="L" during boot-up

 str r0,[r1]

 ldr r0,=CLKCON

 str r2,[r0]   

 b .              ;CPU will die here.

 

WAKEUP_POWER_OFF

 ;Release SCLKn after wake-up from the POWER_OFF mode.

 ldr  r1,=MISCCR

 ldr r0,[r1]

 bic r0,r0,#(7<<17)     ;SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE:L->H

 str r0,[r1]

 

                ;Set memory control registers

 ldr r0,=SMRDATA

 ldr r1,=BWSCON       ;BWSCON Address

 add r2, r0, #52      ;End address of SMRDATA

0      

 ldr r3, [r0], #4   

 str r3, [r1], #4   

 cmp r2, r0  

 bne %B0

 mov r1,#256

0 subs r1,r1,#1      ;1) wait until the SelfRefresh is released.

 bne %B0 

 ldr r1,=GSTATUS3     ;GSTATUS3 has the start address just after POWER_OFF wake-up

 ldr r0,[r1]

 mov pc,r0

 LTORG

   

HandlerFIQ      HANDLER HandleFIQ

HandlerIRQ      HANDLER HandleIRQ

HandlerUndef    HANDLER HandleUndef

HandlerSWI      HANDLER HandleSWI

HandlerDabort   HANDLER HandleDabort

HandlerPabort   HANDLER HandlePabort

IsrIRQ 

 sub sp,sp,#4           ;reserved for PC

 stmfd sp!,{r8-r9}  

 

 ldr r9,=INTOFFSET

 ldr r9,[r9]

 ldr r8,=HandleEINT0

 add r8,r8,r9,lsl #2

 ldr r8,[r8]

 str r8,[sp,#8]

 ldmfd sp!,{r8-r9,pc}

;================================================================================================

; ENTRY  将看门狗、中断之类的程序关掉,省得他们来打扰初始化程序的进行

;=================================================================================================

ResetHandler

 ldr r0,=WTCON        ;watch dog disable

 ldr r1,=0x0        

 str r1,[r0]

 ldr r0,=INTMSK

 ldr r1,=0xffffffff   ;all interrupt disable

 str r1,[r0]

 ldr r0,=INTSUBMSK

 ldr r1,=0x7ff      ;all sub interrupt disable, 2002/04/10

 str r1,[r0]

 [ {FALSE}

                  ;rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);    

                  ;Led_Display

 ldr r0,=GPFCON

 ldr r1,=0x5500  

 str r1,[r0]

 ldr r0,=GPFDAT

 ldr r1,=0x10

 str r1,[r0]

 ]

 ;To reduce PLL lock time, adjust the LOCKTIME register.

 ldr r0,=LOCKTIME

 ldr r1,=0xffffff

 str r1,[r0]

       

     [ PLL_ON_START

 ;Configure MPLL

 ldr r0,=MPLLCON          ;//设置时钟频率

 ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)  ;Fin=12MHz,Fout=50MHz

 str r1,[r0]

 ]

 ;Check if the boot is caused by the wake-up from POWER_OFF mode.

 ldr r1,=GSTATUS2

 ldr r0,[r1]

 tst r0,#0x2

        ;In case of the wake-up from POWER_OFF mode, go to POWER_OFF_WAKEUP handler.

 bne WAKEUP_POWER_OFF

 EXPORT StartPointAfterPowerOffWakeUp

StartPointAfterPowerOffWakeUp

 ;Set memory control registers

    ldr r0,=SMRDATA

 ldr r1,=BWSCON             ;BWSCON Address

 add r2, r0, #52            ;End address of SMRDATA

0      

 ldr r3, [r0], #4   

 str r3, [r1], #4   

 cmp r2, r0  

 bne %B0

 

 ;Initialize stacks         

 bl InitStacks

 

   ;Setup IRQ handler

 ldr r0,=HandleIRQ         ;This routine is needed

 ldr r1,=IsrIRQ            ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c

 str r1,[r0]

                   ;Copy and paste RW data/zero initialized data

 ldr r0, =|Image$$RO$$Limit|  ; Get pointer to ROM data

 ldr r1, =|Image$$RW$$Base|   ; and RAM copy

 ldr r3, =|Image$$ZI$$Base| 

 

         ;Zero init base => top of initialised data

 cmp r0, r1                 ;Check that they are different

 beq %F2

1      

 cmp r1, r3                 ;Copy init data

 ldrcc r2, [r0], #4         ;--> LDRCC r2, [r0] + ADD r0, r0, #4        

 strcc r2, [r1], #4         ;--> STRCC r2, [r1] + ADD r1, r1, #4

 bcc %B1

2      

 ldr r1, =|Image$$ZI$$Limit|  ;Top of zero init segment

 mov r2, #0

3      

 cmp r3, r1      ; Zero init

 strcc r2, [r3], #4

 bcc %B3

 

    [ :LNOT:THUMBCODE

     bl Main                ;Don't use main() because ......

     b .                      

    ]

    [ THUMBCODE             ;for start-up code for Thumb mode

     orr lr,pc,#1

     bx lr

     CODE16

     bl Main                ;Don't use main() because ......

     b .

     CODE32

    ]

;//function initializing stacks      初始化堆栈

InitStacks               

         ;Don't use DRAM,such as stmfd,ldmfd......

         ;SVCstack is initialized before

         ;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'

 mrs r0,cpsr

 bic r0,r0,#MODEMASK

 orr r1,r0,#UNDEFMODE|NOINT

 msr cpsr_cxsf,r1        ;UndefMode

 ldr sp,=UndefStack

 

 orr r1,r0,#ABORTMODE|NOINT

 msr cpsr_cxsf,r1        ;AbortMode

 ldr sp,=AbortStack

 orr r1,r0,#IRQMODE|NOINT

 msr cpsr_cxsf,r1        ;IRQMode

 ldr sp,=IRQStack

   

 orr r1,r0,#FIQMODE|NOINT

 msr cpsr_cxsf,r1        ;FIQMode

 ldr sp,=FIQStack

 bic r0,r0,#MODEMASK|NOINT

 orr r1,r0,#SVCMODE

 

 msr cpsr_cxsf,r1        ;SVCMode

 ldr sp,=SVCStack

         ;USER mode has not be initialized.

 

 mov pc,lr

         ;The LR register won't be valid if the current mode is not SVC mode.

 LTORG

 

SMRDATA DATA                    在初始化堆栈前,先队内存初始化

;// Memory configuration should be optimized for best performance

;// The following parameter is not optimized.                    

;// Memory access cycle parameter strategy

;// 1) The memory settings is  safe parameters even at HCLK="75Mhz".

;// 2) SDRAM refresh period is for HCLK="75Mhz".

     DCD (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))

     DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))   ;GCS0

     DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))   ;GCS1

     DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))   ;GCS2

     DCD ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))   ;GCS3

     DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))   ;GCS4

     DCD ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))   ;GCS5

     DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))    ;GCS6

     DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))    ;GCS7

     DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)   

 

   DCD 0x32            ;SCLK power saving mode, BANKSIZE 128M/128M

     DCD 0x30            ;MRSR6 CL="3clk"

     DCD 0x30            ;MRSR7

; // DCD 0x20            ;MRSR6 CL="2clk"

; // DCD 0x20            ;MRSR7

     ALIGN

 

     AREA RamData, DATA, READWRITE

        ^   _ISR_STARTADDRESS

HandleReset     #   4

HandleUndef     #   4

HandleSWI       #   4

HandlePabort    #   4

HandleDabort    #   4

HandleReserved  #   4

HandleIRQ       #   4

HandleFIQ       #   4

;//Don't use the label 'IntVectorTable',

;//The value of IntVectorTable is different with the address you think it may be.

;//IntVectorTable

HandleEINT0    #   4

HandleEINT1    #   4

HandleEINT2    #   4

HandleEINT3    #   4

HandleEINT4_7  #   4

HandleEINT8_23 #   4

HandleRSV6     #   4

HandleBATFLT   #   4

HandleTICK     #   4

HandleWDT      #   4

HandleTIMER0   #   4

HandleTIMER1   #   4

HandleTIMER2   #   4

HandleTIMER3   #   4

HandleTIMER4   #   4

HandleUART2    #   4

HandleLCD      #   4

HandleDMA0     #   4

HandleDMA1     #   4

HandleDMA2     #   4

HandleDMA3     #   4

HandleMMC      #   4

HandleSPI0     #   4

HandleUART1    #   4

HandleRSV24    #   4

HandleUSBD     #   4

HandleUSBH     #   4

HandleIIC      #   4

HandleUART0    #   4

HandleSPI1     #   4

HandleRTC      #   4

HandleADC      #   4

        END

 

 

 

 

 

 

 

;=========================================

; NAME: 2410INIT.S

; DESC: C start up codes

;       Configure memory, ISR ,stacks

; Initialize C-variables

; HISTORY:

; 2002.02.25:kwtark: ver 0.0

; 2002.03.20:purnnamu: Add some functions for testing STOP,POWER_OFF mode

;=========================================

GET option.s

GET memcfg.s

GET 2410addr.s

BIT_SELFREFRESH EQU (1<<22)

;ARM异常模式的定义

;Pre-defined constants

USERMODE    EQU 0x10

FIQMODE     EQU 0x11

IRQMODE     EQU 0x12

SVCMODE     EQU 0x13

ABORTMODE   EQU 0x17

UNDEFMODE   EQU 0x1b

MODEMASK    EQU 0x1f

NOINT       EQU 0xc0

;ARM个异常模式堆栈

;The location of stacks

UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~

SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~

UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~

AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~

IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~

FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~

;Check if tasm.exe(armasm -16...@ADS1.0) is used.

GBLL    THUMBCODE

[ {CONFIG} = 16 ;[ = IF

THUMBCODE SETL {TRUE}

     CODE32          ; CODE32 表明一下操作都在ARM状态

    |      ;| = ELSE

THUMBCODE SETL {FALSE}

    ]     ;] = ENDIF

;宏定义MOV_PC_LR

    MACRO

MOV_PC_LR

    [ THUMBCODE

            bx lr

    |

            mov pc,lr

    ]

MEND

    MACRO

MOVEQ_PC_LR

    [ THUMBCODE

         bxeq lr

    |

            moveq pc,lr

    ]

MEND

;宏定义-进入异常流程

;HANDLER-宏的名称

;$HandleLabel-宏的参数

;这个宏的作用是把各个中断程序的地址装入当前的PC,2410有两种装断模式 一种是没有中断向量表,一种是使用中断向量表的

;使用中断向量表只能是IRQ方式,当使用中断向量表的时候,中断发生时由2410的中断控制器自动跳转到

;相应的位置。

    MACRO

$HandlerLabel HANDLER $HandleLabel

$HandlerLabel

sub sp,sp,#4        ;decrement sp(to store jump address)

stmfd sp!,{r0}        ;PUSH the work register to stack(lr doest push because it return to original address)!表示数据传送完毕后,将最后的地址写入基址寄存器

ldr     r0,=$HandleLabel;load the address of Handle1XXX to r0

ldr     r0,[r0]         ;load the contents(service routine start address) of HandleXXX

str     r0,[sp,#4]      ;store the contents(ISR) of HandleXXX to stack

ldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)

MEND

;连接器生成的输出段相关的符号

;引入连接器生成的映象文件的各个部分地址。

;OR-只读区域、RW-读写区域、ZI-初始化为0的区域。

IMPORT |Image$$RO$$Base| ; Base of ROM code

IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data)

IMPORT |Image$$RW$$Base|   ; Base of RAM to initialise

IMPORT |Image$$ZI$$Base|   ; Base and limit of area

IMPORT |Image$$ZI$$Limit| ; to zero initialise

;引入外部函数Main,进入C程序。

IMPORT Main    ; The main entry of mon program

;IMPORT LEDTEST

;定义ARM汇编程序段,段名为SelfBoot,程序段为只读的代码段。

AREA    SelfBoot, CODE, READONLY

;程序入口地址

ENTRY

ResetEntry

;程序段执行的第一跳指令,为8个异常中断处理向量,要按顺序放置。

b ResetHandler

b HandlerUndef ;handler for Undefined mode

b HandlerSWI ;handler for SWI interrupt

b HandlerPabort ;handler for PAbort

b HandlerDabort ;handler for DAbort

b .   ;reserved

b HandlerIRQ ;handler for IRQ interrupt

b HandlerFIQ ;handler for FIQ interrupt

LTORG ;声明一个数据缓冲池的开始  

HandlerFIQ      HANDLER HandleFIQ

HandlerIRQ      HANDLER HandleIRQ

HandlerUndef    HANDLER HandleUndef

HandlerSWI      HANDLER HandleSWI

HandlerDabort   HANDLER HandleDabort

HandlerPabort   HANDLER HandlePabort

;采用INTOFFSET寄存器判定IRQ中断源

IsrIRQ

sub sp,sp,#4      

stmfd sp!,{r8-r9}

ldr r9,=INTOFFSET

ldr r9,[r9]

ldr r8,=HandleEINT0

add r8,r8,r9,lsl #2

ldr r8,[r8]

str r8,[sp,#8]

ldmfd sp!,{r8-r9,pc}

;======================================================

; ENTRY

;======================================================

;初始化程序入口指令

ResetHandler

ldr r0,=WTCON       ;watch dog disable

ldr r1,=0x0        

str r1,[r0]

ldr r0,=INTMSK

ldr r1,=0xffffffff ;all interrupt disable

str r1,[r0]

ldr r0,=INTSUBMSK

ldr r1,=0x3ff   ;all sub interrupt disable

str r1,[r0]

;To reduce PLL lock time, adjust the LOCKTIME register.

ldr r0,=LOCKTIME

ldr r1,=0xffffff

str r1,[r0]

       

;Configure MPLL

ldr r0,=MPLLCON         

ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin=12MHz,Fout=50MHz

str r1,[r0]

;设置存储器控制寄存器。

;Set memory control registers

adr r0, SMRDATA

ldr r1,=BWSCON ;BWSCON Address

add r2, r0, #52 ;End address of SMRDATA一共13个寄存器

0      

ldr r3, [r0], #4   

str r3, [r1], #4   

cmp r2, r0  

bne %B0

;禁止Icache和Dcache,禁止MMU

;IMPORT MMU_DisableICache

    ;bl MMU_DisableICache ;

;IMPORT MMU_DisableDCache

    ;bl MMU_DisableDCache ;

    ;IMPORT MMU_InvalidateICache

    ;bl MMU_InvalidateICache ;

    ;IMPORT MMU_DisableMMU

    ;bl MMU_DisableMMU ;

;初始化堆栈

    ;Initialize stacks

bl InitStacks

;建立IRQ中断

; Setup IRQ handler

ldr r0,=HandleIRQ       ;This routine is needed

ldr r1,=IsrIRQ          ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c'

str r1,[r0]

;===========================================================

adr r0, ResetEntry

ldr r2, BaseOfROM

cmp r0, r2

ldreq r0, TopOfROM

beq InitRam

ldr r3, TopOfROM

;将RO区域的代码copy到RW域中并且将ZI区域初始化为0。

0

ldmia r0!, {r4-r7}

stmia r2!, {r4-r7}

cmp r2, r3

bcc %B0

sub r2, r2, r3

sub r0, r0, r2    

  

InitRam

ldr r2, BaseOfBSS

ldr r3, BaseOfZero

0

cmp r2, r3 ;copy 初始化代码

ldrcc r1, [r0], #4

strcc r1, [r2], #4

bcc %B0

mov r0, #0 ;初始化ZI区域为0

ldr r3, EndOfBSS

1

cmp r2, r3

strcc r0, [r2], #4

bcc %B1

bl Main ;bl Main        ;Dont use main() because ......

   b .                      

;堆栈初始化

;function initializing stacks

InitStacks

;Don't use DRAM,such as stmfd,ldmfd......

;SVCstack is initialized before

;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1

;UndefMode堆栈

mrs r0,cpsr

bic r0,r0,#MODEMASK

orr r1,r0,#UNDEFMODE|NOINT

msr cpsr_cxsf,r1   ;UndefMode

ldr sp,=UndefStack

;AbortMode堆栈

orr r1,r0,#ABORTMODE|NOINT

msr cpsr_cxsf,r1   ;AbortMode

ldr sp,=AbortStack

;IRQMode堆栈

orr r1,r0,#IRQMODE|NOINT

msr cpsr_cxsf,r1   ;IRQMode

ldr sp,=IRQStack

   

    ;FIQMode堆栈

orr r1,r0,#FIQMODE|NOINT

msr cpsr_cxsf,r1   ;FIQMode

ldr sp,=FIQStack

;SVCMode堆栈

bic r0,r0,#MODEMASK|NOINT

orr r1,r0,#SVCMODE

msr cpsr_cxsf,r1   ;SVCMode

ldr sp,=SVCStack

;USER mode has not be initialized.

mov pc,lr

;The LR register won't be valid if the current mode is not SVC mode.'

LTORG ;声明一个数据缓冲池的开始

SMRDATA DATA

; Memory configuration should be optimized for best performance

; The following parameter is not optimized.                    

; Memory access cycle parameter strategy

; 1) The memory settings is safe parameters even at HCLK=75Mhz.

; 2) SDRAM refresh period is for HCLK=75Mhz.

        DCD (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28));BWSCON=0x2211D110

    DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))   ;GCS0 BANK0CON=0x0700

    DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))   ;GCS1 BANK1CON=0x7FFC

    DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))   ;GCS2 BANKCON2=0x0700

    DCD 0x1f7c;((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))   ;GCS3 BANKCON3=0x0700

    DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))   ;GCS4 BANKCON4=0x0700

    DCD ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))   ;GCS5 BANKCON5=0x0700

    DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))    ;GCS6 BANKCON6=0x18005

    DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))    ;GCS7 BANKCON7=0x18005

    DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) ;REFRESH=0x008E0459  

   DCD 0x32            ;SCLK power saving mode, BANKSIZE 128M/128M       ;BANKSIZE=0x32

    DCD 0x30            ;MRSR6 CL=3clk   ;MRSRB6=0x30

    DCD 0x30            ;MRSR7    ;MRSRB7=0x30

BaseOfROM DCD |Image$$RO$$Base|

TopOfROM DCD |Image$$RO$$Limit|

BaseOfBSS DCD |Image$$RW$$Base|

BaseOfZero DCD |Image$$ZI$$Base|

EndOfBSS DCD |Image$$ZI$$Limit|

    ALIGN ;通过添加补丁字节使当前位置满足一定的对齐方式

   ;可读写的数据段

    AREA RamData, DATA, READWRITE

;^=MAP:定义一个结构化的内存表(storage map)的首地址,地址为0x33ff8000

        ^   _ISR_STARTADDRESS ;0x33ff8000

HandleReset #   4   ;#--Field:定义一个结构化内存表中的数据域,该域为4个字节

HandleUndef #   4

HandleSWI   #   4

HandlePabort    #   4

HandleDabort    #   4

HandleReserved #   4

HandleIRQ   #   4

HandleFIQ   #   4

;Don't use the label 'IntVectorTable',

;The value of IntVectorTable is different with the address you think it may be.

;IntVectorTable'

HandleEINT0   #   4

HandleEINT1   #   4

HandleEINT2   #   4

HandleEINT3   #   4

HandleEINT4_7 #   4

HandleEINT8_23 #   4

HandleRSV6   #   4

HandleBATFLT   #   4

HandleTICK   #   4

HandleWDT   #   4

HandleTIMER0 #   4

HandleTIMER1 #   4

HandleTIMER2 #   4

HandleTIMER3 #   4

HandleTIMER4 #   4

HandleUART2 #   4

HandleLCD    #   4

HandleDMA0   #   4

HandleDMA1   #   4

HandleDMA2   #   4

HandleDMA3   #   4

HandleMMC   #   4

HandleSPI0   #   4

HandleUART1   #   4

HandleRSV24   #   4

HandleUSBD   #   4

HandleUSBH   #   4

HandleIIC   #   4

HandleUART0    #   4

HandleSPI1    #   4

HandleRTC    #   4

HandleADC    #   4

        END




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
如何升级STM32单片机的代码