uC/OS-Il---多级中断机制

目录

  • 中断处理的一般流程
  • 多级中断机制的出现
  • 多级中断机制的实现
    • 必须在一个任务或中断中配对使用
      • 保存当前中断状态并关中断---OS_ENTER_CRITICAL()
        • 汇编语言函数---OS_CPU_SR_Save()
      • 恢复之前的中断状态以便开中断---OS_EXIT_CRITICAL()
        • 汇编语言函数---OS_CPU_SR_Restore()
    • 必须在中断服务程序中配对用
      • 进入中断服务程序---OSIntEnter()
      • 退出中断服务程序---OSIntExit()

中断处理的一般流程

一般的中断处理流程可以按照以下顺序进行:

  • 保存当前中断状态【OS_ENTER_CRITICAL()】:在进入中断服务程序(ISR)之前,需要保存当前的中断状态。这可以通过将中断状态寄存器的值保存到内存中,或者使用特定的指令将中断状态压入堆栈来实现。保存当前中断状态的目的是为了确保在ISR执行期间不会被其他中断打断。
  • 进入中断服务程序【OSIntEnter()】:保存完当前中断状态后,处理器会跳转到相应的中断服务程序中执行特定的处理逻辑。中断服务程序是由开发人员编写的,用于响应中断事件并执行相应的处理操作。
  • 进行中断处理:在中断服务程序中,会执行与中断相关的处理逻辑。这包括根据中断类型进行相应的处理,访问和操作中断相关的寄存器和数据结构,以及执行与中断相关的任务或操作。
  • 退出中断处理/退出中断服务程序【OSIntExit()】
  • 恢复中断状态【OS_EXIT_CRITICAL()】:在中断处理完成后,通常会恢复之前保存的中断状态,以允许其他中断继续响应。这可以通过将之前保存的中断状态从内存中恢复,或者使用特定的指令将中断状态从堆栈中弹出来实现。

这个流程确保了在中断处理期间,中断的响应是可控的,并且能够保护中断服务程序的临界区代码的执行。通过保存和恢复中断状态,可以确保不同中断之间的正确协调和处理,同时保持系统的可靠性和实时性。

多级中断机制的出现

多级中断机制的目的是为了实现以下功能:

  • 实时性:多级中断机制可以提供更高的实时性。在嵌入式系统中,可能会有多个中断源同时触发中断请求,如果只有一级中断,那么只能按照中断的优先级依次处理,无法及时响应高优先级的中断请求。而多级中断机制可以根据中断的优先级进行分级处理,优先处理高优先级的中断请求,从而提高系统的实时性。
  • 中断嵌套:多级中断机制可以支持中断的嵌套。当一个中断正在处理时,如果另一个中断请求到达,可以通过多级中断机制将当前正在处理的中断暂时挂起,处理新的中断请求,然后再返回继续处理之前的中断。这样可以有效地处理多个中断请求,提高系统的灵活性和响应能力。
    • uC/OS-II支持多级中断嵌套,即在一个中断处理程序中可以发生另一个中断。
    • 这是通过保存和恢复中断状态以及使用中断屏蔽寄存器来实现的。
  • 中断优先级控制:多级中断机制可以对中断进行优先级控制。通过设置不同的中断优先级,可以确保高优先级的中断能够及时得到处理,而低优先级的中断则可以在高优先级中断处理完毕后再进行处理。这样可以根据系统需求对中断进行灵活的调度和控制。

多级中断机制的实现

必须在一个任务或中断中配对使用

OS_ENTER_CRITICAL();  // 禁用中断// 临界区代码,对共享资源进行操作OS_EXIT_CRITICAL();   // 恢复中断

保存当前中断状态并关中断—OS_ENTER_CRITICAL()

  • 在进入临界区之前,调用OS_ENTER_CRITICAL()函数会保存当前的中断状态,并禁用中断。这样可以确保在临界区内不会被其他中断打断。
  • 通过调用OS_ENTER_CRITICAL()宏函数,可以将当前的中断状态保存到cpu_sr变量中,以便在临界区执行完毕后恢复。
  • OS_ENTER_CRITICAL()函数通常在任务的临界区代码之前被调用,用于禁用中断以保护任务的临界区代码
