RISC-V APLIC 中断模块总结——第一篇

一句话先看懂

APLIC = 高级平台级中断控制器(Advanced Platform-Level Interrupt Controller) ,是 RISC-V 高级中断架构(AIA / RTIA)里放在 SoC 侧、专门采样外设有线中断、按优先级仲裁、再打包成 MSI 消息发给 CPU 的那个硬件。

它本身不直接触发 CPU 中断 ,而是通过一条 DMSI 消息总线 把中断"投递"给每个核内部的 IMSIC(中断文件),最终由核内的 mtopei/stopei 这类 CSR 读出"当前最高优先级中断的编号"来响应。

核心结论速览(先记住这 5 条)

|---|-----------------------------------------|---------------------------------------------------|
| # | 结论 | 一句话解释 |
| 1 | 不是 NXP 那种"读 IACKR/写 EOIR"的中断控制器 | RISC-V AIA 用 topei CSR 读编号、写 0 完成,没有独立的"优先级寄存器" |
| 2 | 优先级 = 中断编号(EIID) | EIID 越小优先级越高,不需要像 NXP 那样单独配置 PRI 字段 |
| 3 | 两级 APLIC 级联 | APLIC2(256 路)→ DMSI → APLIC1(1023 路)→ DMSI → 4 个核 |
| 4 | 三级域(Domain) | M(机器域)> S0(监管者域0)> S1(监管者域1),决定中断归属的特权级 |
| 5 | 芯片为了兼容 NXP,还在 APLIC 里"嵌套"了一个老式 INTC | 用于平滑迁移 PPC 老代码,未来版本会移除 |

文档导航(按阅读顺序)

|-------------------------------------------------------|----------------------------------------------|--------------------|
| 文档 | 内容 | 适合什么时候看 |
| 01_模块构成与工作原理 | APLIC 是什么、内部子模块、级联拓扑、DMSI 投递、优先级仲裁规则 | 第一遍,建立整体认知 |
| 02_中断触发链路与响应机制 | 从外设中断到 CPU 执行 ISR 的完整链路,以及 topei/阈值/三种处理模式 | 想搞懂"中断到底怎么流到我的代码" |
| 03_关键寄存器详解 | 必须重点关注的寄存器 + 完整寄存器映射表 | 需要查寄存器、写裸机驱动时 |
| 04_代码配置与常用方式 | MCAL Irq 模块的初始化流程、配置项含义、三种常用配置方式 | 实际动手配中断时 |
| 05_与NXP_MPC5777M_INTC对比 | 和 5777M 的 INTC 逐项对比 + 迁移要点 | 从 NXP 平台迁移、或想理解差异时 |

01 · APLIC 模块构成与工作原理

1.1 APLIC 是什么

APLIC(Advanced Platform-Level Interrupt Controller,高级平台级中断控制器)是 RISC-V 高级中断架构(AIA,本芯片内核文档中也称 RTIA) 定义的三个中断控制器之一。三者分工如下:

|-----------|-----------|------------------------------------------|
| 控制器 | 位置 | 职责 |
| CLINT | 核内 | 管理 hart 本地中断:定时器、软件中断、外部中断入口 |
| IMSIC | 核内 | 接收 MSI 消息,维护"中断文件"(pending / enable 位数组) |
| APLIC | SoC 侧(核外) | 采样外设有线中断 → 仲裁 → 打包成 MSI 消息投递给 IMSIC |

一句话:CLINT 管"本地",IMSIC 管"消息落地",APLIC 管"外设有线中断的采集与派发"

⚠️ 注意:上面有两条 中断输入路径。接在 APLIC1 上的源(IRQ1023:1)只经过 APLIC1,不经过 APLIC2 ;只有接在 APLIC2 上的源(IRQ1279:1024)才需要先经 APLIC2、再经 APLIC1 两级级联。详见 02 篇 2.1

1.2 CCRC4046S 上的实际拓扑:两级级联

CCRC4046S 有 2 个 APLIC 实例,采用级联(chain)方式:

