中断与任务——vxworks

2024-03-01 09:38
文章标签 中断 任务 vxworks

本文主要是介绍中断与任务——vxworks,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

中断处理是整个运行系统中优先级最高的代码,可以抢占任何任务级代码运行。中断机制是多任务环境运行的基础,是系统实时性的保证。几乎所有的实时多任务操作系统都需要一个周期性系统时钟中断的支持,用以完成时间片调度和延时处理。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几乎不能作为信息的接收者,它不可以等待接收消息或信号量。


中断服务程序

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 "vxWorks.h"
#include "intLib.h"
#include "taskLib.h"
#include "sysLib.h"
#include "logLib.h"
  
/* 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("interruptCatcher", PRIORITY, 0x100, 20000, (FUNCPTR)
  
  interruptCatcher, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)
  
  logMsg("taskSpawn 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("++++++++++++++++++++++++++Interrupt generatedn", 0, 0, 0, 0, 0,
  
    0);
  
   /* generate hardware interrupt 2 */
  
   if ((sysBusIntGen(INTERRUPT_NUM, INTERRUPT_LEVEL)) == ERROR)
  
    logMsg("Interrupt not generatedn", 0, 0, 0, 0, 0, 0);
  
  }
  
  else
  
   /* interruptCatcher is dead */
  
   break;
  
 }
  
 logMsg("n***************interruptGenerator Exited***************nnnn", 0,
  
  0, 0, 0, 0, 0);
  
}
  
void interruptCatcher(void) /* task to handle the interrupt */
  
{
  
 int i, j;
  
 STATUS connected;
  
 /* connect the interrupt vector, INTERRUPT_LEVEL, to a specific interrupt
  
 handler routine ,interruptHandler, and pass an argument, i */
  
 if ((connected = intConnect(INUM_TO_IVEC(INTERRUPT_LEVEL), (VOIDFUNCPTR)
  
  interruptHandler, i)) == ERROR)
  
  logMsg("intConnect failedn", 0, 0, 0, 0, 0, 0);
  
 for (i = 0; i < ITER1; i++)
  
 {
  
  for (j = 0; j < LONG_TIME; j++)
  
   ;
  
  logMsg("Normal processing in interruptCatchern", 0, 0, 0, 0, 0, 0);
  
 }
  
 logMsg("n+++++++++++++++interruptCatcher Exited+++++++++++++++n", 0, 0, 0,
  
  0, 0, 0);
  
}
  
void interruptHandler(int arg) /* signal handler code */
  
{
  
 int i;
  
 logMsg("-------------------------------interrupt caughtn", 0, 0, 0, 0, 0, 0);
  
 for (i = 0; i < 5; i++)
  
  logMsg("interrupt processingn", 0, 0, 0, 0, 0, 0);
  
}

程序中的sysBusIntGen()调用将产生一个bus中断,这个函数与特定的BSP密切相关,其原型为:

  STATUS sysBusIntGen
  
  (
  
  int intLevel, /* bus interrupt level to generate */
  
  int vector /* interrupt vector to generate (0-255) */
  
  );

  为了在同一中断源的几种中断服务程序中进行切换,我们应使用如下方式:

vector = INUM_TO_IVEC(some_int_vec_num);
oldfunc = intVecGet (vector);
newfunc = intHandlerCreate (routine, parameter);
intVecSet (vector, newfunc);
...
intVecSet (vector, oldfunc); /* use original routine */
...
intVecSet (vector, newfunc); /* reconnect new routine */

  其中,intHandlerCreate函数的原型为:

FUNCPTR intHandlerCreate
(
FUNCPTR routine, /* routine to be called */
int parameter /* parameter to be passed to routine */
);

  它被用于创建一个中断服务程序,在此之后,通过intVecSet()函数我们就可以将intHandlerCreate()创建的结果与中断向量绑定,intVecSet()函数的原型为:

void intVecSet
(
FUNCPTR * vector, /* vector offset */
FUNCPTR function /* address to place in vector */
);

  12.中断控制12.1中断执行过程

  硬件中断发生时,代码运行的上下文会发生切换,在进入中断处理前,需要保存当前运行的上下文。对于一些无RTOS的单片机系统,这些工作由硬件和编译器共同完成,向量表在编译完成后就填充完成,再写入存储器中,系统运行时不能修改向量表来重新绑定中断入口函数。在VxWorks系统中,除了需要保存通常的寄存器环境外,还需要完成栈切换等;另外还要求中断入口运行时绑定、平台移植性、中断嵌套等,所以VxWorks本身也参与中断封装的管理。VxWorks进行中断封装的伪代码如下:

