我们今天来看看中断,什么是中断呢?中断是一种处理器与外设进行通信的机制,它用于“通知”处理器外部有“重要事件”发生。在一般情况下,中断需要被处理器响应。下来我们来看看中断服务程序(ISR):1、从外设中读取中断状态寄存器的值,以便了解中断类型;2、根据中断类型具体设计处理逻辑;3、清除外设状态寄存器中的中断标识位;4、清除处理器中的中断标识位。具体过程如下

处理器之中断(二)_中断

        我们看到先是外部设备触发中断,然后处理器响应,进行当前上下文信息的保存。再通过获得外部设备中断的类型,当外部设备的类型传进来之后处理器再进行相应的处理。处理完之后再清除外部中断的标志位,进而清除中断的标志位,最后再次获得之前保存的上下文信息进行继续执行。

        那么软件工程师眼中的中断服务程序是怎样的呢?1、不能有返回值,不能有参数传递;2、必须小而高效,避免浮点运算。下面的程序就是不允许的。

处理器之中断(二)_处理器_02

        下来来看看中断的意义。1、应用程序不必关心中断的发生与处理;2、中断服务程序不必关心应用程序的执行状态;3、中断是“上层应用”与“底层代码”的“分隔边界”。如下

处理器之中断(二)_ISR_03

        中断分为两类:硬中断和软中断。硬中断是指通过处理器中断信号线产生的中断;软中断是指通过非法指令或特殊指令触发的中断。中断是分优先级的,当多个中断同时出现时,处理器先响应高优先级的中断。当低优先级中断的 ISR 执行时,可以被高优先级中断再次打断,ISR 比 App Code 拥有更高的执行优先级。那么中断的一个应用就是程序的断点,断点是指调试工具用于暂停代码执行的指令位置,断点的实现原理为处理器的中断支持。软件断点是指利用非法指令异常产生中断实现,而硬件中断是指利用中断寄存器的特性产生中断实现。

        程序断点的实现原理:1、获取原程序指定行对应的代码地址;2、把代码地址中的指令替换为中断触发指令;3、在中断服务程序中将控制权交给调试程序;4、调试程序读写原程序上下文信息;5、调试程序将代码地址中的指令还原;6、原程序从断点处继续向下执行。过程如下

处理器之中断(二)_程序_04

        下来我们来看个工程产品的案例,是要做一款可以进行断点调试的工具,但是不能够影响其实时性。其提出的背景是嵌入式实时系统对时序的要求比较严格,各个线程的执行有相对严格的时间要求。痛点就在于断点调试在嵌入式实时系统中不适用。那么最常规的解决方案是日志调试法,它的原理是:1、在代码中的“关键位置”添加打印语句;2、打印语句尽可能详细的打印上下文信息(函数名,局部变量等);3、当系统出现问题时,查看日志文件,分析问题。但是日志调试法也存在有一定的问题:1、不易维护,打印语句分散于产品代码的各个角落;2、影响效率,过多的打印语句意味着过多的 IO 操作最终会影响产品的整体效率执行;3、分析困难,当日志输出量非常多的时候,很难精确定位问题,另一个就是可能只有添加打印语句的工程师才能看得懂日志输出的信息。

        那么这时唐长老就产生了一个疯狂的想法:同时结合日志调试法和断点调试法的优点,使得实时系统调试时,能够任意查看指定代码行上下文的信息;并且不增加打印语句,不暂停执行。解决方案便是:1、获取原程序指定行对应的代码地址;2、把代码地址中的指令替换为中断触发指令;3、在中断服务程序中抓取全局信息和栈信息;4、抓取的信息发送回调试程序解析并输出。实践的结果便是有了 MProbe 这一款产品,它的特点:1、基于 ARM + Linux 平台完整实现;2、通过中断原理成功获取上下文信息;3、完全不影响程序的执行时序;4、产品关键技术点有中断、ISR、编译信息、GDB、GUI、Socket 以及多线程。