|--------|--------|--------------|-------------------------------------|
| 实例 | 中断源数量 | 基地址 | 作用 |
| APLIC1 | 1023 路 | 0xF0A00000 | 主控制器,直接处理自己的 1023 路 + 接收 APLIC2 的消息 |
| APLIC2 | 256 路 | 0xF0A20000 | 从控制器,采样 256 路后转成 DMSI 发给 APLIC1 |

级联后最大支持 1279 路中断输入 ,最终由 APLIC1 统一生成 DMSI 消息发给 Core0 ~ Core3(共 4 个 hart)。

能不能不配 APLIC2?

  • 可以不用 APLIC2:如果只用 APLIC1 的 1023 路源,APLIC2 可以完全不去初始化(保持复位、不产生任何上游 DMSI),APLIC1 独立工作即可,中断照常响应。
  • 不能只用 APLIC2、不用 APLIC1:APLIC2 是"从"控制器,它的源必须先把中断打包成上游 DMSI 发给 APLIC1,再由 APLIC1 统一投递给 hart。没有 APLIC1,APLIC2 的源到不了核。
  • 外设有线中断不能完全绕过 APLIC:本芯片外设中断是有线信号直接接在 APLIC 引脚上的,必须经 APLIC 采样仲裁后才能变成 MSI 进 IMSIC。除非外设本身支持 MSI/MMSI 直连 IMSIC(本芯片不涉及),否则"跳过 APLIC 直接响应有线中断"不成立。

1.3 APLIC 内部子模块

手册(82.3)给出的 APLIC 结构图包含以下子模块:

|--------------------|----------------------------------------|
| 子模块 | 说明 |
| Registers | APLIC 寄存器组,配置中断优先级、目标 CPU 等信息 |
| M_LEVEL | 机器域(Machine Domain)中断请求处理 |
| S_LEVEL | 监管者域(S0/S1 Domain)中断请求处理 |
| Front End | AHB 总线接口,处理主机对 APLIC 寄存器的访问 |
| IRQ Processing | 同步并采样中断请求 |
| Safety | 功能安全机制:锁步、ECC、EDC 校验 |
| Safety Monitor | 监测并收集功能安全报错信号 |
| Priority | 中断优先级仲裁 |
| IRQ GEN | 按 DMSI 格式生成中断请求消息 |
| CPC | 根据 master id 判断对 APLIC 寄存器访问是否有效(访问保护) |

1.4 三个"域"(Domain)的概念

每个 APLIC 支持 3 个域 ,对应不同的特权级别,这是理解 APLIC 的核心概念

|-----------|---------------------------|--------------|-------------|
| 域 | 全称 | 对应特权级 | 寄存器偏移区 |
| M Domain | Machine Domain(机器域) | M 模式 | 0x8000 起 |
| S0 Domain | Supervisor0 Domain(监管者域0) | S 模式 | 0xC000 起 |
| S1 Domain | Supervisor1 Domain(监管者域1) | S 模式(可做嵌套子域) | 0x10000 起 |

关键点

  • 同一个中断源,可以在 M / S0 / S1 三个域里各有一份独立的配置(sourcecfg、pending、enable、target)。
  • 委托(delegate)机制 :只有 M 域的 SOURCECFG 有 D 位 (S0/S1 域的 SOURCECFG 没有 D 位,只有 SM 触发方式)。所以委托是单向 的:只能由 M 域把某个源"委托"给 S0 或 S1(通过 M 域 SOURCECFG.D=1 + SM 选目标)。S0/S1 域不能自己去"抢"一个 M 域未委托的源------一个源要进 S 模式处理,必须先由 M 域把它委托下来。
  • 域之间存在优先级:M > S0 > S1(S1 作为 S0 子域时最低) 。这里的"子域"指优先级从属关系,不是委托关系。

1.5 中断如何"投递":DMSI 消息

APLIC 不通过电平信号直接连 CPU,而是把仲裁出的中断打包成一条 DMSI(Direct Message Signaled Interrupt)消息,通过 DMSI 总线投递。一条 DMSI 消息携带 3 个字段:

|---------------------------------|-----------------------------------|
| 字段 | 含义 |
| HART_ID | 目标 hart(03,对应 Core0Core3) |
| CONTEXT(Guest_Index) | 为 0 表示监管者中断文件,非 0 表示客户(虚拟机)中断文件 |
| EIID(External Interrupt ID) | 在目标中断文件里的"中断位"编号,同时就是这个中断的优先级 |

