TI PRU INTC中断控制器架构解析与配置实践

📅 2026/7/20 11:18:11
TI PRU INTC中断控制器架构解析与配置实践
1. 项目概述与核心价值如果你正在基于TI的AM335x、AM57x或者类似的Sitara系列处理器开发实时控制系统比如工业伺服驱动器、高速数据采集卡或者自定义的通信协议转换器那么你大概率绕不开一个核心组件PRUProgrammable Real-Time Unit可编程实时单元。而要让这个强大的协处理器与主CPUARM以及众多片上外设如ePWM、eCAP、SPI高效协同工作中断控制器INTC就是那个至关重要的“交通枢纽”和“调度中心”。我最初接触PRU INTC时面对TI技术手册里密密麻麻的寄存器描述和抽象的功能框图也感到一阵头大。它不像通用的ARM GIC通用中断控制器那样有成熟的Linux驱动框架可以依赖很多时候需要开发者直接“撸寄存器”从零开始搭建中断处理链路。但一旦你吃透了它的设计逻辑就会惊叹于其精巧和高效。PRU INTC本质上是一个高度可配置的硬件中断路由与优先级仲裁器。它独立于主CPU的中断系统专门服务于PRU子系统能够捕获多达64个来自芯片内外部的“系统事件”System Events经过处理、映射、优先级排序后最终生成10个“主机中断”Host Interrupts输出。其中2个直接喂给PRU0和PRU1自身另外8个则输出给ARM或DSP主处理器用于触发更上层的ISR中断服务例程。理解并熟练配置PRU INTC是释放PRU实时处理潜力的关键。它能让你实现微秒级甚至纳秒级的确定性的中断响应将时间关键型任务如PWM死区管理、编码器信号解码、高速IO触发从负载繁重的Linux内核中剥离出来交给PRU处理从而构建出稳定、高效的硬实时或软实时子系统。本文将从实际开发者的视角深入解析PRU INTC的架构设计、映射机制并手把手带你完成一个从零开始的配置实践分享那些手册上不会写的调试经验和避坑指南。2. PRU INTC架构深度解析要驾驭PRU INTC不能只停留在调用API的层面必须理解其硬件数据流。你可以把它想象成一个高度自动化的物流分拣中心。2.1 核心功能模块与数据流整个INTC的工作流程可以分解为几个清晰的阶段如下图所示概念模型[ 外部世界 ] -- [ 系统事件 0-63 ] -- [ INTC 处理管道 ] -- [ 主机中断 0-9 ] (ePWM, GPIO, ...) (脉冲信号) (同步、使能、映射、仲裁) (输出给PRU或ARM)第一阶段信号标准化Interrupt Processing来自不同外设的中断信号其电气特性如极性、有效电平和类型电平触发、边沿触发可能五花八门。INTC的第一道工序就是将它们统一化。所有输入信号都会被同步到INTC的内部时钟域并统一转换为高电平有效的脉冲信号。这意味着无论你的外设产生的是低电平有效的中断还是一个持续的电平信号到了INTC内部都会变成一个干净的正脉冲。这个设计简化了后续逻辑但要求开发者清楚你配置给INTC的“系统事件”必须是一个能够产生脉冲的信号源。第二阶段开关控制Interrupt Enabling标准化后的信号并不会直接向后传递。这里有两级“开关”。第一级是全局使能Global Enable位于GERGlobal Enable Register寄存器。把它打开相当于给整个INTC上电。第二级是精细化的个体开关分为两部分系统事件使能每个系统事件0-63都有一个独立的使能位。只有被使能的事件其脉冲才能进入后续流程。这通过EISREnable Indexed Set Register或ESREnable Set Register来配置。主机中断使能每个主机中断输出0-9也有一个使能位。即使有事件被触发并处理完毕如果对应的主机中断输出没打开PRU或ARM也收不到通知。这通过HIEISRHost Interrupt Enable Indexed Set Register配置。实操心得很多新手在调试时发现“事件触发了但没进中断”问题往往就出在这里。一定要检查“事件使能”和“主机中断使能”这两道开关是否都打开了。正确的初始化顺序通常是先配置映射关系再清除可能存在的旧状态然后使能主机中断最后使能系统事件。第三阶段分组与路由Channel Host Mapping这是INTC最核心、也最灵活的部分。64个系统事件不会直接对应10个主机中断中间引入了一个“通道”Channel的概念作为缓冲和分组层。事件到通道的映射Event - Channel你可以将任意一个系统事件分配到10个通道0-9中的任何一个。多个事件可以映射到同一个通道逻辑“或”关系但一个事件不能同时映射到多个通道。通道号越小优先级越高。这个映射关系由CMR1到CMR16共16个寄存器控制每4个事件共享一个32位寄存器。通道到主机中断的映射Channel - Host Interrupt然后你需要将10个通道映射到10个主机中断输出上。同样多个通道可以映射到同一个主机中断例如将通道0和通道1都映射到主机中断2但一个通道不能映射到多个主机中断。官方建议采用直通映射Channel x - Host Interrupt x这样最直观。这个映射由HMR1到HMR3共3个寄存器控制。第四阶段优先级仲裁Prioritization当多个事件同时或几乎同时发生时谁先被处理INTC的硬件优先级仲裁器自动完成这个工作分为两层通道间优先级对于映射到同一个主机中断的多个通道编号小的通道优先级更高。例如映射到主机中断2的通道0比通道3的优先级高。事件间优先级对于映射到同一个通道的多个系统事件事件编号小的优先级更高。例如映射到通道0的系统事件5比系统事件10的优先级高。这个优先级信息是实时可查的。GPIRGlobal Prioritized Index Register寄存器存储着当前所有主机中断中优先级最高的那个系统事件的编号。而每个主机中断也有自己的HIPIRHost Interrupt Prioritized Index Register寄存器告诉你当前对该主机中断而言优先级最高的那个系统事件是哪个。第五阶段状态管理与清除Status Clearing这是中断处理中极易出错的一环。INTC维护着两种状态原始状态Raw Status记录事件是否发生过无论其是否被使能。在SRSR寄存器中查看。使能状态Enabled Status只有当事件被使能且确实发生了这个状态位才会被置位。在SECR寄存器中查看。关键注意事项在中断服务程序ISR中处理完一个中断后必须手动清除对应的系统事件状态位。如果你不清除INTC会认为这个中断一直处于挂起状态可能导致无法触发新的中断或者产生虚假的中断。清除方法有两种向SECR寄存器的对应位写1或者向SICRSystem Interrupt Status Indexed Clear Register写入要清除的事件编号。我强烈推荐使用SICR因为它是一次原子操作更安全。2.2 系统事件System Events详解系统事件是中断的源头。手册中将其分为两段事件 0-31来自PRUSS子系统外部由芯片上的其他外设产生例如ePWM模块的周期中断、比较器中断GPIO的边沿检测eCAP的捕获事件UART的接收完成等。具体哪个事件号对应哪个外设需要查阅你所使用的具体片的《技术参考手册》TRM不同型号的芯片映射关系可能不同。例如AM3358中系统事件16可能是I2C1 Interrupt。事件 32-63由PRU核心自身通过写R31寄存器的特定位来生成。这是PRU之间或PRU向主机ARM发送软件中断的核心机制。例如PRU0可以通过写R31的某一位来触发一个特定的事件从而通知PRU1或ARM。这里有一个重要的硬件特性PRUSSEVTSEL信号。它像一个全局的输入选择器可以改变事件0-31的来源。通过配置CFGCHIP3[3]寄存器位可以在两套不同的外设事件源之间切换。这在芯片引脚复用紧张或者需要动态改变中断源时非常有用。默认情况下该信号为0。2.3 主机中断Host Interrupts与目标INTC最终产生10个主机中断输出Host Interrupt 0 1直接连接到两个PRU核心。具体来说Host Int0 连接到 PRU0 和 PRU1 的R31寄存器第30位Host Int1 连接到第31位。PRU可以通过轮询或事件触发的方式检测这些位的变化。Host Interrupt 2 - 9这8个中断输出到PRUSS子系统外部被映射为PRUSS_EVTOUT0到PRUSS_EVTOUT7。它们最终会连接到ARM或DSP的中断控制器如ARM的GIC的特定输入线上。同样具体的映射关系ARM的哪个中断号对应EVTOUTx需要查TRM。例如在AM335x的Linux内核中PRUSS_EVTOUT0通常被映射到ARM的某个共享中断号。3. INTC配置实践从零搭建一个中断处理链路理论讲得再多不如动手配置一遍。我们假设一个在AM335x上常见的场景用一个GPIO的上升沿例如连接一个按键或传感器触发一个系统事件经过INTC处理后最终让PRU0进入中断同时向ARM发送一个通知。目标将GPIO1的某个引脚假设对应系统事件27的中断映射到PRU0Host Int0和ARM通过EVTOUT0即Host Int2。(注意事件27对应GPIO Bank0中断这是默认映射具体需核对TRM)。3.1 硬件与软件环境准备硬件TI AM335x开发板如BeagleBone Black。软件Linux内核需启用PRUSS驱动通常是uio_pruss或pruss驱动。PRU汇编器/编译器pasm或clpru。用户空间访问PRU内存和寄存器的工具通常通过/dev/mem或UIO驱动映射。我们这里以直接映射/dev/mem并操作寄存器为例这种方式最底层也最能理解原理。在生产环境中可以考虑使用TI的prussdrv库或Linux内核的PRU remoteproc框架。3.2 寄存器定义与内存映射首先我们需要知道INTC寄存器在内存中的位置。根据手册PRUSS的INTC寄存器在PRU本地数据空间的偏移地址是0x00004000长度0x0000300012KB。在全局内存空间ARM可见的基地址是0x01C34000。为了方便我们定义全局基地址#define PRUSS_INTC_BASE 0x01C34000然后我们需要定义关键寄存器的偏移地址。以下是一些最核心的寄存器偏移量相对于INTC基地址// 全局使能 #define INTC_GER (PRUSS_INTC_BASE 0x10) // 系统事件使能索引设置/清除 #define INTC_EISR (PRUSS_INTC_BASE 0x20) #define INTC_EICR (PRUSS_INTC_BASE 0x28) // 系统事件状态使能/清除 (SECR) - 用于清除中断状态 #define INTC_SECR0 (PRUSS_INTC_BASE 0x80) // 事件 0-31 #define INTC_SECR1 (PRUSS_INTC_BASE 0x84) // 事件 32-63 // 系统事件状态索引清除 (SICR) - 另一种清除方式 #define INTC_SICR (PRUSS_INTC_BASE 0x24) // 通道映射寄存器 (CMR) - 每个寄存器控制4个事件共16个 #define INTC_CMR(x) (PRUSS_INTC_BASE 0x40 (x) * 4) // x0..15 // 主机中断映射寄存器 (HMR) - 每个寄存器控制4个通道共3个 #define INTC_HMR(x) (PRUSS_INTC_BASE 0x100 (x) * 4) // x0..2 // 主机中断使能索引设置 (HIEISR) #define INTC_HIEISR (PRUSS_INTC_BASE 0x34) // 主机中断优先级索引寄存器 (HIPIR) - 用于读取当前最高优先级事件 #define INTC_HIPIR(x) (PRUSS_INTC_BASE 0x200 (x) * 4) // x0..93.3 逐步配置流程与代码实现假设我们要配置系统事件27GPIO Bank0中断。步骤1映射系统事件到通道我们决定将事件27映射到通道0最高优先级。每个CMR寄存器是32位每8位控制一个事件的通道号。事件27属于第27 / 4 6组CMR6在组内的位置是27 % 4 3即第3个事件占用bit[31:24]。// 读取当前的CMR6值 uint32_t cmr6_val readl(INTC_CMR(6)); // 清除事件27原来的映射bit[31:24] cmr6_val ~(0xFF 24); // 设置事件27映射到通道0 (值为0) cmr6_val | (0x00 24); // 通道号0写入bit[31:24] // 写回寄存器 writel(cmr6_val, INTC_CMR(6));注意CMR寄存器复位后通常为0意味着所有事件默认映射到通道0。但显式配置是一个好习惯。步骤2映射通道到主机中断我们希望这个中断能同时通知PRU0和ARM。因此我们需要将通道0映射到两个主机中断主机中断0给PRU0。主机中断2对应EVTOUT0给ARM。根据规则一个通道不能映射到多个主机中断。所以我们需要两个通道吗不我们有更巧妙的办法利用多个通道映射到同一个主机中断的特性。方案A推荐将事件27映射到通道0然后将通道0映射到主机中断0PRU。同时将另一个空闲的通道例如通道1也映射到主机中断2ARM但这样需要另一个事件来触发通道1不行。方案B正确思路一个事件只能映射到一个通道但一个主机中断可以接收多个通道。因此我们可以将事件27映射到通道0。将通道0映射到主机中断0PRU。同时将通道0也映射到主机中断2ARM。但这违反了“一个通道不能映射到多个主机中断”的规则。此路不通。正确方案我们需要两个独立的“中断链路”。链路1 (PRU中断)事件27 - 通道0 - 主机中断0。链路2 (ARM中断)事件27 - 通道1 - 主机中断2。这意味着我们需要将同一个系统事件27映射到两个不同的通道。然而手册明确规定“An interrupt should not be mapped to more than one channel.” 所以这条路也被堵死了。最终解决方案这是PRU INTC设计上的一个限制一个硬件事件不能直接分叉给两个主机。通常的实践是PRU处理然后通知ARM将事件27映射到通道0再映射到主机中断0。PRU0在它的中断服务程序中处理这个GPIO事件处理完毕后通过写R31寄存器触发另一个系统事件例如事件32。然后将事件32映射到通道1再映射到主机中断2ARM。这样GPIO事件由PRU实时处理处理完成后软件触发一个事件通知ARM。仅ARM处理如果实时性要求不高可以直接将事件27映射到通道0再映射到主机中断2ARM完全由ARM的中断服务程序处理。为了演示INTC的基本配置我们选择方案2仅让ARM处理。即事件27 - 通道0 - 主机中断2。配置主机映射寄存器HMR。HMR0控制通道0-3。每个通道用8位表示主机中号。// 配置 HMR0: 将通道0映射到主机中断2 uint32_t hmr0_val readl(INTC_HMR(0)); hmr0_val ~(0xFF 0); // 清除通道0的映射 (bits[7:0]) hmr0_val | (0x02 0); // 设置通道0映射到主机中断2 writel(hmr0_val, INTC_HMR(0));步骤3清除可能存在旧中断状态在使能任何中断之前必须清除状态寄存器避免一使能就误触发。// 方法1通过SECR寄存器清除事件27的状态事件2732用SECR0 writel(1 27, INTC_SECR0); // 向bit27写1以清除 // 方法2更清晰通过SICR寄存器清除 writel(27, INTC_SICR); // 写入事件编号27步骤4使能主机中断我们需要使能主机中断2对应ARM。writel(2, INTC_HIEISR); // 使能主机中断2步骤5使能系统事件最后使能系统事件27。writel(27, INTC_EISR); // 使能系统事件27步骤6全局使能INTC打开总开关。writel(1, INTC_GER); // 全局使能步骤7ARM侧中断配置在ARM Linux侧你需要确保设备树Device Tree正确配置了PRUSS和pruss_intc节点并将PRUSS_EVTOUT0映射到ARM GIC的某个中断号。在驱动程序中申请这个中断号并注册中断处理函数。在中断处理函数中同样需要清除INTC中的事件状态否则中断会持续触发。// 在ARM驱动中断处理函数中 static irqreturn_t my_pruss_isr(int irq, void *dev_id) { // 1. 读取HIPIR2主机中断2的优先级索引寄存器获取触发的事件号 uint32_t event_num readl(INTC_HIPIR(2)) 0x3F; // 低6位是事件号 printk(KERN_INFO PRUSS Interrupt! Host Int2, Event: %d\n, event_num); // 2. 清除INTC中的事件状态至关重要 writel(event_num, INTC_SICR); // 或 writel(1 event_num, (event_num32)?INTC_SECR0:INTC_SECR1); // 3. 处理你的业务逻辑... return IRQ_HANDLED; }3.4 配置流程总结与脚本化将上述步骤整合成一个初始化函数void pruss_intc_init_for_gpio_event27(void) { // 1. 映射事件27 - 通道0 uint32_t cmr6_val readl(INTC_CMR(6)); cmr6_val ~(0xFF 24); cmr6_val | (0x00 24); // 通道0 writel(cmr6_val, INTC_CMR(6)); // 2. 映射通道0 - 主机中断2 (ARM) uint32_t hmr0_val readl(INTC_HMR(0)); hmr0_val ~(0xFF 0); hmr0_val | (0x02 0); // 主机中断2 writel(hmr0_val, INTC_HMR(0)); // 3. 清除旧状态 writel(27, INTC_SICR); // 4. 使能主机中断2 writel(2, INTC_HIEISR); // 5. 使能系统事件27 writel(27, INTC_EISR); // 6. 全局使能 writel(1, INTC_GER); printk(PRUSS INTC configured: Event27( GPIO0 ) - Ch0 - HostInt2(ARM)\n); }4. 高级主题中断嵌套与优先级实战PRU INTC支持硬件中断嵌套这对于构建复杂的多优先级实时任务系统非常有用。嵌套的核心思想是当高优先级中断正在服务时临时屏蔽掉相同或更低优先级的中断只允许更高优先级的中断打断当前服务。4.1 嵌套的三种模式INTC提供了三种嵌套方法对应不同的控制粒度1. 全局基于通道的嵌套Global Nesting这是最简单的方式。当一个中断被接受时INTC会自动将“嵌套等级”设置为该中断所在通道的编号。此后所有通道号大于等于该等级的中断都会被屏蔽只有通道号小于该等级即优先级更高的中断才能触发新的主机中断。控制寄存器全局嵌套等级寄存器GNLR。你可以读取它来了解当前被屏蔽的最低通道号也可以手动设置它。工作流程中断发生时硬件自动更新GNLR中断返回前软件需要将GNLR恢复通常设置为一个比所有通道都大的数如10以解除所有嵌套屏蔽。2. 主机独立基于通道的嵌套Host Individual Nesting这种方式为每个主机中断0-9维护独立的嵌套等级。当中断发生在某个主机中断上时只影响该主机中断的通道屏蔽其他主机中断的中断触发不受影响。这提供了更灵活的隔离性。控制寄存器主机中断嵌套等级寄存器HINLR1和HINLR2。每个主机中断对应一个字段。适用场景当你将不同功能域的中断分配到不同的主机中断时例如通信中断给Host2电机控制中断给Host3希望它们之间的嵌套互不干扰。3. 软件手动嵌套Software Manual Nesting最灵活但最复杂。在中断服务程序中软件手动操作HIEISR或EISR/ECR来禁用/启用特定的主机中断或系统事件。流程进入ISR后禁用所有主机中断或特定中断然后根据需要精细地修改系统事件使能位最后再重新使能主机中断。退出ISR前恢复原状。优点可以实现任意复杂的嵌套策略不局限于通道优先级。缺点软件开销大容易出错。4.2 配置示例实现全局嵌套假设我们配置了三个中断源并希望实现嵌套事件10高优先级 - 通道0 - 主机中断2事件20中优先级 - 通道2 - 主机中断2事件30低优先级 - 通道4 - 主机中断2它们的优先级顺序是事件10 事件20 事件30因为通道024且事件号102030。在ARM的中断服务程序中我们需要操作GNLRstatic irqreturn_t pruss_high_priority_isr(int irq, void *dev_id) { uint32_t event_num readl(INTC_HIPIR(2)) 0x3F; uint32_t channel (readl(INTC_CMR(event_num / 4)) ((event_num % 4) * 8)) 0xFF; // 进入ISR时INTC可能已自动设置了GNLR。但我们显式设置以确保。 // 假设我们想屏蔽本通道及更低优先级通道号更大的通道。 // 注意GNLR的值表示被屏蔽的最低优先级通道号。设置GNLRchannel意味着通道号 channel 的被屏蔽。 writel(channel, GNLR_REG_ADDR); // 屏蔽当前及更低优先级通道 // ... 处理高优先级任务 ... // 清除当前中断状态 writel(event_num, INTC_SICR); // 退出ISR前恢复GNLR允许所有中断。设置一个大于最高通道号的值如10。 writel(10, GNLR_REG_ADDR); return IRQ_HANDLED; }当中断事件10触发并进入此ISR后GNLR被设为0。此时通道0、2、4的中断因为通道号0都会被INTC硬件屏蔽不会向主机ARM发起新的中断请求。但是如果有一个更高优先级的中断比如映射到通道-1不通道号最小是0是不存在的所以实际上在事件10的服务过程中事件20和30都无法打断它。只有当事件10的ISR执行完毕将GNLR恢复为10后被挂起的事件20或30才会被递交给ARM。重要提示GNLR、HINLR等嵌套寄存器位于INTC寄存器空间内其具体偏移地址需要查阅更详细的寄存器手册。上述代码中的GNLR_REG_ADDR是一个示例你需要替换为正确的地址例如(PRUSS_INTC_BASE 0x1C)请务必核对所用芯片的TRM。5. 调试技巧与常见问题排查调试PRU INTC就像侦探破案需要系统地检查各个环节。以下是我在实际项目中总结的排查清单和工具。5.1 问题排查流程图当“中断不触发”或“中断行为异常”时可以按以下步骤排查1. 中断源是否产生 ├─ 确认外设如GPIO、ePWM已正确配置并产生中断信号。 └─ 使用逻辑分析仪或示波器测量物理引脚或读取外设中断状态寄存器。 2. INTC输入是否有效 ├─ 读取SRSR1/SRSR2原始状态寄存器查看对应事件位是否置1。 ├─ 若SRSR无变化检查PRUSSEVTSEL配置CFGCHIP3[3]确认事件源选择正确。 └─ 检查系统事件编号是否正确查阅芯片特定TRM。 3. INTC内部通路是否畅通 ├─ 检查事件使能位EISR/ESR是否已设置。 ├─ 检查通道映射CMRx是否正确。 ├─ 检查主机中断映射HMRx是否正确。 ├─ 检查目标主机中断使能位HIEISR是否已设置。 └─ 检查全局使能GER是否为1。 4. INTC输出是否送达 ├─ 对于PRU中断Host0/1PRU程序是否在轮询R31[30]或R31[31]或者是否使能了PRU的事件触发模式 ├─ 对于ARM中断Host2-9 ├─ 检查设备树中pruss_intc的interrupts属性是否正确映射到ARM GIC。 ├─ 在Linux下检查/proc/interrupts看对应的ARM中断号计数是否增加。 └─ 确认ARM驱动已正确request_irq且中断处理函数已注册。 5. 中断状态是否被清除 └─ 这是最常见的问题在ISR中必须读取HIPIR获取事件号并向SICR写入该事件号以清除SECR状态位。未清除会导致中断只触发一次或持续触发。5.2 实用调试工具与命令内存查看在Linux用户空间使用devmem2工具直接读取INTC寄存器验证配置。# 读取事件27的通道映射 (CMR6) devmem2 0x01C340000x406*4 # 读取主机中断2的HIPIR查看 pending 的最高优先级事件 devmem2 0x01C340000x2002*4 # 读取SECR0查看事件0-31的使能状态 devmem2 0x01C340000x80中断状态监控cat /proc/interrupts。找到你的PRUSS EVTOUT对应的ARM中断行观察中断计数是否在预期事件发生时增加。PRU侧调试在PRU汇编/C代码中可以通过写寄存器的方式操作INTC也可以读取R31来检查Host Int0/1的状态。更高级的调试可以使用TI的CCSCode Composer Studio进行单步调试和寄存器查看。5.3 常见坑点与解决方案坑点1中断触发一次后不再触发。原因中断状态位没有清除。INTC的“使能状态”SECR在事件被处理并传递给主机后需要软件手动清除。如果不清除INTC会认为该中断一直处于活动状态不会响应新的相同事件。解决确保在ISR无论是PRU还是ARM的末尾执行状态清除操作。使用SICR寄存器清除更安全、简洁。坑点2中断疯狂触发进入死循环。原因1中断源是电平触发且持续为高。INTC要求输入是脉冲但有些外设中断输出可能是电平。虽然INTC前端有处理但如果电平持续可能产生问题。解决1检查外设中断配置确保是边沿触发模式。或者在ISR中尽快清除外设本身的中断标志。原因2清除中断状态的代码有误例如写错了寄存器或位导致状态位实际没被清除。解决2在ISR中读取HIPIR获取事件号然后用这个事件号去写SICR避免硬编码错误。坑点3多个中断同时发生只有高优先级的被处理低优先级的丢失了。原因这是INTC硬件优先级仲裁的正常行为。如果高优先级中断的服务时间很长低优先级中断可能一直得不到响应。解决优化高优先级ISR的执行时间尽量短小精悍。或者考虑使用不同的主机中断来分离不同优先级域的中断避免它们在同一仲裁池中竞争。对于绝对不能丢失的中断可以考虑提升其通道优先级。坑点4PRU收不到Host Interrupt 0/1。原因PRU默认不会因为R31[30/31]置位而跳转。PRU有两种方式响应轮询在循环中不断检查R31[30/31]。事件触发需要配置PRU的CONTROL寄存器或使用HALT指令等待中断。更常见的是PRU程序在需要等待中断时执行一个HALT指令进入低功耗状态当中断到来时PRU会被唤醒并从HALT后的指令继续执行。但这需要正确配置PRU的唤醒源WAKEUP寄存器。解决明确你的PRU程序设计模式。如果是轮询确保代码路径能执行到检查R31的语句。如果是事件触发确保正确配置了唤醒机制。坑点5ARM侧/proc/interrupts显示中断计数增加但自定义的驱动ISR没被调用。原因驱动中断处理函数注册失败或者申请的中断号与设备树映射的不匹配。解决检查request_irq的返回值。使用cat /proc/interrupts确认中断号是否正确以及中断是否被正确分配到你的驱动名下而不是“nobody”。仔细核对设备树中interrupts ...;属性的值。6. 性能考量与最佳实践在实时系统中中断延迟和确定性是关键。以下是一些优化PRU INTC使用的建议精简ISR中断服务程序无论是PRU还是ARM的ISR执行时间应尽可能短。只做最紧急的状态读取、标志清除和简单计算。将非实时任务推迟到主循环或工作队列中。合理分配通道优先级将最紧急、最频繁的中断分配到编号小的通道如0,1。将非紧急或后台任务的中断分配到编号大的通道如8,9。善用多个主机中断不要把所有中断都映射到同一个主机中断如都映射到Host2给ARM。这会导致所有中断在INTC内部排队仲裁增加延迟。可以根据功能模块划分将电机控制中断映射到Host2通信中断映射到Host3这样它们在INTC出口处就是并行的。PRU处理时间关键中断对于需要极低延迟微秒级的中断优先考虑让PRU来处理映射到Host0或Host1。PRU的响应是确定性的没有操作系统调度开销。避免在ISR中操作INTC映射寄存器CMR、HMR等配置寄存器在系统初始化时设置好之后运行时尽量不要修改。动态重映射会增加复杂性和不确定性。状态清除的原子性使用SICR写入事件编号来清除中断状态而不是直接写SECR。SICR是原子操作可以避免在多核或复杂中断场景下的竞态条件。充分利用嵌套功能对于有明确优先级关系的多级中断合理配置嵌套尤其是全局嵌套可以确保高优先级任务不被低优先级任务阻塞提高系统的实时性。通过深入理解PRU中断控制器的架构、熟练掌握其配置方法、并运用有效的调试手段和最佳实践你就能在基于TI Sitara处理器的嵌入式实时项目中构建出稳定、高效、响应迅速的中断管理系统。这不仅仅是配置几个寄存器更是对硬件实时调度机制的一种深度掌控。