这次实现的是在开发板从nor中启动时就能执行定时器灯闪烁程序,而且这程序不是搬到SDRAM,是直接在nor中执行的。先来介绍一下arm映像文件和scatterfile文件
一、基本概念
arm映像文件其实就是可执行文件,包括bin或hex两种格式,可以直接烧到rom里执行。映像文件一般由域组成,域最多由三个输出段组成(RO,RW,ZI)组成,输出段又由输入段组成。在scatterfile中可以为每一个代码或数据区在装载和执行时指定不同的存储区域地址,所谓域,指的就是整个bin映像文件所处在的区域,Scatlertoading的存储区块可以分成二种类型:装载域:当系统启动或加载时应用程序的存放区。执行域:系统启动后,应用程序进行执行和数据访问的存储器区域,系统在实时运行时可以有一个或多个执行块。映像中所有的代码和数据都有一个装载地址和运行地址(二者可能相同也可能不同,视具体情况而定)。在系统启动时,C函数库中的__main初始化代码会执行必要的复制及清零操作,使应用程序的相应代码和数据段从装载状态转入执行状态。
我们输入的代码,一般有代码部分和数据部分,这就是所谓的输入段,经过编译后就变成了bin文件中ro段和rw段,还有所谓的zi段,这就是输出段。对于加载域中的输出段,一般来说ro段后面紧跟着rw段,rw段后面紧跟着zi段。在运行域中这些输出段并不连续,但rw和zi一定是连着的。zi段和rw段中的数据其实可以是rw属性。
二、系统分析
一般而言,一个程序包括只读的代码段和可读写的数据段。在ARM的集成开发环境中,只读的代码段和常量被称作RO段(ReadOnly);可读写的全局变量和静态变量被称作RW段(ReadWrite);RW段中要被初始化为零的变量被称为ZI段(ZeroInit)。对于嵌入式系统而言,程序映象都是存储在Flash存储器等一些非易失性器件中的,而在运行时,程序中的RW段必须重新装载到可读写的RAM中。这就涉及到程序的加载时域和运行时域。简单来说,程序的加载时域就是指程序烧入Flash中的状态,运行时域是指程序执行时的状态。对于比较简单的情况,可以在ADS集成开发环境的ARM LINKER选项中指定RO BASE和RW BASE,告知连接器RO和RW的连接基地址。对于复杂情况,如RO段被分成几部分并映射到存储空间的多个地方时,需要创建Scatterfile文本文件,通知连接器把程序的某一部分连接在存储器的某个地址空间。需要指出的是,Scatterfile中的定义要按照系统重定向后的存储器分布情况进行。在引导程序完成初始化的任务后,应该把主程序转移到RAM中去运行,以加快系统的运行速度。
下面举个定时器中断在nor中运行的相关设置来说明:
定时器中断函数如下:
int main(void)
{
*(RP)GPIO_PORTD_SEL = 0xff;//这个是作输出
*(RP)GPIO_PORTD_DIR = 0x00;//这个是作输出
*(RP)GPIO_PORTD_DATA = 0x00;//这个是全部输出为1
InitTmier();//定时器中断初始化
while(1);
return 0; //为了消除警告
}
void InitTmier(void)
{
mask_irq(INTSRC_TIMER1);
// 设置timer1通道为重启计数模式
*(RP)TIMER_T1LCR = 87999972; //根据产生中断的时间间隔设置加载的计数值
*(RP)TIMER_T1CR = 0x6; //设置通道1工作于重启计数模式
*(RP)TIMER_T1CR |= 0x1;
irq_enable(INTSRC_TIMER1); /*中断使能*/
unmask_irq(INTSRC_TIMER1); /*打开屏蔽中断*/
}
void Timer_IRQ_Service1(void) //中断服务程序
{
volatile U32 clear_int;
clear_int = *(RP)TIMER_T1ISCR; //读通道1中断状态清除寄存器清除中断
*(RP)TIMER_T1ISCR=clear_int;
if(i==0)
{
//printf("all is 0\n");
*(RP)GPIO_PORTD_DATA = 0x0f;//这个是全部输出为1 灯灭
i="1";
}
else
{
// printf("all is 1\n");
*(RP)GPIO_PORTD_DATA = 0x00;//这个是全部输出为1 灯亮
i="0";
}
}
scatterfile按如下修改:
SDRAM 0x30000000
{
SDRAM 0x30000000
{
boot_gfd.o (BOOT, +First)
* (+RW,+ZI)
}
}
FLASH 0x00000000
{
FLASH 0x00000000
{
int_gfd.o (INT, +First)
* (+RO)
}
}
然后RO_Base为0x00000000,RW_Base为0x30000000,Object为int_gfd.o把这些都设置好了后编译一下生成一个映像文件为led.bin,把这文件用jlink烧录到nor中,然后把开发板打到nor启动,重启开发板就可以看到灯一亮一灭的啦
文章评论(0条评论)
登录后参与讨论