opensbi中plic中断控制逻辑使能

你提供的这两个函数是 PLIC 控制器中中断使能位(IE, Interrupt Enable)的核心读写接口,负责精准定位并操作指定上下文、指定中断块的 PLIC 使能寄存器,我会从功能、地址计算逻辑、参数含义、使用场景四个维度拆解,帮你彻底理解:

一、整体功能总结

  • plic_get_ie:读取 PLIC 中「指定上下文 + 指定中断块」的中断使能寄存器值;
  • plic_set_ie:向 PLIC 中「指定上下文 + 指定中断块」的中断使能寄存器写入值;

这两个函数是fdt_plic_context_save/restore的底层实现依赖——保存上下文时调用plic_get_ie读取使能位,恢复时调用plic_set_ie写回使能位。

二、核心逻辑:PLIC 使能寄存器地址计算

PLCI 使能寄存器的地址是基址 + 上下文偏移 + 中断块偏移,代码中通过以下公式计算:

plic_ie = plic->addr (PLIC基址) + PLIC_ENABLE_BASE (使能寄存器块起始偏移) + PLIC_ENABLE_STRIDE * cntxid (上下文偏移) + 4 * word_index (中断块偏移)
逐部分解析地址构成:
地址组成部分含义
plic->addrPLIC 控制器在 SoC 中的物理基地址(如 QEMU 中的0xC000000),由设备树解析得到
PLIC_ENABLE_BASEPLIC 使能寄存器块的起始偏移(标准 PLIC 规范中为0x2000,和你之前翻译的文档一致)
PLIC_ENABLE_STRIDE * cntxid每个上下文(Context)对应的使能寄存器块偏移:
-PLIC_ENABLE_STRIDE:单个上下文的使能寄存器块大小(标准为0x80,对应 32 个中断块×4字节);
-cntxid:上下文ID(如 Hart0 的 M 态上下文=0,S 态上下文=1)
4 * word_index单个上下文内,按 32 个中断为 1 块的偏移:
-word_index:中断块编号(如 0=irq031,1=irq3263);
- 4 是因为每个中断块对应 32 位(4字节)寄存器
地址计算示例(贴合你之前翻译的文档):

假设:

  • PLIC 基址plic->addr = 0xC000000
  • PLIC_ENABLE_BASE = 0x2000
  • PLIC_ENABLE_STRIDE = 0x80
  • 上下文IDcntxid = 0(Hart0 M 态);
  • 中断块word_index = 0(irq0~31);

则最终地址:

0xC000000 + 0x2000 + 0x80*0 + 4*0 = 0xC002000

和你之前翻译的文档中「上下文0的中断源#0至#31使能位地址=0x002000」(基址偏移)完全一致。

三、函数参数与返回值解析

1. plic_get_ie 函数
staticu32plic_get_ie(conststructplic_data*plic,u32 cntxid,u32 word_index)
参数含义
plicPLIC 硬件数据结构体指针,包含基址、总中断数、上下文数等核心信息
cntxid上下文ID(区分不同 Hart/不同特权级:如 Hart0 M 态=0,Hart0 S 态=1)
word_index中断块编号(按 32 个中断为 1 块,范围 0 ~ (总中断数/32 - 1))
返回值对应中断块的使能寄存器值(32位,每1位对应1个中断的使能状态:1=使能,0=禁用)
2. plic_set_ie 函数
staticvoidplic_set_ie(conststructplic_data*plic,u32 cntxid,u32 word_index,u32 val)
参数含义
plic/cntxid/word_indexplic_get_ie完全一致,定位要写入的使能寄存器
val要写入的 32 位值(每1位设置对应中断的使能状态:1=使能,0=禁用)

四、典型使用场景(结合上下文保存/恢复)

