这次我们介绍的功能是local中断。
首先我们先看一下指令集《The RISC-V Instruction Set Manual Volume II: Privileged Architecture Privileged Architecture Version 1.10》是如何定义的。
文档链接:
https://riscv.org/specifications/privileged-isa/
由上面的定义中,我们能挖掘出3点重要的内容。
- local interrupt是不经过PLIC的,分别有software interrupt、timer interrupt和additional non-standard local interrupt。non-standard local interrupt就是我们今天要介绍的中断,software interrupt和timer interrupt统称CLINT,后面再介绍。
- local interrupt的响应速度高于PLIC的,而且没有仲裁关系,是独立的。
- local interrupt相关的CSR寄存器分别是mip、mie、mideleg和mstatus等。mideleg CSR寄存器是用于授权其他用户模式使用local interrupt。
然后我们来看一下E3关于local interrupt(non-standard local interrupt)的介绍。
定义说明和协议是一样的。
接下来看一下与local interrupt相关的CSR寄存器。
可以看到mie中有LIE0~LIE15,分别是local interrupt的enable信号;mip中有LIP0~15,分别是local interrupt的pending信号;mcasue中也加入了local interrupt0~15中断源的异常代码;msatus中的MIE bit是整个芯片中断的总开关。下面我们看一下local interrupt在整个芯片中的优先级。
原理说完了,下面贴的是测试代码。
#include "encoding.h"
#define U32 *(volatile unsigned int *)
#define DEBUG_SIG 0x70000000
#define DEBUG_VAL 0x70000004
void handle_trap();
void csr_cfg();
//--------------------------------------------------------------------------
// handle_trap function
void handle_trap()
{
//enter handle_trap()
U32(DEBUG_SIG) = 0x4;
while((read_csr(mip) && 0xFFFF0000) != 0x0)
{
U32(DEBUG_VAL) = 0xFF;
}
U32(DEBUG_SIG) = 0xFF;
}
//--------------------------------------------------------------------------
// CSR interrupt configuration function
void csr_cfg()
{
unsigned int csr_tmp;
//mie.MEIE
csr_tmp = read_csr(mie);
U32(DEBUG_VAL) = csr_tmp;
//write_csr(mie,0x0);
write_csr(mie,(csr_tmp | 0xFFFF0888));
//mstatus.MIE
csr_tmp = read_csr(mstatus);
U32(DEBUG_VAL) = csr_tmp;
//write_csr(mstatus,0x0);
write_csr(mstatus,(csr_tmp | 0x8));
}
//--------------------------------------------------------------------------
// Main
void main()
{
csr_cfg();
U32(DEBUG_SIG) = 0x3;
while(1) {asm volatile ("wfi");}
}
接下来就是仿真的波形。
上面是仿真的波形,可以看到local_interrupts[15:0]在某一时刻变为了16’hFFFF,然后CPU触发中断,可以看到mcause变为了32’h8000_001F,8’h1F=8’d31,所以此次上报的local interrupt15中断,符合前面说的优先级。最后在中断处理函数中清除外部local_interrupts[15:0]。
到这里,关于local interrupt的内容已经介绍完毕了,如果觉得还是有用的那就给个赞吧,谢谢。