s3c2440中断程序(烧录到NORFlash,运行在SDRAM中)

发布者:光速思考最新更新时间:2018-07-22 来源: eefocus关键字:s3c2440  中断程序  NORFlas  SDRAM 手机看文章 扫描二维码
随时随地手机看文章

现在正在看韦东山的《嵌入式Linux应用开发完全手册》,看到了中断部分。书上是将程序烧录到NANDFlash中,由于当mini2440板子从NANDFlash启动的时候,会自动将其中的前4KB程序拷贝到CPU内部的SRAM(4KB大小)中,并且将该SRAM的起始地址映射为0x0。所以当中断发生的时候,PC指针指向0x0+offset(如:IRQ就是0x18),可以找到中断服务程序的入口。

但是有4KB的限制,加上U-BOOT一般都烧录到NORFlash中,再将程序搬移到SDRAM中再运行的,恰好手底下有JLINK设备,所以决定写一个烧录到NORFlash,运行在SDRAM中的中断测试程序。

先说一下整体思路:将系统启动时寻找的八个跳转指令写入一个文件,将其加载地址和运行地址都设为0x0,即加载和运行都在NORFlash的0x0。而其余的程序部分:关闭看门狗,设置堆栈,初始化SDRAM,搬移程序到SDRAM中,中断服务函数,按键和LED初始化,main函数等加载地址设为0x40,而运行地址设为SDRAM的起始地址:0x30000000。

这个程序分为head1.S, head2.S, init.c, interrupt.c, mian.c, Makefile, int.lds, s3c24xx.h八个文件组成。

一。head1.S文件:


上面程序中含有八条相对跳转指令b,和两条绝对跳转指令ldr pc,=xx。其中b为位置无关指令,即加载地址与运行地址不同时,仍可以跳转到正确的地方,但是其跳转范围有限,从NORFlash跳到SDRAM中是不可能的。ldr pc, =xx为绝对跳转,是位置相关指令,它是跳转到xx的运行地址处,如HandleIRQ的运行地址为0x3000009c,程序会跳转到0x3000009c处执行。以上两条语句均不会自动保存返回地址。值得注意的是:上面的0x40就是第二段程序(head2.S开始)的起始加载地址,它存放在NORFlash0x40处,所以跳转到0x40处就可以接着执行下面的程序。若是此处写_Reset(初始化程序入口标号,在head2.S文件中),那么程序会跳转到这个标号的运行地址处,即SDRAM中的0x30000008,而此时还没有将程序拷贝到SDRAM中,所以如果这么做,程序必然跑飞。而ldr pc,=HandleIRQ就可以正常跳转到中断服务程序处,这是因为中断发生时,SDRAM初始化和代码搬移已经完成,SDRAM的0x3000009c处存放的就是中断服务程序。


二。head2.S文件:


上面的程序中先定义了几个全局标号,如果不定义HandleIRQ,那么head1.S文件中的跳转是不会成功的,因为在链接之前,该标号没有被定义。其中值得注意的是sdram_start 和sdram_end这两个标号,他们定义的两个.word变量,这两个变量分别为需要搬移的第二段代码的起始地址与终止地址,这两个变量在int.lds链接文件中被定义,下文中有这两个变量的详细介绍。

在_Reset处开始为板子的一些初始化工作,包括关闭看门狗,设置堆栈,初始化SDRAM,将NOR Flash中的代码拷贝到SDRAM中,它们以调用子函数的方式实现。这里用到了跳转指令bl,这个指令和b类似,均为位置无关指令,而且当前pc指针在0x3000xxxx处,需要跳转到的这几个标号的运行地址也在0x3000xxxx处,所以不会出现超过跳转最大范围的问题,所以可以正常跳转。他们两个的不同之处是bl在执行时,返回地址的地址自动保存入lr(r14)寄存器中,在返回时,只用一句:mov pc, lr 即可返回到跳转之前的位置。

