一、以串口中断为例
1.如果串口的波特率为921600bps
2.串口为一个字节产生一次中断
二、波特率为921600bps波特率产生中断说明
说明:波特率为921600bps,串口的帧格式为10bit,也就是
一个起始位,8bit的数据位,还有一个bit的停止位,总计是
10bit传输一个字节。那么波特率位921600bps,那么1秒能够传输
92160个字节。如果每个字节产生一次中断,那么就是92160中断/秒。
注意:每次中断都需要CPU保存上下文,处理,以及恢复;那么这个过程
在A7上的开销是很大的,如果你写的中断服务程序ISR处理比较耗时的话,
那么就问题比较多了。
三、A7的中断响应时间
1.A7的主频位1GHZ以上
2.中断处理的步骤很多,包括内核响应,跳转到ISR,处理数据邓步骤;
如果ISR里面还有复杂的操作,或者系统还有其他中断和高负荷的任务,
那么处理不当会造成数据丢失
四、如何判断中断产生太频繁是否超过CPU能够稳定响应的极限
1.关于波特率921600bps,产生中断频率有多高?
中断频率:92,160 次/秒。这意味着 平均每10.86微秒(1秒 / 92160)CPU就要被中断一次。
也就是10.86us产生一次中断!!
2.cortex-a7能够处理多少中断
Cortex-A7主频高达1GHz+,但响应中断不仅仅是执行ISR(中断服务程序)那几条指令。整个过程涉及巨大的隐性开销。
首先,,关于硬件中断的响应延迟
其次,,关于操作系统的开销
再次,,关于中观处理本身的效率
最后,,系统的总负荷
五、关于A7处理中断
1.硬件中断的响应延时
CPU需要将当前的指令完成,然后进入异常向量
表,然后保存现场,压栈PC和CPSR等寄存器。
然后跳转到中断处理函数。
2.操作系统RTOS或者linux操作系统的开销
首先,内核态的切换:
如果是从用户态任务触发需要先切换到内核态,这个操作的开销是比较昂贵的。
其次,中断的前半部分处理
在linux中,前半部分要比较快的处理,通常是将数据从硬件的FIFO中
拷贝到内存缓冲区中并标记唤醒下半部分。
然后,中断下半部分处理
比如softIRQ软中断,Tasklet,工作队列等。
实际的数据处理通常在这部分进行,调度和切换也需要时间。
再然后,是中断的屏蔽和嵌套
再然后,是中断处理完成后,等待被唤醒的数据处理任务也不一定立即
被调度执行。
3.ISR的效率问题
如果你写的ISR代码的效率比较低,如果有打印,有复杂裸机,
甚至你在中断服务程序中有阻塞的延时操作,那么这个就会让
ISR中断服务程序处理的时间非常长。
4.需要考虑系统的总负荷
Cortex-A7通常运行Linux等复杂操作系统,系统本身有大量进程、线程、中断在竞争CPU时间。10.86微秒的间隔很容易被其他活动打乱。
六、中断处理不及时问题
最坏情况延迟:
系统可能正在处理其他中断(如网络、USB)、执行关键区代码(关中断)、或进行内存管理等。这些都会导致对串口中断的响应出现不可接受的延迟。
一旦CPU错过了一个字节的接收,由于串口是流式的,下一个字节会覆盖前一个,直接导致数据丢失。
七、总结
在92.16kHz的周期性中断轰炸下,由操作系统、上下文切换、内存访问等带来的累积延迟,使得系统无法保证在下一个字节到来前(10.86μs内)完成对上一个字节的完整处理,从而导致响应不过来和数据丢失。
八、解决方案
方案1:启用硬件FIFO并提高中断阈值(首选,最简单)
原理:绝大多数现代UART控制器都有硬件FIFO(如16字节或更深)。不要在每个字节都中断,而是设置一个触发水位(例如,当FIFO收到8个或14个字节时,产生一次中断)。
效果:中断频率立刻降低为原来的 1/8 或 1/16。从92kHz降至11.5kHz或5.76kHz,CPU压力骤减。
实现:查看芯片手册,配置UART的FIFO控制寄存器。
方案二:使用DMA(直接内存访问)
原理:这是为高速数据流设计的终极解决方案。为UART的接收通道配置DMA。DMA控制器会在不打扰CPU的情况下,自动将UART接收到的数据搬运到指定的内存缓冲区中。仅在以下情况通知CPU:
缓冲区满了(半满或全满,产生中断)。
线路空闲超时(一段时间没收到数据,产生中断)。
效果:几乎完全解放CPU。中断频率从字节级降至“缓冲区级”(例如每收256字节中断一次)。
实现:需要配置DMA控制器,并处理好环形缓冲区管理。这是处理921600bps及以上速率最标准、最可靠的方法。
方案三:优化软件架构(如果必须用字节中断)
如果硬件不支持FIFO或DMA,只能从软件层面极致优化:
ISR绝对精简:ISR里只做一件事——将数据寄存器读到一个全局环形缓冲区。不要在ISR内进行任何解析、打印、判断。
使用高优先级任务/线程处理数据:创建一个高优先级的实时任务(在RTOS中)或内核线程(在Linux中),该任务阻塞在一个信号量或队列上。ISR在存入数据后,立即释放该信号量。任务被唤醒后,再从环形缓冲区中取出数据进行处理。
提升中断优先级:将串口接收中断设置为最高优先级之一,减少被其他中断打断的可能。
关闭无关中断:在关键数据接收阶段,可以临时关闭不重要的中断源。