TI C2000 的中断系统刚开始看起来容易混乱,主要原因是它并不是“所有中断都进 PIE”,也不是“直连 CPU 的中断一定优先级最高”。
真正理解它,可以抓住一句话:
C2000 的中断分为 CPU 直连中断、PIE 扩展中断和软件陷阱类中断。大多数外设先进 PIE,再通过 INT1~INT12 送入 CPU;但 RESET、NMI、RTOSINT、INT13、INT14、DLOGINT 等并不经过 PIE。
其中,PIE 是 C2000 中断系统里最重要、也最容易混淆的部分。
1. C28x CPU 的中断入口
C28x CPU 固定支持 32 个中断向量入口。无论芯片外设有多少,最终都必须映射到 CPU 能识别的这些入口上。
从路径上看,中断大致可以分成三类:
| 类型 | 代表中断 | 是否经过 PIE | 说明 |
|---|---|---|---|
| CPU 特殊中断 / 异常 | RESET、EMUINT、NMI、ILLEGAL、USER Trap | 否 | CPU 内核直接处理,部分属于异常或软件陷阱 |
| PIE 外设中断 | INT1 ~ INT12 | 是 | 大多数外设中断都走这条路径 |
| CPU 直连可屏蔽中断 | RTOSINT、INT13、INT14、DLOGINT | 否 | 不经过 PIE,但不代表一定高优先级 |
这三个路径必须分清。
尤其要注意:
直连 CPU 不等于优先级一定高。
例如:
INT13、INT14、DLOGINT 都是 CPU 直连中断,
但它们的硬件优先级低于 INT1~INT12。
2. C28x 硬件中断优先级
下面这张表只列参与硬件优先级仲裁的主要中断。
优先级数字越小,硬件响应优先级越高。
| 硬件优先级 | 中断名 | CPU 向量偏移 | F2833x PIE 表地址 | 路径 | 可屏蔽 | 说明 |
|---|---|---|---|---|---|---|
| 1 | RESET | 0x0000 | 0x0D00 | CPU 直连 | 否 | 系统复位,最高优先级 |
| 2 | EMUINT / Reserved | 0x0022 | 0x0D22 | CPU 直连 | 调试相关 | CPU Emulation Interrupt |
| 3 | NMI | 0x0024 | 0x0D24 | CPU 直连 | 否 | 不可屏蔽中断 |
| 4 | RTOSINT | 0x0020 | 0x0D20 | CPU 直连 | 是 | 实时操作系统中断 |
| 5 | INT1 | 0x0002 | PIE Group 1 | PIE | 是 | ADC、XINT1/2、Timer0、WAKEINT |
| 6 | INT2 | 0x0004 | PIE Group 2 | PIE | 是 | ePWM Trip Zone |
| 7 | INT3 | 0x0006 | PIE Group 3 | PIE | 是 | ePWM 周期/比较事件 |
| 8 | INT4 | 0x0008 | PIE Group 4 | PIE | 是 | eCAP |
| 9 | INT5 | 0x000A | PIE Group 5 | PIE | 是 | eQEP |
| 10 | INT6 | 0x000C | PIE Group 6 | PIE | 是 | SPI、McBSP |
| 11 | INT7 | 0x000E | PIE Group 7 | PIE | 是 | DMA |
| 12 | INT8 | 0x0010 | PIE Group 8 | PIE | 是 | I2C、SCI-C |
| 13 | INT9 | 0x0012 | PIE Group 9 | PIE | 是 | SCI-A/B、eCAN-A/B |
| 14 | INT10 | 0x0014 | PIE Group 10 | PIE | 是 | F2833x 中保留 |
| 15 | INT11 | 0x0016 | PIE Group 11 | PIE | 是 | F2833x 中保留 |
| 16 | INT12 | 0x0018 | PIE Group 12 | PIE | 是 | XINT3~7、FPU LVF/LUF |
| 17 | INT13 | 0x001A | 0x0D1A | CPU 直连 | 是 | XINT13 或 CPU Timer1,器件相关 |
| 18 | INT14 | 0x001C | 0x0D1C | CPU 直连 | 是 | CPU Timer2 |
| 19 | DLOGINT / DATALOG | 0x001E | 0x0D1E | CPU 直连 | 是 | Data Logging Interrupt,硬件优先级最低 |
这里有几个特别容易记错的点:
- RTOSINT 不是最低优先级,它的硬件优先级是 4。
- DLOGINT 才是硬件优先级最低的 CPU 中断。
- NMI 的 CPU 向量偏移是 0x0024,不是 0x0044。
- ILLEGAL 不适合混进普通外设中断优先级表,它属于非法操作陷阱。
3. USER1~USER12:软件 Trap,不是普通外设中断
C28x 还有 USER1~USER12 这些用户软件向量。
它们不要和 INT1~INT14、RTOSINT、DLOGINT 这种硬件中断混在一起理解。
| 向量 | CPU 向量偏移 | F2833x PIE 表地址 | 触发方式 | 说明 |
|---|---|---|---|---|
| USER1 | 0x0028 | 0x0D28 | TRAP | 用户自定义软件陷阱 |
| USER2 | 0x002A | 0x0D2A | TRAP | 用户自定义软件陷阱 |
| USER3 | 0x002C | 0x0D2C | TRAP | 用户自定义软件陷阱 |
| USER4 | 0x002E | 0x0D2E | TRAP | 用户自定义软件陷阱 |
| USER5 | 0x0030 | 0x0D30 | TRAP | 用户自定义软件陷阱 |
| USER6 | 0x0032 | 0x0D32 | TRAP | 用户自定义软件陷阱 |
| USER7 | 0x0034 | 0x0D34 | TRAP | 用户自定义软件陷阱 |
| USER8 | 0x0036 | 0x0D36 | TRAP | 用户自定义软件陷阱 |
| USER9 | 0x0038 | 0x0D38 | TRAP | 用户自定义软件陷阱 |
| USER10 | 0x003A | 0x0D3A | TRAP | 用户自定义软件陷阱 |
| USER11 | 0x003C | 0x0D3C | TRAP | 用户自定义软件陷阱 |
| USER12 | 0x003E | 0x0D3E | TRAP | 用户自定义软件陷阱 |
注意两个地址:
0x001E 是 DLOGINT
0x0020 是 RTOSINT
它们不是 USER1 / USER2。
USER1~USER12 是从:
0x0028 ~ 0x003E
这一段开始的。
4. PIE 的作用:把 12 条 CPU 中断线扩展成 96 个外设槽位
PIE 的全称是:
Peripheral Interrupt Expansion
也就是外设中断扩展模块。
C28x CPU 只有 INT1~INT12 这 12 条主要外设中断入口,但片上外设数量远远超过 12 个,所以 TI 设计了 PIE。
PIE 的结构是:
12 个 PIE 组 × 每组 8 个中断槽位 = 96 个 PIE 中断入口
也就是说:
外设中断
→ PIE 某一组某一槽位
→ CPU INT1~INT12
→ CPU 响应中断
PIE 的优先级分两层:
组间优先级:
INT1 > INT2 > INT3 > ... > INT12
组内优先级:
INTx.1 > INTx.2 > INTx.3 > ... > INTx.8
例如:
INT1.1 和 INT8.1 同时发生,先响应 INT1.1
INT1.1 和 INT1.8 同时发生,先响应 INT1.1
5. F2833x PIE 中断向量表
下面以 F2833x 为例整理 PIE 表。
表格按 INTx.1 → INTx.8 排列,也就是从高优先级到低优先级。
| CPU 中断 | INTx.1 最高 | INTx.2 | INTx.3 | INTx.4 | INTx.5 | INTx.6 | INTx.7 | INTx.8 最低 |
|---|---|---|---|---|---|---|---|---|
| INT1 | SEQ1INT | SEQ2INT | Reserved | XINT1 | XINT2 | ADCINT | TINT0 | WAKEINT |
| INT2 | EPWM1_TZINT | EPWM2_TZINT | EPWM3_TZINT | EPWM4_TZINT | EPWM5_TZINT | EPWM6_TZINT | Reserved | Reserved |
| INT3 | EPWM1_INT | EPWM2_INT | EPWM3_INT | EPWM4_INT | EPWM5_INT | EPWM6_INT | Reserved | Reserved |
| INT4 | ECAP1_INT | ECAP2_INT | ECAP3_INT | ECAP4_INT | ECAP5_INT | ECAP6_INT | Reserved | Reserved |
| INT5 | EQEP1_INT | EQEP2_INT | Reserved | Reserved | Reserved | Reserved | Reserved | Reserved |
| INT6 | SPIRXINTA | SPITXINTA | MRINTB | MXINTB | MRINTA | MXINTA | Reserved | Reserved |
| INT7 | DINTCH1 | DINTCH2 | DINTCH3 | DINTCH4 | DINTCH5 | DINTCH6 | Reserved | Reserved |
| INT8 | I2CINT1A | I2CINT2A | Reserved | Reserved | SCIRXINTC | SCITXINTC | Reserved | Reserved |
| INT9 | SCIRXINTA | SCITXINTA | SCIRXINTB | SCITXINTB | ECAN0INTA | ECAN1INTA | ECAN0INTB | ECAN1INTB |
| INT10 | Reserved | Reserved | Reserved | Reserved | Reserved | Reserved | Reserved | Reserved |
| INT11 | Reserved | Reserved | Reserved | Reserved | Reserved | Reserved | Reserved | Reserved |
| INT12 | XINT3 | XINT4 | XINT5 | XINT6 | XINT7 | Reserved | LVF | LUF |
如果看到有些资料把表头写成:
INTx.8 → INTx.1
那就要注意方向。
INTx.1 才是组内最高优先级,INTx.8 是组内最低优先级。
6. 各 PIE 组功能速查
| PIE 组 | 主要功能 | 典型用途 |
|---|---|---|
| INT1 | ADC、XINT1/2、Timer0、WAKEINT | ADC 采样完成、外部 GPIO 中断、系统节拍 |
| INT2 | ePWM Trip Zone | 过流、过压、硬件保护关断 |
| INT3 | ePWM 周期/比较中断 | 电机控制、电源控制、PWM 更新节拍 |
| INT4 | eCAP | 输入捕获、测速、测脉宽 |
| INT5 | eQEP | 编码器位置、速度、方向反馈 |
| INT6 | SPI、McBSP | 串行通信、音频/同步接口 |
| INT7 | DMA | 数据搬运完成通知 |
| INT8 | I2C、SCI-C | 板级通信、扩展串口 |
| INT9 | SCI-A/B、eCAN-A/B | 上位机通信、CAN 总线 |
| INT10 | Reserved | F2833x 中保留 |
| INT11 | Reserved | F2833x 中保留 |
| INT12 | XINT3~7、FPU 异常 | 外部 GPIO 中断、浮点异常 |
7. 中断源的分流路径
7.1 CPU Timer
三个 CPU Timer 的路径并不一样。
| 中断源 | 去向 | 是否经过 PIE | 说明 |
|---|---|---|---|
| CPU Timer0 | PIE Group 1,INT1.7 | 是 | 普通系统节拍中断 |
| CPU Timer1 | INT13 | 否 | CPU 直连,常用于系统或 RTOS |
| CPU Timer2 | INT14 | 否 | CPU 直连,常用于系统或 RTOS |
所以,不能说“三个 CPU Timer 都进 PIE”。
准确说是:
Timer0 进 PIE
Timer1 / Timer2 直连 CPU
7.2 普通片内外设
大多数片内外设都走 PIE。
例如:
ADC → PIE Group 1
ePWM TZ → PIE Group 2
ePWM INT → PIE Group 3
eCAP → PIE Group 4
eQEP → PIE Group 5
SPI → PIE Group 6
DMA → PIE Group 7
I2C/SCI → PIE Group 8/9
XINT3~7 → PIE Group 12
7.3 外部引脚中断
| 外部信号 | 去向 | 说明 |
|---|---|---|
| XRS / Reset | RESET | 系统复位入口,最高优先级 |
| XNMI | NMI | 不可屏蔽中断 |
| XINT1 | PIE Group 1,INT1.4 | 外部 GPIO 中断 |
| XINT2 | PIE Group 1,INT1.5 | 外部 GPIO 中断 |
| XINT3~XINT7 | PIE Group 12,INT12.1~INT12.5 | 更多外部 GPIO 中断 |
| XINT13 | INT13 | 与 Timer1 相关,具体看器件配置 |
8. PIE 中断响应流程
一个典型的 PIE 外设中断,从产生到进入 ISR,大致经历下面这些步骤:
1. 外设事件发生
2. 外设自己的中断标志位置位
3. 外设自己的中断使能打开
4. PIEIFRx.y 置位
5. PIEIERx.y 允许该槽位
6. PIEACKx 当前允许该组送中断
7. CPU IFRx 置位
8. CPU IERx 允许该 CPU 中断级
9. INTM = 0,全局中断允许
10. CPU 完成当前指令,清流水线,保存上下文
11. CPU 从 PIE 向量表取 ISR 地址
12. 进入 ISR
13. ISR 中清外设中断标志
14. ISR 末尾写 PIEACK,释放该 PIE 组
15. IRET 返回
可以把它理解为三层开关:
外设层:外设自己的中断使能
PIE 层:PIEIERx.y
CPU 层:IER + INTM
三层都打开,中断才真正能进 CPU。
9. PIEACK 是什么
PIEACK 是很多人写 C2000 中断时最容易漏掉的东西。
它不是某一个外设的中断标志,而是 PIE 组级应答锁。
| PIEACK 状态 | 含义 |
|---|---|
| PIEACKx = 0 | 该组可以继续向 CPU 送中断 |
| PIEACKx = 1 | 该组已经有中断送入 CPU,同组其他中断暂时被挡住 |
| 写 1 到 PIEACKx | 清除该组 ACK,允许该组后续中断进入 |
所以在 ISR 里,除了清外设自己的中断标志,还要清 PIEACK。
否则会出现这种现象:
第一次中断能进来,
后面同组中断再也进不来。
本质上不是外设坏了,而是 PIE 组被 ACK 锁住了。
10. 推荐的 ISR 写法
以 ePWM1 中断为例:
interrupt void epwm1_isr(void)
{
/*
* 1. 执行用户中断处理逻辑
* ISR 里尽量不要做耗时任务。
*/
// control_loop();
/*
* 2. 清外设中断标志
*/
EPwm1Regs.ETCLR.bit.INT = 1;
/*
* 3. 最后清 PIEACK
* EPWM1_INT 属于 PIE Group 3
*/
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
比较稳的习惯是:
先处理业务
再清外设标志
最后清 PIEACK
不建议一进 ISR 就清 PIEACK。
尤其是在 ISR 里可能重新打开全局中断的情况下,过早清 PIEACK 可能让同组中断过早参与嵌套,调试会更麻烦。
11. PIE 中断初始化流程
典型初始化流程如下:
/*
* 1. 关闭全局中断
*/
DINT;
/*
* 2. 初始化 PIE 控制器和 PIE 向量表
*/
InitPieCtrl();
InitPieVectTable();
/*
* 3. 修改 PIE 向量表,绑定 ISR 函数
*/
EALLOW;
PieVectTable.EPWM1_INT = &epwm1_isr;
PieVectTable.ADCINT = &adc_isr;
EDIS;
/*
* 4. 使能 PIE 组内中断
*/
PieCtrlRegs.PIEIER3.bit.INTx1 = 1; // EPWM1_INT,Group 3,INTx.1
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // ADCINT,Group 1,INTx.6
/*
* 5. 使能 CPU 层中断
*/
IER |= M_INT3;
IER |= M_INT1;
/*
* 6. 开全局中断和实时调试中断
*/
EINT;
ERTM;
这里要注意两点:
第一,PIE 向量表在 RAM 中,需要用户初始化。
第二,只开 PIEIER 不够,还必须开 CPU IER 和全局中断 INTM。
12. 中断嵌套
C28x 默认进入一个可屏蔽中断后,会自动置位 INTM,阻止新的普通可屏蔽中断打断当前 ISR。
也就是说,默认情况下:
ISR 不会被其他普通中断自动抢占
如果需要中断嵌套,需要在 ISR 中手动处理:
1. 配置好 IER / PIEIER,确保只允许希望嵌套的高优先级中断
2. 根据需要处理 PIEACK
3. 在 ISR 中重新开全局中断,例如 EINT 或 CLRC INTM
中断嵌套虽然能降低高优先级中断延迟,但也会带来几个问题:
| 风险 | 说明 |
|---|---|
| 栈空间增加 | 嵌套越深,保存上下文越多 |
| 同组中断复杂 | PIEACK 处理不当容易乱 |
| 共享变量冲突 | ISR 之间可能同时访问同一资源 |
| 调试困难 | 时序不再线性 |
所以在控制类应用中,常见做法是:
高频 ISR 尽量短
低频任务放后台
非必要不做复杂嵌套
13. 中断延迟
C28x 的中断入口开销常用 8 cycles 来估算,但实际延迟不应该只看这个数字。
真实延迟还会受到这些因素影响:
| 影响因素 | 说明 |
|---|---|
| 当前正在执行的指令 | CPU 通常要完成当前指令后才响应 |
| 流水线状态 | 进入中断前需要清流水线 |
| PIE 仲裁 | PIE 中断还要经过组间/组内仲裁 |
| Flash wait-state | ISR 或向量表在 Flash 中会增加等待 |
| 编译器保存寄存器 | C 语言 ISR 会有额外现场保护 |
| 是否从 IDLE 唤醒 | 唤醒路径可能增加延迟 |
所以更准确的写法是:
8 cycles 是基础入口开销,实际 ISR 响应延迟要结合代码位置、编译器、外设同步和系统状态一起估算。
14. PIEIFR 不要随便清
还有一个很实战的坑:
不要随便用软件读-改-写方式清 PIEIFR。
PIEIFR 是 PIE 层的中断标志寄存器。很多情况下,PIEIFR 会在中断被正确响应时由硬件处理。
如果软件随便清 PIEIFR,尤其是读-改-写操作,很可能出现:
刚来的中断被误清掉
结果就是偶发性丢中断,调试起来非常痛苦。
一般 ISR 里更应该关注:
清外设自己的中断标志
清 PIEACK
而不是随便操作 PIEIFR。
15. PIE 中断和 CPU 直连中断的区别
| 对比项 | PIE 中断 | CPU 直连中断 |
|---|---|---|
| 典型对象 | ADC、ePWM、SCI、SPI、CAN、DMA 等 | RESET、NMI、RTOSINT、INT13、INT14、DLOGINT |
| 路径 | 外设 → PIE → CPU INT1~INT12 | 中断源 → CPU |
| 数量 | 最多 96 个外设槽位 | 固定少量 CPU 入口 |
| 使能层级 | 外设使能 + PIEIER + CPU IER + INTM | 通常 CPU IER + INTM;RESET/NMI 例外 |
| 清标志 | 外设标志 + PIEACK | 一般清对应外设/CPU 标志 |
| 优先级 | INT1 | 按 CPU 固定硬件优先级 |
16. F281x、F2833x 和其他 C2000 器件的区别
C2000 系列很多,不同器件的外设和 PIE 分配并不完全一样。
可以这样理解:
| 内容 | 是否通用 |
|---|---|
| C28x CPU 有 32 个中断向量 | 大体通用 |
| PIE 是 12 组 × 8 槽的结构 | 经典 C2000 器件中常见 |
| INT1~INT12 的 CPU 优先级顺序 | 通用 |
| PIE 组内 INTx.1 高于 INTx.8 | 通用 |
| 某个外设具体在哪个 PIE 槽位 | 不通用,必须查具体芯片手册 |
| F281x 和 F2833x 的外设命名/分配 | 不完全一样 |
| 带 CLA 的器件 PIE 分配 | 要看具体型号 |
例如,F2833x / F2823x 的官方 PIE 表中,INT10 和 INT11 都是 Reserved。
但一些更新的 C2000 器件可能会把 CLA、更多 ADC、CMPSS 等中断映射到不同 PIE 组。
所以笔记里最好写成:
CPU 中断机制可以通用理解,但 PIE 外设映射必须以具体芯片 TRM 为准。
17. 常见误区总结
| 误区 | 正确理解 |
|---|---|
| 三个 CPU Timer 都走 PIE | 错。Timer0 走 PIE,Timer1/2 直连 CPU |
| 直连 CPU 一定高优先级 | 错。INT13、INT14、DLOGINT 直连 CPU,但优先级低于 INT1~INT12 |
| DLOGINT / RTOSINT 是不可屏蔽仿真中断 | 错。它们在 IER 中有使能位,是可屏蔽中断 |
| USER1 / USER2 在 0x001E / 0x0020 | 错。0x001E 是 DLOGINT,0x0020 是 RTOSINT |
| USER 中断由 INTR 触发 | 错。USER1~USER12 由 TRAP 指令触发 |
| PIEACK 不清也没事 | 错。不清 PIEACK,同组后续中断会被挡住 |
| PIEIFR 可以随便软件清 | 错。可能造成丢中断 |
| PIE 优先级可以随便改 | 错。组间和组内硬件优先级固定 |
| F281x / F2833x PIE 表可以混用 | 错。CPU 机制相似,但 PIE 映射必须查具体芯片 |
| ISR 越长越好处理 | 错。ISR 应尽量短,把耗时任务放到后台 |
18. 最后总结
C2000 的中断系统可以按照下面这张逻辑图理解:
特殊 CPU 中断:
RESET / EMUINT / NMI / RTOSINT
→ CPU 直接响应,优先级较高
普通外设中断:
ADC / ePWM / SCI / SPI / CAN / DMA / XINT 等
→ PIE
→ INT1~INT12
→ CPU
CPU 直连低优先级中断:
INT13 / INT14 / DLOGINT
→ 不经过 PIE
→ 但优先级低于 INT1~INT12
软件陷阱:
ILLEGAL / USER1~USER12
→ CPU Trap 类向量
真正写代码时,最关键的是三件事:
1. 使能外设中断、PIEIER、CPU IER 和全局中断
2. 在 ISR 中清外设中断标志
3. 在 ISR 末尾清 PIEACK
只要这三层逻辑理清,C2000 的中断系统就不再是“很多表格堆在一起”,而是一套非常明确的分流、仲裁和应答机制。