vxWorks中断处理
基于VxWorks的多中断处理设计

2 传统多中断处理存在的问题
由于用函数 intConnect()调用的用户中断处理函数在中
断级以 supervisor 方式调用,因此为了保证 VxWorks 的实时
性,应该尽可能在最短的时间内完成操作,以免影响实时系
统对高频突发事件的响应。另外,VxWorks 的 ISR 必须遵循
一个基本约定:不能调用可能引起阻塞的函数和 I/O 操作函
系统的强实时性和可靠性。针对这个问题,下面介绍一种应
用实时操作系统 VxWorks 进行多中断处理的方法。
3.1 多中断处理的程序设计框架 为了能尽快响应中断,VxWorks 中的中断服务程序不在
固定的任务上下文中执行,而且没有任务控制块,所有中断
程序必须共享一个单独的堆栈,这导致许多 VxWorks 函数在
断驱动代码中不保存和恢复浮点寄存器。另外,在多中断系
统中,如果一些中断处理函数长时间占用中断号,容易出现
系统中断号资源不够用的情况,可能导致中断请求超时而引
起系统出现不可预测的后果,不能保证 VxWorks 的可靠性。
3 基于 VxWorks 的多采集板系统中断处理设计
在多采集板的大型系统中,通常采用工业机箱为多块板
路如图 3 所示。CK5 使用 CPLD 寄存器获取外部(cPCI 和 PMC)
—250—
中断和板内中断。当其中一个中断被声明后,CPLD 就向 MV64460 的多目的管脚(MPP)声明一个中断。MV64460 获得 中断请求后就在中断控制器中设置引起中断的寄存器的管 脚。这样,中断控制器就向处理器 MCP7447A 声明了中断 CPU_INT0[4]。
数。如 ISR 不能调用 semTake()来获取一个信号量,因为在此
vxworks操作系统中中断的应用

VxW orks操作系统中中断的应用Ξ籍林峰,曹 伟ΞΞ(南京船舶雷达研究所,江苏南京,210003)摘 要:主要介绍了VxW orks操作系统中中断的重要性以及具体应用,其中涉及了信号量的概念并对其进行了简单描述。
关键词:嵌入式实时操作系统;中断服务程序;信号量中图分类号:TP3 文献标识码:A 文章编号:100920401(2004)0320067203Application of interruption in the operating system of VxW orksJI Lin2feng,C AO Wei(Nanjing Marine Radar Institute,Nanjing210003,China)Abstract:The im portance and concrete application of interruption in the operating system of VxW orks is in2 troduced in this paper,in which the concept of the semaphore is inv olved and is sim ply described.K ey w ords:embedded real2time operating system;interruption of service program;semaphore1 引 言对系统的响应时间有严格要求的系统,我们通常称之为实时系统。
近半个世纪以来,随着计算机技术的发展,实时系统在各高精尖技术领域得到迅猛发展,具有实时操作系统的计算机系统在实时系统中也得到了广泛的应用。
实时操作系统是嵌入式应用软件的基础和开发平台,它不同于分时操作系统,它的主要任务是对事件进行实时的处理。
虽然时间可能在无法预知的时刻到达,但是软件必须在事件发生时在严格的时限内作出响应。
VxW orks就是一个由Wind River Sys2 tem公司推出的嵌入式实时操作系统,具有多任务、可裁减、可靠性好、实时性高等特点,其在航天领域的出色表现而使之备受广大电子行业的青睐。
Vxworks基础

