当前位置:首页 > 2410init.s的分析
; NAME: 2410INIT.S
;/************************************此头文件的功能***********************************/ 本汇编语言程序包含option.inc, memcfg.inc, 2410addr.inc,通常启动代码是在2410init.s汇编文件;特殊功能寄存器定义在2410addr.s;Memory Bank 配置在mencfg.s;还有系统的选项等在option.s文件
GET option.inc GET memcfg.inc GET 2410addr.inc
;
;此处GET相当于C语言中的include ;
BIT_SELFREFRESH EQU (1<<22)
;ram的自刷新设置位, 相当于c里面
#define BIT_SELFREFRESH (1<<22), 就是第22位置1
/**************************************************************************** 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 ~
;/***************************************************************************** GBLL THUMBCODE ;定义一个全局逻辑变量THUMBCODE [ {CONFIG} = 16 ; CONFIG为汇编器的内置变量,if CONFIG==16 这里表示目
tasm.exe是什么程序,有什么作用??? 就是THUMB汇编编译文件 前处于16位编译方式
THUMBCODE SETL {TRUE} ;SETL给全局逻辑变量赋值
;设置THUMBCODE 为 true表示告诉系统 当前想用thumb,但实际启动时不行,只能 以32为编译模式启动后再跳
[]的用法怎样??? \表示\表示\表示\ CODE32 ;启动时强制使用32位编译模式 | ;否则
THUMBCODE SETL {FALSE} ;如果系统要求是ARM指令,则直接设置THUMBCODE
为 false 说明当前的是32位编译模式 ]
MACRO
;宏定义,普通跳转,用于子程序的返回
MOV_PC_LR ;名字为MOV_PC_LR
[ THUMBCODE ;如果在THUMB模式下
bx lr ;直接跳转到lr指示的返回地址,用BX指令跳转到
THUMB指令,并转换模式 | mov pc,lr ] MEND
MACRO ;宏定义,如果上面的指令把标志位改变了,符合EQ的条件,则跳转 MOVEQ_PC_LR ;带条件的函数返回 [ THUMBCODE bxeq lr
;如果在thumb模式
;若状态为nZCv,即运算结果为非负(n),为零(Z),有进位
;否则
;把函数返回地址LR赋值给PC实现返回
;
(C),无溢出(v),则跳转回ARM状态
eq根据Z判断,相等即Z=1(为0)则跳转
bx和mov这两条语句都是进行跳转,但bx跳转之后从
THUMBCODE状态转换到ARM状态,有模式转换,但mov语句只是实现跳转,没有模式转换。 | moveq pc,lr ] MEND
;否则
;把lr赋值给pc实现跳转 ;宏定义结束
;/****************************MACRO $HandlerLabe1************************** MACRO
$HandlerLabel HANDLER $HandleLabel ; HandlerLabel为中断服务入口地址
; HANDLER为宏名
; $HandlerLabel 展开后要被下面这段程序替换掉,是个跳转的标号
;$HandleLabel,它是个函数的入口地址。 $HandlerLabel
sub sp,sp,#4 ;减少sp,预留一个字,用于存放跳转地址 stmfd sp!,{r0} ;将要使用的r0寄存器入栈
ldr r0,=$HandleLabel ;把向量表中的HandleLabel[标号]的地址装入r0 ldr r0,[r0] ;把HandleXXX所指向的内容(也就是中断程序的入口)放入r0 str r0,[sp,#4] ;把中断服务程序(ISR)压入栈,保存在高一个地址预留
的空间中,但SP没变。
ldmfd sp!,{r0,pc} ;用出栈的方式恢复r0的原值和为pc设定新值(也就完
成了到ISR的转跳),将中断函数首地址出栈,放入pc
中,系统将跳转到对应的中断处理函数。
MEND
/****************************************************************************** IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data)注意,这里的rom只是一种定义,有可能是真正硬件上的rom也有可能只是单纯的readonly区域
IMPORT |Image$$RW$$Base| ; Base of RAM to initialize, 在运行域中要初始化的RAM的开始地址
IMPORT |Image$$ZI$$Base| ; Base and limit of area, 需要清零的RAM区域的开始
地址
IMPORT |Image$$ZI$$Limit| ; to zero initialize, 需要清零的RAM区域的结束地址
IMPORT Main ; The main entry of mon program
AREA Init,CODE,READONLY ;这表明下面的是一个名为Init的只读代码段
ENTRY
/***************************************************************************** ASSERT :DEF:ENDIAN_CHANGE ;下面是大小端的一个判断,ENDIAN_CHANGE
已经在Option.s中定义为FALSE [ ENDIAN_CHANGE ;在这个部分中使用了断言ASSERT, ASSERT :DEF:ENTRY_BUS_WIDTH ;在这个部分使用了判断逻辑伪指令,
ENTRY_BUS_WIDTH已被定义
判断逻辑伪指 [ ENTRY_BUS_WIDTH=32 ;如果总线宽度为32
令格式:\”,用
b ChangeBigEndian ;DCD 0xea000007 ]
;如果总线宽度为16
[ ENTRY_BUS_WIDTH=16
伪操作DCD: 格式:标号 DCD (或 DCDU ) 表达式 用于分配一段字内存单元并用伪操作中指定的表达式初始化 于判断变量X 是否被定义 andeq r14,r7,r0,lsl #20 ;DCD 0x0007ea00
]
[ ENTRY_BUS_WIDTH=8 ;如果总线宽度为8 streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea
]
| ;如果以上情况都没有发生 b ResetHandler ;则跳转到复位入口地址,因为ENDIAN_CHANGE已经被
设成FALSE,所以系统开机或者复位后就来到这了,转跳
到复位程序入口
]
/******************************************************************************
b HandlerUndef ;handler for Undefined mode 转跳到未定义异常模式程序入口 b HandlerSWI ;handler for SWI interrupt 转跳到SWI 中断程序入口 b HandlerPabort ;handler for PAbort 跳转到指令异常退出模式程序入口 b HandlerDabort ;handler for DAbort b . ;reserved
跳转到数据异常退出模式程序入口
保留
b HandlerIRQ ;handler for IRQ interrupt 跳转到IRQ中断程序入口
b HandlerFIQ ;handler for FIQ interrupt 跳转到FIQ中断程序入口 b EnterPWDN ;掉电模式 Must be @0x20
/**************************************************************************** ChangeBigEndian ;ChangeBigEndian的首地址(标号)
;@0x24 ;在0x24处
[ ENTRY_BUS_WIDTH=32 ;32位总线宽
DCD 0xee110f10 ;0xee110f10 => mrc p15,0,r0,c1,c0,0
;DCD分配一段连续的字存储单元并初始化
DCD 0xe3800080 ;0xe3800080 => orr r0,r0,#0x80
; //Big-endian
;//在这里用于将各种指令的机器码直接存入内存 DCD 0xee010f10 ;0xee010f10 => mcr p15,0,r0,c1,c0,0 ]
[ ENTRY_BUS_WIDTH=16 ;16位 DCD 0x0f10ee11 DCD 0x0080e380 DCD 0x0f10ee01
]
[ ENTRY_BUS_WIDTH=8 ;8位 DCD 0x100f11ee ;读取p15的c1寄存器中的内容到arm的r0 DCD 0x800080e3 ;修改内容,这个命令执行的效果是选择Big-endian,
指令意义:r0=r0 or 0x0100 0000 DCD 0x100f01ee ;把命令写回协处理器,上面的指令把c1的第7位置为了1 ]
DCD 0xffffffff ;swinv 0xffffff is similar with NOP and run well in both endian mode. DCD 0xffffffff ;(0xffffffff在大小端模式中都为空操作) DCD 0xffffffff DCD 0xffffffff
DCD 0xffffffff
b ResetHandler ;//复位
*****************************************************************************/ EnterPWDN
mov r2,r0 ;r2=rCLKCON,rCLKCON [3:2]位为电源模式标志位。
tst r0,#0x8 ;POWER_OFF mode? 按位与并判断, 若[3]为1,表示进入掉电模式 bne ENTER_POWER_OFF ; 若[3]为1则跳转到ENTER_POWER_OFF
基础知识不扎实,需要恶补一下~~~ tst 和bne连用: 先是用tst进行位与运算,然后将位与的结果与0比较,如果不为0,则跳转, tst 和beq连用: 先是用tst进行位与运算,然后将位与的结果与0比较,如果为0,则跳转
TST{条件}操作数1, 操作数2
意思:将操作数1与操作数2进行按位与的运算,根据结果更新CPSR中条件标志位的值。它一般用来检测是 否设置了特定的位。
ENTER_STOP ;进入停止模式相关处理
REFRESH寄存器是DRAM/SDRAM的刷新控制器 REFRESH[22]为0:自动刷新,为1:自刷新 ;进入PWDN后如果不是sleep则进入stop
ldr r0,=REFRESH ;r0指向sdram的刷新控制寄存器地址
ldr r3,[r0] ;r3=rREFRESH ,r3获得当前sdram的控制信息 mov r1, r3
orr r1, r1, #BIT_SELFREFRESH ;在控制信息中加入自刷新命令,orr是按位或
共分享92篇相关文档