VxWorks信号、中断处理与定时机制

为了获得尽可能的、最快的中断反应时间,VxWorks的中断处理程序(ISRs)运行在它们特定的上下文中(独立于任何任务的上下文)。

信号

支持软件信号功能。

信号可以异步改变任务控制流。获得信号的任务立即挂起当前的执行,在下次调度它运行时转而执行指定的信号处理程序。信号处理程序在信号接收任务的上下文中执行,使用该任务的堆栈。在任务阻塞时,信号处理程序仍可被唤醒。

与用于任务间通信相比,信号机制适合于错误和异常处理。通常,信号处理程序可以作为中断处理程序看待。任何可能导致调用程序阻塞的函数均不能在信号处理程序中调用。

由于信号是异步的,很难预测当信号处理程序执行时,哪种资源是可用的。为了系统安全起见,信号处理程序仅能调用那些能在中断处理程序中安全使用的函数,否则可能导致系统死锁。

wind内核支持两种类型的信号接口:

UNIX BSD风格的信号;

POSIX兼容的信号。

调用基本信号接口函数之前,必须调用sigInit()初始化信号函数库。正常情况下,在中断允许之前,在程序usrConfig.c的usrInit()函数中调用。

信号在很多方面相似于硬件中断,基本信号接口提供31个不同信号。调用sigvec()或sigaction()可为信号指定一个信号处理程序。这与调用intConnect()为中断指定一个中断处理程序(ISR)相似。可以调用kill()将信号发送给任务,这类似于中断发生。函数sigsetmask()和sigblock()或sigprocmask()可以用来像屏蔽中断那样屏蔽信号。

POSIX队列信号

sigqueue()函数提供与kiil()等价的功能:向任务发送信号。区别:sigqueue()排队发送给任何任务的多个信号,而kill()仅提交一个信号。

中断服务程序

VxWorks的库intLib和IntArchLib提供中断函数。

设置中断处理程序

intConnect(),允许将指定的C函数与任意中断相联系。返回OK成功,ERROR失败。

中断处理函数不能是调用任何可能引起阻塞和执行I/O操作的操作系统函数。

不能调用可能引起调用阻塞的函数:如在中断处理程序中不能试图获取一个信号量,因为信号量可能不可用,内核将该调用者切换到阻塞状态。然而,中断服务程序可以释放一个信号量,解除等待在该信号量上的任务。因为存储器函数malloc()和free()都需要获得一个信号量,因而中断处理程序中不能调用他们。例如中断服务程序不能调用任何创建和删除函数。

中断服务程序也不能通过vxworks驱动执行I/O操作,尽管I/O系统不存在内在的约束,多数设备驱动由于可能需要等待设备而引起调用者阻塞,因此需要任务上下文交换。一个例外是vxworks管道驱动,它允许中断服务程序执行写操作。

在开发过程中,可以调用checkStack()函数查看一个任务堆栈的使用情况或整个系统堆栈的使用情况。

VxWorks支持记录功能,任务可以向系统输出平台打印文本信息。这种机制为中断处理程序提供可特殊的支持,中断处理程序可以调用logMsg()向系统输出信息。logMsg()必须带6个整型参数。

原型:int logMsg(char *fmt,int arg1,int arg2,int arg3,int arg4,int arg5,int arg6)参考logLib库。

中断服务程序也不能调用使用浮点协处理器的函数。vxworks由intConnect()创建的中断驱动代码不能保存和恢复浮点寄存器。因此中断服务程序不能包含浮点指令。如果一定要用浮点指令,必须明确调用fppArchLib库中的函数。

中断级异常

当任务引起一个异常,例如非法指令或总线错,系统将该任务挂起,而系统的其余部分继续执行。而当中断引起一个异常时,则系统没有安全的资源用于处理异常。这是因为中断处理程序没有可以挂起的上下文。

这时,vxworks首先将该异常的描述保存在低端内存,然后执行系统复位,每次引导时,vxworks引导ROM检查低端内存是否有异常描述出现,如果检查到,则将其显示在系统平台上。

保留的最高中断级以确保对这些事件的零延时(zero-latency)反应。

intLockLevelSet()用来设置整个系统的中断上锁级别。如果不指明级别,默认值是系统支持的最高中断级。

中断与任务的通信

中断服务程序与一般任务的通信机制有:

共享存储区和环缓冲,中断服务程序可以与任务共享变量、缓冲和环形缓冲。

信号量:中断服务程序能够释放信号量(不包括互斥信号量和VxMP贡献信号量),任务能够等待该信号量;

消息队列,中断服务程序可以向消息队列发送消息,任务可以从消息队列接收消息(不包括VxMP使用的共享消息队列),如果队列已满,消息则被丢弃。

管道,中断服务程序可以向管道写数据,任务可以从中读取。任务和中断服务程序能够向共享的管道写数据,但如果管道已满,由于中断服务程序不允许阻塞,数据将被丢弃。中断服务程序不允许调用除了write()之外的其他任何I/O函数调用。

信号灯:中断服务程序能够通过发信号来通知任务,触发相应的信号处理程序的异步调度。

