《VxWorks7编程指南》笔记(四)——中断服务程序ISR

2024-02-14 18:20

本文主要是介绍《VxWorks7编程指南》笔记(四)——中断服务程序ISR,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

 

1.中断服务程序ISR

2.针对ISR的VxWorks配置

3.ISR可用资源

4.ISR编程与调试

5.修改系统时钟ISR

6.运行时的ISR信息

7.ISR与工作队列死机


1.中断服务程序ISR

外部事件通常通过中断的方式通知系统,因此硬件中断处理是实时操作系统中的关键功能。

为了以最快速度响应中断,VxWorks中断服务程序执行在独有的上下文,而非任何任务是上下文中。除非系统专门进行过配置,否则不会推迟ISR的执行。

2.针对ISR的VxWorks配置

VxWorks系统默认支持SIR。中断栈可以按大小和附加特性进行配置。中断栈必须足够大,以处理中断嵌套时的最坏情况。

中断栈配置

所有的的ISR使用相同的中断栈空间。系统将在初始化时根据设定的配置参数为中断栈分配空间。其大小必须足够大,以应付中断嵌套时的最坏情况。中断栈大小由宏ISR_STACK_SIZE定义。

注意:某些架构不允许使用独立的中断栈,而需要使用被中断任务的栈空间。在这种架构下,必须确保创建任务时分配了足够大的栈空间,以处理中断嵌套和嵌套调用的最坏情况。

 

中断栈填充

默认情况下,中断栈空间被填充为0xEE。对栈空间进行填充的做法,对于开发过程中的调试很有帮助。具体可以使用checkStack()函数进行栈空间检查。

在进行系统配置时,建议不要对中断栈空间进行填充,以获得更佳的性能。可以使用配置参数VX_GLOBAL_NO_STACK_FILL关闭栈空间填充功能。

 

中断栈保护

如果使能了MMU功能,系统就可以通过配置INCLUDE_PROTECT_INTERRUPT_STACK组件,提供对中断栈始末的guard zone保护。

可以通过如下配置参数设置guard zone的大小:

  • INTERRUPT_STACK_OVERFLOW_SIZE:设置中断栈上溢大小;
  • INTERRUPT_STACK_UNDERFLOW_SIZE:设置中断栈下溢大小;

当添加了guard zone,栈空间的大小通常是MMU大小的整数倍。

3.ISR可用资源

所有的VxWorks功能库,如链表、环形缓冲区,都可以在ISR中使用。然而对于从ISR中调用函数还是有一些限制。

全局变量errno可以作为中断进入与退出代码的一部分而被保存和获取。所以,ISR刻意像其他代码一样引用和修改errno。

 

4.ISR编程与调试

对于ISR的最基础的要求就是,ISR代码应该尽可能的短。ISR中不应该添加耗时的函数,此外还有一些限制:ISR不能调用会导致ISR阻塞的函数,也不能调用使用浮点数协处理器的函数;对于C++使用也有限制。

非阻塞函数

虽然ISR中可以使用许多VxWorks功能,但是需要注意一些重要的限制条件。这些限制都是源于如下事实:ISR不是运行在常规的任务上下文中,且没有任务控制块,因此所有的ISR都共享同一个栈空间。

因为上述原因,对于ISR的最基础的限制条件就是,不能在ISR中调用会导致ISR自身阻塞的函数。例如,在ISR中不能尝试获取一个信号量,因为如果当前无法获取该信号量,那么内核将尝试把ISR切换到挂起状态。然而,ISR可以释放信号量,从而释放任何在等待该信号量的任务。

内存相关函数malloc()和free()中会尝试获取信号量,所以在ISR中不应该调用这两个函数。因此在ISR中不应该调用任何创建或删除函数。

ISR也不能通过VxWorks驱动执行I/O操作。尽管对I/O系统没有内在的限制条件,大多数的设备驱动仍然需要一个任务上下文环境,因为它们可能阻塞等待设备的任务。一个例外时VxWorks pipe驱动,ISR可以使用该驱动执行写操作。VxWorks还提供了几个供ISR调用的函数,用于向系统控制台中输出信息:logMsg()、kprintf()、kputs()。

 

浮点数协处理器函数

默认条件下,中断驱动代码不保存和读取浮点数寄存器。如果一个ISR需要执行浮点数指令,那么它必须使用fppArchLib库中提供的函数,对浮点数协处理器中的寄存器进行显示的保存和读取。

 

共享数据区的间接访问

ISR不应该直接访问共享数据区。一个ISR将继承被它抢占的任务的内存环境,如果该任务不包括共享数据区,那么ISR就不能访问共享内存,否则会导致系统异常。

