arm启动文件2440init.s分析

本文是关于嵌入式Linux的学习资料,主要分析了S3C2440处理器的启动文件2440init.s,该文件包含了配置内存、初始化中断、设置栈指针和启动C变量等关键步骤。文中还介绍了汇编语言的相关知识,如ARM指令集和宏定义,并提供了启动流程图和代码段的详细解释,适合嵌入式开发者参考学习。
摘要由CSDN通过智能技术生成

 最近整理电脑,找到了一些当初学习嵌入式linux时的资料,现在共享出来。方便大家学习之用,无所谓原创,无非就是在前人的基础上,进行了系统化的分析和综合而已。不过,还是加入了不少个人学习的思路跟方法,我觉得这才是最重要的。本来想共享到百度文库,赚点积分的,无奈百度嫌我格式太乱不允许上传,就直接复制到这里了,呵呵!


最近在学习嵌入式软件,现分享自己部分成果。平台:s3c2440 mcu

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

; NAME: 2440INIT.S

; DESC: C start up codes

;      Configure memory, ISR ,stacks

;Initialize C-variables

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

 

 

 

;注意:axd调试时,可以看到 指令pc地址从0x30000000开始,这是因为ram的起始地址是0x30000000.

;并且如果从nand启动,则处理器自动把nand首部的4k字节,复制到ram中,然后pc跳到0x30000000,开始执行。

 

;此源文件通常包含一些宏定义和常量定义

 

;通用的《启动流程图》:

;入口->屏蔽所有中断,禁止看门狗->根据工作频率设置PLL寄存器->初始化存储控制相关寄存器->初始化各模式下的栈指针

;->设置缺省中断处理函数->将数据拷贝到RAM中,数据段清零->跳转到c语言main入口函数中

 

 

;GET伪指令用于将一个源文件包含到当前源文件中,并将被包含文件在当前位置进行汇编处理,类似于c的include指令

;GET INLCUDE伪指令不能 用来包含目标文件,INCBIN伪指令 可以包含目标文件,

;被INCBIN伪指令包含的文件, 不 进行汇编处理,该执行文件或数据直接放入当前文件,编译器从INCBIN后边开始继续处理

;区分GET,INCLUDE,INCBIN的用法和作用

      

       GEToption.inc             ;定义芯片相关配置

       GETmemcfg.inc           ;定义存储器配置

       GET2440addr.inc  ;定义寄存器符号

 

 

;REFRESH寄存器[22]bit :SDRAM刷新模式 0- auto refresh; 1 - self refresh

;用于节电模式中,SDRAM自动刷新

BIT_SELFREFRESH EQU   (1<<22)

 

;Pre-defined constants

;模式预定义常量,给cpsr【4-0】赋值,改变运行模式

USERMODE   EQU        0x10

FIQMODE    EQU 0x11

IRQMODE    EQU 0x12

SVCMODE    EQU        0x13

ABORTMODE  EQU       0x17

UNDEFMODE  EQU       0x1b

MODEMASK   EQU       0x1f ;模式屏蔽位

NOINT      EQU    0xc0   ;1100 0000,中断屏蔽掩码

 

;The location of stacks

;0x30000000 = 768M 

;定义各模式下的堆栈常量,是一个递减栈,后边标上了各个栈的大小

UserStack       EQU       (_STACK_BASEADDRESS-0x3800)  ; ~ 0x33ff4800      大小不定,跟堆大小相对应。毕竟是用户态栈

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

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

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

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

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

 

 

;处理器分为16位 32位两种工作状态 程序的编译器也是分16位和32两种编译方式 下面程序根据处理器工作状态确定编译器编译方式

;code16伪指令指示汇编编译器后面的指令为16位的thumb指令

;code32伪指令指示汇编编译器后面的指令为32位的arm指令

 

;Arm上电时处于ARM状态,故无论指令为ARM集或Thumb集,都先强制成ARM集,待init.s初始化完成后

;再根据用户的编译配置转换成相应的指令模式。为此,定义变量THUMBCODE作为指示,跳转到main之前

;根据其值切换指令模式

 

;Check if tasm.exe(armasm -16 ...@ADS 1.0)is used.

;检测工作模式,根据CONFIG的数值,确定工作模式

;{CONFIG}应该来自于ADS环境,在本环境中设置是进入时在ARM环境下,没有设置ARM/THUMB混合环境

;关于是否设置混合编程,在环境设置选项里的ARM Assembler 选项下,由ATPCS -> ARM/Thumb interworking选项负责

