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

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

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

  (1ISR中不能调用可能导致blocking的函数,例如:

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

  (b)mallocfree可能导致blocking,因此也不能使用;

  (c)应避免进行VxWorks I/O系统操作(除管道外);

  (d)应避免在ISR中进行浮点操作。

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

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

  11.中断服务程序

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

  (1intConnect():中断连接,将中断向量与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()函数。

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

/* macros to convert interrupt vectors <-> interrupt numbers */
#define IVEC_TO_INUM(intVec)
  ((int) (intVec))
#define INUM_TO_IVEC(intNum)
  ((VOIDFUNCPTR *) (intNum))

  结合12可知一般挂接一个中断服务程序的调用为:

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

  (1intLock():使中断禁止

  (2intUnlock():开中断

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

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

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

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

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

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

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

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/435263.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jwt获取token_JWT实现token认证

1.JWT是什么&#xff1f;Json Web Token(JWT)是目前比较流行的跨域认证解决方案&#xff0c;是一种基于JSON的开发标准&#xff0c;由于数据是可以经过签名加密的&#xff0c;比较安全可靠&#xff0c;一般用于前端和服务器之间传递信息&#xff0c;也可以用在移动端和后台传递…

神经网络与深度学习——TensorFlow2.0实战(笔记)(三)(第一个Python程序)

从程序中了解知识点&#xff0c;有详细的备注 # 判断变量num是否为正数 # 注释语句 是对程序进行说明的语句&#xff0c;在程序运行过程中不被执行 # ctrl/进行多行注释num0 # 赋值语句 大小写敏感 可以以分号结尾&#xff0c;但是在同一行必须以分号隔开 # 其数据类型由所赋…

Sqlce与SQL Server2000/2005数据转换程序

先上图 功能介绍&#xff1a; 1.根据Mssql2000/2005创建sqlce数据库表结构及索引(如果操作的表为空&#xff0c;则取mssql2000/2005的所有表&#xff0c;否则取录入的操作的表&#xff0c;用逗号隔开) 2.从mssql2000/2005导数据到已建好的sqlce(如果操作的表为空&#xff0c;则…

SRAM和SDRAM的区别

DRAM&#xff0c;动态随机存取存储器&#xff0c;需要不断的刷新&#xff0c;才能保存数据。而且是行列地址复用的&#xff0c;许多都有页模式。 SRAM&#xff0c;静态的随机存取存储器&#xff0c;加电情况下&#xff0c;不需要刷新&#xff0c;数据不会丢失&#xff0c;而且…

docker java镜像_Springboot整合MongoDB的Docker开发,其它应用也类似

1 前言Docker是容器开发的事实标准&#xff0c;而Springboot是Java微服务常用框架&#xff0c;二者必然是会走到一起的。本文将讲解如何开发Springboot项目&#xff0c;把它做成Docker镜像&#xff0c;并运行起来。2 把Springboot打包成Docker镜像Springboot的Web开发非常简单&…

神经网络与深度学习——TensorFlow2.0实战(笔记)(三)(python输入和输出)

从程序中学习知识点 1. #输出函数可以输出字符串常量 print("hello") #输出数学表达式 print(12) #输出变量 print(num) 2. #string input(提示信息) #接收用户的输入&#xff0c;并以字符串类型返回;即键盘输入123&#xff0c;并将123赋值给string numint(input…

ManulResetEvent与AutoResetEvent

定义 ManualResetEvent&#xff1a;通知正在等待的线程已发生事件。 AutoResetEvent&#xff1a;通知正在等待的线程已发生事件。 代码 ManualResetEvent测试 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;…

Timer

[摘要] Timer是实时操作系统的一个重要组成部分。本文结合近阶段的学习和实验情况&#xff0c;对VxWorks中的时间函数和定时器作了一些探讨。主要介绍了Timer的机制&#xff0c;相关的函数&#xff0c;并给出了一些具体的例子。 一. Tick Tick是指每秒中定时器中断的次数。POS…

神经网络与深度学习——TensorFlow2.0实战(笔记)(三)(python常量、变量和表达式)

从程序中学习知识点 1. #支持6中表达形式 数字 字符串 列表 元组 字典 集合 #数字 整型(正整数 负整数 零) #Python3中的整数可以任意大&#xff0c;而不用担心位数不够而导致溢出的情况 intnum12345678909999999999999 print(intnum,type(intnum)) #浮点数 小数 floatnum1 …

reentrantlock非公平锁不会随机挂起线程?_程序员必须要知道的ReentrantLock 及 AQS 实现原理...

专注于Java领域优质技术&#xff0c;欢迎关注作者&#xff1a;Float_Luuu提到 JAVA 加锁&#xff0c;我们通常会想到 synchronized 关键字或者是 Java Concurrent Util(后面简称JCU)包下面的 Lock&#xff0c;今天就来扒一扒 Lock 是如何实现的&#xff0c;比如我们可以先提出一…

关于SOAP的几篇文章

转载自&#xff1a;/show-1598-1.shtml PHP操作soap我总觉得是一件非常痛苦的事情&#xff0c;但没有办法&#xff0c;现在很多功能都是基于WebService的&#xff0c;比如那个amazon的&#xff0c;但其实很多 公司都也还是提供了restful之类的接口&#xff0c;使得PHP与其他系统…

VxWorks动态加载

注&#xff1a;最近在做热补丁的功能&#xff0c;看到一篇gateway写的文章&#xff0c;觉得很通俗易懂的&#xff0c;就将搜集到的资料又整理了一下&#xff0c;供大家参考。 使用动态加载目标模块的方式有很多好处&#xff0c;比如可以在不破坏原来的环境下增加调试定位功能&a…

excel办公常用的宏_让领导看傻!精美168套办公常用excel模板免费领

HR们面试的时候&#xff0c;是不是经常看到应聘者的简历上技能那一栏写着精通Excel、PPT等办公技能&#xff1f;你知道Excel用到什么程度才算精通吗&#xff1f;能够用excel做表格就算精通吗&#xff1f;还是要能够熟练使用各种函数&#xff1f;你做出来的Excel报表也许是这样的…

神经网络与深度学习——TensorFlow2.0实战(笔记)(三)(python运算符和表达式)

从程序中学习知识点 1.算术运算符 #运算符&#xff08;Operator&#xff09;&#xff1a;完成不同类型的常量、变量之间的运算 #除法运算 / 结果是一个浮点型的精确数的值&#xff0c;与java等其他语言的不同之处 print(7/2,7.0/2,-7/2) #整除运算 print(7//2,-7//2) print(7…

VxWorks系统BSP配置文件及生成下载

%A VxWorks BSP主要配置文件 config.h , Makefile 注解和 BSP生成下载实例。%A%A 相关内容可参考 VxWorks BSP和启动过程%A%A config.h文件配置%A%A /*%A This file contains the configuration parameters for the CPU evaluation board.%A */%A%A #ifndef INCconfigh%A #defi…

float32精度_PyTorch 1.6来了:新增自动混合精度训练、Windows版开发维护权移交微软...

刚刚&#xff0c;Facebook 通过 PyTorch 官方博客宣布&#xff1a;PyTorch 1.6 正式发布&#xff01;新版本增加了一个 amp 子模块&#xff0c;支持本地自动混合精度训练。Facebook 还表示&#xff0c;微软已扩大了对 PyTorch 社区的参与&#xff0c;现在拥有 PyTorch 在 Windo…

神经网络与深度学习——TensorFlow2.0实战(笔记)(三)(python语句)

1.if语句 #if语句 x,y 3,5 if x<y:print("x<y") elif xy:print("xy") else:print("x>y") 2.条件表达式 x,y3,5 #表达式1(条件为真的结果) if 判断条件 else 表达式2(条件为假的结果) print(x if x>y else y) 3.while语句 #死循环…

建立调试环境

建立调试环境 Tornado采用支持主机/目标机开发模式。本节以x86系列目标机为例介绍调试环境的建立 。 7.1.1 配置文件config.h 目标机运行的程序包括两部分&#xff1a;引导文件bootrom.sys和操作系统影像文件VxWorks。 引导文件bootrom.sys的主要作用类似于BIOS&#xf…

天气预报的获取

好久没有写技术文章了&#xff0c;2010年工作太忙&#xff0c;奔波在国内各地&#xff0c;也没什么时间关注一些技术方面的事情&#xff0c;最近有一个项目封闭开发&#xff0c;有些时间来写些琐碎的东西&#xff0c;就当是整理下最近的东西吧&#xff0c;没什么技术价值&#…

神经网络与深度学习——TensorFlow2.0实战(笔记)(四)(python列表与元组)

序列数据结构 1.成员是有序排列的 2.每个元素的位置称为下标或索引 3.通过索引访问序列中的成员 4.Python中的序列数据类型有字符串、列表、元组 "abc" ≠ "bca" 5.Python中的列表和元组&#xff0c;可以存放不同类型的数据 列表使用方括号[ ]表示&a…