为各种目标板的硬件功能提供了统一的软件接口 它们包括: 硬件初始化 中断处理和产生 硬件时钟和定时器管理 内存映射和分配 BSP还包括boot Rom和其它启动机制 sysLib和sysALib库是VxWorks可移植的核心
Vxworks操作系统将一切与硬件有关的功能模块都放在BSP库中。该BSP库是硬件与软件的接口,处理硬件的初始化、中断处理与产生、硬件时钟与定时管理、局部和总线内存空间的映射、内存大小定义,等等。能够自行启动目标机、初始化目标机、能够与host通信以下载Vxworks核、把控制权交给Vxworks核来调用用户应用程序等功能。
Tornado 系统结构
POSIX Library
Real-Time Embedded Application
Host
VxSim
Debug Agent
Tornado Plug-ins
Target
Target Server
Launcher
Core OS
BSP
Ethernet
Serial Line
板支持包(BSP)
VxWorks的特点--高度伸缩性的环境
Stand-alone kernel up to full featured OS
0
100
200
300
400
500
Maximum Equipped
File System
Networking
O.S.
m
Memory Requirements (Kbytes)
VxWorks (1)
Vxworks提供了一套丰富的任务间通信机制,包括: ●内存共享(Shared memory):简单的数据共享方法 ●信号量(Semaphore):用于基本的互斥及同步 ●消息队列(Message queues)和管道(pipe): 用于同一CPU上任务间消息的传递 ●套接口(Socket)和远程程序调用(RPC): 用于网络上任务间的通信 ●信号(Signal):用于异常处理 此外,Vxworks提供了三种共享内存的对象(shared-memory objects) 来实现运行在不同CPU上的任务间的高速同步和通信。 ●共享信号量(shared semaphores):有二进制,记数型两种 ●共享消息队列(shared message queues) ●共享内存分区(shared-memory partitions):有系统类型和用户类型
VxWorks下基于ML507嵌入式系统的中断处理

虚拟仪表的 G U板卡, P 采用 V wok 作为顶层控制 , x r s
其中采用中断机制与外界通信是一个重要手段 , 由于 硬件环境为 Vr x X ie5F T型号的 F G C U为 IM公 t P A,P B
司 Pw r 4 05处理器 , oe c4 x p 理解其特有 的架构 , 并编写 相应的中断处理程序 , 对于操作系统 的完整移植 以及 上层 程序 的正 常运行 至关 重要 。
b d e p r t g s se Vx 0 k k s i p si l o ce t r o l ae m e d d p af r T e i tru t e d d o e ai y t m W r s ma e t o sb e t r ae a moe c mpi t d e n c b d e ltom. h n er p h di gm e h im r vd d b W o k so ih p ro ma c n rd cn ae c wh c sa c r e t h e n a ln c a s p o i e yVx r si fhs ef r n ei e u i gltn y, n ih i c o d dwih te r— a tme e ur me t I t i p p r t e itru t h n l g me h im b s d o P wepc 4 p o e s r i l i r q i e n . n hs a e , h n er p a di n ca s n ae n o r 40 rc so s a ay e . e n lz d Th n, t e po e so tru th n ln rg a h r c s fi er p a d ig p o rmmig i e c b d i eal n n sd s r e n d ti i . K e wo d Vx 0 k ; Po r c 4 y rs W rs wep 4 0; itru th n ln ner p a di g; i tru ts rie ru ie ner p evc o tn
VxWorks中的中断应用设计要点

VxWorks中的中断应⽤设计要点硬件中断处理是实时系统设计中的关键性问题,设计⼈员有必要对其作深⼊研究,以更好地满⾜开发⼯作需要。
⽂中以VxWorks操作系统为软件平台,讨论了在实时系统中进⾏中断应⽤设计时要注意的⼀些问题。
由于软硬件的相关性,选⽤⼴泛应⽤的X86架构的嵌⼊式汁算机为硬件平台,对PenriumCPU和计算机主板对硬件中断的管理机制也做了详细介绍所得出的研究结论在具体的开发项⽬中均得以验证,可供相关技术⼈员参考。
硬件中断处理是实时系统设计中最重要、最关键的问题。
⽂中综合软硬件,从⼯程应⽤的⾓度对此问题加以讨论。
⽂中所述内容针对的软件平台是VxWorks实时操作系统,硬件平台选⽤⼴泛使⽤的X86架构的嵌⼊式计算机,全⽂按照CPU、主板、操作系统⾃下⽽上的顺序展开。
1 Pentium CPU的中断类型有两类事件可引起Pentium挂起当前的指令流,即中断和异常。
中断是由外部事件引发的,在程序执⾏的任何时刻都可能出现;异常也称异常中断,是由内部事件引发的。
中断和异常各有两类触发源:(1)中断。
可屏蔽中断:CPU的INTR引脚收到有效信号,如果Pentium标志寄存器IF位为1,则允许中断,否则信号在CPU内被屏蔽。
⾮屏蔽中断:CPU的NMI引脚收到有效信号⽽引发的中断,这类中断不能被阻⽌。
(2)异常。
执⾏异常:CPU试图执⾏⼀条指令的过程中出现错误、故障等不正常条件⽽引发的异常中断。
执⾏软件中断指令:Pentium指令系统中包括⼀些如INTO,INT n这类软件中断指令,执⾏时产⽣异常中断。
详细分类的话,Pentium可以识别256种中断和异常。
每种中断给予⼀个编号,即0~255,称为中断向量号(interrupt vector number)。
其中NMI、异常以及系统保留占⽤中断向量号0~31,⽽32~255为⽤户中断向量号,可供INTR和⾃定义软件中断(如汇编中的INT指令)使⽤。
VxWorks任务调度与中断学步园

