嵌入式中的中断问题_第1页
嵌入式中的中断问题_第2页
嵌入式中的中断问题_第3页
嵌入式中的中断问题_第4页
嵌入式中的中断问题_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、原文地址:C语言中关于中断的问题(嵌入式)前提:中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展让标准C支持中断。具代表事实是,产生了一个新的关键字_interrupt。下面的代码就使用了_interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。 _interrupt double compute_area (double radius) double area = PI * radius * radius; printf(" Area = %f", area); return area; 这个函数有太多的错误了,以至让人不知

2、从何说起了:1). ISR 不能返回一个值。2). ISR 不能传递参数。3). 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。4). 与第三点一脉相承,printf()经常有重入和性能上的问题。 对于printf()经常有重入和性能上的问题的理解:由于存在任务的调度,它实时系统,可剥夺型内核中是危险的,如同一个安静的水雷。可能会被触发,也可能安然无恙。由于它运行结果的不可预期性,会使系统带来隐患。下面引用一段别人的解释:这主要在多任务

3、环境中使用,一个可重入的函数简单来说,就是:可以被中断的函数。就是说,你可以在这个函数执行的任何时候中断他的运行,在OS的调度下去执行另外一段代码而不会出现什么错误。而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等等,所以他如果被中断的话,可能出现问题,所以这类函数是不能运行在多任务环境下的。把一个不可重入函数变成可重入的唯一方法是用可重入规则来重写他。其实很简单,只要遵守了几条很容易理解的规则,那么写出来的函数就是可重入的。第一,不要使用全局变量。因为别的代码很可能覆盖这些变量值。第二,在和硬件发生交互的时候,切记执行类似disinterrupt()之类的操作,就是关闭硬

4、件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/退出核心”或者用OS_ENTER_KERNAL/OS_EXIT_KERNAL来描述。第三,不能调用任何不可重入的函数。第四,谨慎使用堆栈。最好先在使用前先OS_ENTER_KERNAL。还有一些规则,都是很好理解的,总之,时刻记住一句话:保证中断是安全的!通俗的来讲吧:由于中断是可能随时发生的,断点位置也是无法预期的。所以必须保证每个函数都具有不被中断发生,压栈,转向ISR,弹栈后继续执行影响的稳定性。也就是说具有不会被中断影响的能力。既然有这个要求,你提供和编写的每个函数就不能拿公共的资源或者是变量来使用,因为该函数使用的同时,ISR

5、(中断服务程序)也可那会去修改或者是获取这个资源,从而有可能使中断返回之后,这部分公用的资源已经面目全非。满足下列条件的函数多数是不可重入的:(1)函数体内使用了静态的数据结构;(2)函数体内调用了malloc()或者free()函数;(3)函数体内调用了标准I/O函数。 下面举例加以说明。可重入函数void strcpy(char* lpszDest, char* lpszSrc) while(*lpszDest = *lpszSrc ); *dest=0;非可重入函数1char cTemp; / 全局变量void SwapChar1(char* lpcX, char* lpcY) cTem

6、p = *lpcX; *lpcX = *lpcY; lpcY = cTemp; / 访问了全局变量,在分享内存的多个线程中可能造成问题非可重入函数2void SwapChar2(char* lpcX, char* lpcY) static char cTemp; / 静态局部变量 cTemp = *lpcX; *lpcX = *lpcY; lpcY = cTemp; / 使用了静态局部变量,在分享内存的多个线程中可能造成问题 如何写出可重入的函数?在函数体内不访问那些全局变量,不使用静态局部变量,坚持只使用局部变量,写出的函数就将是可重入的。如果必须访问全局变量,记住利用互斥信号量来保护全局变

7、量。近来在LPC的中断过程上看了点文献,作为一个初学者感觉这个内容与其它的处理器还是有很大的区别,比如说三星的S3C4510B,两者在中断的处理上理念是完全不同的,个人感觉LPC的要难一些,很多地方感觉上是在和ARM的规范打擦边球,下面具体说一下相关内容。基础知识:LPC2294的EXT中断分为了三类,包括FIQ,Vectored IRQ,non- Vectored IRQ,其中,以FIQ的优先级最高,而以non- Vectored IRQ的优先级最低,系统一共提供了27个中断源,并且给这27个中断源进行了固定的编号,但是注意,这个编号和优先级没有任何的关系,并非是编号在前面的优先级就越高,见