#define  OS_CRITICAL_METHOD   3u#if OS_CRITICAL_METHOD == 3u
#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}
#define  OS_EXIT_CRITICAL()   {OS_CPU_SR_Restore(cpu_sr);}
#endif
汇编语言函数—OS_CPU_SR_Save()
OS_CPU_SR_SaveMRS     R0, PRIMASK                ; Set prio int mask to mask all (except faults)CPSID   IBX      LR
  • MRS R0, PRIMASK:将当前的优先级屏蔽寄存器(PRIMASK)的值加载到寄存器R0中。PRIMASK寄存器用于控制全局中断的使能和禁止。
  • CPSID I:禁止所有中断。通过将中断控制状态寄存器(CPSR)的中断使能位(I)置为1,禁止所有中断的触发。
  • BX LR:返回到调用该函数的地址。使用BX LR指令将程序控制权返回给调用者。
  • 注释【Set prio int mask to mask all (except faults)】:这句话的意思是将优先级中断屏蔽寄存器设置为屏蔽所有中断(除了故障中断)
    • 在某些处理器架构中,有一个优先级中断屏蔽寄存器(Priority Interrupt Mask
      Register),用于控制中断的优先级和屏蔽。通过设置该寄存器的值,可以选择性地屏蔽或允许特定优先级的中断。
      这句话中提到的操作是将优先级中断屏蔽寄存器设置为屏蔽所有中断,除了故障中断。这意味着除了故障中断(如硬件故障或异常)之外,其他所有中断都会被屏蔽,不会被处理器响应。
      这种设置通常用于特殊情况下,例如在处理器初始化或特定任务执行期间,需要暂时屏蔽所有中断,以确保关键代码的执行或处理器的稳定性。只有故障中断才能继续被处理器响应,以确保系统的可靠性和安全性。

这段代码的作用是将当前的中断状态保存到寄存器R0中,并禁止所有中断。通过保存中断状态,可以在后续需要时恢复中断状态,以确保临界区的原子性和可靠性。

恢复之前的中断状态以便开中断—OS_EXIT_CRITICAL()

  • 在退出临界区时,调用OS_EXIT_CRITICAL()函数会恢复之前保存的中断状态,允许其他中断继续执行。
  • 通过调用OS_EXIT_CRITICAL()宏函数,可以将之前保存的中断状态从cpu_sr变量中恢复,使得中断状态回到进入临界区之前的状态。这样可以确保在临界区执行期间不会发生中断,保证临界区的原子性和可靠性。
#define  OS_CRITICAL_METHOD   3u#if OS_CRITICAL_METHOD == 3u
#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}
#define  OS_EXIT_CRITICAL()   {OS_CPU_SR_Restore(cpu_sr);}
#endif
汇编语言函数—OS_CPU_SR_Restore()
OS_CPU_SR_RestoreMSR     PRIMASK, R0BX      LR
  • MSR PRIMASK, R0:将寄存器R0的值写入PRIMASK寄存器,这个值用于恢复中断状态。
  • BX LR:将程序控制权返回到调用该函数的地址,即返回到LR寄存器中保存的地址。

这段代码的作用是将之前保存的中断状态寄存器的值恢复,以便恢复之前的中断状态。

必须在中断服务程序中配对用

进入中断服务程序—OSIntEnter()

  • 进入中断服务程序(ISR)应该在中断已经被禁用的情况下调用
  • OSIntEnter()函数是在ISR中使用,用于禁用中断以保护ISR的临界区代码
  • 你的ISR可以直接增加OSIntNesting而不调用这个函数,因为OSIntNesting已经被声明为全局变量。即使直接增加了OSIntNesting,仍然必须调用OSIntExit()。
  • 必须成对地调用OSIntEnter()和OSIntExit()。换句话说,对于ISR开始时的每次调用OSIntEnter(),必须在ISR结束时调用一次OSIntExit()。
  • 可以嵌套中断,最多可以达到255层。
  • 代码在增加操作周围删除了OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL(),因为OSIntEnter()总是在中断被禁用的情况下调用。
void  OSIntEnter (void)
{if (OSRunning == OS_TRUE){if (OSIntNesting < 255u){OSIntNesting++;                      /*增加中断服务程序(ISR)的嵌套级别*/}}
}

退出中断服务程序—OSIntExit()

  • 这个函数用于通知uC/OS-II,你已经完成了对ISR(中断服务程序)的维护。当最后一个嵌套的ISR完成后,uC/OS-II会调用调度器来确定是否有新的高优先级任务准备运行。
  • 当调度器被锁定时(请参阅OS_SchedLock()),防止重新调度。
