所有现代微处理器和微控制器都有某种类型的中断设施。此功能对于提供许多应用程序所需的响应能力至关重要。当然,响应性和可预测性也是使用实时操作系统背后的一个关键目标,因此这两个主题可能会略有冲突。使用中断可能会损害操作系统的实时完整性。这个主题,以及这个冲突的解决方法,在之前的一篇文章中有介绍。在这里,我们将了解 Nucleus SE 采用的中断处理策略。

在所有情况下,中断都不受 Nucleus SE 控制——它们在发生时根据优先级和向量以通常的方式进行处理。它们的执行时间只是从可用于运行主线应用程序代码和调度程序的时间中“偷走”。显然,这意味着所有中断服务程序都应该简单、简短和快速。

本机和托管中断

Nucleus SE 确实提供了两种处理中断的方法:“本机”中断服务例程没什么特别的,与操作系统交互的机会有限(至少在选择优先级调度程序时它们会这样做);“托管”中断服务例程可以进行更广泛的 API 调用。

通过一些进入/退出宏,与 Nucleus SE 应用程序一起使用的中断服务例程可以被指定为本地或托管。

本机中断

Nucleus SE 原生中断是标准的中断服务例程——您可以将它们视为“非托管”。当 am 中断可能以高频率发生并且需要以非常低的开销进行服务时,通常会使用它们。该例程最有可能用 C 编码,因为许多现代嵌入式编译器支持通过中断 关键字编写中断服务例程。唯一保存的上下文信息是编译器认为必要的。这会导致本地中断例程可以执行的操作受到很大限制,我们很快就会看到。

要构建 Nucleus SE 原生中断服务例程,只需按照通常的方式编写 ISR,包括 开头调用宏NUSE_NISR_Enter()和 结尾调用NUSE_NISR_Exit()。这些宏在nuse_types.h中定义, 只需将全局变量NUSE_Task_State设置 为NUSE_NISR_CONTEXT。

托管中断

如果您在 ISR 可以执行的操作方面需要更大的灵活性,Nucleus SE 托管中断可能是解决方案。与本机中断的主要区别在于上下文保存。托管中断不仅仅允许编译器堆叠几个寄存器,而是在进入时保存完整的任务上下文(在其上下文块中)。然后从最后的上下文块加载当前任务的上下文。这容纳了当前任务可能被 ISR 代码的操作改变的可能性;当使用优先级调度程序时,这是完全可能的。Nucleus SE 上下文保存和恢复的完整描述包含在较早的文章中。

显然,完整的上下文保存比本地中断执行的几个寄存器的堆叠表示更高的开销。这是额外灵活性的代价,也是处理中断的方法有多种选择的原因。

托管中断是使用宏NUSE_MANAGED_ISR()构造的,该宏在nuse_types.h 中定义。这个宏构造了一个包含以下序列的函数:

任务上下文保存

将NUSE_Task_State设置 为NUSE_MISR_CONTEXT

调用用户提供的 ISR 代码函数

将NUSE_Task_State恢复 到之前的设置

任务上下文还原

该宏采用两个参数:中断名称,用作构造例程的函数名称;包含用户提供的 ISR 逻辑的函数的名称。

Nucleus SE 实时时钟 ISR(本文稍后将介绍)用作托管 ISR 的示例。

来自中断服务例程的 API 调用

可以从本机或托管 ISR 调用的 API 函数的范围取决于已选择的调度程序。从广义上讲,优先级调度程序的使用为作为 API 函数调用的结果调用调度程序提供了许多机会,这在本机 ISR 中将是一个问题。

来自具有优先级调度程序的本机 ISR 的 API 调用

具有优先级调度程序的本地 ISR 允许有限范围的 API 函数调用。这种限制是 Nucleus SE API 灵活性的结果——许多调用可能导致任务准备就绪,并且本机 ISR 无法调用调度程序(因为任务上下文未保存)。如果不启用任务阻塞,则具有更大的灵活性。