看门狗

提供一个看门狗机制,允许任何C函数与一个特定的时间延迟相联系。以系统时钟中断级作为中断服务代码来执行。

wdLib库函数。

看门狗定时器首先由wdCreate()创建,调用wdStart()启动计时器,一个以tick为单位的参数作为延时计时器的值,另一个参数是计时器结束时要调用的C程序。在计时器计时结束之前的任意时刻,调用wdCancel()将取消该看门狗定时器。

当需要延时一个任务的执行时,可以使用看门狗定时器。一旦一个任务调用wdStart()函数启动一个看门狗定时器,看门狗定时器进入延时态。一旦看门狗定时器计时结束,它将调用由wdStart()指定的一个中断服务程序。该中断服务程序在该任务的上下文之外执行。

利用看门狗处理任务时限

实时系统任务重要特征是具有时限约束。因此超出时限的任务必须进行处理,以控制危害程度,通常启动一个时限事故处理任务(deadline handlers)。看门狗可以启动这种时限事故处理任务。

POSIX时钟和计时器

VxWork提供一个软件时钟(数据结构struct timespec,定义在time.h),用来以秒和纳秒两种单位记录时间,这个软件时钟由系统时钟tick来修改。

同时提供一个POSIX 1003.1b标准时钟和计时器接口。

POSIX标准支持识别多个虚拟时钟,但是整个系统仅需要一个实时时钟CLOCK_REALTIME(定义在time.h中)。VxWorks提供访问这个整个系统范围内实时时钟的函数,参见clockLib库。不支持虚拟时钟。

POSIX计时器功能提供这种功能支持:任务可以在一段时间后通知自身。程序可以创建、设置和删除一个计时器。参见timerLib库。当计时器到达,将向该任务发送默认的信号(SIGALARM)。函数sigaction()将安装一个信号灯处理程序sigHandler,该程序将在计时器结束时调用。

另外一个POSIX函数nanosleep(),允许指定一个以秒和纳秒为单位的睡眠或延时时间,其功能与WIND核中的taskDelay()类似,后者以tick作为延时单位。二者只是延时单位不同,而不是精度不同。这两个延时函数有相同的精度,都有系统时钟频率决定。

POSIX内存上锁接口

许多操作系统实现内存分页和交换功能。这些技术通过将内存块数据拷贝到硬盘和从硬盘拷贝数据到内存,从而允许应用程序使用比物理内存大得多的存储空间,也就是虚拟内存。但这些技术使得系统执行难以预测,因而不适合于实时系统。

由于wind核是为实时系统设计,因而不能采用内存分页和交换技术。然而POSIX 1003.1b实时扩展标准包含实现分页和交换技术的操作系统。这些系统中,需要实时性能的应用可以利用POSIX锁页功能,也就是,强制声明一块内存是不能被分页和不能被交换到硬盘的,从而保证系统操作这块内存的确定性。

为了实现最大可能的可移植性,VxWorks实现了POSIX锁页函数调用。VXWORKS所有的内存都是有效的(不会发生交换),总是“上锁”的。实现他们只是为了其他POSIX兼容系统与vxworks系统之间应用程序移植的方便。

POSIX锁页函数在mmanPxLib库中,包含INCLUDE_POSIX_MEM选项,操作系统将会自动包含该库。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
zynq+vxworks中断处理过程如下: 1. 配置中断控制器:在zynq中,中断控制器是GIC(Generic Interrupt Controller)。需要在vxworks中配置GIC,使其能够正确地响应中断请求。 2. 注册中断服务例程(ISR):在vxworks中,需要编写中断服务例程来处理中断请求。可以使用intConnect()函数将ISR与中断向量号关联起来。 3. 使能中断:使用intEnable()函数使能中断,使其能够响应中断请求。 4. 处理中断:当中断请求到达时,GIC会将中断请求发送给vxworks内核。内核会根据中断向量号找到对应的ISR,并执行ISR中的代码来处理中断请求。 5. 中断处理完成:当ISR执行完毕后,需要使用intAck()函数向GIC发送中断确认信号,告诉GIC该中断已经被处理完毕。 下面是一个示例代码,演示了如何在zynq+vxworks系统中处理中断请求: ```c #include <vxWorks.h> #include <sysLib.h> #include <intLib.h> #define INTC_BASE_ADDR 0x41200000 #define INTC_DIST_BASE_ADDR 0x41210000 #define INTC_DIST_CTR 0x1000 #define INTC_DIST_ENABLE 0x100 #define INTC_IRQ_ID 61 void myIsr(void* arg) { printf("Interrupt received!\n"); // 处理中断请求 ... // 发送中断确认信号 intAck(INUM_TO_IVEC(INTC_IRQ_ID)); } void intInit() { // 配置GIC ... // 注册ISR intConnect(INUM_TO_IVEC(INTC_IRQ_ID), myIsr, NULL); // 使能中断 intEnable(INTC_IRQ_ID); } int main() { // 初始化中断 intInit(); // 等待中断请求 while(1); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值