2. 中断控制器 (ICU) 详解:中断请求节点 (SRN)、服务请求节点、中断路由

好,咱们接着聊中断系统。上一章我讲了中断的基本概念,这一章咱们深入内核,看看AURIX TC3xx的中断控制器到底是怎么工作的。说白了,中断控制器就是整个中断系统的“交通枢纽”。

我个人习惯把ICU理解成一个“快递分拣中心”。外设产生的中断信号就像一个个快递包裹,需要经过分拣、路由,最后准确送到CPU手里。这个过程中,有三个核心角色:中断请求节点 (SRN)服务请求节点中断路由。咱们一个一个拆开看。

2.1 中断请求节点 (SRN) —— 中断的“发件人”

SRN,全称Service Request Node。你想想看,每个能产生中断的外设,比如CAN模块、GPT12定时器、ADC,它们内部都有一个或多个SRN。SRN就是中断信号的源头。

每个SRN都有一个唯一的编号,叫做SRN编号。这个编号很重要,它是中断路由的“身份证”。在TC3xx里,SRN的数量是固定的,具体多少颗芯片不一样,但几百个是有的。

SRN的核心功能就两个:

  • 捕获中断事件:外设内部条件满足时,SRN会捕获这个事件。
  • 产生中断脉冲:捕获到事件后,SRN会向中断系统发送一个脉冲信号。这个脉冲是电平触发还是边沿触发?嗯,这里要注意,TC3xx的SRN默认是电平触发,但你可以通过配置寄存器改成边沿触发。

核心要点:每个SRN对应一个中断源。你写驱动时,第一步就是找到外设对应的SRN编号。比如,CAN模块的SRN编号通常是固定的,在数据手册里能查到。

我在项目中遇到过一个问题:某个外设的中断一直不触发,查了半天发现是SRN的触发方式配错了。默认是电平触发,但我配成了边沿触发,而外设产生的是电平信号。嗯,这种低级错误,犯过一次就记住了。

2.2 服务请求节点 —— 中断的“分拣员”

SRN产生中断信号后,信号会送到服务请求节点。服务请求节点,你可以理解成中断系统的“分拣员”。它的任务是把SRN送来的中断信号,分配给对应的CPU核心。

TC3xx有多个CPU核心(比如TC397有6个核),每个核都有自己的中断控制器。服务请求节点的作用就是决定:这个中断信号,应该发给哪个核?

服务请求节点内部有一个关键寄存器:ICR (Interrupt Control Register)。这个寄存器里存着两个重要信息:

  • CPU编号:指定中断发给哪个CPU核(0~5)。
  • 优先级:指定中断的优先级(0~255)。

每个SRN都对应一个服务请求节点。也就是说,每个中断源都可以独立配置它要发给哪个核、优先级多高。这种设计非常灵活,你可以把高优先级的中断分配给CPU0,把低优先级的分配给CPU1,实现负载均衡。

个人经验:我建议把实时性要求高的中断(比如电机控制PWM中断)分配给CPU0,把通信类中断(比如CAN接收中断)分配给CPU1。这样能避免一个核忙死、其他核闲死的情况。

2.3 中断路由 —— 中断的“快递路线”

服务请求节点决定好目标CPU和优先级后,中断信号就要通过中断路由送到目标CPU。中断路由,说白了就是一条条“快递路线”。

TC3xx的中断路由采用矩阵式结构。什么意思呢?就是每个服务请求节点都可以连接到任意一个CPU核的中断控制器。这种设计的好处是:

  • 灵活性高:你可以动态调整中断的分配,不用改硬件。
  • 扩展性好:增加新的外设或CPU核,只需要在路由矩阵里加一条路径就行。

中断路由的配置,主要通过SRE (Service Request Enable)寄存器和ICR寄存器完成。SRE寄存器控制是否使能某个SRN的中断,ICR寄存器控制路由的目标和优先级。

我曾经在调试一个多核项目时,发现中断响应时间忽长忽短。查了半天,原来是中断路由配置错了:两个中断源配到了同一个优先级,导致中断嵌套混乱。嗯,从那以后,我每次配中断都会仔细检查优先级是否唯一。

