如何检测RISC-V(Microchip PolarFire MPFS)中函数是否从中断处理程序调用
RISC-V M模式下函数区分中断/主调用上下文的正确实现
针对你遇到的mcause.interrupt无法可靠判断当前是否处于中断上下文的问题,以下是两种在M模式下可用的可靠方案:
方案1:利用mstatus.MIE寄存器位判断
进入中断陷阱时,硬件会自动清除mstatus寄存器的MIE位(全局中断使能位),直到中断处理程序执行mret指令前才会恢复该位。主代码正常运行时(未主动关中断),MIE位是置位状态。
实现代码:
#include <stdint.h> static inline uint32_t read_mstatus(void) { uint32_t val; __asm__ volatile ("csrr %0, mstatus" : "=r"(val)); return val; } #define MSTATUS_MIE_MASK (1U << 3) void your_function(void) { // 检查是否处于中断上下文:MIE位未置位则是中断调用 if (!(read_mstatus() & MSTATUS_MIE_MASK)) { // 中断调用时执行的额外操作 // ... } // 主代码与中断调用共享的核心逻辑 // ... }
方案2:维护全局上下文标记
在中断处理程序的入口和出口分别设置/清除一个全局标记变量,确保函数能通过该变量判断当前上下文。需注意变量的访问要保证原子性,或在关中断环境下操作。
实现代码:
#include <stdbool.h> // volatile修饰确保编译器不会优化该变量的访问 volatile bool g_in_interrupt = false; // 中断处理程序示例框架 void interrupt_handler(void) { g_in_interrupt = true; // 处理中断逻辑,调用目标函数 your_function(); g_in_interrupt = false; __asm__ volatile ("mret"); } void your_function(void) { if (g_in_interrupt) { // 中断调用时的额外操作 // ... } // 核心逻辑 // ... }
补充说明:
mcause.interrupt位的作用仅在进入陷阱时判断触发源是中断还是异常,陷阱退出后该位的状态不会被硬件自动清除,主代码运行时可能保留之前陷阱的状态,因此确实无法用来判断当前是否处于中断上下文。
内容的提问来源于stack exchange,提问作者Vladimir Tichy
相关产品推荐
相关产品推荐