VxWorks任务调度与中断学步园最近在看有关任务调度和中断的文章,主要的话题或者讨论点可以归为如下几个递进的问题:(1)引发任务调度的情况、原因(2)何为抢占调度?抢占调度是否就指中断引发的调度?(3)关中断是否禁止任务调度?针对上述问题,本文简单说一下个人的理解,有不妥之处还请大家多指点。
下面就以VxWorks操作系统为例,讨论任务调度和中断的关系。
问题(1)引发任务调度的情况、原因首先,看一下VxWorks任务调度时机的两种情况:1) 同步任务切换引起的原因是当前运行的任务可能执行了如下下列操作:①进行阻塞、延迟、挂起的调用如,调用 taskDelay、taskSuspend、semTake等。
②使更高优先级任务就绪而发生优先级抢占如,通过semGive释放信号量,导致更高优先级的任务就绪。
③降低自身优先级或者退出如,任务可通过taskPrioritySet改变自身优先级;通过exit终止自身执行等。
2) 异步任务切换通常由中断服务使高优先级任务就绪引起(如)由上面的描述可知,中断是导致任务可能发生调度的一种情况,而且一般被归为异步任务切换。
而除了同步任务切换和异步任务切换之外,可能还有提及到抢占调度和非抢占调度,进而又联系到中断。
问题(2)何为抢占调度?抢占调度是否就指中断引发的调度?个人认为,VxWorks的抢占调度就是指,由于有高优先级的任务处于就绪状态,而导致系统需要进行任务切换。
另外,我们知道VxWorks系统(wind内核)采用的调度策略为:默认采用基于优先级的抢占式调度;同时,还使用轮转调度。
从这点也能说明,所谓抢占式调度主要是基于任务优先级而言的,而不是针对中断(或者异步任务切换)。
如果非要额外再给抢占式调度下个定义或者归类的话(虽然个人觉得没必要,理解即可),应该包括:1)异步任务切换(中断引发)2)同步任务切换中的第②类,即由于当前运行任务的某种操作,使更高优先级任务就绪而发生优先级抢占除了上述两种情况之外的其他任务切换,都可以认为是当前运行的任务主动放弃CPU使用权,而非被抢占。
vxworksprintf与logMsg及中断相关内容(转载加总结)
vxworksprintf与logMsg及中断相关内容(转载加总结)1. printf需要调用输入/输出设备资源,若在intr中使用printf,可能会由于标准输入/输出设备在被使用中(一般会semtake一下),这导致intr被阻塞,这在vxworks在是不被允许的,可能就导致系统响应速度极其慢或者忽快忽慢(因为通常情况下intr的第一步操作是自私的关闭所有中断,此时资源等到in/out设备可以使用才会继续往下执行)。
logMsg里面的实现是将消息发送给sysLog这个任务,查看一下vxworks发现,这个任务的优先级为0(不知道是不是我们的比较特别)。
这带来一个规则:若在intr中,sysLog不会进行抢占操作将logMsg中的信息输出出来(毕竟interrupt的优先级是最高的),但是intr一执行完,它立刻抢占,将信息输出。
若在普通的任务(优先级 > 0)中调用logMsg,它会毫不留情的抢占,将信息输出。
2. 相关解释printf( ) - write a formatted string to the standard output stream (ANSI).logMsg( ) does not actually perform the output directly to the logging streams, but instead queues the message to the logging task, logMsg( ) can be called from interrupt service routines.printf()是将信息输出到标准输出设备(STDIN/STDOUT)中,如果此时设备正在工作,那么就会发生阻塞.logMsg()是使用消息队列的方式,它将信息地址发送到队列,由专门的任务将信息打印出来.关于LogMsg的工作机理。
LogMsg利用消息队列将用户所发的消息传送给LogTask,然后由LogTask将其显示在屏幕或者其他输出设备上。
第4.3节 VxWorks信号中断和定时
18
VxWorks中断处理流程
保存CPU寄存器 从中断控制器读中断向量号 顺序调用该中断服务程序 通知中断控制器中断服务程序结束 恢复CPU寄存器 返回
第4章
.
19
中断和优先级
第4章
.
20
ISR的使用限制
第4章
.
ISR执行完成之前,其它任务不能执行 ISR中不能调用某些VxWorks函数,尤其是,ISR不
信号量
ISR释放信号量,任务等待接收信号量
消息队列
ISR发送消息,任务等待接收消息,如果消息队列满,该消息被丢弃
管道
ISR向管道写消息,任务读消息
信号
ISR可以向任务发送signal。
23
调试中断
第4章
.
中断处理程序可以调用logMsg()向系统输出诊断信 息
logMsg(“foo = %d\n”,foo,2,3,4,5,6) 向tLogTask发送请求为我们实现printf()的功能
轮询硬件 检查系统错误
VxWorks提供对两种定时器的相同的接口
系统时钟 辅助时钟
26
系统时钟
第4章
.
系统时钟完成下列工作
增加ticks计数(使用tickGet()获得计数值)
更新延时和超时计数器
检查循环调度
默认的时钟频率是60Hz
sysClkRateSet()
设置时钟频率
参考sigLib (组件:INCLUDE_SIGNALS)
6
信号编号
第4章
.
31个信号编号,从1-31
#define #define #define #define
Vxworks基于S3C44B0X处理器的中断处理设计
⑥
20 Si eh E gg 0 7 c.T c . nn .
V w rs x ok 基于 S 4 O 3 4 B X处理 器的 C 中断处理设计
徐 伟 鞠晓东
( 中国石油大学资源与信息学 院, 北京 124 ) 0 29
摘
要
嵌入式微处理器和嵌入式实时操作 系统是嵌入式 系统 的两大核心技 术。详细分析 了 wn i r 司的嵌入 式实时 i Rv 公 d e
表 1 S C 4 O 异 常 向 量 表 3 4B X
中断向量入 口地址
异常中断类 型
st、 e)未定义指令 ( nendIsutn 、 U df e t co ) 软件 中断 i nr i
(WI 、 取 中止 ( ree br) 数 据 中止 ( a S )预 Pe t aot 、 f h Dt a
IU 将 中 断 号 ( u e) 换 成 中 断 向量 地 N M nmbr 转
址 , IU — O IE 宏 N M T —V C则将中断向量地址转换为中
断号 。宏 定 义在 iAc. v r h中实 现 。 h
根据指定 的配置参数完成 。为能够处理最 坏情况 下的中断嵌套 , 必须分配足够大的中断堆栈空间。
2 V w rs x ok 中断处理机制
硬 件 中断 处 理 是 实 时 操 作 系 统 中最 重 要 的部
研究方 向: 智能检测技 术。
维普资讯
1 8期
徐
伟 , : x ok 基 于 ¥ C 4 O 等 V w rs 3A B X处理器的 中断处理设计
V w rs中断处 理 完成 以下 工 作 : 存 C U 中 x ok 保 P 断 的上下文 、 调用 中断服 务程 序 (S 、 IR) 中断服 务 程 序 返 回后 , 恢复 中断 的上下 文 。
23 VxWorks中断驱动实验
函数名称:intConnect ( )
函数说明:设置指定中断的服务函数。
STATUS intConnect
(
VOIDFUNCPTR * vector, /* 中断向量 */
VOIDFUNCPTR routine, /* 中断服务函数 */
iБайду номын сангаасt
parameter /* 参数 */
)
函数名称:sysGpioIntConnect ( )
#include "cacheLib.h"
#include "lstLib.h"
/* Needed to maintain protocol list. */
#include "iv.h"
#include "stdlib.h" #include "sysLib.h" #include "intLib.h" #include "taskLib.h"
(
FUNCPTR * vector,
/* 中断向量的偏移*/
FUNCPTR function
/* 向量中的地址 */
)
函数名称:intVecGet ( )
函数说明:获取中断向量。
FUNCPTR intVecGet
(
FUNCPTR * vector
/* 中断向量的偏移 */
)
所有的中断服务函数都会使用同一个堆栈,这个堆栈是在系统启动时建立的,所以中断
五 实验报告书编写要点
1. 编写 interrupt 工程,并编写相应的程序实现对外部中断 2 的响应; 2. 下载 VxWorks 内核; 3. 启动目标服务器; 4. 下载并运行 interrupt 工程; 5. 观察结果。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Vxworks作为一个实时嵌入式操作系统,通常采用中断的方式来满足系统实时性的要求,因此,熟悉其中断的处理过程对于VxWorks操作系统的开发是至关重要的.本文通过编写和调试基于AT91RM9200处理器的VxWorks嵌入式操作系统的BSP,来讨论VxWorks操作系统的中断机制。
1 VxWorks中断处理机制及AICAT91RM9200使用一个8优先级,可单独屏蔽中断的中断向量控制器AIC。
在ARM体系结构中,有7种异常中断,对应有一个异常中断向量表。
ARM体系结构要求这个异常中断向量表从0地址处开始,对于外部中断请求IRQ,系统又增加了一块由中断控制器控制的中断向量表。
2 AT91RM9200 BSP的中断驱动的实现2.1 中断驱动中定义的函数STATUS at91rm9200LvlVecChk (int*,int*);STATUS at91rm9200LvlVecAck(int,int);STATUS at91rm9200LvlEnable(int);STATUS at91rm9200LvlDisable(int);2.2 高级中断控制器AIC的初始化在usrInit()中excVecInit()函数对异常中断向量进行初始化.整个中断库,以及中断控制器的初始化都是在syslib.c中的sysHwInit2()函数中完成的.该函数在sysClkConnect()中被调用,因为系统时钟中断要在内核开放中断后就要使能,因此内核在初始化为一个多任务环境后,就产生一个usrRoot()的任务,在该任务中要建立系统时钟中断,因此调用了sysClkConnect()函数,中断库以及中断控制器的初始化也就完成了。
高级中断控制器必须进行初始化,其初始化是在板级支持包BSP的中断驱动程序中。
具体的实现函数是void at91rm9200IntDevInit(void)。
该函数在文件syslib.c的sysHwInit2()函数中调用。
at91rm9200IntDevInit(void)函数中主要是配置系统的钩子函数,然后对中断源向量寄存器和中断模式寄存器进行配置,同时要清除并禁止AIC中所有的中断。
2.3 中断驱动中的回调函数在intEnt中,程序很快就进入了特权模式(SVC32),如果是中断可嵌套模式,要设置该模式下的堆栈,并且将中断深度intCnt值加1.然后跳转到intIntRtnPreempt中,在intIntRtnPreempt中为后来调用中断驱动中的函数开辟了32个字节的堆栈空间,并且将程序指针拉到at91rm9200LvlVecChk函数处执行,at91rm9200LvlVecChk函数是在中断驱动中定义的函数,是用来检测当前挂起的中断中,优先级最高的中断源。
检测出最高优先级的中断后,首先要禁止该中断,因此要调用at91rm9200LvlDisable函数,该函数也在中断驱动中定义。
在禁止中断的过程中,需要通过intLock和intUnLock函数来保护临界代码不被新的中断打断。
at91rm9200LvlVecChk()函数是通过读AIC_IVR寄存器来获取当前最高优先级的中断,将获得的中断号和中断向量赋给2个变量,并且禁止该中断。
at91rm9200LvlVecAek()函数是在中断处理结束后,通过写AIC_EIOC寄存器来清除刚刚处理的中断,并将其使能。
at91rm9200LvlEnable(int leve1)和at91rm9200LvlDisable(int level)来允许和禁止中断,从而保护临界代码不被新的中断所打断。
2.4 中断驱动程序实现的流程图中断驱动程序实现的流程图如图1所示。
图1 中断驱动程序实现的流程图3 VxWorks中断模块实现机制3.1 异常中断向量表的生成及实现在usrInit()函数中通过intVecBaseSet((FUNCPTR*)VEC_BASE_ADRS)函数对异常中断向量表的基址进行设置,VEC_BASE_ADRS在configall.h中定义为程序运行空间的起始地址,但是在ARM中并没有中断基址寄存器,由于ARM9有重影射机制,可以将程序运行空间的起始地址影射成0地址,这也符合ARM体系结构通常都是把异常中断向量表放在0地址处的惯例,异常中断向量表可以从反汇编bootrom_uncmp后的0地址处看到。
当有内置的外设中断或外部中断产生时,系统首先跳转到异常中断向量表的0x18处,此处是IRQ中断向量的位置,该内存中放置的是一条跳转指令,因为excVecInit()对中断向量表初始化后,生成了一个exeEnterTbl,在这个表中列出了异常向量和对应入口函数的结构表,exeEnterTbl 结构如图2所示。
图2 excEnterTbl的结构由于ARM9用了重影射机制,因此重影射之后,系统将LOCAL_MEM_LOCAL_ADRS 影射成0地址,中断向量表从0地址处开始。
从excVecInit()的反汇编代码可以看出,系统把指令ldr pc,[pc,#244]的反汇编代码放在了从0x00000004开始的每个异常中断向量地址处,也就是将excEnterTbl中每个异常处理函数的入口地址都放在了(0xF4+0x8+0x4+所对应异常相对于未定义指令异常(0x00000004)的偏移)的内存中,这样就将异常向量和异常处理入口函数关联起来了。
3.2 中断向量表的结构及生成那么当系统产生中断后,VxWorks是如何设置中断向量表,并且将中断向量和中断处理入口程序关联起来的呢?和异常向量表有点类似,但是中断向量表是VxWorks操作系统动态分配的一段连续的内存空间,这个空间的结构如图3所示。
图3 VxWorks中断向量表的结构因为是动态分配,所以在这段内存空间中,操作系统只给当前中断分配了中断号、中断处理函数的入口和被传递的参数。
每个中断源按照中断号顺序排列,在为每个中断源分配的内存空间中头4个字节是中断向量表的初始化函数的入口,该函数对于每个中断源来说是通用的,然后顺序放置的是中断号、中断处理函数入口和被传递的参数.通过intconnect()函数可以将中断向量和中断处理函数关联起来,因此在系统获知了发生中断的中断号时,就可以找到相应的中断处理函数去处理该中断。
当发生IRQ异常时,系统强制把程序指针拉到0x18处,在0x18处是这样一条指令ldrpc,[pc,#244],IRQ异常相对于未定义指令异常的偏移是0x14,所以相当于把0x114地址处的内容赋给pc,而0x114处的内容正是IRQ异常向量处理的入口函数intEnt的地址,因此程序跳转到intent处去执行。
4 中断处理跟踪调试的部分反汇编代码通过使用ARM Developer Site仿真器,在0x18处设置断点后单步执行来分析中断处理的过程。
中断处理函数的入口处代码如下:2070b174[0xe59fb410] ldr r11,0x2070b58c; /*=#0x207a40c8,0x207a40c8是中断向量表的位置*/2070b178[0xe59dc018] ldr r12,[r13,#0x18] /*将0x207b1ce8中的内容给r12应该是中断号!!!*/ 2070b17c[0xe59bb000] ldr r11,[r11,#0] /*0x207a40c8处的内容是0x21ffbef8*/2070b180[0xe08b318c] add r3,r11,r12,lsl #3 /*将0x21ffbef8(内存地址)给r3,0x21ffbef8的内容是向量0x207064b0,这是debug口中断处理函数的入口*/2070b184[0xe79ba18c] ldr r10,[r11,r12,lsl#3]2070b188[0xe5930004] ldr r0,[r3,#4] /*相应的参数传递给r0*/2070b18c[0xe1a0e00f] mov r14,pc2070b190[0xe1a0f00a] mov pc,r10 /* r10=0x207064b0,跳转到debug口中断处理函数处执行*/0x21ffbef8(中断向量表基址)处的情况是:21ffbef8[0x2070b434] dcd 0x2070b434 4.p21ffbefc[0x00000000] dcd 0x00000000....21ffbf00[0x207064b0] dcd 0x207064b0.dp21ffbf04[0x207a9990] dcd 0x207a9990..z21ffbf08[0x2070b434] dcd 0x2070b434 4.p21ffbf0c[0x00000002] dcd 0x00000002....21ffbf10[0x2070b434] dcd 0x2070b434 4.P21ffbf14[0x00000003] dcd 0x00000003....21ffbf18[0x2070b434] dcd 0x2070b434 4.P21ffbf1c[0x00000004] dcd 0x00000004....5 结语Vxworks操作系统首先调用excVecInit()生成一个异常中断向量表excEnterTbl,当有IRQ 中断发生时,根据excEnterTbl中0x00000018处的指令ldr pc,[pc,#244]跳转到0x00000114处,即IRQ异常中断的入口处intEnt执行,随后通过读AIC_IVR寄存器得到当前优先级最高的中断,返回这个中断号,并跳转到intConnect()函数给该中断号关联的中断处理程序入口去执行。
在这个过程中,中断向量表的生成是Vxworks动态分配的,在AT91RM9200中,为0到31号中断源在中断向量表中都分配了空间,该空间的格式固定。
中断处理结束后,通过往AIC_EIOC寄存器中写任意值,从中断中返回。
点灯调试S3C44B0 vxworks BSP1. romInit的调试方法:/*************点亮0号端口的LED,验证内存配置是否成功*******************/LDR r1, L$_PCONCLDR r2, L$_PCONC_VALUESTR r2, [r1]LDR r1, L$_PUPCLDR r2, L$_PUPC_VALUESTR r2, [r1]LDR r1, L$_PDATCLDR r2, L$_PDATC_LED0STR r2, [r1]B . /*为了防止后面语句的影响,用该语句进行无限循环,使用ADS进行内存访问*//*****************************************************************************/2. C函数的调试方法#define IOPDATA (*(volatile unsigned *)(0x1d20014))IOPDATA = 0xFFF8;while(1);/***************** 代码运行到此函数,2004-10-10,9:39 ******************/3. 中断处理函数的调试方法:验证时钟中断服务程序是否工作正常void sysClkInt (void){if(intTimers == 0){IOPDATA = 0xFFF2; /*点亮LED1*/intTimers = 1;}else{IOPDATA = 0xFFF1; /* 熄灭LED1 */intTimers = 1;}if (sysClkRoutine != NULL)(* sysClkRoutine) (sysClkArg);}关于xworks中断的处理函数实现:STATUS intEnable ( int level /* level to be enabled */ ){return (*sysIntLvlEnableRtn) (level); /*在自己的BSP中实现*/ }STATUS intDisable( int level /* level to be disabled */ ){return (*sysIntLvlDisableRtn) (level);}STATUS intConnect(VOIDFUNCPTR* vector, /* vector id */VOIDFUNCPTR routine, /* interrupt service routine */int argument /* argument for isr */){int vecNum;VEC_ENTRY *pVec;if (intVecTable == NULL)return ERROR; /* library not initialized */vecNum = IVEC_TO_INUM (vector);/* check vector specified is in range allocated */if (vecNum < 0 || vecNum >= intNumVectors)return ERROR;pVec = &intVecTable[vecNum];if (routine == NULL){routine = intUninitVec;argument = vecNum;}pVec->routine = routine;pVec->arg = argument;return OK;}STATUS intLibInit(int numLevels, /* number of levels */int numVectors, /* number of vectors */int mode /* type of interrupt handling */){int i;if (intVecTable == NULL){/* Allocate and initialize the vector table */intVecTable = malloc (numVectors * sizeof (VEC_ENTRY));if (intVecTable != NULL){intNumVectors = numVectors;/* initialize table with uninitialized vec handler */for (i = 0; i < numVectors; i++){intConnect (INUM_TO_IVEC(i), NULL, 0);}/* connect architecture interrupt exception */if (mode & INT_PREEMPT_MODEL)EXC_CONNECT_INTR_RTN (intIntRtnPreempt);elseEXC_CONNECT_INTR_RTN (intIntRtnNonPreempt);return OK;}return ERROR; /* malloc failure */}return OK; /* already initialized */}STATUS excVecInit (void){FAST int i;/* initialise ARM exception mode registers */armInitExceptionModes ();/* initialise hardware exception vectors */for (i = 0; i < NUM_EXC_VECS; ++i){/** Each vector contains a LDR PC,[PC,#offset] instruction to* load the PC from a table of addresses stored at* EXC_VEC_TABLE_BASE. This allows full 32 bit addressing rather* than 12 bit (MOV #) or 24 bit (B).*/*(UINT32 *)excEnterTbl[i].vecAddr = 0xE59FF000 |(EXC_VEC_TABLE_BASE - 8 - FIRST_VECTOR);*(VOIDFUNCPTR *)(excEnterTbl[i].vecAddr + EXC_VEC_TABLE_BASE - FIRST_VECTOR) = excEnterTbl[i].fn;}/** Branch through zero has to be handled differently if it is* possible for address 0 to be be branched to in ARM and Thumb* states (no LDR pc,[pc,#n] in Thumb state). The following* instruction, installed at address 0, will cause an undefined* instruction exception in both ARM and Thumb states.*/*(UINT32 *)EXC_OFF_RESET = 0xE7FDDEFE;/* now sort out the instruction cache to reflect the changes */CACHE_TEXT_UPDATE(EXC_OFF_RESET, EXC_OFF_IRQ + 4);/* install default IRQ handler */_func_armIrqHandler = excIntHandle;return OK;}中断的调试:1.验证romInit.s能否捕获中断,中断控制器能否正确产生中断,在romInit.s的IRQ中断处理入口处点灯:_romIRQ:SUB sp, sp, #4STMFD sp!, {r1}/******点亮1号端口的LED,验证是否捕获到中断**************************************/ LDR r1, L$_PDATCLDR r2, L$_PDATC_LED0STR r2, [r1]/****************************************************************************************/LDR r1, L$_IRQVecLDR r1, [r1]STR r1, [sp, #4]LDMFD sp!, {r1, pc}为了验证中断发生时,是否可以跳转到intEnter中处理,写了如下测试代码替代intEnter: void sysKeyInt(void){FS44B0XIntLvlVecAck(21,21);if(IOPDATA&(0x08) != 0x08)IOPDATA = 0xFFF8; /*点亮LED*/elseIOPDATA = 0xFFF1; /* 熄灭LED */}void FS44B0XExcVecSet(void){int i;i=(int)&excEnterUndef;*(volatile int *)(S3C_EXE_BASE+0x0) = i;i=(int)&excEnterSwi;*(volatile int *)(S3C_EXE_BASE+0x4) = i;i=(int)&excEnterPrefetchAbort;*(volatile int *)(S3C_EXE_BASE+0x8) = i;i=(int)&excEnterDataAbort;*(volatile int *)(S3C_EXE_BASE+0xC) = i;i=(int)&sysKeyInt; /* intEnt; */*(volatile int *)(S3C_EXE_BASE+0x14) = i;return;}为了验证intEnter函数是否被执行,添加如下调试代码:STATUS FS44B0XIntLvlVecChk(int* pLevel, /* ptr to receive old interrupt level */int* pVector /* ptr to receive current interrupt vector */){int newLevel;int intPendMask = 0x2000000; /*0~26位为正常中断,27位保留*/int count;UINT32 isr;int i;for(i=0;i<5;i++){Delay(2000);Led_DisplayOn(0x01); /* VPINT(FS44B0X_PDATC)= 0xFFF2; 点亮第1盏灯*/Delay(2000);Led_DisplayOn(0x02); /* VPINT(FS44B0X_PDATC)= 0xFFF4; */}Led_DisplayOn(0x02);/* Read pending interrupt register and mask undefined bits */FS44B0X_INT_REG_READ (FS44B0X_INT_PEND, newLevel);/** Step through the bits looking for a 1. This *will* terminate.* We could use ffsLsb() for this if we don't mind the function call* overhead*/for (count = 0, isr = 25; count < FS44B0X_INT_NUM_LEVELS; count++){if (intPendMask & newLevel)break;isr--;intPendMask >>= 1;}*pVector = 21;/* Acknowledge the interrupt as given in FS44B0X sample code *//* FS44B0X_INT_REG_WRITE(FS44B0X_INT_PEND,(1 << isr)); */FS44B0X_INT_REG_WRITE(FS44B0X_I_ISPC,0xFFFFFFF); /*清除IRQ_MASK中的悬挂位*/return OK;}。