;IF ELSE ENDIF指令

    

       GBLL    THUMBCODE

       [{CONFIG} = 16        

THUMBCODE SETL  {TRUE}         ;如果设置了config,则允许thumb指令,但THUMBCODE为真并不表明以下就是thumb指令,只是允许

           CODE32                      ;code32表示以下是arm指令,在处理器刚开始时,必须以arm模式运行

             |                                  ;此处容易产生错觉,丢掉CODE32这一行

THUMBCODE SETL  {FALSE}

    ]

 

;bx是带状态切换的跳转指令,跳转到Rm指定的地址执行程序,若Rm的位[0]为1,则跳转时自动将CPSR的标志T

;T置位,即把目标地址的代码解释为Thumb代码;若Rm的位[0]为0,则跳转时自动将CPSR中的标志T复位,即把

;目标地址的代码解释为ARM代码

 

;定义两个宏,宏的作用:子函数返回(无条件,有条件)。

             MACRO 

      MOV_PC_LR

             [ THUMBCODE                         ;如果允许thumb指令,则需要根据最低位设置状态。

           bx lr                                   ;跳转,附带状态切换

             |

           mov pc,lr

             ]

       MEND

 

             MACRO

       MOVEQ_PC_LR   ;相等则跳转,相等与否由寄存器某些位确定,在此处,有其上一句的指令执行结果决定

             [ THUMBCODE

       bxeq lr

             |

           moveq pc,lr

             ]

       MEND

 

;重点分析下面这个宏,它对中断处理函数的调用很重要

 

 

;MACRO和MEND伪指令用于宏定义,MACRO标识开始,MEND标识结束。用MACRO和MEND定义的一段代码,称为

;宏定义体,这样在程序中就可以通过宏指令多次调用该代码段。伪指令格式:

 

;MACRO

;{$label} macroname {$parameter} {$parameter} ...

              ;宏定义体

;MEND

 

;其中  $label 宏指令被展开时,label可被替换成相应的符号,通常为一个标号,在一个标号前使用$表示被汇编时将

;使用相应的值替代$后的符号。

;macroname 所定义的宏的名称

;$parameter 宏指令的参数,当宏指令被展开时将被替换成相应的值,类似于函数中的形式参数

;对于子程序代码较短,而需要传递的参数比较多的情况下,可以使用汇编技术。首先要用MACRO和MEND伪指令定义宏,包括宏定义

;体代码。在MACRO伪指令之后的第一行定义宏的原型,其中包含该宏定义的名称,及需要的参数。在汇编程序中可以通过该宏定义

;的名称来调用它,当源程序被汇编时,汇编编译器将  展开 每个宏调用,用宏定义体代替源程序中的宏定义的名称,并用实际的参数

;值代替宏定义时的形式参数

 

 

;在arm中,用的是满递减堆栈:stmfd,ldmfd,如果用其他的方式,arm可能不能有效识别

;注意:满递减指的是在入栈时的操作方式,在出栈时则正好相反的次序

;关于堆栈在数据放置方式,存取顺序上,可以参见《自学手册》P84中的实例分析

;例子:

;STMFD sp!,{R0-R7,LR}:(满递减:先减再放数值)sp根据数据个数,减小相应个数值的数据单位(一步到位),然后利用for循环语句,从当前sp位置,依次存储R0-R7,LR.即:sp处最后指向的是R0数据处

;LDMFD sp!,{R0-R7,LR}:复制一个变量为sp值,用该变量依次将数据存入R0-R7,LR,变量值增加,最后,变量指向下一个将要取的值,完成后sp获得该变量值;

;risc模式,这是对ram的操作

 

 

;确切说,这是宏函数,编译时对调用语句要做相应的展开

 

             MACRO

$HandlerLabel HANDLER $HandleLabel

 

$HandlerLabel                            ;标号

       sub  sp,sp,#4          ;留出一个空间,为了存放跳转地址给pc。见:str r0,[sp,#4] ,注意sp值并未改变

      

       stmfd      sp!,{r0}  ;把r0中的内容入栈,保存起来

      

       ldr     r0,=$HandleLabel    ;这是一个伪指令,不是汇编指令,目的:把$HandleLabel本身所在的地址给r0

      

       ldr     r0,[r0]                           ;把HandleXXX所指向的内容(也就是中断程序的入口地址)放入r0

      

       str     r0,[sp,#4]                  ;把入口地址放入刚才留出的一个空间里

      

       ldmfd   sp!,{r0,pc}         ;出栈的方式恢复r0原值和为pc设定新值(也就完成了到ISR的转跳)。注:栈中r0内容在低地址

      

       MEND

 

;这几个变量是ads环境下自动设置的,可以见环境配置选项里:ARM Linker->Output下,RO Base,RW Base

;RW Base 没设置,因为代码段的结束便是数据段的开始,这个ads可以自动设置

;IMPORT 引用变量

       IMPORT  |Image

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值