Nucleus 实时操作系统中断(上)
Nucleus 实时操作系统中断(上)
Interrupts in the Nucleus SE RTOS
所有现代微处理器和微控制器都有某种中断设施。这种能力对于提供许多应用程序所需的响应能力是必不可少的。当然,响应性和可预测性也是使用实时操作系统背后的一个关键目标,因此这两个主题确实存在轻微的冲突。使用中断可能会损害操作系统的实时完整性。这一主题,以及冲突的解决方法,目前不讲。在这里,我们将了解Nucleus SE使用的中断处理策略。
在所有情况下,中断都不是由Nucleus SE控制的,它们是在中断发生时根据优先级进行处理的,并以通常的方式进行矢量化。它们的执行时间只是从运行主线应用程序代码和调度程序的可用时间中“偷走”的。显然,这意味着所有的中断服务程序都应该简单、简短和快速。
本机中断和托管中断
Nucleus SE确实提供了两种处理中断的方法:“本机”中断服务例程没有什么特别的,并且与操作系统交互的机会有限(至少在选择优先级调度器时是这样);“托管”中断服务例程可以进行更广泛的API调用。
通过一些进入/退出宏,与Nucleus SE应用程序一起使用的中断服务例程可以被指定为本机或托管的。
本机中断
Nucleus SE本机中断是标准的中断服务例程,您可以将其视为“非托管的”。当am中断可能以很高的频率发生并且需要以非常低的开销进行服务时,通常使用它们。由于许多现代嵌入式编译器都支持通过interrupt关键字编写中断服务例程,所以这个例程很可能是用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中定义。此宏构造包含以下序列的函数:
- task context save
- set NUSE_Task_State to NUSE_MISR_CONTEXT
- call user-supplied ISR code function
- restore NUSE_Task_State to previous setting
- task context restore
宏接受两个参数:中断的名称,用作构造的例程的函数名;包含用户提供的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()
但是,唯一真正有用的是NUSE_Signals_Send(),因为这提供了一个很好的方法来指示任务需要一些工作。
如果禁用了阻塞(这意味着许多API调用可能无法使任务就绪),则可以使用许多其他API函数:
NUSE_Task_Suspend()
NUSE_Task_Resume()
NUSE_Task_Sleep()
NUSE_Task_Relinquish()
NUSE_Task_Reset()
NUSE_Signals_Receive()
来自托管ISR或具有非优先级调度程序的本机ISR的API调用
当使用run-to-completion、round-robin或time-sliced调度器时,可以从ISR调用范围更广的API函数。如果使用类似的ISR优先级,则受管调度器有助于提高ISR的优先级。这是因为允许调用可能导致调度不同的任务。NUSE_Reschedule()中的代码有助于此功能,该代码检测调用的上下文是ISR,并禁止上下文切换(允许它在ISR结束时发生)。调度程序操作的完整细节在前面的一篇文章中介绍过。
一个关键的要求是ISR中的API调用不能导致当前任务的挂起,例如等待一个资源。换句话说,这种调用应该在suspend选项设置为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 timer;
for (timer=0; timer
<nuse_timer_number; timer++)="">
{
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
/* reschedule? */
if
(NUSE_Timer_Reschedule_Time[timer] != 0)
{
/* yes: set up time */
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 task;
for (task=0; task
<nuse_task_number; task++)=""> {
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将通过递减其计数器值来循环为每个计时器提供服务。如果计时器过期(即计数器达到零),则两个操作将生效:
如果配置了计时器过期例程,并且计时器具有指向函数的有效(非空)指针(在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 实时操作系统中断(上)的更多相关文章
- Nucleus 实时操作系统中断(下)
Nucleus 实时操作系统中断(下) Nucleus RTOS兼容性 由于中断在Nucleus SE中的实现方式与Nucleus rto截然不同,因此不应期望有特定的兼容性.Nucleus RTOS ...
- dsp5509的中断系统
1. DSP5509有32个中断,中断分为软件中断和硬件中断,同时软件中断不可以屏蔽.软件中断由指令触发.55x在中断时DSP会自动保存ST0_55.ST1_55.ST2_55三个寄存器. 2. 其中 ...
- Nucleus PLUS的启动、执行线程和中断处理
nucleus系统是实时嵌入式操作系统,具有实时.任务抢先.多任务内核,当中95%的代码由C语言写成,极易移植.开放的源代码使得配置和裁剪方便,再加上体积小(所有二进制映像可仅20K).响应高速等特性 ...
- Nucleus PLUS简单介绍
近些年来,随着嵌入式系统飞速的发展,嵌入式实时操作系统广泛地应用在制造工业.过程控制.通讯.仪器仪表.汽车.船舶.航空航天.军事.装备.消费类产 品等方面.今天嵌入式系统带来的工业年产值超过了1万亿美 ...
- S3C2440上RTC时钟驱动开发实例讲解(转载)
嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤.一为总结经验,二希望能给想入门嵌入式Linux的朋友提供方便.如有错误之处,谢请指正. 共享资源,欢迎转载:http:/ ...
- Hadoop生态上几个技术的关系与区别:hive、pig、hbase 关系与区别
初接触Hadoop技术的朋友肯定会对它体系下寄生的个个开源项目糊涂了,我敢保证Hive,Pig,HBase这些开源技术会把你搞的有些糊涂,不要紧糊涂的不止你一个,如某个菜鸟的帖子的疑问,when to ...
- 【翻译】运行于x86机器上的FreeBSD的PCI中断
来源 http://people.freebsd.org/~jhb/papers/bsdcan/2007/article/article.html 摘要 在拥有多个独立设备的计算机里一个重要的元素是一 ...
- 系统中断与SA_RESTART
今天在调试程序时,sem_timedwait居然返回了一个Interrupted system call,错误码为EINTR.系统中断这东西我一向只闻其名,不见其"人",不想今天遇 ...
- MCS-51系统中断优先级的软扩展
摘要:鉴于MCS-51系统只提供“二级中断嵌套”,提出扩展51系统中断优先级的纯软件方法.其利用51系统内建的中断允许寄存器IE和中断优先级寄存器IP,通过屏蔽字机制来实现:以C51的形式,给出这种扩 ...
随机推荐
- 病毒木马查杀实战第013篇:一个基于.NET的“敲竹杠”病毒研究
前言 恶意程序发展至今,其功能已经从最初的单纯破坏,不断发展为隐私的窥探,信息的盗取,乃至如今非常流行的"敲竹杠"病毒,用于勒索.可见随着时代的发展,病毒的作者们往往也是想利用自己 ...
- hdu5025 状态压缩广搜
题意: 悟空要救唐僧,中途有最多就把钥匙,和最多五条蛇,要求就得唐僧并且拿到所有种类的钥匙(两个1只拿一个就行),拿钥匙i之前必须拿到钥匙i-1,打蛇多花费一秒,问救出唐僧并且拿到所有种类 ...
- CVE-2017-11826:Office Open XML 标签嵌套解析混淆漏洞
\x01 前言 CVE-2017-11826 据说是 360 在 2017 年 9 月底发现的一个关于 XML 格式解析的一个漏洞,之后微软在 10 月份发布了关于 CVE-2017-11826 的补 ...
- 全套office版本安装教程及下载地址
1:office 2003 安装教程及下载地址 https://mp.weixin.qq.com/s/HHGFdiLgL-xhDAAlox2axw 2:office 2007 安装教程及下载地址 ht ...
- C# 通过DataSet 获取SQL 存储过程返回的多个结果集(tables)
测试数据:Northwind 链接地址: https://files.cnblogs.com/files/louiszh/NorthWind.zip 首先创建一个测试存储过程: IF EXISTS ( ...
- Windows反调试技术(下)
OD的DBGHELP模块 检测DBGHELP模块,此模块是用来加载调试符号的,所以一般加载此模块的进程的进程就是调试器.绕过方法也很简单,将DBGHELP.DLL改名. #include <Wi ...
- 逆向工程初步160个crackme-------6
工具:1. 按钮事件地址转换器E2A 2. PEID 3. Ollydbg 同样我们先来运行一下这个程序, ok按钮是被禁用的,有一个help按钮点击后弹出一个消息框:消息框显示提示信息为.本程序需要 ...
- ZOHO的下一个25年:用心为企业服务
来源:中国软件网 作者:海策 在25周年会上,ZOHO大中华区总裁侯康宁先生豪情壮志,"25岁的ZOHO,已经成长为非典型一线大厂." 1996年,ZOHO成立.截止2021年,Z ...
- [面向对象之继承应用(在子类派生重用父类功能(super),继承实现原理(继承顺序、菱形问题、继承原理、Mixins机制),组合]
[面向对象之继承应用(在子类派生重用父类功能(super),继承实现原理(继承顺序.菱形问题.继承原理.Mixins机制),组合] 继承应用 类与类之间的继承指的是什么'是'什么的关系(比如人类,猪类 ...
- 在微信框架模块中,基于Vue&Element前端的事件和内容的管理
在微信后台管理中,我们需要定义好菜单对应的事件管理,因为微信通过菜单触发相关的事件,因此菜单事件的响应关系,我们如果处理好,就能构建出我们的微信应用入口了.通过入口,我们可以响应用户菜单的事件,如响应 ...