ldr pc,=on_sdram这一条绝对跳转指令就可以使程序跳转到SDRAM中去执行,所以on_sdram标号处以后的程序均在SDRAM上运行。上述初始化操作在NOR Flash上运行。然后跳转到了SDRAM中继续执行剩下的程序。

msr cpsr_c, #0x53这一条语句设置CPSR寄存器的低八位(cpsr_c表示CPSR寄存器的低八位),通过设置这个寄存器,将系统设为管理模式,允许IRQ中断,ARM模式。这里不明白的可以查看芯片手册中关于CPSR寄存器的解释部分。


上面的程序是关看门狗,设置堆栈的子程序。

关闭看门狗是为了省去一直“喂狗”的麻烦(如果不一直向系统写入特定的数据,看门狗会认为系统死掉,而重启系统)。关闭的方法就是向控制看门狗的寄存器WTCON(地址为0x53000000)写入0x0。

设置堆栈是为了后面C程序的运行和中断保存现场。其方法是:先将系统设置为IRQ中断模式,在此模式下设置中断指针为0x33500000(这个数可以更改,首先,堆栈是向低地址生长的,其次,SDRAM的截止地址为0x34000000,要留有一部分给C程序,所以这里设置为0x33500000);然后将系统再设为管理模式,设置该模式下的堆栈指针为0x34000000.然后返回即可。



上面的程序是初始化内存(主要是SDRAM)。初始化内存即配置控制内存的寄存器,需要配置的一共是13个,它们的地址是连贯的,初始地址为0x48000000。

s3c2440中一共有八个bank(bank0~bank7)每个bank128M(bank6和bank7的大小及bank7的起始地址可以自由配置,这样使得SDRAM地址的连贯得到保证),其中只有bank6和bank7可以使用SDRAM,mini2440中使用两块16位32M的SDRAM组成一个32位64M的SDRAM放在了bank6上。这里不明白的可以去看s3c2440芯片手册中关于内存的部分。

根据芯片手册,结合《嵌入式linux应用开发完全手册》将13个寄存器配置成上图中的数据。配置方式为将第一个寄存器地址给r0,将要配置的数据初始地址给r1,然后用ldr指令将r1地址内的数据传入r3,再用str指令将r3中的数据传入r0地址处的寄存器中,如此循环。r2为第十三个寄存器的地址,当r0与r2相同时,说明13个寄存器全部配置完成,跳出循环并返回。



上面的程序是将第二段程序(sdram_start到最后)从NORFlash拷贝到SDRAM中。

adr这个指令是位置无关指令,它会获取标号的加载地址(即当前实际运行在什么地方),所以可以用这个指令来判断程序运行在什么地方。这里将sdram_start这个标号的实际地址0x40传入了r0中,此时r0中即为需要拷贝的程序的起始地址。

r1为SDRAM的起始地址,也就是我们要拷贝到的目标地址。

sdram_start和sdram_end这两个标号处在head2.S文件的开头处分别定义了两个.word变量,且在链接文件lds中赋值(看下文中的int.lds文件),这两个变量的差值即为第二段程序的总长度,所以最终r2代表了第二段程序的结束地址。

后面就是进行循环,将代码从0x40拷贝到0x30000000处的过程,当拷贝完成,子程序返回。


上面程序为IRQ的服务程序,完成的功能是:保存现场,保存此时的pc值,进入下一级中断服务程序,当下一级服务程序返回时,恢复现场,并将CPSR还原。

由于ARM的指令流水线及PC始终指向将要运行的地址,需要先计算中断返回的地址,sub lr, lr, #4即为这个操作,有兴趣的可以去查找一下ARM指令流水线。