8、下面说明。关键内容:两套控制渠道,第一套:在ARM体系中,本来有SWI,FIQ,IRQ等这些中断的定义,并且已经定义了这些中断的开关控制位,就是在CPSR寄存器中,该寄存器包含了一个I位和一个F位,I位用于控制IRQ中断的开关,F用于控制FIQ的开关,但是值得注意的是CPSR的读取和修改在用户模式下是不能完成的,必须要通过SWI指令进入到特权模式下才可以进行修改。第二套:在LPC的SFR(特殊功能寄存器)中,也提供了一套寄存器用于控制相应的中断的进行,这组控制器叫做VIC寄存器(都以VIC开头),改组寄存器包括了所有的与中断有关的设置,开启,分类等功能,仅仅是将外部中断引脚对应的部分功能分离出

9、去,由EXT系列的寄存器来处理,因此,对这一个系列的寄存器的掌握是非常重要的!两者间的关系:仅仅在第二套控制渠道下打开FIQ,IRQ中断是不够的,如果ARM内核没有开中断的话,整个系统就不会有中断产生,因此,常见的做法是这样:先将第二套渠道的控制内容处理好,然后通过SWI软件中断指令,将ARM处理器的模式切换为特权模式,在特权模式下,对CPSR进行“读出修改写回”的操作,将中断打开,然后在返回到用户模式。LPC的中断的特殊性:FIQ的中断和普通的ARM规定是没有任何区别的,即是在产生中断时,指令跳转到0x0000001C处开始执行,这个是没有什么疑问的。但是IRQ的响应过程就不同了,先看下面一

10、段代码,这个是写在程序的头部的部分字节:ResetLDRPC, ResetAddr;/ 0x00000000,Reset->Supervisor ModeLDRPC, Und_Addr;/ 0x00000004,Undefined Instruction->Undefined ModeLDRPC, SWI_Addr;/ 0x00000008,Software Interrupt->Supervisor ModeLDRPC, PAbort_Addr;/ 0x0000000c,Abort(Prefetch)->Abort ModeLDRPC, DAbort_Addr;/ 0

11、x00000010,Abort(Data)->Abort ModeDCD0xB9205F80;/ 0x00000014,Reserved->LDRPC, PC,#-0xFF0 ;/ 0x00000018,IRQ->IRQ ModeLDRPC, FIQ_Addr;/ 0x0000001c,FIQ指令为“LDRPC, PC,#-0xFF0”非常特殊,其并没有跳转到IRQ中断程序的入口处,而是进行了一个PC的运算后赋值,这里就要说明其缘由。在LPC系列中,IRQ的响应过程,程序的入口地址并不是直接写在这条语句中,而是放在一个寄存器中,该寄存器是:VICVectAddr,其地址是0x

12、FFFFF030,现在就很明白了,在执行语句“LDRPC, PC,#-0xFF0”时,PC的值已经变为该语句的后面第二条语句的地址了,也就是0x00000020,而0x000000200xFF0时,发生借位,其结果恰好为0xFFFFF030,也就是说,通过这个简单的运算,使PC跳转到了寄存器VICVectAddr中包含的值为地址的位置上,这样就简单的完成了IRQ的跳转。当然,IRQ中断源不止一个,其中断服务程序也不止一个,这个寄存器的值是自动更新的,另有一组寄存器VICVectAddr015(后面有数字)将IRQ的16个中断源的地址分别放在对应的位置上(优先级等内容有另外的寄存器来控制,这里不

13、多说),当IRQ中断发生时,硬件自动将对应的VICVectAddr015中的某个对应的地址传给VICVectAddr寄存器,这个过程不用我们来编程实现。 原文链接:uCOS-II在ARM移植中的中断处理uCOS II是一个源码公开、可移植、可固化、可剪裁和抢占式的实时多任务操作系统,其大部分源码是用ANSI C编写,与处理器硬件相关的部分使用汇编语言编写。总量约200行的汇编语言部分被压缩到最低限度,以便于移植到任何一种其它的CPU上。uCOS II最多可支持56个任务,其内核为占先式,总是执行就绪态的优先级最高的任务,并支持Semaphore (信号量)、Mailbox (邮箱)、Messa

