ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

HRTOS 为什么退出中断必须调用 os_interrupt_exit()?——8051 中断现场与嵌套机制详解

HRTOS 为什么退出中断必须调用 os_interrupt_exit()?——8051 中断现场与嵌套机制详解 在使用 HRTOS 的过程中有一个与普通 8051 中断程序不同的地方HRTOS 中断处理完成后不能简单地直接退出中断而需要调用os_interrupt_exit()。很多刚接触 HRTOS 的开发者可能会产生疑问为什么不能像普通 8051 中断一样直接RETI原因在于HRTOS 的中断机制并不是简单地执行一个中断函数。HRTOS 对 8051 的中断入口、中断堆栈、任务切换、中断嵌套以及内核调度进行了统一管理。因此os_interrupt_exit()实际上承担的是中断退出阶段的系统级处理工作。一、HRTOS 的中断入口不是普通函数调用传统 C 程序中如果需要执行一个函数通常采用function();本质上属于函数调用过程需要按照编译器的调用规则保存返回地址等信息。而 HRTOS 的中断入口采用的是跳转进入而不是普通函数调用。这样设计的一个重要原因是为了进一步压缩 8051 上非常有限的 DATA 资源。在 HRTOS 的设计中通过跳转进入中断处理路径可以节约约2 字节 DATA的资源。对于 8051 这种 RAM 极其有限的架构来说2 字节并不是一个可以忽略的数字。因此HRTOS 并没有简单地把中断处理设计成一个普通 C 函数调用而是从底层入口开始进行专门优化。二、为什么 HRTOS 要自己管理中断退出普通 8051 中断通常可以理解为发生中断 ↓ 进入中断服务程序 ↓ 执行中断代码 ↓ RETI ↓ 返回原来的执行环境而 HRTOS 的中断过程更加复杂发生中断 ↓ 进入 HRTOS 中断处理 ↓ 执行中断任务 ↓ 可能调用 HRTOS API ↓ 可能触发更高优先级中断 ↓ 可能进入中断嵌套 ↓ 中断退出 ↓ HRTOS 判断后续运行状态 ↓ 恢复对应运行环境因此中断结束时不能简单理解为“中断函数执行完了直接 RETI 就可以了。”HRTOS 必须先处理自己的运行现场和调度状态。这就是os_interrupt_exit()存在的核心原因。三、HRTOS 为中断专门分配 8 字节堆栈空间为了支持上述机制HRTOS 为中断运行环境专门规划了8 字节堆栈空间。这 8 字节并不是简单地全部用于一次普通中断而是按照 HRTOS 的中断执行路径进行分层使用。整体布局可以理解为HRTOS 中断堆栈8 字节 ┌────────────────────────┐ │ 第 1 层进中断 │ 0 字节 ├────────────────────────┤ │ 第 2 层中断调用 API │ 2 字节 ├────────────────────────┤ │ 第 3 层高优先级中断 │ 2 字节 ├────────────────────────┤ │ 第 4 层嵌套任务 API │ 2 字节 ├────────────────────────┤ │ 第 5 层更高优先级中断 │ 2 字节 └────────────────────────┘ 总计8 字节这里需要特别注意进入中断本身不额外消耗这 8 字节中的堆栈空间。后续根据执行路径逐级使用剩余空间。四、为什么中断调用 API 后需要额外 2 字节HRTOS 的中断程序并不一定只是执行几条简单指令。在实际应用中中断可能需要调用 HRTOS API例如进行任务唤醒、消息处理或者其他内核相关操作。因此进入中断后如果继续调用 HRTOS API需要使用相应的堆栈空间。此时使用2 字节随后如果在这个运行环境下又发生更高优先级中断则继续使用2 字节这样形成逐层嵌套的现场结构。五、HRTOS 的中断嵌套最多支持两级HRTOS 并不是无限制地允许中断不断嵌套。为了保证 8051 这种资源受限平台上的确定性同时避免无限增加堆栈消耗HRTOS 对中断嵌套进行了明确限制HRTOS 只允许两个中断优先级。也就是说系统最多形成第一层 普通中断 ↓ 第二层 高优先级中断而不会继续无限向下嵌套。六、如果再次发生更高优先级中断怎么办这里是 HRTOS 中断机制比较重要的一个设计。假设当前已经处于中断 ↓ 中断嵌套任务此时如果又发生一个更高优先级的中断HRTOS 不会继续无限创建新的中断嵌套层级。原因是HRTOS 的中断嵌套深度已经达到设计上限。此时这个中断会由HRTOS 内核层面进行拦截。随后系统返回到中断嵌套任务继续执行。也就是说HRTOS 对中断嵌套深度进行了明确控制而不是将最终的堆栈安全完全交给应用程序。七、整个中断过程可以这样理解一个完整的执行过程可以表示为普通任务 │ │ 外部中断触发 ▼ 中断任务 │ │ 调用 HRTOS API ▼ 使用 2 字节现场空间 │ │ 高优先级中断触发 ▼ 中断嵌套任务 │ │ 调用 HRTOS API ▼ 再次使用 2 字节现场空间 │ │ 再次发生更高优先级中断 ▼ 达到 HRTOS 中断嵌套上限 │ ▼ 由 HRTOS 内核层面拦截 │ ▼ 返回中断嵌套任务继续执行这也是为什么 HRTOS 的中断退出过程不能简单地交给普通RETI。八、os_interrupt_exit() 到底做了什么os_interrupt_exit()可以理解为HRTOS 中断退出阶段的统一处理入口。它并不是简单替代RETI这个硬件指令。更重要的是在真正结束当前中断运行环境之前HRTOS 需要根据当前系统状态完成相应的内核处理。例如需要考虑当前处于哪一级中断环境是否存在中断嵌套中断过程中是否调用了 HRTOS API是否产生了任务调度需求当前应该恢复哪个运行环境是否应该返回原任务是否应该继续执行更高优先级的任务因此普通中断退出 ↓ 不能简单 RETI ↓ os_interrupt_exit() ↓ HRTOS 完成中断退出阶段处理 ↓ 恢复正确运行环境这就是os_interrupt_exit()必须存在的原因。九、为什么不能在中断函数最后直接 RETI如果应用程序绕过 HRTOS 的中断退出机制直接结束中断那么 HRTOS 就无法完整参与中断退出过程。例如中断 ↓ 调用 HRTOS API ↓ 系统状态发生变化 ↓ 直接 RETI此时中断虽然从硬件层面返回了但 HRTOS 需要维护的运行状态并不一定已经完成处理。尤其是在涉及中断嵌套 任务唤醒 调度请求 任务切换等机制时直接退出会破坏 HRTOS 对整个运行环境的统一管理。因此在 HRTOS 中中断退出属于内核运行流程的一部分而不是普通中断函数的最后一条语句。十、为什么这种设计特别适合 80518051 最大的问题之一就是资源有限。HRTOS 不能按照大型处理器的思路无限增加堆栈也不能通过大量 RAM 换取简单的软件设计。因此 HRTOS 在中断机制上采用了非常明确的资源规划8 字节 ↓ 固定中断堆栈资源 ↓ 分层使用 ↓ 限制中断嵌套深度 ↓ 保证运行边界确定这种设计虽然对内核提出了更高要求但可以使中断运行过程更加可控。对于硬实时系统而言明确的资源边界本身就是系统设计的一部分。十一、HRTOS 中断机制的核心特点综合来看HRTOS 的中断机制具有以下特点1. 中断入口采用跳转方式不是普通 C 函数调用。这样可以减少调用过程中的资源消耗并节约约 2 字节 DATA。2. 中断拥有独立的 8 字节堆栈规划通过固定资源控制中断运行环境。3. 支持中断嵌套允许更高优先级中断打断当前中断处理过程。4. 中断嵌套深度受到限制HRTOS 只允许两个中断优先级。5. 超过嵌套上限后由内核拦截不会继续无限消耗堆栈而是返回当前中断嵌套任务继续运行。6. 中断退出必须经过 HRTOS通过os_interrupt_exit()完成 HRTOS 所需的中断退出处理。十二、总结HRTOS 的中断机制并不是简单地在 8051 中断入口写一个 C 函数然后最后执行RETI。它实际上建立了一套完整的中断运行环境8051 硬件中断 ↓ HRTOS 中断入口 ↓ 中断任务 ↓ HRTOS API ↓ 高优先级中断 ↓ 中断嵌套任务 ↓ 达到嵌套上限 ↓ HRTOS 内核拦截 ↓ 返回当前嵌套任务 ↓ os_interrupt_exit() ↓ 恢复正确运行环境因此os_interrupt_exit()并不是一个普通的“中断退出函数”。它是 HRTOS 将8051 硬件中断、任务调度、中断嵌套以及内核运行状态连接起来的重要接口。对于使用 HRTOS 的应用程序而言中断函数应按照 HRTOS 的中断机制进行退出而不能按照普通 8051 中断程序的方式直接结束。在只有有限 RAM、有限寄存器组和有限硬件资源的 8051 平台上通过固定的堆栈规划和明确的嵌套边界可以在资源可控的前提下实现中断嵌套和实时调度。
返回列表