// 示例:保存 Hart0 S 态的 irq0~31 使能位structplic_data*plic=plic_get_hart_data_ptr(scratch);u32 cntxid=plic_get_hart_scontext(scratch);// 获取S态上下文IDu32 word_index=0;// irq0~31 中断块// 读取使能位(保存到缓冲区)u32 enable_val=plic_get_ie(plic,cntxid,word_index);enable_buf[word_index]=enable_val;// 示例:恢复 Hart0 S 态的 irq0~31 使能位u32 restore_val=enable_buf[word_index];plic_set_ie(plic,cntxid,word_index,restore_val);

五、关键注意点

  1. 地址对齐4 * word_index保证了地址按 4 字节对齐(RISC-V 32位寄存器要求),避免非对齐访问异常;
  2. volatile 关键字volatile void *plic_ie防止编译器优化寄存器读写(PLIC 是硬件寄存器,必须实时读写);
  3. 上下文ID 映射cntxid不是直接的 Hart ID,而是 PLIC 为每个 Hart 的 M/S 态分配的上下文编号(如 Hart0 M 态=0,S 态=1;Hart1 M 态=2,S 态=3)。
关键点plic_get_ieplic_set_ie
核心动作计算地址 → 读取 32 位使能寄存器值计算地址 → 写入 32 位使能寄存器值
地址计算核心基址 + 上下文偏移 + 中断块偏移同 get_ie,保证地址精准匹配
底层依赖readl(读取32位内存映射寄存器)writel(写入32位内存映射寄存器)
上层调用场景PLIC 上下文保存(fdt_plic_context_save)PLIC 上下文恢复(fdt_plic_context_restore)

六、cntxid 分配规则

6.1、通用分配规则(最常见的场景)

绝大多数 PLIC 实现中,上下文ID 按「Hart 编号 + 特权级」线性分配,规则为:

cntxid = 2 × hart_id + (特权级标识)
  • 特权级标识:M 态 = 0,S 态 = 1;
  • 示例:
    • Hart0 M 态 →2×0 + 0 = 0
    • Hart0 S 态 →2×0 + 1 = 1
    • Hart1 M 态 →2×1 + 0 = 2
    • Hart1 S 态 →2×1 + 1 = 3
    • Hart2 M 态 →2×2 + 0 = 4
    • Hart2 S 态 →2×2 + 1 = 5

这和你理解的「Hart1 M=2、S=3」完全一致,是 OpenSBI/QEMU/Linux 中最主流的分配方式。

6.2、特殊情况:上下文ID 分配的灵活性

PLIC 规范仅定义「每个上下文对应独立的使能/阈值寄存器」,但未强制上下文ID 的分配规则,部分场景会有差异:

  1. 仅支持 M 态的 PLIC
    嵌入式极简 PLIC 可能只支持 M 态,此时上下文ID 直接等于 Hart ID(如 Hart0=0、Hart1=1、Hart2=2),无 S 态上下文。
  2. 虚拟化场景(H 扩展)
    支持虚拟化的 PLIC 会为 VS/VU 态分配额外上下文,规则变为:
    cntxid = 4 × hart_id + (特权级标识)
    • Hart0 M=0、S=1、VS=2、VU=3;
    • Hart1 M=4、S=5、VS=6、VU=7;
  3. 厂商自定义分配
    部分 SoC 厂商会按「特权级优先」分配(如所有 M 态上下文在前,S 态在后):
    • Hart0 M=0、Hart1 M=1、Hart2 M=2;
    • Hart0 S=3、Hart1 S=4、Hart2 S=5;
6.3、代码中如何确认实际的 cntxid 映射

在 OpenSBI 中,无需硬编码,可通过以下函数获取当前 Hart 对应特权级的 cntxid:

structsbi_scratch*scratch=sbi_scratch_thishart_ptr();// 获取当前 Hart M 态的 cntxidu32 m_cntxid=plic_get_hart_mcontext(scratch);// 获取当前 Hart S 态的 cntxidu32 s_cntxid=plic_get_hart_scontext(scratch);
  • 对于 Hart0,m_cntxid通常返回 0,s_cntxid返回 1;
  • 对于 Hart1,m_cntxid通常返回 2,s_cntxid返回 3;

