——…——
8中断管理
中断处理与 CPU 架构密切相关。
8.1 Cortex-M CPU 架构基础
——暂略——
8.2 RT-Thread 中断工作机制
中断处理过程
RT-Thread 中断管理中,将中断处理程序分为中断前导程序、用户中断服务程序、中断后续程序三部分。
中断前导程序
主要工作内容:
- 保存CPU中断现场
对于cortex-M,处理器硬件会将当前运行部分的上下文寄存器自动压入中断栈中 - 通知内核进入中断状态
用户中断服务程序
分为两种情况:
- 在中断处理过程中不需要进行线程切换
这种情况下用户中断服务程序和中断后续程序运行完毕后退出中断模式,返回被中断的线程。
- 在中断处理过程中需要进行线程切换
这种情况会调用 rt_hw_context_switch_interrupt()函数进行上下文切换,该函数跟 CPU 架构相关,不同 CPU 架构的实现方式有差异。
中断服务程序是一种需要特别注意的运行环境,它运行在非线程的执行环境下,在这个运行环境中不能使用挂起当前线程的操作,因为当前线程并不存在。
中断后续程序
主要工作内容:
- 通知内核离开中断状态
- 恢复中断前的 CPU 上下文
如果在中断处理过程中未进行线程切换,那么恢复 from 线程的 CPU上下文,如果在中断中进行了线程切换,那么恢复 to 线程的 CPU 上下文。
中断栈
中断栈可以保存在打断线程的栈中,当从中断中退出时,返回相应的线程继续执行。
中断栈也可以与线程栈完全分离开来,即每次进入中断时,在保存完打断线程上下文后,切换到新的中断栈中独立运行。
RT-Thread 采用的方式是提供独立的中断栈。
使用独立中断栈相对来说更容易实现,并且这样中断就不会占用线程的栈空间,从而提高了内存空间的利用率,且随着线程的增加,这种减少内存占用的效果也越明显。
中断的底半处理
用户需要保证所有的中断服务程序在尽可能短的时间内完成。
当一个中断发生时,中断服务程序需要取得相应的硬件状态或者数据。对于一些复杂中断,为了提高系统的响应能力和并发能力,通常需要将该中断分割为两部分,即上半部分(Top Half)和底半部分(Bottom Half)。
在上半部分中,取得硬件状态和数据后,打开被屏蔽的中断,给相关线程发送一条通知(可以是 RT-Thread 所提供的信号量、事件、邮箱或消息队列等方式),然后结束中断服务程序;
而接下来,相关的线程在接收到通知后,接着对状态或数据进行进一步的处理,这一过程称之为底半处理。
下半部会在合适的时机由操作系统调用。这样一来就大大的减少了中断处理所需要的时间。
8.3 RT-Thread 中断管理接口
RT-Thread 把中断和异常封装为一组抽象接口,从而使操作系统和系统底层的异常、中断硬件隔离开来。
中断服务程序挂接:系统把用户的中断服务程序 (handler) 和指定的中断号关联起来。
中断源管理:通常在 ISR (Interrupt Service Routines,中断服务程序)准备处理某个中断信号之前,我们需要先屏蔽该中断源,在 ISR 处理完状态或数据以后,及时的打开之前被屏蔽的中断源。
屏蔽中断源可以保证在接下来的处理过程中硬件状态或者数据不会受到干扰。
全局中断开关:使用中断锁最主要的问题在于,在中断关闭期间系统将不再响应任何中断,也就不能响应外部的事件,所以中断锁对系统的实时性影响非常巨大。
中断通知:当整个系统被中断打断,进入中断处理函数时,需要通知内核当前已经进入到中断状态。
8.4中断与轮询
轮询法的概念是:由CPU定时发出询问,依序询问每一个周边设备是否需要其服务,有即给予服务,服务结束后再问下一个周边,接着不断周而复始。
在实时系统中轮询模式可能会出现非常大的问题:当一个程序持续地执行时
(轮询时),它所在的线程会一直运行,比它优先级低的线程都不会得到运行。)
所以通常情况下实时系统中更多采用的是中断模式来驱动外设。
中断的缺点:对于高速设备,数据带宽利用率未达100%,使得数据吞吐量不足,系统开销消耗在了线程切换上。
发送数据量越小,发送速度越快,对于数据吞吐量的影响也将越大。归根结底,取决于系统中产生中断的频度如何。