DMSI 网络的特点:

  • 树状拓扑 + 基于信用(credit)的流控,避免"队首阻塞"(一个 hart 忙不会堵住发往其他 hart 的消息)。
  • 与 IMSIC 直接连接时(DMSI 模式),APLIC 是 IMSIC 中断文件的独占中断源,保证实时性和优先级顺序。

1.6 优先级仲裁规则

APLIC 从"已使能(enabled)且已挂起(pending)"的中断里选出最高优先级:

  1. 先比域:M 域 > S 域(S0/S1)。S1 作为 S0 子域时优先级最低。
  1. 再比 hart :同一域内用**循环仲裁(RR)**选 hart 索引。
  1. 再比 EIID :同一 hart 的多个中断,EIID 越小优先级越高
  1. 最后比中断索引 :同一 hart 同一 EIID 的多个中断,索引越小优先级越高

另一种可选的仲裁模式(APLIC_CTL.PTY_M)是"Hart 公平轮询",基于 HART_ID 做 RR,可以避免某域持续抢占导致某些 hart 中断延迟无界。

1.7 功能安全(ASIL-D)

APLIC 恒定受 ASIL-D 级保护,主要安全机制:

  • 双核锁步(DCLS / lockstep):双份逻辑比对。
  • ECC / EDC 校验:寄存器、数据通路。
  • E2E(端到端)校验:解码器冗余检查。
  • 线中断双轨保护、溢出保护
  • 自动启动 FSM :复位后自动跑一轮安全诊断错误注入,aplic_safety_enabled 拉高表示自检完成。
  • 相关寄存器集中在安全寄存器块(偏移 0x4000 起):SFTY_PASSWDSFTY_CTRLSFTY_DIAGSFTY_BUILDSFTY_ERR_STASFTY_LAT_ERR

02 · 中断触发链路与响应机制

这一篇回答两个问题:一个外设中断,从引脚电平到最后执行 ISR,中间经过了什么? 以及 CPU 到底怎么"响应"和"结束"这个中断?

2.1 完整触发链路(一图看懂)

关键:芯片有 APLIC1 和 APLIC2 两个实例,中断源接在哪一级,走的路径就不同。下面两条路径都画出来。

要点:

  • 路径 A :接在 APLIC1 上的源(IRQ1023:1)只经过 APLIC1,不经过 APLIC2
  • 路径 B :接在 APLIC2 上的源(IRQ1279:1024)必须先经 APLIC2 采样仲裁,打包成上游 DMSI 发给 APLIC1,再由 APLIC1 和自己的 1023 路源统一仲裁后投递给 hart。
  • 无论哪条路径,最终都是 APLIC1 统一发出 DMSI 消息到目标 hart 的 IMSIC。

2.2 分步拆解

第 1 步:外设发出中断请求

外设按配置的触发方式(上升沿 / 下降沿 / 高电平 / 低电平)在引脚上给出中断信号。

第 2 步:APLIC 采样 + 仲裁

APLIC 的 IRQ Processing 子模块同步采样中断信号,Priority 子模块按 01 篇 1.6 节的规则 选出"最高优先级的已使能 + 已挂起中断"。

第 3 步:打包成 DMSI 消息

IRQ GEN 子模块把选中的中断按 TARGET_N 寄存器里的配置,打包成一条 DMSI 消息(HART_ID + Context + EIID)发出去。

第 4 步:IMSIC 中断文件落地

消息到达目标 hart 的 IMSIC 后,把中断文件里 pending[EIID] 位置 1(前提是该 EIID 在核内已使能)。

第 5 步:核陷入主要中断

pending + enabled 成立后,IMSIC 向核发出外部中断信号。核陷入对应的主要中断(Major Interrupt)

|-------|------|------------------|
| 主要中断号 | 名称 | 含义 |
| 11 | MEI | M 模式外部中断 |
| 9 | SEI | S 模式外部中断 |
| 10 | VSEI | VS 模式(虚拟监管者)外部中断 |