始终允许以下 API 调用:
NUSE_Task_Current()
NUSE_Task_Check_Stack()
NUSE_Task_Information()
NUSE_Task_Count()
NUSE_Partition_Pool_Information()
NUSE_Partition_Pool_Count()
NUSE_Mailbox_Information()
NUSE_Mailbox_Count()
NUSE_Queue_Information()
NUSE_Queue_Count()
NUSE_Pipe_Information()
NUSE_Pipe_Count()
NUSE_Semaphore_Information()
NUSE_Semaphore_Count()
NUSE_Event_Group_Information()
NUSE_Event_Group_Count()
NUSE_Signals_Send( )
NUSE_Timer_Control()
NUSE_Timer_Get_Remaining()
NUSE_Timer_Reset()
NUSE_Timer_Information()
NUSE_Timer_Count()
NUSE_Clock_Set()
NUSE_Clock_Retrieve()
NUSE_Release_Information()
然而,唯一真正有用的是NUSE_Signals_Send(),因为它提供了一种向任务表明需要一些工作的好方法。

如果禁用阻塞,这意味着许多 API 调用可能无法使任务准备就绪,则可以使用许多附加 API 函数:
NUSE_Partition_Allocate()
NUSE_Partition_Deallocate()
NUSE_Mailbox_Send()
NUSE_Mailbox_Receive()
NUSE_Mailbox_Reset()
NUSE_Queue_Send()
NUSE_Queue_Receive()
NUSE_Queue_Jam()
NUSE_Queue_Reset()
NUSE_Pipe_Send()
NUSE_Pipe_Receive()
NUSE_Pipe_Jam()
NUSE_Pipe_Reset()
NUSE_Semaphore_Obtain()
NUSE_Semaphore_Release()
NUSE_Semaphore_Reset()
NUSE_Event_Group_Set( )
NUSE_Event_Group_Retrieve()
本机 ISR 永远不允许某些 API 调用,因为它们不可避免地需要调度程序进行操作:
NUSE_Task_Suspend()
NUSE_Task_Resume()
NUSE_Task_Sleep()
NUSE_Task_Relinquish()
NUSE_Task_Reset()
NUSE_Signals_Receive()
来自具有非优先级调度程序的托管 ISR 或本机 ISR 的 API 调用

当使用运行到完成、循环或时间片调度程序时,可以从 ISR 调用范围更广的 API 函数。如果使用优先级调度程序,受管 ISR 可促进类似的广泛范围。这是因为允许可能导致调度不同任务的调用。此功能由NUSE_Reschedule() 中的代码促进,该代码检测调用的上下文是 ISR 并抑制上下文切换(允许它在 ISR 结束时发生)。调度程序操作的全部细节在之前的一篇文章中都有介绍。

一个关键要求是 ISR 内的 API 调用不得导致当前任务的暂停——例如,等待资源。换句话说,此类调用应在挂起选项设置为NUSE_NO_SUSPEND 的情况下进行。

鉴于此限制条件,可以使用以下 API 调用:
NUSE_Task_Current()
NUSE_Task_Check_Stack()
NUSE_Task_Information()
NUSE_Task_Count()
NUSE_Task_Suspend()
NUSE_Task_Resume()
NUSE_Task_Reset()
NUSE_Partition_Allocate()
NUSE_Partition_Deallocate()
NUSE_Partition_Pool_Information()
NUSE_Partition_Pool_Count()
NUSE_Mailbox_Send()
NUSE_Mailbox_Receive()
NUSE_Mailbox_Reset()
NUSE_Mailbox_Information()
NUSE_Mailbox_Count()
NUSE_Queue_Send( )
NUSE_Queue_Receive()
NUSE_Queue_Jam()
NUSE_Queue_Reset()
NUSE_Queue_Information()
NUSE_Queue_Count()
NUSE_Pipe_Send()
NUSE_Pipe_Receive()
NUSE_Pipe_Jam()
NUSE_Pipe_Reset()
NUSE_Pipe_Information()
NUSE_Pipe_Count()
NUSE_Semaphore_Obtain()
NUSE_Semaphore_Release()
NUSE_Semaphore_Reset()
NUSE_Semaphore_Information()
NUSE_Semaphore_Count()
NUSE_Event_Group_Set()
NUSE_Event_Group_Retrieve()
NUSE_Event_Group_Information()
NUSE_Event_Group_Count()
NUSE_Signals_Send()
NUSE_Timer_Control()
NUSE_Timer_Get_Remaining()
NUSE_Timer_Reset()
NUSE_Timer_Information( )
NUSE_Timer_Count()
NUSE_Clock_Set()
NUSE_Clock_Retrieve()
NUSE_Release_Information()
一些 API 调用是不允许的,因为它们特别适用于当前任务:
NUSE_Task_Relinquish()
NUSE_Signals_Receive()
NUSE_Task_Sleep()
实时时钟 ISR