14、geQueue(消息队列)等多种常用的进程间通信机制。与大多商用RTOS不同的是,uCOS II公开所有的源代码.并可以免费获得,只对商业应用收取少量License费用。uCOS II移植跟OS_CUP_C.C、OS_CPU_A.S、OS_CPU.H 3个文件有关,中断处理的移植占据了很大一部分内容。作为移植的一个重点,本文以标准中断(IRQ)为例讨论了移植中的中断处理。1 uCOS II系统结构uCOS II的软硬件体系结构如图1。应用程序处于整个系统的顶层.每个任务都可以认为自己独占了CPU,因而可以设计成为一个无限循环。大部分代码是使用ANSI C语言书写的,因此uCOS II的可移植性

15、较好。尽管如此,仍然需要使用C和汇编语言写一些处理器相关的代码。uCOS II的移植需要满足以下要求:1)处理器的C编译器可以产生可重入代码:可以使用C调用进入和退出CriTIcal Code(临界区代码);2)处理器必须支持硬件中断,并且需要一个定时中断源;3)处理器需能容纳一定数据的硬件堆栈;4)处理器需有能在CPU寄存器与内存和堆栈交换数据的指令。移植uCOS II的主要工作就是处理器和编译器相关代码以及BSP(Board Support Package)的编写。uCOS II处理器无关的代码提供uCOS II的系统服务,应用程序可以使用这些API函数进行内存管理、任务间通信以及创建、删

16、除任务等。2 uCOS II移植过程中需要注意的几个问题uCOS II移植的中断处理跟ARM体系结构和uCOS II处理中断的过程有关,必须注意这2个方面的问题才能高效移植。2.1 ARM 处理器7种操作模式用户模式(USER MODE)是ARM 通常执行状态,用于执行大多数应用程序;快速中断模式(FIQ MODE)支持数据传输或通道处理;中断模式(IRQ MODE)用于通用中断处理;超级用户模式(SVC MODE)是一种操作系统受保护的模式:数据中止模式(ABT MODE)指令预取指中止、数据中止时进入该模式;未定义模式(UND MODE)当执行未定义的指令时进入该模式;系统模式(SYS M

17、ODE)是操作系统一种特许的用户模式。除了用户模式之外,其他模式都归为特权模式,特权模式用于中断服务、异常或者访问受保护的资源特权模式中除系统模式之外另5种模式又称为异常模式,在移植过程中必须设置中断向量表来处理异常。uCOS II的移植主要处理标准中断(IRQ)、快速中断(FIQ)和软件中断(SWI)。2.2 uCOS II中断响应的过程以IRQ中断为例,假设CRPS中I_bit位为0,当有IRQ中断时,CPU强制进入IRQ模式,当前的CPSR拷贝到SPSR_irq中,PC值保存在LR_irq中,置CPSR中的I位以关闭IRQ中断。数据保存之后,CPU强行从0X00000018开始执行,PC

18、值保存了OS_CPU_IRQ_ISR()的地址, 然后执行OS_CPU_IRQ_ISR()。在OS_CPU_IRQ_ISR()中OS_CPU_IRQ_ISR_Handler()被调用来检测中断源并执行中断。OS_CPU_IRQ_ISR_Handler()返回以后,OS_CPU_IRQ_ISR()又调用OSIntExit()来确认是否有比ISR优先级更高的任务要执行。如果当前中断任务仍然是优先级最高的任务,OSIntExit()返回,OS_CPU_IRQ_ISR()弹出中断堆栈,如果优先级更高的任务需要执行,OSIntExit()调用OSIntCtxSw()执行优先级更高的任务。2.3 uCOS