stmdb ,ldmia为多个寄存器与内存之间的操作指令。此处的stmdb将寄存器r0-r12,lr这些寄存器的值保存入IRQ的堆栈中,这是入栈操作。此处ldmia将刚才保存入堆栈的数据再传入r0-r12,中,将刚才的lr换为了pc,既是将刚才计算的返回地址,传给pc,即可返回中断发生时的地方继续执行。此处的^表示:将SPSR_irq中的数据传入CPSR中,而SPSR_irq在进入中断时自动将CPSR保存进去,所以这个操作,可以使系统回到进入中断前的状态。

EINT_Handle在interrupt.c中可以看到。

三。init.c文件





上面程序实现的功能为:初始化led和按键,写了几个led开关的子程序,打开外部中断。

这里的程序很简单,只说明一下init_irq这个函数。这个函数先是将连接到板子上按键的I/O口设置为外部中断模式,然后将相对应的几个外部中断的屏蔽取消,然后取消了这几个外部中断上一级的屏蔽。但此时中断并没有完全打开,再结合上文中msr cpsr_c, #53才将这几个外部中断完全打开。这里不理解的可以去看一下s3c2440芯片手册中关于中断的讲解。


四。interrupt.c文件



上面的程序就是上文中说到的下一级中断处理函数,它实现的功能十分简单,将每个中断都对应了一种led的变化形式,以此来观察中断程序是否正常运行。

EINTPEND这个寄存器中反映出具体是哪个外部中断产生了,它的每一位对应一个外部中断,该位被置1,说明中断发生,且会被CPU响应(没有被屏蔽),通过这个寄存器中的值即可知道哪个中断发生了。

当处理完中断后,需要将各个中断寄存器清空,清空方法为相对应寄存器的位(刚才置1的位)写1(注意不是0)。至于SRCPND和INTPND寄存器,大家可以在芯片手册上查到,它们分别表示通过一级屏蔽(子中断屏蔽)和二级屏蔽之后的对应的中断。


五。main.c文件


这个文件调用了一些初始化子程序,他们分别在init.c和interrupt.c中,然后进入死循环,死循环中始终让led1进行间隔亮灭。此时如果中断发生,则会进入中断服务程序。这里十分简单,就不详细地说了。


六。int.lds文件


该文件就是整个程序的链接文件。它将整个程序分为两段,第一段加载地址和运行地址均为0x0,第二段加载地址(由AT()确定)为0x40,运行地址为0x30000000。

.{空格} ={空格}0x30000000说明此处的运行地址为0x30000000。此处注意空格,没有的话会报错。

_sdram_start{空格}={空格}. 说明_sdram_start这个变量的值为0x30000000。

当second段语句执行完,定位符(.)变成了当前地址(也就是所有程序的结束地址)。所以_sdram_end变量的值即为所有程序的结束地址。它与_sdram_atart相结合就可以得出第二段程序(需要搬移的程序)的大小。


七。Makefile文件


makefile文件是整个工程的编译链接命令。由上面的程序可以看出,首先对.o文件进行链接,但是此时.o文件尚未生成,所以会先去生成这些.o文件。

那么根据命令:arm-linux-gcc -Wall -O2 -c -o $@ $< 即可逐个生成.o文件。该条命令是只编译不链接。$@代表目标文件,$<代表第一个依赖文件。

然后用链接命令:arm-linux-ld -Tint.lds -o int_elf $^ 来生成可执行文件int_elf。其中-Tint.lds为以int.lds文件所定义的地址分布来链接文件。$^代表全部的依赖文件。

arm-linux-objcopy -O binary -S int_elf $@ 用elf文件生成一个二进制文件int.bin。

arm-linux-objdump -D -m arm int_elf > int.dis 是将int_elf这个可执行文件进行反汇编生成int.dis反汇编文件。我们可以通过这个文件来查看程序的反汇编代码及每条语句的运行地址。


八。编写调试程序中的注意事项