实时时钟 (RTC) ISR 是 Nucleus SE 提供的唯一完整的中断服务例程。除了为 Nucleus SE 提供所有必需的计时功能外,它还可以作为如何编码托管中断的示例。

RTC ISR 操作

RTC ISR 提供​​的工具在之前的文章中进行了概述,其中涵盖了 Nucleus SE 中系统时间的广泛主题。所有功能都是可选的,具体取决于应用程序的配置方式。这是 RTC ISR 的完整代码。
#if NUSE_TIMER_NUMBER != 0
{
U8 定时器;
对于(定时器=0;定时器 {
if (NUSE_Timer_Status[timer])
{
if (–NUSE_Timer_Value[timer] == 0)
{
NUSE_Timer_Expirations_Counter[timer]++;
#if NUSE_TIMER_EXPIRATION_ROUTINE_SUPPORT ||
NUSE_INCLUDE_EVERYTHING
if (NUSE_Timer_Expiration_Routine_Address[timer]
!= NULL)
{
((PF1)NUSE_Timer_Expiration_Routine_Address[timer])
NUSE_Timer_Expiration_Routine_Parameter[timer]);
}
#endif
/* 重新安排?/
if (NUSE_Timer_Reschedule_Time[timer] != 0)
{ /
yes: 设置时间 /
NUSE_Timer_Value[timer] =
NUSE_Timer_Reschedule_Time[timer];
}
else
{ /
no: disable */
NUSE_Timer_Status[timer] = FALSE;
}
}
}
}
}
#endif
#if NUSE_SYSTEM_TIME_SUPPORT || NUSE_INCLUDE_EVERYTHING
NUSE_Tick_Clock++;
#endif
#if NUSE_TASK_SLEEP || NUSE_INCLUDE_EVERYTHING
{
U8 任务;
对于(任务=0;任务 {
if (NUSE_Task_Timeout_Counter[task] != 0)
{
NUSE_Task_Timeout_Counter[task]–;
if (NUSE_Task_Timeout_Counter[task] == 0)
{
NUSE_Wake_Task(task);
}
}
}
}
#endif
#if NUSE_SCHEDULER_TYPE == NUSE_TIME_SLICE_SCHEDULER
if (–NUSE_Time_Slice_Ticks == 0)
{
NUSE_Reschedule();
}
#endif
我们将查看 RTC ISR 中四个功能领域中的每一个:

计时器

如果配置了任何应用程序计时器,ISR 将通过递减其计数器值来循环服务每个应用程序计时器。如果计时器到期(即计数器达到零),则会执行两个操作:

如果配置了计时器到期例程并且计时器具有指向函数的有效(非NULL)指针(在NUSE_Timer_Expiration_Routine_Address[] 中),则执行该例程,并从NUSE_Timer_Expiration_Routine_Parameter[]接收参数。

如果计时器具有重新安排时间(即NUSE_Timer_Reschedule_Time[] 中的非零值),则计时器将重新加载该值。

应用程序计时器在之前的文章中有更详细的描述。

系统时钟

如果配置了系统时钟,NUSE_Tick_Clock的值 只会增加。关于系统时间的进一步讨论可以在之前的文章中找到。

任务睡眠

如果启用了任务睡眠(即配置了 API 调用NUSE_Task_Sleep() ),则检查每个任务的超时计数器(NUSE_Task_Timeout_Counter[] 中的条目),如果非零,则递减。如果任何计数器达到零,则唤醒相应的任务。

时间片调度

如果正在使用时间片调度程序,则时间片计数器 ( NUSE_Time_Slice_Ticks ) 会递减。如果它达到零,则调用调度程序。对NUSE_Reschedule()的调用 负责重置计数器。

托管中断

RTC ISR 是托管中断的原因的一些解释可能很有用,因为在适当的情况下,用户可能希望将其重新编码为本地中断以减少开销。例如,如果只使用系统时间工具(即没有应用程序计时器、没有任务睡眠和时间片调度程序),本地中断就可以了。托管中断的需求如下:

如果使用计时器并配置了到期例程,这些例程可能会进行 API 调用(从中断上下文),这将导致重新调度。这些受到与从 ISR 进行的 API 调用相同的限制(参见本章前面部分)。

如果优先级调度器正在使用中,任务休眠期满可能需要调度更高优先级的任务。

如果使用时间片调度器,肯定会从 RTC ISR 中调用它,因此托管中断是强制性的。

Nucleus RTOS 兼容性

由于与 Nucleus RTOS 相比,Nucleus SE 中的中断以非常不同的方式实现,因此没有特别的兼容性。Nucleus RTOS 有原生/低级/高级中断方案,有点类似于 Nucleus SE 中的原生和托管中断。

低级和高级 ISR

低级 ISR

低级中断服务程序 (LISR) 作为普通 ISR 执行,包括使用当前堆栈。Nucleus RTOS 在调用 LISR 之前保存上下文,并在 LISR 返回后恢复上下文。因此,LISR 可以用 C 编写并且可以调用其他 C 例程。但是,只有少数 Nucleus RTOS 服务可供 LISR 使用。如果中断处理需要额外的 Nucleus RTOS 服务,则必须激活高级中断服务程序 (HISR)。Nucleus RTOS 支持嵌套多个 LISR。

高级情监侦

HISR 是动态创建和删除的。每个 HISR 都有自己的堆栈空间和自己的控制块。每个的内存由应用程序提供。当然,HISR 必须在被 LISR 激活之前创建。

由于 HISR 有自己的堆栈和控制块,如果它试图访问已经被访问的 Nucleus RTOS 数据结构,它可能会被暂时阻塞。

HISR 可使用三个优先级。如果在处理较低优先级的 HISR 期间激活较高优先级的 HISR,则优先级较低的 HISR 会以与任务被抢占大致相同的方式被抢占。具有相同优先级的 HISR 按照它们最初被激活的顺序执行。在恢复正常任务调度之前,所有激活的 HISR 都会被处理。

Nucleus RTOS 中断 API 调用

Nucleus RTOS 有许多 API 调用来支持其中断结构。这些都没有在 Nucleus SE 中实现。

对于本机中断,API 调用提供以下功能:

控制(启用/禁用)中断(本地和全局)

设置中断向量

对于低级中断:

向内核注册低级 ISR

对于高级中断:

创建/删除高级中断

激活高级中断

获取应用程序中的高级中断数(当前)

获取指向所有高级中断的控制块的指针

获取当前高级中断的控制块指针

获取有关高级中断的信息
相关实战:https://www.yunduoketang.com/article/xianshangzhibodajian1.html
https://www.yunduoketang.com/article/xianshangzhibodajian1.html
https://www.yunduoketang.com/article/wangluozhibojiaoxue1.html
https://www.yunduoketang.com/article/wangluozhibojiaoxue1.html
https://www.yunduoketang.com/article/wangluozhibojiaoxue1.html

Nucleus SE RTOS 中的中断相关推荐

  1. Nucleus SE RTOS初始化和启动

    Nucleus SE RTOS初始化和启动 Nucleus SE RTOS initialization and start-up 对于任何类型的操作系统,都有某种类型的启动机制.具体的工作方式因系统 ...

  2. 使用Nucleus SE实时操作系统

    使用Nucleus SE实时操作系统 Using the Nucleus SE real-time operating system 到目前为止,在本系列文章中,我们详细介绍了Nucleus SE提供 ...

  3. RTOS 中采样任务的设计

    引言 在现实生活中,大多数我们所接触到的信号都是一种模拟信号,电压.电流.声音信号等.我们在嵌入式开发过程中,有时候会涉及到模拟信号的采集,在采集过程中,为了更好地还原出信号原本的样子,有这个一个采样 ...

  4. 嵌入式中的中断服务程序

    嵌入式中的中断服务程序 中断是嵌入式系统中重要的组成部分,但是在标准 C 中不包含中断.许多编译开发商在标准 C 上增加了对中断的支持,提供新的关键字用于标示中断服务程序(ISR),类似于__inte ...

  5. Keyboard驱动中button中断的处理机制

    Keyboard驱动中button中断的处理机制 ********************************LoongEmbedded************************ 作者:Lo ...

  6. uboot中的中断macro宏

    目录 uboot中的中断macro宏 引入 内存分配 流程概览 普通中断 保存现场 中断函数打印具体寄存器 恢复现场 软中断 空间获取 保存现场 附录速记 疑惑待解 uboot中的中断macro宏 引 ...

  7. java中的jpa_JPA教程–在Java SE环境中设置JPA

    java中的jpa JPA代表Java Persistence API,它基本上是一个规范,描述了一种将数据持久存储到持久存储(通常是数据库)中的方法. 我们可以将其视为类似于Hibernate之类的 ...

  8. JPA教程–在Java SE环境中设置JPA

    JPA代表Java Persistence API,它基本上是一个规范,描述了一种将数据持久存储到持久存储(通常是数据库)中的方法. 我们可以将其视为类似于Hibernate的 ORM工具的东西,除了 ...

  9. Microsoft Windows CE .NET 中的中断体系结构

    概述 通过 Microsoft Windows CE .NET,Microsoft 已经升级了 Windows CE 的中断体系结构.该操作系统 (OS) 所具有的处理共享中断的能力极大地扩展了 Wi ...

  10. Linux中的中断管理机制

    1.中断相关基础知识介绍 1.1.中断产生背景 假设现在CPU需要去获取一个键盘的时间,如果处理器发出一个请求信号之后一直在轮询键盘的响应,由于键盘响应速度比处理器慢得多并且需要等待用户输入,这对于C ...

最新文章

  1. php layui table,layui table 相关问题汇总
  2. mysql 存储过程逻辑表达 and_MySQL - 存储过程 (二)- 逻辑判断语句
  3. 团队冲刺(二)个人工作总结9
  4. 【机器学习】太香啦!只需一行Python代码就可以自动完成模型训练!
  5. activity7 拖不动_Activiti7相关问题汇总
  6. [luoguP4705]玩游戏
  7. 推荐一个集录屏、截图、音频于一体的软件给大家
  8. python3.8 实现鼠标自动移动_“新生报到”!【移动机器人 HD-1500】负载1500kg,实现了重型货物运输的自动化...
  9. VB.NET工作笔记015---vb.net获取cpu使用率,内存使用率_未能找到具有指定类别名“Processor”、计数器名“% Processor Time”的性能计数
  10. 如何掌握眼神接触技巧?
  11. pandas读取xlsx文件,编码问题
  12. 浅谈TCP优化(转)
  13. redis内存分析工具rdbtools
  14. ENVI:影像的规则裁剪和不规则裁剪
  15. windows电脑版便签工具哪款好用?
  16. 普通人下场全球贸易,新一轮结构性机会浮出水面
  17. SAP SD跨公司销售案例教程后台配置
  18. 美团点评 2019校园招聘 后台开发方向
  19. snapper命令技巧
  20. 即时通信和实时通信的区别

热门文章

  1. 无参考图像质量评价——漏勺模型
  2. C语言小游戏,笑傲江湖之鸿蒙
  3. 大行bya412和java513_真实解密大行bya412和k3区别在哪里?哪款最好?老司机透漏评测...
  4. Leetcode520Detect Capital检测大写字母
  5. 一台服务器​最大并发 tcp 连接数多少?65535?
  6. 對Googgle adsense廣告作弊和Googeladsense點擊廣告的生存前景看法
  7. 单播、广播、组播的区别和特点
  8. IPv6技术精要--第5章 IPv6公网单播地址
  9. protect 继承_【private,public,protect三种继承方式的区别】
  10. Unity打包安卓出现报错 Exception: Unknown CPU architecture for libraryxxx.a