第 6 步:读 topei CSR 拿编号

核在外部中断入口里读取对应特权级的 topei CSR (读"当前最高优先级外部中断"),返回的数值就是 EIID

|------------------|-------|------------------------------------------|
| CSR | 特权级 | 代码中的读取位置 |
| mtopei(0x035C) | M 模式 | MI11_Handlercsrrw t1, mtopei, t0 |
| stopei | S 模式 | MI9_Handlercsrrw t1, stopei, t0 |
| vstopei | VS 模式 | MI10_Handlercsrrw t1, vstopei, t0 |

注意代码用的是 csrrw(读后写),写入 t0(=0),这本身就是**"读编号 + 完成中断"合并成一条指令**的技巧。

第 7 步:跳转 ISR

以 EIID 为下标查向量表(m_AplicIsrVectorTable[hart][eiid] / s_AplicIsrVectorTable),取出函数地址并跳转执行。

第 8 步:完成中断

ISR 执行完后,向对应 topei CSR 写 0 完成中断(同时把硬件阈值栈弹栈,恢复之前的中断阈值)。

2.3 响应机制的核心概念

2.3.1 中断文件(Interrupt File)

IMSIC 为每个特权模式维护一个"中断文件",本质是两个大小相同的位数组

  • pending 数组:记录"已到达但未处理"的中断;
  • enable 数组:指定"hart 当前接受哪些中断"。

同一个位下标 = 同一个中断标识(EIID)。

中断文件大小(File Size) :手册 14.4.10 规定,每个中断文件支持的中断标识数量 n64 的倍数(64 / 128 / 192 / 256,256 为最大)。这里有两个特别容易混的数字:

|-------------------|---------------|-------------------------------------------|
| 量 | 值 | 说明 |
| 文件大小 n(标识位数组长度) | 64 的倍数,最大 256 | 手册称"中断标识的数量",也把它叫做中断文件大小 |
| 有效中断标识号 | 1 ~ n-1 | 标识号 0 永远无效 |
| 实际可用中断数 | n-1 | 手册原话:"外部中断实际数量 = imsic_{x}_file_size - 1" |

所以"文件大小 256"对应的是 255 个有效 EIID(1~255) ,而不是 256 个。本芯片 S 模式文件大小取 256(有效 EIID 1255)、M 模式取 64(有效 EIID 163),与 82.2 节"M 最多 63 级 / S 最多 255 级"一致(详见 2.3.5)。

2.3.2 优先级 = EIID

在一个中断文件内,优先级直接由 EIID 决定,EIID 越小优先级越高(手册 14.4.12)。因此:

  • 不存在像 NXP INTC 那样的独立"优先级寄存器";
  • 想给某个外设中断"更高优先级",就给它分配更小的 EIID

但这只是外部中断 的规则。本地中断(CLINT 的定时器/软件中断/调试等)的优先级不是由 IID 决定的 ,而是由 iprio[i] 寄存器单独配置(手册 14.4.24):

  • 本地主要中断的有效优先级 = iprio[i](未配置时 iprio[i]==0);
  • 外部主要中断的有效优先级 = EIID
  • 嵌套向量模式下,本地中断的 iprio 值会被当作 EIID 报告,于是本地 + 外部统一"以 EIID 比优先级"

2.3.3 阈值(eithreshold)与嵌套

  • eithreshold 寄存器会屏蔽优先级 ≤ 阈值的所有外部中断=0 表示全开。
  • 嵌套向量模式下,IMSIC 维护一个硬件阈值栈:每进入一个中断,硬件自动把该中断的优先级压入阈值栈(从而只允许更高优先级的中断抢占);写 0 到 topei 时弹栈恢复。

2.3.4 三种中断处理模式(直接 / 向量 / 嵌套向量)

CRV6 内核(CCRC4046S 的 CPU)支持三种 中断处理模式,由 mtvec/stvec 的 MODE 字段(以及内核配置选项 -rtia_snvi)决定。手册把它们分成两类:直接 + 向量 (RISC-V AIA 标准模式)和嵌套向量(CRV6 专有扩展)。