1.第二段程序的实际的运行地址与lds中的运行地址一定要一致,因为其中大多为位置有关指令,若是不一致就不能跳转到正确的位置。所以要保证sdram_start标号的运行地址就是0x30000000,因为后面是以sdram_start标号为起始位置进行代码搬移的。本人在编写的时候,忽略了这一点,将sdram_end标号及_sdram_end变量的定义写到了sdram_start之前,所以经过搬移,sdram_start标号的运行地址为0x30000000,但是系统根据lds文件会认为它的运行地址是0x30000004。所以导致了程序一直不通。

    2.注意跳转指令b、bl、ldr pc,=xx的使用,前两个是位置无关指令,有跳转范围,后一个是位置相关指令,无跳转范围。这三个中只有bl可以自动保存返回地址。

3.结合芯片手册搞懂各个寄存器的配置方式及其对应的地址,写错了地址,配置是不可能成功的。还要注意板子上按键和led分别对应的I/O接口,不要搞错了。


关键字:s3c2440  中断程序  NORFlas  SDRAM 引用地址:s3c2440中断程序(烧录到NORFlash,运行在SDRAM中)

上一篇:S3C2440 SDRAM寄存器初始化设置
下一篇:S3c2440代码重定位详解

推荐阅读最新更新时间:2024-03-16 16:09

基于WinCE的智能车载仪表设计
  引言   随着高性能电子显示技术的发展,汽车仪表电子化的程度越来越高。国内外已开发出了多功能全电子显示仪表、平视显示仪表、汽车导航系统、行车记录仪等高技术产品。未来,车用电子化嵌入式仪表具有以下优点:提供大量复杂的信息,使汽车的电子控制程度越来越高;满足小型、轻量化的要求,使有限的驾驶空间更人性化;高精度和高可靠性实现汽车仪表的电子化,降低了故障的发生率;设有在线故障诊断系统,一旦汽车发生故障,可以找到故障来源,方便维修;外形设计自由度高,汽车仪表盘造型美观。基于以上优点,汽车会越来越多地采用各种用途的电子化仪表。造型新颖、功能强大的嵌入式电子化仪表将是今后车用仪表的发展趋势和潮流。   1 智能车载仪表系统结构   本智
