请问一下大虾,arm7 cortex m3中断程序?

基于ARM7软中断程序的设计-嵌入式系统-与非网
笔者在设计一项目时采用LPC2458。此CPU为ARM7内核,带512K字节的片内FLASH,98k字节的片内RAM,支持片外LOCAL BUS总线,可从片外NOR FLASH启动CPU.由于代码量较大,程序放在片外的NOR FLASH中。且存在片外NOR FLASH在运行程序时,需对片外的NOR FLASH擦写的需求。图1为存储部分框图。
图1存储部分原理框图
在设计中,片外NOR FLASH的大小为16M字节。其中2M规划为存放运行程序,剩余的空间用于产品运行日志,告警灯存储空间。因此存在着在程序运行时对片外NOR FLASH擦写的需求。如果程序正在正常运行的片外FLASH中去擦写FLASH,会存在总线冲突的问题,无法实现此功能。我们采用ARM7内核的SWI软中断功能来实现。
2 ARM软中断原理(SWI)
软中断(SWI)目前没有找到任何官方的正式定义。笔者尝试与硬中断对比定义如下:
1.软中断发生的时间是由程序控制的,而硬中断发生的时间是随机的。
2.软中断是由程序调用发生的,而硬中断是由外设引发的。
3.硬中断处理程序要确保它能快速完成它的任务,这样程序执行时才不会等待较长的时间。
在C程序中调用软件中断需要用到编译器的扩展功能,使用关键字&_SWI&来声明中断函数。注意软中断号码同时在函数定义时指定。
_swi(0x24) void my_swi(void);
这样当调用函数my_swi的时候,就会用&SWI 0X24&来代替普通的函数调用&BL my_swi&。
可以发现软件中断同样存在着中断分支的问题,即需要根据中断号码来决定调用不同的处理程序。软中断号码只存在于SWI指令码当中,因此需要在中断处理程序中读取触发中断的指令代码,然后提取中断号信息,再进行进一步处理。下面是软中断指令的编码格式:
ARM状态下的SWI指令编码格式,32位长度,其中24位是中断编号。
Thumb状态下的SWI指令编码格式,16位长度,其中低8位是中断编号。
为了在中断处理程序里面得到SWI指令的地址,可以利用LR寄存器。每当响应一次SWI的时候,处理器都会自动保存并调整LR寄存器,使里面的内容指向SWI下一条指令的地址,所以把LR里面的地址内容上溯一条指令就是所需的间隔不一样,如果进入SWI执行前是在ARM状态下,需要通过LR-4来获得SWI指令地址,如果是在Thumb状态下进入,则只有LR-2就可以了。
下面是一段提取SWI中断号码的例程:
MRS R0,SPSR;检查进入SWI响应前的状态
TST R0,#T_bit;是ARM还是Thumb?#T_bit=0x20
LDRNEH R0,[LR, #-2];是Thumb,读回SWI指令码
BICNE R0, R0, #0xff00;提取低8位
LDREQ R0, [LR, #-4];是ARM,读回SWI指令码
BICEQ R0, #ff000000;提取低24位;
寄存器R0中的内容是正确的软中断编号了。
关注与非网微信 ( ee_focus )
限量版产业观察、行业动态、技术大餐每日推荐
享受快时代的精品慢阅读
旗下网站:
与非门科技(北京)有限公司 All Rights Reserved.
京ICP证:070212号
北京市公安局备案编号: 京ICP备:号您当前的位置:&>&&>&
ARM7启动代码的分析与设计
随着生活水平的提高和IT技术的进步,8位处理器的处理能力已经不能满足嵌入式系统的需要了;而16位处理器在性能和成本上都没有很大的突破。并且在8位机的开发中,大多使用汇编语言来编写用户程序。这使得程序的可维护性、易移植性等都受到了极大的挑战。正是基于此,ARM公司适时的推出了一系列的32位嵌入式微控制器。目前广泛使用的是ARM7和ARM9系列,ARM7TDMI内核的ARM7处理器广泛应用于工业控制、仪器仪表、汽车电子、通讯、消费电子等嵌入式设备。本文主要以philips公司ARM7TDMI核的LPC2119为例来分析如何编写ARM7的启动代码。
1、启动代码
在嵌入式系统软件的开发中,应用程序通常是在嵌入式操作系统的开发平台上采用C语言编写的。然而,在ARM系统上电复位后,需要设置中断向量表、初始化各模式堆栈、设置系统时钟频率等,而这些过程都是针对ARM内部寄存器结构的操作,用C语言编程是很难实现的。因此在转到应用程序的c/c++编写之前,需要用ARM的汇编语言编写启动代码,由启动代码完成系统初始化以及跳转到用户C程序。在ARM设计开发中,启动代码的编写是一个极重要的过程。然而启动代码随具体的目标系统和开发系统有所区别,但通常包含以下部分:
&向量表定义
&地址重映射及中断向量表的转移
&堆栈初始化
&设置系统时钟频率
&中断寄存器的初始化
&进入C应用程序
下面就结合PHILIPS的LPC2119的启动代码来分析与说明ARM7处理器的启动代码的编写。
1.1向量表定义
ARM芯片上电或复位后,系统进入管理模式、ARM状态、PC(R15)指向0x地址处。中断向量表为每一个中断设置1个字的存储空间,存放一条跳转指令,通过这条指令使PC指针指向相应的中断服务程序入口,继而执行相应的中断处理程序。LPC2219的中断向量表和其它基于ARM核的芯片中断向量表较类似,只要注意LPC2219要使向量表所有数据32位累加和为零(0xx0000001C的8个字的机器码累加), 才能使用户的程序脱机运行。
1.2 地址重映射及中断向量表的转移
ARM7处理器在复位后从地址0读取第一条指令并执行,因此系统上电后地址0必须是非易失的ROM/FLASH,这样才能保证处理器有正确可用的指令。为了加快对中断的处理以及实现在不同操作系统模式下对中断的处理,这就需要重新映射中断向量表、Bootblock和SRAM空间的一小部分。ARM具有非常灵活的存储器地址分配特性。ARM处理器的地址重映射机制有两种情况:
①由专门的寄存器完成重映射(Remap),只需对相应的Remap寄存器相应位设置即可。
②没有专门的Remap控制寄存器需要重新改写用于控制存储器起始地址的块(Bank)寄存器来实现Remap。在LPC2119上的重映射,可以通过存储器映射控制器来实现。实现REMAP操作的程序实现如下:
MOV R8,#0x; /设置新向量表起始地址/
LDR R9,=Interrupt_Vector_T /读原向量表源地址/
LDMIA R9!,(R0-R7); /复制中断向量表及中断处理程序的入口地址到RAM中(64字节)/
STMIA R8!,(R0-R7)
LDMIA R9!,(R0-R7)
STMIA R8!,(R0-R7)
LDR R8,=MEMMAP ; /REMMAP操作/
MOV R9,#0x02
STR R9, [R8]
1.3 堆栈初始化
启动代码中各模式堆栈空间的设置是为中断处理和程序跳转时服务的。当系统响应中断或程序跳转时,需要将当前处理器的状态和部分重要参数保存在一段存储空间中,所以对每个模式都要进行堆栈初始化工作,给每个模式的SP定义一个堆栈基地址和堆栈的容量。堆栈的初始化有两种方法:第一种方法是结合ADS开发套件中的分散加载文件来定义堆栈。第二种方法是最简单也是最常用的一种就是直接进入对应的处理器模式,为SP寄存器指定相应的值。下面给出了用第二种方法初始化管理模式和中断模式堆栈的程序:
MSR CPSR_c, #0xD3 ; /切换到管理模式,并初始化管理模式的堆栈/
LDR SP, Stack_Svc
MSR CPSR_c, #0xD2 ; /切换到IRQ模式,并初始化IRQ模式的堆栈/
LDR SP, Stack_Irq
1.4 系统部分时钟初始化
时钟是芯片各部分正常工作的基础,应该在进入main()函数前设置。部分ARM7片子内部集成有PLL(锁相环)电路,用户可以用低频率的晶振通过PLL电路获得一个较高频率的时钟。LPC2119内部的PLL电路接受的输入时钟频率范围为10~25MHz,输入频率通过一个电流控制振荡器(CCO)倍增到范围10~60MHz。同时为了使高速的ARM处理器与低速的外设正常通讯和降低功耗(降低外设运行速度使功耗降低),LPC2119又集成了一个额外的分频器。PLL的激活是由PLLCON寄存器控制。PLL倍频器和分频器的值由PLLCFG寄存器控制。对PLLCON或PLLCFG寄存器的更改必须遵循严格的顺序,否则所作更改是无法生效的(在连续的VPB周期内向PLLFEED寄存器写入0xAA、0x55,在此期间中断必须是被禁止的。)
1.5 中断初始化
ARM7的向量中断控制器(Vectored Interrupt Controller)可以将中断编程为3类:FIQ、向量IRQ、非向量IRQ。FIQ中断请求的优先级最高,其次是IRQ中断请求,非向量IRQ的优先级最低。VIC具有32个中断请求输入,但在LPC2219中只占用了17个中断输入。对于这17个中断源的IRQ/FIQ选择,由VICIntSelect寄存器控制,当对应位设置位1时,则此中断为FIQ中断,否则为IRQ中断。若再将IRQ中断设置到向量控制寄存器(VICVectCntIn)中,则此中断为向量IRQ中断,否则为非向量IRQ中断。FIQ中断是专门用来处理那些需要及时响应的特殊事件,尽可能地只给FIQ分配一个中断源。
1.6 进入C应用程序
至此,系统各部分的初始化基本完成,可以直接从启动代码转入到应用程序的main()函数入口。从启动代码转入到应用程序的实例代码如下:
IMPORT main
LDR R0,=main
一个优秀的启动代码将给应用程序的开发提供一个良好的开发平台。本文中较详细的讨论了启动代码的编写及难点。其中在堆栈初始化过程中要特别的注意两点:
①要尽量给堆栈分配快速和高带宽的存储器。
②尽量避免过早将处理器切换到用户模式,一般在系统初始化的最后阶段才切换到用户模式(用户模式没有权限通过修改CPSR来进行模式切换)。
嵌入式系统的迅猛发展,使启动代码的编写成为嵌入式系统开发人员应该具备的能力。本文有助于正在从事嵌入式ARM开发的读者理解启动代码的内涵与编写出适合自己的启动代码。
经过反复的比较和遴选,《今日电子》和21ic中国电子网举办的2013年度产品奖正式揭晓…
() () () () () () () () ()最近学习ARM7的中断。对于进入中断服务程序后的清除中断标志不是很明白,望解答!_百度知道
最近学习ARM7的中断。对于进入中断服务程序后的清除中断标志不是很明白,望解答!
清除EINT1中断标志
}这里不应该是判断外部中断信号是否由高电平变低吗;&#47!=0)
&#47while((EXTINT&0x02);等待外部中断信号恢复为高电平(若信号为低?为什么while条件中是判断EXTINT,则中断标志会一直置位)
{ EXTINT=0x02;&#47
提问者采纳
打起字来好累的。如果有中断产生,每个位对应一种中断EXTINT 里面包含多个中断标志位的状态。你可以百度一下这两种区别,一种是电平触发,估计你是不了解这两者区别了,看你的提问!。IO口产生的中断一般有两种,里面的状态位就会置1,一种是边沿触发!。按你的代码是检查低位数过来第2位是否有中断产生。你看看那个位的中断标志是什么意思就知道是什么引起中断了
谢谢你的回答。是这样,这里是使用外部中断1(也就是低位数第二位就是)。使用电平触发。向EXTINT相应位置1是清除中断标志。按你的说法,检测这一位如果有中断产生,那么相应位就置1了,那么还将EXTINT= 0x02再置1有什么特殊的用处?这里我疑问的是,电平触发时,在中断服务函数里,为什么这么清除中断标志。
你看看芯片资料上面是怎么清中断标志的,往EXTINT相应位写1看看是不是清中断标志位。按理说应该有其它专门的寄存器清标志的。如果你不清这个标志位,一但退出中断程序,又会马上跳进去。清了的话,就会等到下次被置位(触发)才进去。如果外部一直是低电平,就算你清了也没用,一但退出中断程序,中断标志又被置位,这样又会进去了。
while((EXTINT&0x02)!=0)& &{ EXTINT=0x02;& &}程序就是说EXTINT的相应位置1时,才执行EXTINT= 0x02即再重新置1,这是什么道理呢?可能我还是哪里没理解吧,先调试调试
那里不就清清楚楚写着 “可向该位写入1将该位清零” 么 !!!执行EXTINT= 0x02 就是清零EINT1 置1是由硬件完成,并不是你软件能改变的。EXTINT= 0x02 这句看上去像是把那个位置1,但这个写操作准确来说是清零。
对啊,是清零啊。但是我有问题的是清零的条件,while((EXTINT&0x02)!=0)
EXTINT&0x02)!=0 这个是一个读操作,如果你检查到那个位被置1了,你当然要去处理这个中断,你读的是一种状态。进去中断后,你要手动清除这种状态,就是那个清零的操作。否则你可以想像,在你退出中断之后,虽然你处理了一些事情,但是那个状态还没清除,那么硬件又会跳进去你的中断程序,继续处理。清除那个标示,就是告诉硬件,我已经做完了要做的,我清除标志了。
不好意思,我没看完就追问了。估计我懂你的意思了。就是说,外部电平变低,产生中断后,硬件置1EXTINT的相应位。程序里不断检测EXTINT相应位是否为1,如果为1,那么软件进行的写操作EXTINT= 0x02,将其中的位清零。这里的写操作实际上是将寄存器相应位清零是吧?这里就是我之前没理解的地方了
是的就是那样。当然,真正写程序还不仅仅要清零,还要加入你自己要做的事情
真的很感谢你耐心的解答,很赞。虽然我反反复复追问,但你的回答都很及时!耽误你的时间了,再次谢谢你!
提问者评价
真的很赞,解答的很耐心
其他类似问题
为您推荐:
中断服务程序的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁ARM7中断嵌套(SPI中断与外部中断0)能否实现?==
热门型号:
&&&当前位置:
ARM7中断嵌套(SPI中断与外部中断0)能否实现?
用户名:米其林r
注册时间:
ARM7中断嵌套(SPI中断与外部中断0)能否实现?
问题提出背景:在采用SPI接口的A/D模块(CS5532)时,如果SPI收发数据采用中断,则中断一次表示一个字节数据收发完成。在启动A/D后,当A/D模块一次数据转换好后,SOD数据线会被拉低(转换期间是高电平),但是通过SPI接口无法监测到线状态中断,所以想把SOD再引入到外部中断0,当外部中断0产生中断后,在外部中断0中读取A/D数据时SPI中断将无法响应,所以无**常读取4个字节的数据,因为ARM在进入IRQ中断时自动屏蔽IRQ中断。请问:怎么解决能实现嵌套?
用户名:年轻不在
注册时间:
此问题的换向解决方法是:1.SPI不采用中断方式,采用查询;2.将SPI的MISO引脚正常配置为IO,然后监测,当变低之后再配置为MISO读取数据,不知这么可否?3.外部中断0来了先禁止自己,然后置全局标志,退出中断,然后在主程序中判断标志为真就读取数据,然后再开放外部中断0。隐患,别的地方如果调用了读取函数,同样会出现以上的问题。
用户名:hgjinwei
注册时间:
ARM进中断时自动屏蔽IRQ中断,你不可以进中断后第一条指令就允许IRQ吗?
用户名:LPC300
注册时间:
一般来说,ARM7并不支持硬件中断嵌套,如果真要嵌套,就必须采用软件嵌套,这就要涉及的底层汇编程序的编写的。总的中断嵌套的过程如下:& &&&当发生IRQ中断。就会进入IRQ模式,而此时IRQ中断是被禁能的,PC就会跳转到中断向量表来查找该IRQ中断的入口地址来执行总的中断服务函数。而此时,我们可以对当前的任务环境、SPSR、链接寄存器进行压栈保存,然后系统切换为处理器模式,执行与中断相关的服务函数,此时IRQ中断自然被使能,同样在执行该相关程序也会被其他中断给打断,而当中断服务函数执行结束时,又进入IRQ模式,弹出进入时各个任务环境及SPSR的值,总的一个中断服务函数执行结束。
热门型号:}

我要回帖

更多关于 stm32和arm7 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信