|--------------|-----------------------------------------------------------------------|---------------------------------------------------|------------------------------|
| 维度 | ① 直接模式 (Direct) | ② 向量模式 (Vectored) | ③ 嵌套向量模式 (Nested Vectored) |
| mtvec.MODE | 0 | 1 | 3(CRV6 扩展) |
| 谁当"主"中断控制器 | CLINT | CLINT | IMSIC(CLINT 退为辅助) |
| 中断识别步骤 | 3 步 :trap 入口看 mcause → 读 mtopi 拿主要中断号 IID → 读 mtopei 拿 EIID | 2 步 :硬件按 IID 直接跳向量表;但外部中断仍要再读 mtopei 拿 EIID | 1 步:所有中断(含本地)统一用 EIID 识别 |
| 本地中断怎么识别 | 软件读 mtopi | 硬件按 IID 直接跳表 | 按 EIID(经 IMSIC 文件)跳表 |
| 外部中断怎么识别 | 软件读 mtopei | 仍要读 mtopei(所有外部中断共享同一个向量表条目) | 按 EIID 直接跳表(不再读 topei 二次识别) |
| 向量表 | 无(所有陷阱共用一个入口,软件分发) | 64 条,按主要中断号 IID 索引 | 最多 256 条,每个 EIID 一条 |
| 中断阈值 | 软件 eithreshold(只影响外部中断) | 软件 eithreshold | 硬件自动维护阈值栈,低延迟嵌套抢占 |
| 嵌套抢占 | 软件自行处理 | 软件自行处理 | 硬件自动压/弹阈值栈 |

mtopimtopei 别搞混mtopi(Machine Top Interrupt )读的是主要中断(本地,IID)mtopei(Machine Top External Interrupt ,多一个 e = external)读的是外部中断(EIID) 。两者都返回"标识号 + 优先级",读到 0 表示没有待处理且已使能的对应中断(手册 14.4.26)。S 模式对应的是 stopi(本地)/ stopei(外部)。嵌套向量模式下本地中断也走 IMSIC 当 EIID 报告,所以这时统一读 mtopei/stopei 即可。

三句话讲清区别

  1. 直接模式 :最"原始",所有陷阱共用一个入口,软件要一层层剥:先看是不是中断(mcause),再看是哪个主要中断(mtopi 的 IID),最后看是哪个外部中断(mtopei 的 EIID)。优点是不需要向量表,缺点是外部中断要三步才定位到 ISR。
  1. 向量模式 :让硬件帮忙做第一步------mtvec 配成向量模式后,硬件按主要中断号(IID)直接跳到对应向量表条目。但外部中断仍然"一刀切" :所有外部中断共享同一个主要外部中断条目,进去后还是要读 mtopei 拿 EIID、再查一次表。所以本地中断是"一步到位",外部中断仍是"两步"。
  1. 嵌套向量模式 (CRV6 专有):把 CLINT 的本地中断也改走 IMSIC,于是本地中断和外部中断统一用 EIID 一个编号识别 ,硬件按 EIID 一步跳到独立向量表条目(向量表最多 256 个条目,其中索引 0 给异常处理程序,有效 EIID 是 1~255 ),并用硬件阈值栈自动管理嵌套抢占------这是为实时低延迟抢占做的增强。

本芯片 MCAL 用哪种? 代码里:

复制代码

默认是 ② 向量模式(TRAP_VECTORED_MODE,MODE=1) ,不是嵌套向量模式。对应地,major_interrupt.cMI11_Handler/MI9_Handler 里是先读 mtopei 拿到 EIID,再用 m_AplicIsrVectorTable[hart][eiid] 查表跳转------这正是"向量模式下外部中断两步识别"的体现。若要启用嵌套向量模式,把 TRAP_HANDLING_MODE 改成 TRAP_NESTED_VECTORED_MODE(MODE=3)重新编译即可(代码已提供对应实现)。

2.3.5 中断源到底跟"EIID"还是"IID"对应?(附手册章节)

这是最容易绕晕的一点。一句话结论:

外设中断源(APLIC 采集的)→ 对应 EIID;本地中断源(CLINT 的定时器/软件中断/调试/RAS/看门狗)→ 对应 IID。