这也是你之前看到的fdt_plic_context_save/restore中,通过smode选择plic_get_hart_scontext/plic_get_hart_mcontext的原因——固件已封装好 cntxid 映射,无需开发者手动计算

小结
关键点通用规则(主流)特殊场景
Hart1 M 态 cntxid2(符合你的理解)1(仅M态PLIC)/4(虚拟化场景)
Hart1 S 态 cntxid3(符合你的理解)无(仅M态PLIC)/5(虚拟化场景)
核心建议无需硬编码,通过plic_get_hart_*context获取实际 cntxid避免依赖固定数值,以固件提供的接口为准

简单来说:在无虚拟化、支持 M/S 态的标准 PLIC 中,Hart1 M=2、S=3 是完全正确的;若涉及特殊场景,以代码中plic_get_hart_*context的返回值为准即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1135905.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机行业的本质

1.概述计算机行业的本质,有两种最重要的本质,一个if else while;一个是结构关系,像是数据库的关系表。任何程序的运转无法是 if else while 控制具体的运算行为,这行为可以是数学运算,可以是io的写入,可以是…

救命神器!8款AI论文软件测评:研究生毕业论文痛点全解

救命神器!8款AI论文软件测评:研究生毕业论文痛点全解 2026年AI论文工具测评:为何要关注这些“救命神器” 在研究生阶段,撰写毕业论文不仅是学术能力的体现,更是时间与精力的巨大挑战。从选题构思到文献检索&#xff0c…

PyQt上位机界面构建:超详细版布局管理讲解

PyQt上位机界面构建:从零掌握专业级布局管理在工业自动化、嵌入式调试和数据采集系统中,上位机软件是连接操作人员与底层设备的“神经中枢”。它不仅要稳定可靠地完成通信控制任务,更要提供清晰直观的操作体验。一个结构混乱、缩放错乱的界面…

Packet Tracer中RIP路由更新过程动态追踪指南

用Packet Tracer“看懂”RIP:从路由更新到网络收敛的全过程追踪你有没有过这样的经历?在学习动态路由协议时,老师讲得头头是道——“路由器会周期性广播自己的路由表”、“跳数加一后转发”、“最终实现全网收敛”……但这些过程到底长什么样…

MySQL/MongoDB

