历史上的今天
返回首页

历史上的今天

今天是:2024年11月08日(星期五)

正在发生

2019年11月08日 | ARM9学习4-S3C2410的启动代码分析-For ADSv1.2

2019-11-08 来源:51hei

通常,启动代码是指CPU复位后到进入C语言的main函数之前需要执行的那段汇编代码.这是由于C语言程序的运行需要具备一定的条件,比如:分配好外部数据空闿堆栈空间和中断入口等筿另外汇编代码可以更直接的对硬件进行操使效率更高. 通常启动代码是放在2410init.s汇编文件;特殊功能寄存器定义在2410addr.s;Memory Bank 配置在mencfg.s;还有系统的选项等在option.s文件;2410init.s不仅包括复位后执行的代码,还包括CPU进入掉电模式,产生中断等和处理器直接相关的,用汇编实现的代码.
;=========================================
; 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
; 2003.05.19:jcs:Configure UPLL in init.s not usbmain.c
;=========================================
  //首先,启动代码定义了一些常量 ,相当于C中的INCLUDE
GET option.inc
GET memcfg.inc
GET 2410addr.inc

BIT_SELFREFRESH EQU (1<<22) //自刷新常量
//;;处理器模式常量 
USERMODE    EQU  0x10
FIQMODE     EQU  0x11
IRQMODE     EQU  0x12
SVCMODE     EQU  0x13
ABORTMODE   EQU  0x17
UNDEFMODE   EQU  0x1b
MODEMASK    EQU  0x1f  //系统模式
NOINT           EQU  0xc0  //屏蔽所有的中断,即置位I,F位
//;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 is used.
;arm处理器有两种工作状态 1.arm:32位 这种工作状态下执行字对准的arm指令 2.Thumb:16位 这种工作状态执行半字对准的Thumb指令
;因为处理器分为16位 32位两种工作状态程序的编译器也是分16位和32两种编译方式 所以下面的程序用于根据处理器工作状态确定编译器编译方式
;code16伪指令指示汇编编译器后面的指令为16位的thumb指令
;code32伪指令指示汇编编译器后面的指令为32位的arm指令
;这段是为了统一目前的处理器工作状态和软件编译方式(16位编译环境使用tasm.exe编译)
GBLL THUMBCODE ;设置一个全局逻辑变量
[ {CONFIG} = 16 ;if config==16 这里表示你的目前处于领先地16位编译方式,{CONFIG}为汇编器内置变量
THUMBCODE SETL {TRUE} ;设置THUMBCODE 为 true
CODE32 ;转入32位编译模式
|      ;else
THUMBCODE SETL {FALSE} ;设置THUMBCODE 为 false

[ THUMBCODE     ;if THUMBCODE==TRUE
CODE32          ;for start-up code for Thumb mode;转入32位编译方式
]

;注意下面这段程序是个宏定义 很多人对这段程序不理解 我再次强调这是一个宏定义 所以大家要注意了下面包含的HandlerXXX HANDLER HandleXXX将都被下面这段程序展开。

;这段程序用于把中断服务程序的首地址装载到pc中,有人称之为“加载程序”。其大致作用是把宏的第一个参数$HandlerLabel转变为一个标号,然后让程序跳转到第二个参数 $HandleLabel(第二个参数应该为一个地址)对应的值的地址去。可以分析出,sp和r0在执行前后都没有变化,程序就实现了跳转

;本初始化程序定义了一个数据区(在文件最后),34个字空间,存放相应中断服务程序的首地址。每个字空间都有一个标号,以Handle***命名。

;在向量中断模式下使用“加载程序”来执行中断服务程序。

;这里就必须讲一下向量中断模式和非向量中断模式的概念

;向量中断模式是当cpu读取位于0x18处的IRQ中断指令的时候,系统自动读取对应于该中断源确定地址上的指令取代0x18处的指令,通过跳转指令系统就直接跳转到对应地址

;函数中 节省了中断处理时间提高了中断处理速度标 例如 ADC中断的向量地址为0xC0,则在0xC0处放如下代码:ldr PC,=HandlerADC 当ADC中断产生的时候系统会

;自动跳转到HandlerADC函数中

;非向量中断模式处理方式是一种传统的中断处理方法,当系统产生中断的时候,系统将interrupt pending寄存器中对应标志位置位 然后跳转到位于0x18处的统一中断

;函数中 该函数通过读取interrupt pending寄存器中对应标志位 来判断中断源 并根据优先级关系再跳到对应中断源的处理代码中

MACRO 
$HandlerLabel HANDLER $HandleLabel    //
$HandlerLabel 
sub sp,sp,#4                     ;减少sp(预留一个字,用于存放转跳地址) 
stmfd sp!,{r0}                    ;把工作寄存器压入栈(lr does not push because it return to original address) 
ldr     r0,=$HandleLabel    ;将HandleXXX的址址放入r0 
ldr     r0,[r0]                       ;把HandleXXX所指向的内容(也就是中断程序的入口)放入r0 
str     r0,[sp,#4]                  ;把中断服务程序(ISR)压入栈,保存在高一个地址预留的空间中,但SP没变。 
ldmfd   sp!,{r0,pc}              ;用出栈的方式恢复r0的原值和为pc设定新值(也就完成了到ISR的转跳) ;

                   ADS仅支持FD(满递减)型堆栈,故只能用stmfd和ldmfd
MEND

;========================================================================================
//在这里用IMPORT伪指令(和c语言的extren一样)引入|Image$$RO$$Base|,|Image$$RO$$Limit|...
//这些变量是通过ADS的工程设置里面设定的RO Base和RW Base设定的,最终由编译脚本和连接程序导入程序. 
//那为什么要引入这玩意呢,最简单的用处是可以根据它们拷贝自已 ,从把RW和ZI变量从加载域中复制到运行域中
//一个arm由RO,RW,ZI三个断组成 其中RO为代码段,RW是已经初始化的全局变量,ZI是未初始化的全局变量(对于GNU工具 对应的概念是TEXT ,DATA,BSS)。

;========================================================================================
IMPORT  |Image$$RO$$Base|    ; ROM code(也就是代码)的开始地址 
IMPORT  |Image$$RO$$Limit|    ; ROM code的结束地址 (也就是RW在加载域中的起始地址) 
IMPORT  |Image$$RW$$Base|   ; 在运行域中要初始化的RAM的开始地址 
IMPORT  |Image$$ZI$$Base|      ; area(需要清零的RAM区域)的开始地址 
IMPORT  |Image$$ZI$$Limit|       ; area的结束地址 

;这里引入一些在其它文件中实现在函数,包括为我们所熟知的main函数
IMPORT  Main    ; The main entry of mon program 
;从这里开始就是正真的代码入口了! 
AREA    Init,CODE,READONLY       ;这表明下面的是一个名为Init的代码段 
ENTRY                                            ;定义程序的入口(调试用) 其中关键字ENTRY是指定编译器保留这段代码,因为
                                                       编译器可能会认为这是一段亢余代码而加以优化。链接的时候要确保这段代码
                                                         被链接在0地址处,并且作为整个程序的入口 
;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 not be used here because the linker generates error. 
ASSERT :DEF:ENDIAN_CHANGE 
[ ENDIAN_CHANGE                         ;下面是大小端的一个判断,在Option.inc里已经设为FALSE 
     ASSERT  :DEF:ENTRY_BUS_WIDTH 
     [ ENTRY_BUS_WIDTH=32          //‘[’=IF
      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 ;因为设成FALSE,所以系统复位后就来到这了,转跳到复位程序入口 
    ] 
//=====================================================================================
;ARM要求中断向量表必须放置在仿地址开始,连续8X4字节的空间内.每当一个中断发生以后,ARM处理器便强制把PC指针置为向量表中对应中断类型的地址值。因为每个中断只占据向量表中1个字的存储空间,只能放置一条ARM指令,使程序跳转到存储器的其他地方,再执行中断处理 
//=====================================================================================
b HandlerUndef           ;转跳到Undefined mode程序入口 
b HandlerSWI              ;转跳到SWI 中断程序入口 
b HandlerPabort          ;转跳到PAbort(指令异常)程序入口 
b HandlerDabort          ;转跳到DAbort(数据异常)程序入口 
b .                                ;保留 
b HandlerIRQ              ;转跳到IRQ 中断程序入口 
b HandlerFIQ              ;转跳到FIQ 中断程序入口 
;@0x20 不知道是什么意思,地址?
b EnterPWDN ; Must be @0x20.
;================================================================================== 
;下面是改变大小端的程序,这里采用直接定义机器码的方式,至说为什么这么做就得问三星了 
;反正我们程序里这段代码也不会去执行,不用去管它 
;================================================================================== 
ChangeBigEndian    //通过设置CP15中的C1的位7来设置存储格式为大端模式。
;@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. SDRAm应该设置为自刷新的模式
; 2. All interrupt should be maksked for SDRAM/DRAM self-refresh. 所有中断必须屏蔽 for SDRAM/DRAM self-ref
; 3. LCD controller should be disabled for SDRAM/DRAM self-refresh. LCD 控制器关闭
; 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);           //PWDN:powerdown
EnterPWDN   
mov r2,r0  ;r2=rCLKCON                 //rCLKCONr [3;2]位为电源模式标置位。若[3]为1,表示转为了掉电模式
tst r0,#0x8  ;POWER_OFF mode?   //按位与判断,若[3]为1则跳转到ENTER_POWER_OFF
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                                     //表示不相等则往回跳转到标号为0的位置,在此为上一句。
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.注意在rGSTATUS3寄存器中应该保存掉电模式唤醒的返回地址,rGSTATUS3,4可在掉电下保存信息
;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.

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

推荐阅读

史海拾趣

Glow-Lite Corp公司的发展小趣事

对于红外遥控发射电路,网友可能会有多方面的问题。以下是一些可能的问题及其详细回答:

一、红外遥控发射电路的基本工作原理是什么?

回答
红外遥控发射电路的基本工作原理是,当用户按下遥控器上的某个按键时,遥控器内部的微控制器(CPU)会读取与该按键对应的二进制数据,并通过信号调理电路进行处理。随后,这些数据被调制电路转换为适合传输的信号,并经过放大后,由红外线发射二极管以红外光的形式发射出去。接收设备上的红外接收头接收到这些红外光信号后,会将其转换为电信号,并经过进一步的处理还原为原始的控制指令,从而实现遥控功能。

二、红外遥控发射电路常见的故障有哪些?

回答
红外遥控发射电路常见的故障主要包括以下几个方面:

  1. 电池电量不足或接触不良:这是最常见的故障之一,当电池电量不足或电池卡簧接触不良时,会导致遥控器无法正常工作。

  2. 按键故障:按键上的导电橡胶易磨损、老化,或按键电路中的铜箔线条断裂、开焊等,都会导致按键失灵。

  3. 振荡电路故障:振荡电路中的陶瓷谐振器易受到机械冲击而损坏,导致振荡频率偏移或停振,进而影响遥控信号的发射。

  4. 红外发光二极管故障:红外发光二极管可能因引脚开焊、内部开路或失效等原因而无法正常工作。

  5. 驱动电路故障:驱动电路中的晶体三极管、电阻等元件可能因开路、放大系数下降等原因导致故障。

  6. 编码集成电路故障:编码集成电路是整个遥控器的核心部分,其内部集成了多个复杂的电路。如果编码集成电路发生故障,将直接影响遥控信号的生成和发射。

三、如何判断红外遥控发射电路是否故障?

回答
判断红外遥控发射电路是否故障,可以采用以下几种方法:

  1. 观察指示灯:如果遥控器上有指示灯,可以通过观察指示灯是否闪亮来判断遥控器是否有红外信号发射。

  2. 替换法:用一个确认无故障的遥控器去控制同一台设备,如果控制有效,则说明原遥控器可能存在故障。

  3. 万用表检测:使用万用表测量遥控器电池电压、按键电阻、红外发光二极管两端电压等,以判断电路是否正常。

  4. 收音机检测:利用收音机的中频载波与遥控器振荡频率接近的特点,通过收音机接收遥控器发出的信号来判断遥控器是否具有发射能力。

四、如何维修红外遥控发射电路的故障?

回答
维修红外遥控发射电路的故障,需要根据具体的故障原因采取相应的措施。以下是一些常见的维修方法:

  1. 更换电池:如果电池电量不足或接触不良,应更换新电池或清理电池卡簧。

  2. 清洁按键:如果按键故障是由于导电橡胶磨损或灰尘等杂物造成的,可以用软布蘸无水酒精清洗按键表面。

  3. 更换元件:如果振荡电路、红外发光二极管、驱动电路或编码集成电路等元件损坏,应更换相应的元件。

  4. 焊接修复:如果电路中存在开焊、断裂等现象,应使用焊接工具进行修复。

  5. 调整电路:如果故障是由于电路参数设置不当或元件老化等原因造成的,应对电路进行调整或更换老化元件。

通过以上方法,可以有效地解决红外遥控发射电路中的常见故障。

Hendon Semiconductors公司的发展小趣事

随着电子产品的不断小型化和集成化,表面贴装技术(SMT)成为了电子制造行业的重要趋势。Hendon Semiconductors紧跟这一趋势,不断提升其表面贴装和精密制造能力。公司引进了先进的生产设备和测试仪器,确保产品的质量和可靠性。同时,Hendon Semiconductors还加强了对生产过程的监控和管理,通过严格的质量控制体系确保每一片电路板都符合客户的要求。

DALLAS公司的发展小趣事

随着移动设备市场的蓬勃发展,Dallas公司敏锐地捕捉到了电池电量管理技术的市场需求。在深入研究和技术攻关后,Dallas成功推出了可编程锂离子电池电量计DS2790。这款产品集成了先进的微控制器、大容量程序和数据存储器以及精密的电池电流、电压和温度测量系统,为定制单节电池电量计的算法提供了优秀的平台。DS2790的推出不仅满足了市场需求,也为Dallas公司在电池管理技术方面赢得了声誉。

东晶(ECEC)公司的发展小趣事

面对日益激烈的市场竞争和环境保护的压力,东晶电子坚持品质至上和绿色生产的理念。公司引进了先进的品质管理体系和环境管理体系,通过ISO9001、ISO14000等认证,确保产品质量的稳定性和可靠性。同时,公司还积极推广绿色生产理念,采用环保材料和工艺,降低生产过程中的能耗和排放,实现可持续发展。

BOWEI公司的发展小趣事

为了满足市场需求和降低成本,东晶电子不断进行产能扩张和自动化升级。公司引进了国际先进的生产设备和技术,提高了生产效率和产品质量。同时,公司还加大了对自动化设备的投入,减少了人力成本,提高了生产效率。这些措施不仅提升了公司的竞争力,也为公司的长远发展奠定了基础。

Electrocube Inc公司的发展小趣事

Electrocube Inc公司的创始人在创立之初便面临着重重挑战。当时,电子行业正处于快速发展阶段,市场竞争激烈。然而,创始人凭借对电子技术的深刻理解和敏锐的市场洞察力,成功开发出了一款高性能、低成本的电容器产品。这款产品迅速获得了市场的认可,为公司赢得了第一桶金,也为后续的发展奠定了坚实的基础。

问答坊 | AI 解惑

信号的反射问题

信号在传输线上传输时,若遇到阻抗不连续的情况,就会发生信号的反射现象. 我想知道信号是怎样反射的,为什么在阻抗不匹配时就会发生反射现象?有哪些解决措施? :( …

查看全部问答>

Android编译环境(1) - 编译Native C的helloworld模块 ZT

Android编译环境本身比较复杂,且不像普通的编译环境:只有顶层目录下才有Makefile文件,而其他的每个component都使用统一标准的Android.mk. Android.mk文件本身是比较简单的,不过它并不是我们熟悉的Makefile,而是经过了Android自身编译系统的很 ...…

查看全部问答>

别傻了(9):能力强就可以高枕无忧

你的能力并不能确保你的安全 很多公司在招聘员工或对外宣传时说我们公司注重员工的能力,提倡员工能发挥自己的主观能动性 (确实有一些公司是提倡创新的,但是极少数,大部分都只是打打口号而已)。对于刚入职的员工来说可能都会有一种心理,那就 ...…

查看全部问答>

求大虾按图给个元件列表

要做个充电器,不知道与充电芯片相连的元件的参数.还有接口要接MICROUSB,有四条线,地线、读数据线、写数据线、+5V线 ,就直接把OUT接在5V线上就可以了贝? …

查看全部问答>

pcc中如何实现用ie打开不同格式的文件?

比如在IE中点击一个avi文件的链接,自动就会启动mediaplayer来播放,如果点击一个bt文件的链接,自动就会启动bt程序来下载,这个过程如何实现?需要用到哪些技术?请高手指点 …

查看全部问答>

初学嵌入式软件开发,不知道该从那些方面入手,有经验的可否提供一些建议?

我是学软件工程的,专业方向选的是嵌入式方向,现在课程比较少 我想先找点书看,可不知道该看什么样的书,大家可否给点意见?…

查看全部问答>

LCD 显示不正常

大家好 我问个问题: 我用STM32的LCD例程  修改下 在FPGA板子上跑起来 遇到的几个问题如下: 1、初始化后 花屏 2、清屏 不能清白色 其他颜色可以 3、 字符显示不正常 会出现乱码 请问 有谁遇到过类似问题吗…

查看全部问答>

自助借还书机(ZT2000)

感创ZT2000自动借还书设备是通过与图书馆自动化系统数据相连接,由读者自行借还馆内图书资料;帮助图书馆在有限的人力资源条件下,增进图书流通速率、简化借还流程,进而提高图书馆从业人员工作效率及服务品质的一种自助设备。 该自助借还书设备 ...…

查看全部问答>

索尼要裁员1万,日本电子制造业出了啥问题?

传索尼最早将在今年年底前全球裁员1万人,约占雇员总数的6%。这家公司一直是日系企业的中间代表,大家知道日系企业的一大特点就是不到万不得已是尽量不裁员,号召企业与员工共同成长,这比中国的国企还国企。究竟日本电子企业出什么问题了,本人不 ...…

查看全部问答>