为了可靠地访问共享数据区,ISR必须使用一个已经包含了共享数据区的任务。该任务在ISR执行完毕后可以执行对共享数据区的相关操作。

 

中断与任务之间的通信

尽管VxWorks支持直接连接运行在中断级的ISR,但是中断事件通常会传播到任务级代码中。许多VxWorks功能不适用于中断级代码,包括任何设备的I/O(除了pipe)。然而,如下技术可以用于ISR到任务级代码之间的通信。

  • 共享内存与环形缓冲区

ISR可以与任务级代码共享变量、缓冲区和环形缓冲区。

  • 信号量

ISR可以释放任务所需要的信号量(除了互斥信号量和VxMP共享信号量)。

  • 消息队列

ISR可以向等待接收消息队列中的消息的任务发送消息(除了VxMP中使用的共享消息队列)。如果队列已满,则该消息将被丢弃。

  • 管道

ISR可以向供任务读取的管道中写入消息。任务和ISR可以向同一个管道中写入消息。因为ISR不能被阻塞,所以如果管道已满,那么写入的消息将被丢弃。除了write()函数,ISR中不能在管道中触发任何I/O函数。

  • 信号

ISR可以向任务发送信号,从而异步调度相关的信号处理函数。

  • VxWorks事件

ISR可以向任务发送VxWorks事件。

 

高中断优先级保留

大多数应用程序都可以使用VxWorks中断。但是有些情况下,类似于关键运动控制或系统失效响应等事件,需要拥有低级别的控制。在这些情况下,最好能够保留最高级别的中断,确保以零延时响应这些事件。为了实现零延时,VxWorks提供了intLockLevelSet()函数,用于将系统范围内的中断锁级别设定到一个特定的级别。如果没有指定一个级别,那么将使用处理器架构所支持的最高级别。

 

对高中断级别ISR的限制

对链接到未屏蔽的中断优先级(既可以是比intLockLevelSet()函数设置的中断优先级高的级别,也可以是由硬件定义的非屏蔽中断优先级)的ISR由特殊的限制:

  • ISR只能通过intVecSet()函数连接
  • ISR不能使用任何基于中断锁的VxWorks操作系统功能。否则后果就是,除了系统重启,ISR不能安全地执行任何VxWorks函数调用。

 

对于I/O的使用限制

通常,ISR不能通过VxWorks驱动执行I/O操作,因为这些操作会导致ISR阻塞。这意味着标准的I/O函数,如printf()和puts()不能用于调试ISR。基础的供ISR调试使用的方法包括:

  • 在ISR中使用全局变量,该全局变量可以根据相关数据进行更新。之后就可以在运行时通过shell显示这些变量的值。
  • 在ISR中使用如下函数向控制台输出信息:logMsg()、kprintf()、kputs()。

使用全局变量的优点在于:实现简单且对ISR执行的性能影响最小。缺点在于如果系统因为ISR中的某个bug导致挂起,就不能使用shell显示变量的值了。

使用logMsg()函数的优点在于:可以自动向控制台打印消息,相较于kprintf()和kputs(),对于ISR的执行性能的影响更小。缺点在于,如果系统在调用该函数后短暂地挂起了,那么消息可能无法显示在控制台中。原因是由于logMsg()的异步操作首先是把消息写入到一个消息队列,然后logging任务将消息打包再发送到控制台。

使用kprintf()与kputs()的优点在于:它们可以同步地输出消息(使用轮询模式),因此可以在bug出现时精确地反映出ISR已经执行到哪个阶段(也可用于内核启动期间或任务切换钩子函数中)。缺点在于,因为它们使用串口输出信息,所以或显著影响ISR的执行性能。

 

中断级异常

当一个任务产生了硬件异常,如非法指令或总线错误,那么该任务将被挂起。系统中的其他任务将继续执行,而不被中断。然而,当一个ISR导致了类似的异常,系统中将没有相应的安全保障用于处理这些异常。ISR不具备可以挂起的上下文环境。相反,VxWorks将这些异常描述信息保存在内存空间的一个特殊区域,并执行系统重启。

VxWorks的BootLoader将检测低内存空间中的异常描述信息是否存在,如果检测到,则会在系统控制台中显示出来。BootLoader的“e”命令用于重新显示异常描述信息。类似的异常信息如下:

workQPanic:Kernel work queued from ISR overflowd.

 

ISR与内核工作队列死机(work queueu panic)

为了减少工作队列溢出,可以使用WIND_JOBS_MAX内核配置参数增加内核工作队列大小。

与内核工作队列死机相关的错误信息如下:

workQPanic:kernel work queue overflow

5.修改系统时钟ISR

可以根据应用程序需要,在usrClock()函数中添加相关的函数。