void  OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */OS_CPU_SR  cpu_sr = 0u;
#endifif (OSRunning == OS_TRUE){OS_ENTER_CRITICAL();if (OSIntNesting > 0u)                           /*防止OSIntNesting变量的值溢出或循环*/{OSIntNesting--;}if (OSIntNesting == 0u)                          /*只有当所有的中断服务程序(ISR)都完成时,才重新调度…*/{if (OSLockNesting == 0u)                     /*…并且未被锁定*/{OS_SchedNew();OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];if (OSPrioHighRdy != OSPrioCur)          /*如果当前任务是最高优先级的就绪任务,则不进行上下文切换*/{
#if OS_TASK_PROFILE_EN > 0uOSTCBHighRdy->OSTCBCtxSwCtr++;         /*"增加到此任务的上下文切换次数*/
#endifOSCtxSwCtr++;                          /*跟踪上下文切换的次数*/OSIntCtxSw();                          /*执行中断级别的上下文切换*/}}}OS_EXIT_CRITICAL();}
}

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

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

相关文章

【短文】【踩坑】可以在Qt Designer给QTableWidge添加右键菜单吗?

2023年11月18日&#xff0c;周六上午 今天早上在网上找了好久都没找到教怎么在Qt Designer给QTableWidge添加右键菜单的文章 答案是&#xff1a;不可以 在Qt Designer中无法直接为QTableWidget添加右键菜单。 Qt Designer主要用于创建界面布局和设计&#xff0c;无法直接添加…

基于STC12C5A60S2系列1T 8051单片机的SPI总线器件数模芯片TLC5615实现数模转换应用

基于STC12C5A60S2系列1T 8051单片的SPI总线器件数模芯片TLC5615实现数模转换应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍SPI总线器件数模芯片TLC5615介绍通过按…

数据结构与算法编程题5

从有序表中删除重复元素&#xff0c;使表中所有元素值均不相同。 #include <iostream> using namespace std;typedef int ElemType; #define Maxsize 100 #define OK 1 #define ERROR 0 typedef struct SqList {ElemType data[Maxsize];int length; }SqList;void Init_…

单链表相关面试题--2.反转一个单链表

/* 解题思路&#xff1a; 此题一般常用的方法有两种&#xff0c;三指针翻转法和头插法 1. 三指针翻转法记录连续的三个节点&#xff0c;原地修改节点指向 2. 头插法每一个节点都进行头插 */ // 三个指针翻转的思想完成逆置 struct ListNode* reverseList(struct ListNode* head…

python-opencv 培训课程笔记(1)

python-opencv 培训课程笔记&#xff08;1&#xff09; 博主参加了一次opencv库的培训课程&#xff0c;把课程所学整理成笔记&#xff0c;供大家学习&#xff0c;第一次课程包括如下内容&#xff1a; 1.读取图像 2.保存图像 3.使用opencv库显示图像 4.读取图像为灰度图像 …

PlayCover“模拟器”作弊解决方案

当下的游戏市场&#xff0c;移动游戏已占据了主导地位&#xff0c;但移动端游戏碍于屏幕大小影响操作、性能限制导致卡顿等因素&#xff0c;开始逐步支持多端互通。但仍有一些游戏存在移动端与 PC 端不互通、不支持 PC 端或没有 Mac 版本&#xff0c;导致 Mac 设备体验游戏不方…

docker部署lnmp环境

文章目录 前期准备&#xff1a;一、部署mysql1.1 获取 Mysql 5.7.22 镜像1.2 启动mysql容器 二、部署php2.1 获取php 7.2镜像2.2 启动php 容器2.3 php的扩展安装 三、部署nginx3.1 获取nginx:1.14镜像3.2 启动nginx容器3.3 编写nginx虚拟主机配置文件&#xff0c;使其支持php3.…

【以图会意】操作系统的加载流程

声明&#xff1a;本图为博主方便自己记忆理解&#xff0c;诸多疏漏望请博友理性观看&#xff01;如有错误不足恳请指正。 首先&#xff0c;操作系统是一段程序&#xff0c;他保存在ROM中&#xff0c;在开机时&#xff0c;CPU被激活&#xff0c;首先将IR置为BIOS&#xff08;Bas…

《洛谷深入浅出基础篇》 图的基本应用