MySQL 和 MongoDB 是两种非常流行的数据库系统,但它们在设计理念、数据模型、使用场景等方面有显著差异。以下是它们的主要对比: 1. 类型 MySQL:关系型数据库(RDBMS),基于 SQL(结构化查询语言&…

提供基于comsol中相场方法模拟多孔介质两相驱替(水气、油水等等)的算例(也可以定做水平集驱...

提供基于comsol中相场方法模拟多孔介质两相驱替(水气、油水等等)的算例(也可以定做水平集驱替的算例),可在此基础上学会利用comsol软件进行两相流驱替的模拟,拓展研究,具体参考算例附后。 附赠基…

嵌入式DFMEA模板表格

DFMEA 是 Design Failure Mode and Effects Analysis 的缩写,中文译为设计失效模式及后果分析,是嵌入式、电子工程等工业领域产品设计阶段的核心可靠性分析工具,目的是提前识别设计缺陷、预判失效风险,并制定预防措施,…

救命神器10个AI论文软件,助本科生轻松搞定毕业论文!

救命神器10个AI论文软件,助本科生轻松搞定毕业论文! AI 工具如何成为论文写作的得力助手 在当今信息爆炸的时代,本科生撰写毕业论文的压力与日俱增。无论是选题、资料收集、结构搭建,还是语言润色和降重处理,每一个环节…

基于Thinkphp-Laravel的智能分配出租车叫车打车网约车管理系统的可视化大屏分析系统设计

目录摘要项目开发技术介绍PHP核心代码部分展示系统结论源码获取/同行可拿货,招校园代理摘要 Thinkphp-Laravel智能分配出租车叫车管理系统整合了PHP框架的高效开发能力与智能算法优化,实现出租车资源的动态调度与可视化分析。系统采用Laravel的优雅语法与ThinkPHP的…

揭秘AI论文生成高阶玩法:7工具1小时出15万字问卷论文带真实参考文献

90%的学生都不知道这个隐藏功能… 你是否还在为论文卡壳彻夜改稿?是否还在为查重率飙升而焦虑到失眠?业内导师圈流传着一个鲜为人知的秘密:真正的科研高手早已用上“黑科技”——一种能在1小时内批量产出15万字问卷论文、自动配齐真实参考文…

手把手教你计算LED显示屏尺寸大小(含分辨率)

手把手教你精准计算LED显示屏尺寸与分辨率:从理论到实战的完整指南你有没有遇到过这样的情况?项目现场已经搭好了支架,电源也接上了,结果发现买回来的LED屏拼完之后宽了10厘米、矮了一行模组,要么得拆墙重装&#xff0…

基于Thinkphp-Laravel的月子会所服务系统

目录基于ThinkPHP-Laravel的月子会所服务系统摘要项目开发技术介绍PHP核心代码部分展示系统结论源码获取/同行可拿货,招校园代理基于ThinkPHP-Laravel的月子会所服务系统摘要 月子会所服务系统是基于ThinkPHP和Laravel框架开发的综合管理平台,旨在提升月子会所的运…

BusyBox集成telnetd实现远程登录:项目应用示例

忙得动不如连得上:用 BusyBox 的 telnetd 实现嵌入式远程登录实战你有没有过这样的经历?手里的开发板通电后黑屏无输出,串口线插了半天也只看到一串启动日志戛然而止;现场设备突然宕机,但没人能去拆机接线;…

I2S协议物理层解析:一文说清数据同步与时钟关系

I2S协议物理层解析:一文说清数据同步与时钟关系在数字音频的世界里,信号的“纯净”与“准确”是工程师永恒的追求。无论是你在智能音箱中听到的一声清澈人声,还是车载音响播放的高保真交响乐,背后都离不开一套精密的通信机制——I…

基于python的食品公司采购管理系统的设计与实现_usr5txay

目录摘要内容关于博主开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!摘要内容 食品公司采购管理系统基于Python开发,旨在优化采购流程、提升供应链效率并降低运营成本。系统采用…

RS485和RS232通信电平标准入门级解析

RS485与RS232:不只是电平不同,更是两种通信哲学的碰撞你有没有遇到过这种情况?调试一个传感器,用串口线连上PC就能通,换到工业现场一公里外就频繁丢包;或者想把三四个设备挂到一条线上轮询数据,…

pjsip呼叫控制逻辑设计:拨号、接听、挂断完整示例

pjsip呼叫控制实战:从拨号到挂断的完整逻辑拆解你有没有遇到过这样的场景?在开发一款软电话应用时,点击“拨打”按钮后,对方没反应;或者来电了却无法正确弹出提示;最头疼的是通话中突然断开,日志…

燃料电池功率跟随cruise仿真模型!!!此模型基于Cruise2019版及Matlab201...

燃料电池功率跟随cruise仿真模型!!!此模型基于Cruise2019版及Matlab2018a搭建调试而成,跟随效果很好,任务仿真结束起始soc几乎相同。 控制模型主要包括燃料堆控制、DCDC控制、驱动力控制、再生制动控制、机械制动等模块…

医药信息管理|基于Python + Django医药信息管理系统(源码+数据库+文档)

医药信息管理 目录 基于PythonDjango医药信息管理系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取: 基于PythonDjango医药信息管理系统 一、前言 博主介绍&#xff1a…

加法器学习路径:掌握数字设计的第一步

加法器学习路径:掌握数字设计的第一步在数字电路的世界里,加法器远不止是“两个数相加”这么简单。它是一扇门——推开这扇门,你看到的不是单一功能模块,而是整个数字系统设计思维的缩影。从最基础的逻辑门组合,到影响…