在系统启动的初始化过程中,系统时钟ISR usrClock()函数被挂接到系统时钟定时器中断上。每个系统时钟中断都将调用usrClock(),用于更新系统tick值并执行调度。

在usrClock()函数中添加代码也要遵守在ISR中调用函数的要求。

6.运行时的ISR信息

针对每个与VxWorks连接的ISR,系统都创建了一个内核对象。ISR对象提供了一种管理系统中所有ISR信息的方法。

可以参考isrLib和isrShow API参考手册,了解用于获取ISR信息的相关函数。

INCLUDE_ISR_SHOW组件提供了isrShow(),INCLUDE_ISR_OBJECT提供了isrLib。

7.ISR与工作队列死机

如果ISR以非常高的频率填充内核工作队列,导致内核处理不过来,那么会将工作队列填满,使得无法再将新的工作项添加到工作队列中。这将导致称为工作队列死机(work queue panic)的致命错误。

为了降低中断响应时间,VxWorks内核在执行关键区代码时不会锁中断,如任务状态改变、上下文切换、重新调度等等。使能中断后,ISR将以尽可能快的速度执行。如果在内核执行关键区代码的过程中产生了一个中断,而ISR同样调用了需要执行关键代码的内核函数,那么内核将延迟关键区代码的执行,知道具备安全执行的条件为止。这个过程是通过内核工作队列实现的。工作队列可以高效地将内核关键区排入队列,并且不会阻塞ISR中非关键区的代码执行。

考虑到性能因素,工作队列被设计为一个具有固定大小的环形缓冲区。可以通过WIND_JOBS_MAX配置参数配置其大小,该大小必须是2的幂次。

 

工作队列死机(work queue panic)

通常,工作队列死机是由于设备驱动不恰当的写操作导致的。例如:

  • 确认中断失败。如果一个ISR未能确认一个中断,那么将导致一直产生相同的中断。
  • 在中断上下文执行了太多的操作。为了最佳的实时性能,可以将ISR中的复杂操作转移到与中断源相关的合适优先级的任务中执行。ISR应该使用一个内核调用唤醒该任务(例如semGive()).
  • 将设备突发事件作为独立中断处理。应该在关闭设备相关的中断之后在任务上下文中处理突发事件。当没有再检测到未处理的事件且任务将会挂起时,就可以再次使能中断源了。

这篇关于《VxWorks7编程指南》笔记(四)——中断服务程序ISR的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Spring Boot结成MyBatis-Plus最全配置指南

《SpringBoot结成MyBatis-Plus最全配置指南》本文主要介绍了SpringBoot结成MyBatis-Plus最全配置指南,包括依赖引入、配置数据源、Mapper扫描、基本CRUD操... 目录前言详细操作一.创建项目并引入相关依赖二.配置数据源信息三.编写相关代码查zsRArly询数据库数

SpringBoot启动报错的11个高频问题排查与解决终极指南

《SpringBoot启动报错的11个高频问题排查与解决终极指南》这篇文章主要为大家详细介绍了SpringBoot启动报错的11个高频问题的排查与解决,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一... 目录1. 依赖冲突:NoSuchMethodError 的终极解法2. Bean注入失败:No qu

JavaScript错误处理避坑指南

《JavaScript错误处理避坑指南》JavaScript错误处理是编程过程中不可避免的部分,它涉及到识别、捕获和响应代码运行时可能出现的问题,本文将详细给大家介绍一下JavaScript错误处理的... 目录一、错误类型:三大“杀手”与应对策略1. 语法错误(SyntaxError)2. 运行时错误(R

Python使用date模块进行日期处理的终极指南

《Python使用date模块进行日期处理的终极指南》在处理与时间相关的数据时,Python的date模块是开发者最趁手的工具之一,本文将用通俗的语言,结合真实案例,带您掌握date模块的六大核心功能... 目录引言一、date模块的核心功能1.1 日期表示1.2 日期计算1.3 日期比较二、六大常用方法详

MySQL中慢SQL优化方法的完整指南

《MySQL中慢SQL优化方法的完整指南》当数据库响应时间超过500ms时,系统将面临三大灾难链式反应,所以本文将为大家介绍一下MySQL中慢SQL优化的常用方法,有需要的小伙伴可以了解下... 目录一、慢SQL的致命影响二、精准定位问题SQL1. 启用慢查询日志2. 诊断黄金三件套三、六大核心优化方案方案

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解

SpringBoot整合MybatisPlus的基本应用指南

《SpringBoot整合MybatisPlus的基本应用指南》MyBatis-Plus,简称MP,是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,下面小编就来和大家介绍一下... 目录一、MyBATisPlus简介二、SpringBoot整合MybatisPlus1、创建数据库和