* 00 e8 kk kk kk kk call _intEnt * 通知内核
* 05 50  pushl %eax * 保存寄存器
* 06 52  pushl %edx
* 07 51  pushl %ecx
* 08 68 pp pp pp pp pushl $_parameterBoi * push BOI param
* 13 e8 rr rr rr rr call _routineBoi * call BOI routine
* 18 68 pp pp pp pp pushl $_parameter * 传中断入口参数
* 23 e8 rr rr rr rr call _routine  * 调用中断处理C函数
* 28 68 pp pp pp pp pushl $_parameterEoi * push EOI param
* 33 e8 rr rr rr rr call _routineEoi * call EOI routine
* 38 83 c4 0c addl ?, %esp  * pop param
* 41 59  popl %ecx * 恢复寄存器
* 42 5a  popl %edx
* 43 58  popl %eax
* 44 e9 kk kk kk kk jmp _intExit * 通过内核退出

  12.2中断使能/禁止

  VxWorks提供两个重要API:

  (1)intLock():使中断禁止

  (2)intUnlock():开中断

  可以用intLock/intUnlock提供最高级别的互斥机制以保护临界区域不被打断,例如:

oldlevel = intLock();
/* 写XXX寄存器 */
XXX_REG_WRITE(pChan, XXX_UBRDIV, XXX_CNT0_115200 | XXX_CNT1_VAL); 
intUnlock(oldlevel);

  用intLock()禁止中断后,当前执行的任务将一直继续,中断处理和任务调度得不到执行,直到该任务主动调用intUnLock解锁中断为止。对于intLock和unLock的使用,我们要注意如下几点:

  (1)不要在中断禁止期间调用vxWorks系统函数,否则有可能意外使能中断,违反临界代码的设计意图。另外,intLock也不能屏蔽调度,如果在中断禁止代码区使用系统调用,就可能出现任务调度,其他任务的运行可能会解锁中断;

  (2)中断禁止对系统的实时性有很大的影响,在解决执行代码和中断处理互斥问题才可使用,并且应使中断禁止时间尽可能的短。对于任务间的互斥问题,可以使用taskLock()和taskUnLock()来解决;

  (3)有些CPU中断是分级,我们可以用intLockLevelSet()和intLockLevelGet()来操作中断闭锁的级别。缺省情况下,taskLock禁止所有等级的中断。

  至此,我们可以对“互斥”问题进行一个系统的总结,主要有如下几种方法:

  (1)intLock禁止中断:解决任务和ISR之间的互斥问题;

 int lock = intLock();
 //. . critical region that cannot be interrupted
 intUnlock(lock);

  (2)taskLock禁止优先级抢占调度:当当前任务正在运行时,除了中断服务程序外,高优先级的任务也不允许抢占CPU;

 taskLock();
 //. . critical region that cannot be interrupted .
 taskUnlock();

  (3)二进制信号量或互斥信号量。

semTake (semMutex, WAIT_FOREVER);
 //. . critical region, only accessible by a single task at a time .
semGive (semMutex);

  总的来说,在实时系统中采取“禁止中断”的方法会影响系统对外部中断及时响应和处理的能力;而“禁止优先级抢占调度”方法阻止了高优先级的任务抢先运行,在实时系统中也是不适合的。因此,信号量无疑是解决互斥问题的最好方法。


<script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/buttonLite.js#style=-1&uuid=&pophcol=3&lang=zh"></script> <script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/bshareC0.js"></script>
阅读(4) | 评论(0) | 转发(0) |
0

上一篇:关于问题vxworks与linux区别

下一篇:没有了