[单片机]
基于WinCE的智能车载仪表设计
s3c2440外部中断操作详解
要想正确地执行2440的外部中断,一般需要完成两个部分内容:中断初始化和中断处理函数。 在具体执行中断之前,要初始化好要用的中断。2440的外部中断引脚EINT与通用IO引脚F和G复用,要想使用中断功能,就要把相应的引脚配置成中断模式,如我们想把端口F0设置成外部中断,而其他引脚功能不变,则GPFCON=(GPFCON & ~0x3) | 0x2。配置完引脚后,还需要配置具体的中断功能。我们要打开某一中断的屏蔽,这样才能响应该中断,相对应的寄存器为INTMSK;还要设置外部中断的触发方式,如低电平、高电平、上升沿、下降沿等,相对应的寄存器为EXTINTn。另外由于EINT4到EINT7共用一个中断向量,EINT8到EINT23
[单片机]
s3c2440的处理器结构和外设连接
1、S3C2440处理器结构 S3C2440处理器的结构如下图所示,其核心单元为ARM9TDMI处理器核,主要包括16K的指令Cache和16K的数据Cache,以及分开的指令和数据MMU单元等。CP15为一个协处理器(Co-Processor)。通过AMBA2.0(Advanced Microcontroller Bus Architecture)总线接口与外部设备相连。 IVA指Instruction Virtual Address,指令虚拟地址;DVA指Data Virtual Address,数据虚拟地址。IPA指Instruction Physical Address,指令物理地址;DPA指Data Physical
[单片机]
<font color='red'>s3c2440</font>的处理器结构和外设连接
s3c2440裸机-电阻触摸屏编程(5.触摸屏校准原理-五点校准法)
1.触摸屏校准原理 之前点的触摸屏解析出来的ADCDATA的bit 表示坐标ADC的转换结果,那么这些结果都是通过电压值来转换过来的。 所谓触摸屏校准,就是让触摸屏坐标(电压值)与LCD的坐标能够对应起来,所以校准就是要找到一个公式把电压值转换成和LCD宽高相符合的坐标值。 如下图,上面一层膜是TS触摸屏,下面一层是LCD显示屏,如果我们的LCD size是480*272,那么当我们点击触摸屏上的原点,那它的坐标可能不是(0,0),而是(X1', Y1'),因此我们需要对触摸屏进行校准,期望把x', y’的坐标能够映射成和lcd一样的坐标0,0. 那么如何较准呢,如下图以X方向为为例。 如果触摸
[单片机]
<font color='red'>s3c2440</font>裸机-电阻触摸屏编程(5.触摸屏校准原理-五点校准法)
s3c2440裸机-电阻触摸屏编程(3.触摸屏TSC的初始化和中断服务程序框架)
1. ADC中断产生流程 中断源: 这里是ADC和TSC共用一个中断源。 SRCPND表示哪个中断源产生了中断请求。 INTMODE:配置中断模式 配置中断屏蔽寄存器 中断挂起寄存器(用来显示当前优先级最高的、正在发生的中断, 需要清除对应位) 从SRCPND寄存器可以读到ADC和TSC复用的同一个中断源,那么如何区分呢? 可以从SUBSRCPND寄存器配置,如下: 当bit 9被置1时,表示TSC中断。那么我们需要打开subsrcmask寄存器 所以TSC中断的产生流程如下: 2. TSC编程实现   ①初始化TSC,ADCTSC寄存器   ②设定TSC处于“等待中断模式”
[单片机]
<font color='red'>s3c2440</font>裸机-电阻触摸屏编程(3.触摸屏TSC的初始化和<font color='red'>中断</font>服务<font color='red'>程序</font>框架)
430f149的定时器A的中断程序
使用定时器来计时,每隔1s让led等发生变化: #include #include Config.h int count =0; int a;void Port_Init() { LED8DIR = 0xff; //设置IO口方向为输出 } void TIMERA_Init(void) //连续计数模式,计数到0XFFF { TACTL |= TASSEL1 + TACLR + ID0 + ID1 + MC0 + TAIE; //SMCLK做时钟源,8分频,增加计数 模 式,开中断 smclk
[单片机]
S3C2440 DMA工作原理
这里具体DMA CONTROL寄存器(DCON)的配置说明,进而引出DMA的各种工作方式。 Atomic transfer:指的是DMA的单次原子操作,它可以是Unit模式(传输1个data size),也可以是burst模式(传输4个data size),具体对应DCON 。 Data Size:指的是单次原子操作的数据位宽,8、16、32,具体对应DCON 。 Request Source:DMA请求的来源有两种,软件&硬件模块,由DCON 控制;当为前者时,由软件对DMASKTRIG寄存器的位0置位触发一次DMA 操作。当为后者时,具体来源由DCON 控制,不同硬件模块的某时间触发一次DMA操作,具体要见不同的硬件模
[单片机]
<font color='red'>S3C2440</font> DMA工作原理
vxworks中断服务程序
中断服务程序用来处理来自硬件的中断,是设备驱动程序的重要组成部分。为及时响应外部中断,防止中断丢失.中断服务程序应该尽量的小,只把最必要的任务放在中断服务程序里面执行。一般在系统启动,硬件设备成功初始化之后将ISR与中断向量挂上:也可以在系统启动后的任何时刻挂中断向量。调试中经常采用后一种方式。在VxWorks中有两个不同的函数可提供挂中断:intConnect和pciIntConnect。两者的区别是intConnect使用的中断向量是独占的,pcilntConnect则可在各个不同的ISR之间共享中断向量。实际上pcilntConnect内部调用了 intConnect函数,在内部使用一个链表来管理多个不同的ISR。pciln
[工业控制]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved