基于嵌入式操作系统VxWorks的多任务并发程序设计(5)――中断与任务

更新时间:2023-10-27 09:56:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

基于嵌入式操作系统VxWorks的多任务并发程序设计(5)――中断与任务

中断处理是整个运行系统中优先级最高的代码,可以抢占任何任务级代码运行。中断机制是多任务环境运行的基础,是系统实时性的保证。几乎所有的实时多任务操作系统都需要一个周期性系统时钟中断的支持,用以完成时间片调度和延时处理。VxWorks 提供tickAnnounce(),由系统时钟中断调用,周期性地触发内核。

为了快速响应中断,VxWorks的中断服务程序(ISR)运行在特定的空间。不同于一般的任务,中断服务程序没有任务上下文,不包含任务控制块,所有的中断服务程序使用同一中断堆栈,它在系统启动时就已根据具体的配置参数进行了分配和初始化。在ISR中能使用的函数类型与在一般任务中能使用的有些不同,主要体现在: (1)ISR中不能调用可能导致blocking的函数,例如:

(a)不能以semTake获取信号量,因如果该信号量不可利用,内核会试图让调用者切换到blocking态;

(b)malloc和free可能导致blocking,因此也不能使用; (c)应避免进行VxWorks I/O系统操作(除管道外); (d)应避免在ISR中进行浮点操作。

(2)在ISR中应以logMsg打印消息,避免使用printf;

(3)理想的ISR仅仅调用semGive等函数,其它的事情交给semTake这个信号量的任务去做。一个ISR通常作为通信或同步的发起者,它采用发送信号量或向消息队列发送一个消息的方式触发相关任务至就绪态。ISR几乎不能作为信息的接收者,它不可以等待接收消息或信号量。 11.中断服务程序

VxWorks中与中断相关的重要API函数或宏有:

(1)intConnect():中断连接,将中断向量与ISR入口函数绑定

SYNOPSIS STATUS intConnect ( VOIDFUNCPTR * vector,/* interrupt vector to attach to */ VOIDFUNCPTR routine, /* routine to be called */ int parameter /* parameter to be passed to routine */ ); intConnect只是调用了下文将要介绍的intHandlerCreate()和intVecSet()函数。

(2)INUM_TO_IVEC(intNum):将中断号转化为中断向量的宏。与INUM_TO_IVEC对应的还有一个IVEC_TO_INUM(intVec),实现相反的过程。INUM_TO_IVEC和IVEC_TO_INUM的具体定义与特定的BSP有关,例如:

/* macros to convert interrupt vectors <-> interrupt numbers */ #define IVEC_TO_INUM(intVec) ((int) (intVec)) #define INUM_TO_IVEC(intNum) ((VOIDFUNCPTR *) (intNum)) 结合1、2可知一般挂接一个中断服务程序的调用为:

intConnect(INUM_TO_IVEC(INTERRUPT_LEVEL),(VOIDFUNCPTR)interruptHandler,i); 例1:中断服务程序

/* includes */ #include \ #include \ #include \ #include \ #include \ /* function prototypes */ void interruptHandler(int); void interruptCatcher(void); /* globals */ #define INTERRUPT_NUM 2 #define INTERRUPT_LEVEL 65 #define ITER1 40 #define LONG_TIME 1000000 #define PRIORITY 100 #define ONE_SECOND 100 void interruptGenerator(void) /* task to generate the SIGINT signal */ { int i, j, taskId, priority; STATUS taskAlive; if ((taskId = taskSpawn(\PRIORITY, 0x100, 20000, (FUNCPTR) interruptCatcher, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR) logMsg(\interruptCatcher failedn\0, 0, 0, 0, 0, 0); for (i = 0; i < ITER1; i++) { taskDelay(ONE_SECOND); /* suspend interruptGenerator for one second */ /* check to see if interruptCatcher task is alive! */ if ((taskAlive = taskIdVerify(taskId)) == OK) { logMsg(\0, 0, 0, 0, 0, 0); /* generate hardware interrupt 2 */ if ((sysBusIntGen(INTERRUPT_NUM, INTERRUPT_LEVEL)) == ERROR) logMsg(\not generatedn\0, 0, 0, 0, 0, 0); } else /* interruptCatcher is dead */ break; } logMsg(\Exited***************nnnn\0, 0, 0, 0, 0, 0); } void interruptCatcher(void) /* task to handle the interrupt */ { int i, j;

本文来源:https://www.bwwdw.com/article/y0l2.html

Top