什么是图&#xff1f; 我们在生活中学习中能看见很多图&#xff0c;地图&#xff0c;路线图&#xff0c;思维导图等等&#xff0c;它们都有一个特点&#xff0c; 你从中任找一个点&#xff0c;你可以找到&#xff0c;从这个点出发&#xff0c;能够到达什么地方&#xff0c;也…

【C++历练之路】list的重要接口||底层逻辑的三个封装以及模拟实现

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; &#x1f354;前言&#xff1a; 在C的世界中&#xff0c;有一种数据结构&#xff0c;它不仅像一个神奇的瑰宝匣&#xff0c;还像一位能够在数据的海洋中航行的智慧舵手。这就是C中的list&#xff0c;一个引人入胜的工具…

低代码平台全解析:衍生历程、优势呈现与未来趋势一览无余

在数字化时代&#xff0c;应用程序的开发与更新已成为企业保持竞争力的关键。传统的编码方式&#xff0c;虽然精细且功能强大&#xff0c;但耗时且要求开发者具备较高的技术水平。在这样的背景下&#xff0c;低代码开发平台的出现无疑为企业带来了福音。 低代码开发平台是一种创…

大数据-之LibrA数据库系统告警处理(ALM-12057 元数据未配置周期备份到第三方服务器的任务)

告警解释 系统安装完成后会检查元数据是否有周期备份到第三方服务器的任务&#xff0c;然后每1小时会检查一次。如果元数据未配置周期备份到第三方服务器的任务&#xff0c;将发送严重告警。 在用户创建元数据周期备份到第三方服务器的任务后&#xff0c;告警消除。 告警属性…

Redis ACL 规则说明

Redis ACL 规则说明 前情回顾ACL 定义规范启用和禁用用户允许和禁止调用命令允许或禁止访问某些 Key为用户配置有效密码 ACL 命令说明 前情回顾 上一篇文章 我们整体性的介绍了 Redis 的 ACL&#xff0c;我们来回顾下 ACL 的两种配置方式。 redis 使用 acl 有两种方式可以配置…

微服务 Spring Cloud 7,Nacos配置中心的Pull原理,附源码

目录 一、本地配置二、配置中心1、以Nacos为例&#xff1a;2、Pull模式3、也可以通过Nacos实现注册中心 三、配置中心提供了哪些功能四、如何操作配置中心1、配置注册2、配置反注册3、配置查看4、配置变更订阅 五、主流的微服务注册中心有哪些&#xff0c;如何选择&#xff1f;…

程序员的护城河-并发编程

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码&#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&…

为何公司强调流程员工总是觉得反感?

在企业管理中&#xff0c;流程设计对于提高效率和降低风险至关重要。然而&#xff0c;很多企业在流程设计时常犯一些常见的错误&#xff0c;导致基层员工对流程感到烦扰&#xff0c;甚至产生抵触情绪。本文将通过分析一个企业的报销流程问题&#xff0c;探讨如何优化流程以提高…

开关电源测试方法分享:开关电源关机维持时间的测试步骤、测试标准

开关电源关机维持时间是指切断电源后输出电压下降到稳压范围外为止的时间。关机维持时间是开关电源测试项目之一&#xff0c;测试时需要用到交流电源、电子负载、示波器等测试设备。那么开关电源测试系统要如何测试关机维持时间呢? 开关电源关机维持时间的测试步骤 关机维持时…

[C/C++]数据结构 LeetCode:用栈实现队列

题目描述: 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x) 将元素 x 推到队列的末尾int pop() 从队列的开头移除并返回元素int peek() 返…

java基础练习缺少项目?看这篇文章就够了(上)!

公众号&#xff1a;全干开发 。 专注分享简洁但高质量的动图技术文章&#xff01; 项目概述 本教程适合刚学习完java基础语法的同学&#xff0c;涉及if语句、循环语句、类的封装、集合等基础概念&#xff0c;使用大量gif图帮助读者演示代码操作、效果等&#xff0c;是一个非常…

如何在 Linux 上部署 RabbitMQ

如何在 Linux 上部署 RabbitMQ 文章目录 如何在 Linux 上部署 RabbitMQ安装 Erlang从预构建的二进制包安装从源代码编译 Erlang RabbitMQ 的安装使用 RabbitMQ Assistant 连接 RabbitMQ Assistant 是一款优秀的RabbitMQ 可视化管理工具&#xff0c;提供丰富的管理功能。下载地址…