19、 II的临界段代码uCOS II使用关中断来保护临界代码。它定义了2个宏来开中断(OS_EXIT_CRITICAL(),关中断(OS_ENTER_CRITICAL()。OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()有3种方法来实现,uCOS II建议使用第3种方法可以保存当前处理器状态的值。3 uCOS II移植过程中的中断处理uCOS II中断处理跟CRT.S、OS_CPU_A.S和BSP.C有关,其移植过程主要有以下几个步骤。3.1 在CRT.S中设置中断向量表ARM的中断向量表位于ROM 的最底部,其地址范围为0X000000000X0000001C,设置如

20、下:VECTORS:LDR PC,RESET_ADDRLDR PC,UNDEF_ADDRLDR PC,SWI_ADDRLDR PC,PABT_ADDRLDR PC,DABT_ADDRNOP /*保留向量*/LDR PC,IRQ_ADDRLDR PC,FIQ_ADDRRESET_ADDR:. WORD RESET_HANDLERUNDEF_ADDR:.WORD UNDEFHANDLERSWI_ADDR:.WORD SWI HANDLERPABT_ADDR:.WORD PABT_HANDLERDABT_ADDR:.WORD DABT_ HANDLER.WORD 0 /*保留地址*/IRQ_ADDR

21、:.WORD IRQ_HANDLERFIQ_ADDR:.WORD FIQ HANDLERUNDEF_HANDLER:B UNDEF_HANDLERSWI_HANDLER: B SWI_HANDLERPABT_HANDLER: B PABT_HANDLERDABT_HANDLER: B DABT_HANDLERIRQ_HANDLER: B OS_CPU_IRQ_ISR/*跳转到OS_CPU_IRQ_ISR(在OS_CPU_A.S中)*/FIQ_HANDLER: B OS_CPU_FIQ_ISR/*跳转到OS_CPU_FIQ_ISR(在OS_CPU_A.S中) */这里设置了标准中断异常(IRQ)

22、和快速中断异常(FIQ)的中断入口,其余异常都设置为死循环,当发生这些异常的时候,必须使系统复位才能退出死循环。3.2 移植中断任务切换中断任务切换(OSIntCtxSw)和任务切换函数(OSCtxSw)比较相似,主要有以下几步组成:1)调用OSTask SwHook()2)OSPrioCur=OSPrioHighRdy3)OSTCBCur=OSTCBHighRdy4)SP=OSTCBHighRdy->OSTCBStkPtr/获取高优先级的任务堆栈指针5)从高优先级的任务的堆栈中弹出高优先级的任务上下文6)执行高优先级的任务3.3 移植中断服务程序以IRQ中断为例中断服务程序(OS_CP

23、U_IRQ_ISR)主要依据上面所描述的“uCOS II中断响应的过程”编写,其主要代码如下:LDR R0,OS_IntNestingLDRB R1,R0ADD R1,R1,#1STRB R1,R0CMP R1,#lBNE OS_CPU_IRQ_ISR_1LDR R4,OS_TCBCurLDR R5,R4STR SP,R5OS_CPU_IRQ_ISR_1:MSR CPSR_c,#(NO_INT | IRQ32_MODE)/切换到SVC模式LDR R0,OS_CPU_IRQ_ISR_HandlerMOV LR,PCBX R0MSR CPSR_c,#(NO_INT | SVC32_MODE)/切换

24、到SVC模式LDRR0,OS_IntExit /OSIntExit()MOV LR,PCBX R0在代码中省略了现场工作寄存器的保护与恢复及工作模式的切换。3.4 移植中断处理程序以IRQ中断为例,移植中断处理程序:C程序void OS_CPU_IRQ_ISR_Handler(void) PFNCT pfnct; /定义中断函数指针 pfnct=(PFNCT)VICVectAddr; /获取函数地址 while(pfnct!=(PFNCT)0) (*pfnct)(); /调用中断函数 pfnct=(PFNCT)VICVectAddr; /获取新的中断函数 /所有中断都执行完毕退出中断处理程序依

25、赖中断控制器的中断响应顺序,所以uCOS II把OS_CPU_IRQ_ISR_Handler()归属于用户程序的一部分。在中断返回之前,中断处理程序要处理完所有的中断响应,以避免在多个中断同时响应或中断处理过程中响应中断的情况下, 进入OS_CPU_IRQ_ISR () 和退出OS_CPU_IRQ_ISR()时,OS_CPU_IRQ_ISR()耗尽保存CPU寄存器的堆栈空间。另外,在OS_CPU_IRQ_ISR_Handler()中不要清CPSR的I位来开放中断,因为没有必要使用中断嵌套,OS_CPU_IRQ_ISR_Handler()在返回之前会检查并处理所有的中断。3.5 编写中断函数中断

26、函数一般采用C语言编写,uCOS II建议中断函数应尽量短,一般做法是在中断函数中缓存数据,给任务发送一个信号来处理数据。中断函数的地址在系统初始化的时候要置人中断向量寄存器(VICVectAddr015)。由于向量中断控制器(VIC)的特殊结构,在中断函数中要写一次中断向量寄存器(VICVectAddr)。4 中断处理的应用示例uCOS II要提供周期性信号源,用于实现时间延时和确认超时。节拍率应为10100 Hz。时钟节拍源可以由专门的硬件定时器产生,以下就以IRQ中断方式产生节拍源为示例。初始化中断控制器:C程序void VICInit(void) VICIntEnClr=0xfffff