芯片里其实有两套并列的编号体系,各管一类中断:

|----------|-------------------------------|--------------------------------------------------------------------------------------------------|-----------------------------------|---------------------------------------------|
| 编号 | 全称 | 管哪些中断 | 谁来分配 | 手册位置 |
| IID | 主要中断标识(Major Interrupt ID) | 核内本地中断:软件中断(SSI/MSI)、定时器(STI/MTI)、外部中断入口(SEI/MEI)、计数器溢出(COV)、调试(DBG)、RAS(LRAS/HRAS)、看门狗(WDT) | 硬件固定(IID 0~63) | 14.4.21 节 表 14-7 |
| EIID | 外部中断标识(External Interrupt ID) | APLIC 采集的外设中断(1279 路) | 软件在 APLIC TARGET_N.EIID配置 | 82.5.2.25 (寄存器)、7.3.7.2 表 7-19(源列表) |

几点关键理解:

  1. IID 是"内核自带本地中断"的编号 ,硬件固定,共 64 个(IID 0~63)。完整对照表在手册 14.4.21 节 表 14-7------例如 IID=11 是 M 模式外部中断 MEI、IID=7 是 M 定时器 MTI、IID=3 是 M 软件中断 MSI、IID=48 是看门狗 WDT。
  1. EIID 是"外设中断"的编号 ,它是 IMSIC 中断文件里的一个位,同时就是该中断的优先级 (越小越高)。注意:"哪个外设源配哪个 EIID"不是手册写死的 ,而是软件在 APLIC 的 TARGET_N.EIID 字段里配的(见 03 篇 3.1 ④)。外设源本身的列表(IRQ 号 → 哪个外设的哪一路中断)在手册 7.3.7.2 节 表 7-19
  1. 两种模式下编号体系会"合并"

    • 直接 / 向量模式 :本地中断用 IID、外部中断用 EIID,两层识别。
    • 嵌套向量模式 :CLINT 把本地中断也改走 IMSIC,用 iprio 配置的优先级值当作 EIID,于是本地 + 外部统一用 EIID(一层)。

回到"256 条 EIID → 只能 245 个外部中断?"的疑问:

  • 手册的"256"指嵌套向量模式下向量表最多 256 个条目(索引 0~255) ,其中索引 0 固定给异常处理程序 ,所以有效 EIID 是 1~255,共 255 个(不是 245)。
  • 而且这 255 是 S 模式 的数字;M 模式最多只有 63 个(EIID 1~63)(手册 82.2 节)。
  • 更关键:这 255 / 63 个 EIID 是本地中断和外部中断共享 的编号空间。嵌套向量模式下,本地中断(通过 iprio)也会占掉一部分 EIID,剩下的才分配给 APLIC 外设中断。所以"外部中断能有多少个"= 总 EIID 数 − 本地中断占用的数量,既不是 256,也不是 245。
  • 本芯片 MCAL 代码把 M 和 S 的向量表都定义成 64(HART_M_EIID_MAX/HART_S_EIID_MAX = 64,见 2.4),即当前配置里 M 模式用 EIID 1~63,S 模式也先按 64 条处理(手册说 S 最多可到 255,用满需自行扩展向量表)。

2.4 代码视角的链路(对应源码文件)

|----------------|----------------------------------------------------------------------------------------------------------------|
| 环节 | 源码位置 |
| 外部中断向量入口 | Source/common/vector_riscv/major_interrupt.cMI11_Handler(MEI) / MI9_Handler(SEI) / MI10_Handler(VSEI) |
| 读 topei + 查表跳转 | 上述 handler 内 csrrw t1, mtopei/stopei/vstopei + jalr t3 |
| 向量表定义 | Source/common/vector_riscv/vector_riscv.hm_AplicIsrVectorTable[RESOURCE_CHIP_CORE_NUM][HART_M_EIID_MAX] |
| 保存/恢复现场 | vector_riscv.hSAVE_CONTEXT / RESTORE_CONTEXT / S_SAVE_CONTEXT 宏 |

关键向量表大小

复制代码