相关热门文章
  • perl多进程和进程池
  • 成都二手房交易按新标准计税...
  • 无线传感网络传输协议综述【1...
  • 广西北海阳光工程钱到底能不...
  • 卢俊卿:让科技创新活力迸发...
  • 承接自动化测试培训、外包、实...
  • Solaris PowerTOP 1.0 发布
  • For STKMonitor
  • busybox的httpd使用CGI脚本(Bu...
  • 项目小体会
  • 收音机驱动与v4l2架构的关系,...
  • 北测检测认证公司怎么样?...
  • 如何将linux驱动改为裸机驱动(...
  • Fedora 20开机卡在LOGO界面,...
  • 如何实现Linux下选择性删除一...
给主人留下些什么吧!~~
评论热议

这篇关于中断与任务——vxworks的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/762008

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

FreeRTOS学习笔记(二)任务基础篇

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、 任务的基本内容1.1 任务的基本特点1.2 任务的状态1.3 任务控制块——任务的“身份证” 二、 任务的实现2.1 定义任务函数2.2 创建任务2.3 启动任务调度器2.4 任务的运行与切换2.4.1 利用延时函数2.4.2 利用中断 2.5 任务的通信与同步2.6 任务的删除2.7 任务的通知2

Flink任务重启策略

概述 Flink支持不同的重启策略,以在故障发生时控制作业如何重启集群在启动时会伴随一个默认的重启策略,在没有定义具体重启策略时会使用该默认策略。如果在工作提交时指定了一个重启策略,该策略会覆盖集群的默认策略默认的重启策略可以通过 Flink 的配置文件 flink-conf.yaml 指定。配置参数 restart-strategy 定义了哪个策略被使用。常用的重启策略: 固定间隔 (Fixe

第49课 Scratch入门篇:骇客任务背景特效

骇客任务背景特效 故事背景:   骇客帝国特色背景在黑色中慢慢滚动着! 程序原理:  1 、 角色的设计技巧  2 、克隆体的应用及特效的使用 开始编程   1、使用 黑色的背景: ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7d74c872f06b4d9fbc88aecee634b074.png#pic_center)   2

FreeRTOS学习笔记(四)Freertos的中断管理及临界保护

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Cortex-M 中断管理1.1 中断优先级分组1.2 相关寄存器1.3 相关宏定义1.4 FreeRTOS 开关中断 二、临界段及其保护2.1 taskENTER_CRITICAL( ) 和 taskEXIT_CRITICAL( )2.2 taskENTER_CRITICAL_FROM_ISR( )

AsyncTask 异步任务解析

1:构建AsyncTask 子类的回调方法: A:doInBackground:   必须重写,所有的耗时操作都在这个里面进行; B: onPreExecute:     用户操作数据前的调用; 例如:显示一个进度条 等 ; C: onPostExecute:    当doInBackground 执行完成后;会自动把数据传给onPostExecute方法;也就是说:这个方法是处理返回的数据的方法

Cortex-A7:ARM官方推荐的嵌套中断实现机制

0 参考资料 ARM Cortex-A(armV7)编程手册V4.0.pdf ARM体系结构与编程第2版 1 前言 Cortex-M系列内核MCU中断硬件原生支持嵌套中断,开发者不需要为了实现嵌套中断而进行额外的工作。但在Cortex-A7中,硬件原生是不支持嵌套中断的,这从Cortex-A7中断向量表中仅为外部中断设置了一个中断向量可以看出。本文介绍ARM官方推荐使用的嵌套中断实现机

使用Node-API进行异步任务开发

一、Node-API异步任务机制概述         Node-API异步任务开发主要用于执行耗时操作的场景中使用,以避免阻塞主线程,确保应用程序的性能和响应效率。         1、应用场景: 文件操作:读取大型文件或执行复杂的文件操作时,可以使用异步工作项来避免阻塞主线程。网络请求:当需要进行网络请求并等待响应时,可以使用异步工作项来避免阻塞主线程,从而提高应用程序的响应性能。数据库操

探索Invoke:Python自动化任务的瑞士军刀

文章目录 探索Invoke:Python自动化任务的瑞士军刀背景:为何选择Invoke?`invoke`是什么?如何安装`invoke`?简单的`invoke`库函数使用方法场景应用:`invoke`在实际项目中的使用场景一:自动化测试场景二:代码格式化场景三:部署应用 常见问题与解决方案问题一:命令执行失败问题二:权限不足问题三:并发执行问题 总结 探索Invoke:P

RISC-V (十)任务同步和锁

并发与同步 并发:指多个控制流同时执行。         多处理器多任务。一般在多处理器架构下内存是共享的。           单处理器多任务,通过调度器,一会调度这个任务,一会调度下个任务。  共享一个处                                理器一个内存。                 单处理器任务+中断: 同步: 是为了保证在并发执行的环境中各个控制流可