27、; VICDefVectAddr=-(INT32U)Non_Vect_IRQ_Handler; VICVectAddr0= (INT32U)OSTickISR; VICVectCntl0= (0x20 | 0x04); VICIntEnable= 1<<4; 定时器0中断函数:C程序void OSTickISR(void) TO_IR = 0xff; OSTimeTick(); /调用OSTimeTick() VICVectAddr=0; /通知中断控制器中断结束当定时中断发生时调用OS_CPU_IRQ_ISR Handler(),得到OSTickISR()的地址并执行,在OSTi

28、ckISR()中调用OSTimeTick()为uCOS II提供周期性信号源。此代码在GNU工具链ARM-GCC下编译通过,并在EasyARM2100开发实验板上得到验证。5 结束语通过示例讲述了在uCOS II移植过程中的中断处理所需要注意的几个问题和通用方法,经笔者在GNU工具链下编译、调试,并在实验板上得到很好的验证。这种移植方案的中断函数都使用C语言编写,具有较好的移植性,有利于对不同需求的用户进行中断扩充,增强了中断嵌套时uCOS II运行的稳定性,使移植具有更好的通用性。ARM中断处理的研究 在嵌入式系统中常用的RISC处理器是ARM核,它具有体积小、功耗低、成本低、性价比高的特点

29、。然而,不管是哪种型号的arm处理器,也无论该嵌入式系统中是否有操作系统,中断处理,特别是IRQ中断,始终是必须的,而中断处理的核心问题是上下文的保存。能否安全而又高效地保存上下文,将影响一个嵌入式系统的性能与稳定。笔者对arm处理器的普通中断处理、任务切换中断处理、可重人中断处理和基于优先级的可重人性中断处理的上下文保存技术进行分析与总结。为保证理论的正确性,核心的程序代码都经过了实验的检测。1 系统中断处理简介arm处理器的中断主要有两种:IRQ普通中断和FIQ快速中断。快速中断本质上与普通中断没有太大的差别,它们在处理机制上有许多相同的地方。IRQ中断是最频繁的也是最为影响系统性能的,所

30、以对它的研究与处理也就最有价值。下面简要地介绍一下IRQ异常发生时ARM处理器的工作过程。在IRQ中断发生时,arm处理器的硬件会自动执行以下工作:将被中断任务模式的CPSR值保存到IRQ模式中的SPSR寄存器中;将被中断任务模式的PC值保存到IRQ模式中的LR寄存器中;将模式自动切换到IRQ模式,并将CPSR中的bit7位置1禁止后继IRQ中断的发生;PC被赋予0xl8的地址值,程序将从0xl8片开始执行。结合图1,可以更好地理解arm中断处理机制的工作过程。 2 普通中断处理有些arm嵌入式系统可能对中断的要求比较低,即发生中断后首先查询相应的中断源,然后进行中断服务,最后从中断服务程序中

31、返回到被中断处继续运行程序。如何在这种简单应用中保证安全又高效地处理中断呢?“安全”就意味着中断发生时上下文被完好保存不被破坏,“高效”就是说保存尽可能少的寄存器(当然是建立在安全的基础上的)。由图1可知,在普通中断处理中,中断服务就可以在IRQ模式中运行。根据ATPCS的调用规则,在子程序调用中arm编译器保存了R4R11寄存器,因此就没有必要再次保存。那么剩下的寄存器就必须予以保存,防止从中断服务程序返回后被破坏。可以用汇编语言和C语言书写处理代码。首先假设初始化代码中已正确建立了IRQ堆栈。 <所有已使能中断的查询与服务>将同时发生的中断全部服务,以提高效率LDMFD SP!,R0-R3,R12,R14 ;恢复上下文在上述保存上下文中没有必要保存SPSR。因在非嵌套的中断处理程序中,它不会被任何顺序的中断所破坏。如果用C语言来书写该处理程序,可以使用关键字一IRQ来说明,以告诉编译器实现如下的操作:保存.ATPCS规定的被破坏的寄存器;保存其他中断处理程序中用到的寄存器;同时将(LR-4)赋予程序计数器PC,实现中断程序的返回并且恢复CPSR寄存器的内容。普通中断处理的C语言程序可以按如下格式编写: 可见,无论是用C语言还是汇编语言来编写,它们的工作原理都是一样的。图2给出了普通中断

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论