注意:手册说 S 模式最多支持 255 个优先级(EIID 1~255),但当前 MCAL 代码把 HART_S_EIID_MAX 定义为 64,若用到 64 以上的 S 模式 EIID 需要核对。

2.4.1 两级向量表:mtvecm_AplicIsrVectorTable

外部中断最终到 ISR,其实经过两张表,别混为一谈:

|-----|------------------------------------------------|---------------------------------------------------------|
| | 硬件陷阱向量表 | 软件分发表 |
| 符号 | m_trap_vector.m_trap 段) | m_AplicIsrVectorTable[核][64].m_irq_vector_table 段) |
| 挂在哪 | mtvec(0x0305)= &m_trap_vector | MODE | 不挂任何 CSR,普通全局数组 |
| 索引 | 按 IID (64 条 j MIx_Handler 跳转) | 按 EIID(存函数指针) |

  • 没有 IVPR/IVOR (那是 PPC/MPC57xx 的寄存器)。RISC-V 对应 IVPR 角色的是 mtvec/stvec/vstvec;也没有 IVOR0~15 那种"每源一个偏移寄存器",所有陷阱统一由 mtvec 表按 IID 索引。
  • mtvecMcu_core_riscv.hHart_M_GlobalInterruptEnable() 里初始化:RV_CSR_WRITE(CSR_MTVEC, (uint32)&m_trap_vector | TRAP_VECTORED_MODE);

查表跳转(major_interrupt.cMI11_Handler)是运行时动态查,不是编译期绑定:

复制代码

表内容由 Irq.cIrq_sInterruptSourceInit() 在初始化时填:m_AplicIsrVectorTable[CoreId][eiidIdx] = (uint32)IrqHandler;

2.4.2 相同 EIID 的中断:回调会冲突,且无法区分

DMSI 消息只有 HART_ID + Context + EIID 三个字段(手册 82.4.1),不携带中断源索引。所以:

  • 多个源配同一个 EIID 是允许的,硬件仲裁时用 source index 比优先级(82.4.3),但投递给 IMSIC 时只送 EIID ------ 它们在 IMSIC 里共享同一个 pending[EIID] ,CPU 读 mtopei 只能拿到 EIID。
  • 软件向量表按 EIID 一维索引,同 EIID 只有一格;初始化是直接赋值 = IrqHandler后初始化的源会覆盖先初始化的,最终只剩一个 handler。
  • 因此相同 EIID 的回调就是同一个,代码区分不了是哪个源触发 。正确用法是 Irq_Cfg.c同一核内 EIID 不能重复 。真要区分,只能在 ISR 里读 APLIC 的 SOURCE_PENDING 源挂起寄存器逐个查,或给不同源分配不同 EIID。
相关推荐
国科安芯1 天前
卫星电源管理系统中高可靠MCU的功耗特性与电源监控功能分析
人工智能·单片机·嵌入式硬件·mcu·安全·电源管理系统·抗辐射
qq_402995751 天前
诊断协议栈配置Agent
arm开发·人工智能·stm32·单片机·mcu
国科安芯1 天前
小卫星综合电子系统中功能安全与抗辐射加固的协同设计研究
嵌入式硬件·安全·架构·risc-v·抗辐射·小卫星·综合电子系统
意法半导体STM321 天前
【官方原创】STM32CubeMX2 1.1.0新版本发布
stm32·单片机·嵌入式硬件·mcu
花 满 楼3 天前
国芯科技CCFC3008PCS BIST (内建自测试) 分析总结
mcu·嵌入式·bist
jianqiang.xue3 天前
低功耗产品架构专项优化:电池供电设备休眠、唤醒、漏电流、待机功耗极致优化
stm32·单片机·mcu·物联网·架构·esp32
笨笨饿4 天前
#135_代码中的类型重定义艺术:从基础封装到函数类型设计
开发语言·stm32·单片机·嵌入式硬件·mcu·物联网·嵌入式实时数据库
电子科技圈5 天前
从工厂直达全球市场:emnify为联网设备制造商推出免费SGP.32引导网络接入的OEM计划
嵌入式硬件·mcu·物联网·智能硬件·iot·交通物流
Messy create5 天前
【BMS-三级架构】
单片机·mcu·架构·能源