2.4 中断优先级与仲裁

当多个中断同时到达同一个CPU核时,CPU怎么决定先处理哪个?这就涉及到中断优先级仲裁

TC3xx的中断优先级范围是0~255,数值越大优先级越高。CPU的中断控制器会维护一个优先级队列,当多个中断同时到达时,它会选择优先级最高的那个先处理。

如果两个中断优先级相同呢?嗯,这里有个细节:TC3xx支持轮询模式优先级模式。在优先级模式下,相同优先级的中断会按照SRN编号的大小顺序处理,编号小的优先。

优先级范围 说明 推荐用途
0~63 低优先级 后台任务、低频率中断
64~127 中优先级 通信中断、定时器中断
128~191 高优先级 实时控制中断
192~255 最高优先级 紧急中断、故障处理

避坑指南:我曾经把两个关键中断配成了相同优先级,结果在高速运行时,两个中断互相抢占,导致系统崩溃。记住:关键中断的优先级一定要唯一,避免优先级冲突。

2.5 中断响应流程 —— 从SRN到CPU

咱们把整个流程串起来,看看一个中断从产生到被CPU处理,到底经历了哪些步骤:

  1. 外设产生事件:比如CAN模块收到一帧数据。
  2. SRN捕获事件:CAN模块内部的SRN检测到接收事件,产生中断脉冲。
  3. 服务请求节点分配:服务请求节点根据ICR配置,决定把中断发给CPU1,优先级设为100。
  4. 中断路由传输:中断信号通过路由矩阵,送到CPU1的中断控制器。
  5. 优先级仲裁:CPU1的中断控制器检查当前正在运行的中断优先级,如果新中断优先级更高,就抢占当前任务。
  6. CPU响应中断:CPU保存现场,跳转到中断服务函数执行。
  7. 中断服务函数执行:处理CAN数据。
  8. 中断返回:CPU恢复现场,继续执行被中断的任务。

你看,整个过程环环相扣。任何一个环节出问题,中断都可能无法正常工作。

2.6 实战配置示例

说了这么多理论,咱们来点实际的。下面是一个配置CAN模块中断的代码示例,我加了详细注释:

/* 配置CAN模块中断,SRN编号为100,发给CPU0,优先级150 */
void CAN_Interrupt_Config(void)
{
    /* 1. 使能SRN中断 */
    IfxScuWdt_clearCpuEndinit();  /* 解锁寄存器保护 */
    
    /* 2. 配置服务请求节点:目标CPU=CPU0,优先级=150 */
    SRN_ICR[100].B.PN = 0;        /* CPU编号:0 */
    SRN_ICR[100].B.PIPN = 150;    /* 优先级:150 */
    
    /* 3. 使能中断路由 */
    SRN_SRE[100].B.SRE = 1;       /* 使能SRN100的中断 */
    
    IfxScuWdt_setCpuEndinit();    /* 重新锁定寄存器 */
    
    /* 4. 配置CPU0的中断控制器,使能该中断 */
    CPU0_ICU.IECR.B.IE = 1;       /* 使能中断 */
}

这段代码看起来简单,但有几个坑要注意:

  • 配置ICR寄存器前,一定要先解锁寄存器保护(clearCpuEndinit),否则写不进去。
  • 优先级不要配成0,0是空闲优先级,不会触发中断。
  • SRN编号一定要查数据手册确认,不要想当然。

我的习惯:我会在工程里建一个中断配置表,把所有中断的SRN编号、目标CPU、优先级都列出来。这样既方便管理,也方便后期调试。你想想看,几百个中断源,全靠脑子记,迟早要出问题。

2.7 本章小结

好,这一章的内容就到这儿。咱们总结一下:

  • SRN是中断的源头,每个外设都有对应的SRN编号。
  • 服务请求节点负责分配中断给哪个CPU、优先级多高。
  • 中断路由是信号传输的通道,矩阵式结构让配置更灵活。
  • 优先级仲裁决定多个中断同时到达时谁先处理。

下一章,咱们会讲中断服务函数的编写规范和注意事项。到时候我会分享一些实战中踩过的坑,保证让你少走弯路。