第4章 中断系统:中断优先级与仲裁、中断服务函数(ISR)编写、中断嵌套与抢占、实战:外部中断驱动
各位同学,欢迎来到中断系统这一章。
说实话,中断是嵌入式开发的灵魂。没有中断,你的CPU就得像个傻子一样轮询等待,效率低得可怜。我刚开始做TC275时,就被它那套复杂的中断系统搞得有点懵——但搞懂之后,你会发现它其实很优雅。
4.1 中断优先级与仲裁机制
TC275的中断系统,说白了就是一套“谁更重要,谁先处理”的规则。它支持多达256个中断节点,每个节点都有自己的优先级。
优先级是怎么工作的?
每个中断源都有一个8位的优先级寄存器,取值范围0-255。数值越大,优先级越高。0表示中断被禁用。
我遇到过一个问题:两个中断同时触发,结果系统卡死了。后来发现,是我把两个中断设成了相同优先级,又没有配置好仲裁规则。
核心概念:仲裁机制
TC275使用硬件仲裁器来决定哪个中断先被响应。仲裁规则很简单:
- 比较两个中断的优先级数值
- 数值大的先执行
- 如果数值相同,则比较中断节点编号,编号小的优先
嗯,这里要注意:仲裁是在中断请求到达CPU之前完成的。所以你的软件不需要做任何判断,硬件已经帮你选好了。
4.2 中断服务函数(ISR)编写
写ISR,说白了就是写一个函数,但这个函数有特殊要求。
ISR的基本结构:
IFX_INTERRUPT(MyISR, 0, 1)
{
// 你的中断处理代码
// 注意:要尽量短,别在里面做复杂运算
// 清除中断标志位
IfxSrc_clearRequest(&SRC_xxx);
}
这里我解释一下参数:
MyISR:函数名,随便起0:中断优先级,0-2551:CPU编号,TC275有3个CPU,一般用CPU0
我的个人习惯:
ISR里只做三件事:
- 读取硬件状态
- 设置一个标志位
- 清除中断标志
真正的处理逻辑,放到主循环里去做。这样能保证中断响应速度。
我曾经犯过一个错误:在ISR里调用了printf函数。结果系统直接崩溃。为什么?因为printf是阻塞的,而且可能触发其他中断,造成死锁。
警告:ISR中绝对不要做的事
- 不要调用printf、malloc等库函数
- 不要做浮点运算
- 不要使用延时函数
- 不要访问共享资源而不加锁
4.3 中断嵌套与抢占
中断嵌套,说白了就是一个中断正在执行,另一个更高优先级的中断来了,CPU会暂停当前ISR,去处理新的中断。
TC275支持嵌套吗?
支持的。默认情况下,所有中断都可以互相嵌套。但你可以通过配置来禁止嵌套。
我建议:除非你很清楚自己在做什么,否则不要轻易开启嵌套。因为嵌套会带来很多问题:
- 栈空间消耗增大
- 调试困难
- 可能出现优先级反转
如何控制嵌套?
通过CPU的PSW寄存器中的ICR位域来控制。你可以设置一个“中断屏蔽级别”,只有优先级高于这个级别的中断才能抢占当前ISR。
// 设置中断屏蔽级别为10
// 只有优先级大于10的中断才能嵌套
IfxCpu_irq_installInterruptHandler(&MyISR, 10);
你想想看,这就像给中断系统加了一个“门槛”。低于门槛的,乖乖排队;高于门槛的,可以插队。
4.4 实战:外部中断驱动
好了,理论讲完了,咱们来点实际的。写一个外部中断驱动,让一个按键触发中断,控制LED亮灭。
硬件连接:
| 引脚 | 功能 |
|---|---|
| P00.0 | 按键输入(外部中断) |
| P00.1 | LED输出 |
代码实现:
// 1. 初始化外部中断
void ExtInt_Init(void)
{
// 配置P00.0为输入
IfxPort_setPinMode(&MODULE_P00, 0, IfxPort_Mode_inputPullUp);
// 配置中断源
IfxSrc_init(
&SRC_P00_0, // 中断源寄存器
IfxSrc_Tos_cpu0, // 目标CPU
20 // 优先级
);
// 设置触发方式:下降沿触发
IfxSrc_enable(&SRC_P00_0);
}
// 2. 中断服务函数
IFX_INTERRUPT(ExtInt_ISR, 0, 20)
{
// 翻转LED状态
IfxPort_togglePin(&MODULE_P00, 1);
// 清除中断请求
IfxSrc_clearRequest(&SRC_P00_0);
}
// 3. 主函数
int main(void)
{
// 初始化
ExtInt_Init();
// 配置LED引脚为输出
IfxPort_setPinMode(&MODULE_P00, 1, IfxPort_Mode_outputPushPull);
while(1)
{
// 主循环做其他事情
// 中断来了会自动处理
}
}
避坑指南:
我曾经在配置外部中断时,忘记设置触发方式。结果按键按下去没反应。查了半天才发现,默认是电平触发,而我需要的是边沿触发。
记住:外部中断一定要明确配置触发方式!
调试技巧:
- 先用示波器看按键波形,确认有没有抖动
- 在ISR里加一个计数器,看中断是否被正确触发
- 如果中断不响应,检查中断使能位和全局中断开关
好了,这一章的内容就到这里。中断系统是TC275的精华所在,搞懂了它,你就能写出高效、可靠的嵌入式程序。下一章,咱们聊聊定时器,那个东西也很有意思。
本章要点回顾:
- 中断优先级0-255,数值越大优先级越高
- ISR要短小精悍,别做复杂操作
- 中断嵌套要谨慎使用
- 外部中断记得配置触发方式
公众号:蓝海资料掘金营,微信deep3321