一、基础知识
我们编写的源文件(.c 或.s)经过ARM 编译器的编译生成ELF 格式的目标文件(后缀名为.o),目标文件经过ARM 连接器连接以后生成ELF 格式的映像文件(后缀名为.axf),此时的映像文件还包含一些调试信息,我们还需要通过fromelf 工具将其转换成适合在ROM 或RAM 中运行的二进制代码(后缀名为.bin),这时生成的二进制映像文件就可以被烧写入目标板的ROM 或FLASH 中,当目标板上电后可以通过各种方式在ROM 或RAM 中运行。
一个可执行程序的映像文件由一个或多个域组成,域分为两种:一种是映像文件在存储器中存放的地址,称为加载域;另一种是映像文件运行时的地址,称为运行域。每个域由一个或3 个输出段组成,每个输出段则由一个或多个输入段组成。输入段包含程序代码、已经初始化的数据、未经初始化的存储区、被初始化为0 的存储区,输入段据此可分为三种属性:RO(只读,包括代码和常量)、RW(可读可写,包括已经初始化的全局变量和静态变量)、ZI(未初始化的变量,需初始化为0), 连接器根据属性将输入段分组,组成不同的输出段。一个输出段是有具有相同属性的输入段组成的,输出段的属性与其中输入段的属性相同,因而输出段也分为三种。域由不同属性的输出段组成,输出段在域中的排列顺序为RO 输出段排在最前,然后是RW 输出段,RW 输出段和RO 输出段可以不连续,最后是ZI 输出段,ZI 输出段是紧接着RW 输出段的(加载域只包含RO、RW 输出段,原因见后述)。
可执行镜像一开始一般是存储在系统的ROM 或FLASH 中,RO 段是只读的,在运行的时候我们不能改变它,所以RO 段在运行的时候可以驻留在ROM 或FLASH 中,也可以拷贝到运行速度更快的RAM 中;RW 段在运行的时候,我们需要对其读写,在运行前这一段必须被拷贝至RAM 中;ZI 段为未初始化的全局变量段,只需要在程序运行之前建立ZI 并将其所在区域全部清零即可,因此镜像装载域不必包含ZI 输出段,但在运行域需要包含ZI,并且ZI 必须处于RAM。
通过以上说明,我们知道如果某个镜像只有RO 段的话,程序可以不必拷贝至RAM,但是如果程序包含RW 段的话,RW 段是必需要拷贝至RAM 中的,如果有必要的话还需在RAM 中创建ZI 段,并将其清零。为保证程序的正确执行,而进行必要的数据拷贝和清零,就是应用程序执行环境的初始化。
二、S3C2440启动的基本原理
Nand Flash启动
当S3C2440 开发板采用的是Nand Flash 启动,镜像一开始是存储在Nand Flash 中,而Nand Flash只能作为存储程序和数据之用,无法在其中运行程序,所以S3C2440 开发板启动代码中应用环境初始化这一步和上述步骤稍有不同。S3C2440 镜像文件加载和运行时的地址映射关系如下图所示:
S3C2440 没有上电之前映像文件存储在Nand Flash 中,Nand Flash 有专门的控制器控制,不占用存储器BANK。当开发板上电时,Nand Flash 的前4K 被复制到S3C2440 芯片内部的一块容量为4K 的SRAM(被称为“Steppingstone”),然后这块SRAM 被映射到地址0x00000000 处,程序从此处开始运行。因为Nand Flash 中不能运行程序,所以在这4K 的代码中必须包含一段代码将Nand Flash 中的程序拷贝至S3C2440 的SDRAM 中(0x30000000 开始)。应用环境初始化应该包含这段代码。
Nand Flash 中的映像文件被拷贝至从0x30000000 开始的SDRAM,这时候映像文件还没有真正被执行,此时是加载状态,加载域如上图所示,包括所有RO 属性的输出段和RW 属性的输出段,ZI 属性的输出段此时还不存在。在映像文件运行时,会生成3 个运行域,如上图所示,RO 和RW 属性的运行域的起始地址和加载时是相同的,所以在应用程序执行环境初始化中不需要对其进行拷贝,ZI 运行域则需要在映像开始被执行前建立并被初始化为0,所以应用程序执行环境初始化中也要包含这类代码。(注意:RO 和RW 属性的运行域的起始地址和加载时是相同的,即拷贝到SDRAM后就不用再移动了。ADS中设置的RO Base和RW Base决定了程序的链接地址)
Nor Flash启动
当S3C2440采用Nor Flash启动时,代码可以在上面直接运行。但为了运行的效率,还是把程序拷贝到SDRRAM中运行。加载时地址关系和运行时地址关系和Nand Flash的基本相似。Nand Flash启动时,会将RO段和RW段同时拷贝到SDRAM中,然后再建立ZI段。从Nor Flash启动时是先拷贝RO段,然后再拷贝RW段,最后建立ZI段。
三、相关启动代码分析
- ;一个arm 程序是由R0,RW,ZI 三个段组成。其中R0 为代码段,RW 是已经初始化的全局变量,ZI 是未
- ;初始化的全局变量,启动代码要将RO段和RW段复制到RAM 中并将ZI 段清零。编译器使用下列变量
- ;来记录各段的起始地址和结束地址。这些标号的值是通过编译器的设定来确定的如ADS中对ro-base 和
- ;rw-base 的设定。
- 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
-
-
- ;===========================================================
-
- ldr r0, =BWSCON
- ldr r0, [r0]
- ands r0, r0, #6 ;通过判断OM[1:0] != 0, 得知是NOR FLash boot
- bne copy_proc_beg ;不用读取 nand flash
- adr r0, ResetEntry ;OM[1:0] == 0, 从NAND FLash 启动
- cmp r0, #0 ;再比较入口是否为0地址处,如果不是则用了仿真器
- bne copy_proc_beg ;用仿真器的情况也不要用 nand flash启动
- ;nop
- ;===========================================================
- nand_boot_beg ;这一段代码完成从NAND读代码到RAM
- [ {TRUE}
- bl RdNF2SDRAM
- ]
-
-
- ldr pc, =copy_proc_beg ;此时的PC已经在0x30000000以后,是copy_proc_beg连接时的地址
- ;这个标号下面的代码完成的功能就是把nor flash 的内容拷贝到ram 当中。
- ;===========================================================
- copy_proc_beg
- adr r0, ResetEntry ;装载地址,ResetEntry值->r0
- ldr r2, BaseOfROM ;BaseOfROM值
- cmp r0, r2 ;比较RO,R2
- ldreq r0, TopOfROM ;如果相等的话(说明在内存中运行),TopOfROM->r0 当从Nand Flash中启动时r0=r2,当从Nor Flash启动时则不相等
- beq InitRam ;同时跳到InitRam
- ;下面这个是针对代码在NOR FLASH时的拷贝方法
- ;功能为把从ResetEntry起,TopOfROM-BaseOfROM大小的数据拷到BaseOfROM
- ;TopOfROM和BaseOfROM为|Image$RO$Limit|和|Image$RO$Base|
- ;|Image$RO$Limit|和|Image$RO$Base|由连接器生成为生成的代码的代码段运行时的起启和终止地址
- ;BaseOfBSS和BaseOfZero为|Image$RW$Base|和|Image$ZI$Base|
- ;|Image$RW$Base|和|Image$ZI$Base|也是由连接器生成,两者之间就是初始化数据的存放地放
- ldr r3, TopOfROM
- 0
- ldmia r0!, {r4-r7}
- stmia r2!, {r4-r7}
- cmp r2, r3
- bcc %B0
-
- sub r2, r2, r3 ;这两句代码是修正字非对齐的情况,因为是按4个字节拷贝的,但RO段大小不一定是4个字节对齐的
- sub r0, r0, r2
-
- InitRam
- ldr r2, BaseOfBSS
- ldr r3, BaseOfZero
- 0
- cmp r2, r3
- ldrcc r1, [r0], #4
- strcc r1, [r2], #4
- bcc %B0 ;这一段是对ResetEntry 里面定义好的数据拷贝到RW 段。
-
-
- mov r0, #0
- ldr r3, EndOfBSS
- 1
- cmp r2, r3
- strcc r0, [r2], #4
- bcc %B1 ;初始化ZI段
-
- ldr pc, =%F2 ;goto compiler address
- 2
-
- ; [ CLKDIV_VAL>1 ; means Fclk:Hclk is not 1:1.
- ; bl MMU_SetAsyncBusMode
- ; |
- ; bl MMU_SetFastBusMode ; default value.
- ; ]
-
-
- [ :LNOT:THUMBCODE
- bl Main ;不要用main()因为main()是ADS默认入口,编译器会添加其他代码
- b . ;跳转到Main不成功则挂起
- ]
-
-
- [ THUMBCODE ;for start-up code for Thumb mode
- orr lr,pc,#1
- bx lr
- CODE16
- bl Main ;Do not use main() because ......
- b .
- CODE32
- ]
-
-
- 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|
关键字:S3C2440 启动代码 执行环境
引用地址:
S3C2440启动代码中应用程序执行环境的初始化
推荐阅读最新更新时间:2024-03-16 14:46
基于ARM9芯片的S3C2440和Linux操作系统设计SPI驱动程序
在嵌入式开发过程中,许多系统通常使用串口驱动来满足通信要求,但在实际应用中,使用SPI通信方式会更加高效和快捷[2]。SPI接口是一种高速、高效的串行接口技术,因而SPI设备在数据通信应用中十分方便[3]。本文基于ARM9芯片的S3C2440和Linux操作系统,设计了一种SPI驱动程序,该驱动程序功能可靠灵活、易于移植,可应用于多种嵌入式平台,实现ARM与设备之间的通信。 1 硬件说明 1.1 S3C2440开发平台 采用三星公司的SoC芯片S3C2440[4]作为核心处理器,主频为400 MHz,并与64 MB SDRAM和64 MB NAND Flash共同组成核心部分。此外,该平台也为用户提供了大量的通
[单片机]
s3c2440的nandflash启动
上文介绍了s3c2440对nandflash的基本操作,其中提到了s3c2440具有nandflash自启动的功能,本文就详细介绍该功能的实现方法。 nandflash由于其自身的特点,不具备运行程序的功能。但s3c2440通过称为“Steppingstone”的内部SRAM缓存,实现了可以运行存储在外部nandflash中的启动代码的功能。它的机制是:当检测到是由nandflash启动时,系统会自动把nandflash中的前4k字节的数据加载到Steppingstone中,然后把该Steppingstone映射为Bank0,因此系统会从Steppingstone开始运行程序,从而实现了s3c2440
[单片机]
s3c2440裸机-I2c编程-3.i2c中断服务程序
Start信号之后,发出设备地址,在第9个时钟就会产生一个中断,我们根据i2c的流程图来编写中断程序。 每传输完一个数据将产生一个中断,I2C操作的主体在中断服务程序,它可以分为两部分:写操作,读操作。 完整code如下: static p_i2c_msg p_cur_msg; int isLastData(void) { if (p_cur_msg- cnt_transferred == p_cur_msg- len - 1) return 1; /* 正要开始传输最后一个数据 */ else return 0; } void resume_iic_with_
[单片机]
S3C2440串口(1)
1.S3C2440串口概述 串口通讯一般要增加电平转换电路,原因是TTL/CMOS电平与RS232电平不一致: TTL/CMOS电平: CMOS电平: 常用的电平转换芯片是MAX3232。 S3C2440有3个独立的异步串口,可以选择工作在中断或DMA方式下。每个UART包括一个波特率发生器、发送器、接收器和一个控制单元。 UART有FIFO模式和非FIFO模式。FIFO模式下可以利用64字节的发送/接收缓冲寄存器,非FIFO模式下只使用了发送/接收缓冲寄存器中的1个字节。本篇入门级以非FIFO为例。 2.串口设置及相关寄存器 串口引脚是GPIO复用的。本篇UART只用3根引脚:TXD、RXD、GND。 TXD0 – G
[单片机]
单片机定时器中断原理及s3c2440的定时器使用方法
在程序中,需要延时的时候,通常状况下有两种方法:1、循环语句实现,这种方法简单易用,但是无法得到一个精确的延时时间;2、定时器定时,可达到精确延时。 中断的概念 什么是中断:CPU在处理某一事件A时,发生的另外某一事件B请求CPU去处理(产生了中断),随后CPU暂时中断当前正在执行的任务,去对事件B进行处理,CPU处理完事件B后再返回之前中断的位置继续执行原来的事件A,这一过程总称为中断。 中断流程示意图 使CPU中断的事件称中断源。中断源向CPU发出中断请求,CPU暂时中断原来执行的事件A转去做事件B。事件B处理完毕后继续返回原先中断的地方(该过程称中断返回,原先中断的地方为断点),继续执行原先的事件。 中断的优
[单片机]
s3c2440 ARM9 裸机驱动第一篇-GPIO驱动(C)
此文为对于LED驱动的补充: 废话不说,先上代码。 start.s .text .global _start _start: ldr r0 ,= 0x53000000 @WATCHDOG ADD mov r1 ,#0x0 str r1 , @r1 的数据写入r0 关看门狗 ldr sp ,=1024*4 @设置栈 bl main @跳转到main执行 halt: b halt led.c #define GPFCON (*(volatile unsigned long *)0x56000050) #define
[单片机]
S3C2440的camera接口特性及WinCE 下的驱动
S3C2440是应用十分广泛且适用于嵌入式系统的一款嵌入式处理器。winCE 5.0/6.O是微软公司开发的一款专用于嵌入式系统的实时操作系统。其模块化设计使开发人员可以根据需求定制设备。目前,国内大部分OEM商都提供了对S3C2440的camera接口在WinCE5.O/6.0下的驱动支持。遗憾的是,目前国内OEM商提供的驱动仅限于对几款微型摄像头(如ov9650等)的驱动支持。当用户采用CCD摄像头作为图像采集的前端设备时,原来的驱动已经不能使用了,而CCD摄像头因其优越的性能,在监控领域扮演着主力军角色。本文从分析S3C2440的camera接口特性出发,详细介绍当摄像设备为CCD摄像头时,在WinCE 5.O/6.0操
[嵌入式]
入门 | S3C2440启动过程分析
S3C2440启动过程算是一个难点,不太容易理解,而对于S3C2440启动过程的理解,影响了后面裸机代码执行流程的分析,从而看出S3C2440启动过程的重要性。 S3C2440启动方式和启动方式选择 在S3C2440的datasheet《S3C2440A_UserManual_Rev13.pdf》中搜索map,可以在第5章中搜索到下图。 从此图中,可以得知 OM = 01,10,Not using NAND flash for boot ROM OM = 00,Using NAND flash for boot ROM 而OM 又是什么呢? 从S3C2440的datasheet《S3C2440A_UserManua
[单片机]