欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

【RISC-V】Trap和Exception

发布时间:2024/3/12 编程问答 55 豆豆
生活随笔 收集整理的这篇文章主要介绍了 【RISC-V】Trap和Exception 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

文章目录

  • 控制流 (Control Flow)和Trap
  • RISC-V Trap处理中涉及的寄存器
    • mtvec (Machine Trap-Vector Base-Address)
    • mepc (Machine Exception Program Counter)
    • mcause (Machine Cause)
    • mstatus (Machine Status)
    • 中断与异常含义
  • RISC-V Trap处理流程
    • Top Half(Trap发生时,Hart自动执行流)
    • Bottom Half(软件需要做的事情)
    • 退出 trap:编程调用 MRET 指令

控制流 (Control Flow)和Trap

  • 控制流(Control Flow)
    • branch(条件分支指令), jump (无条件跳转指令),由程序正常自主控制的流程
  • 异常控制流 (Exceptional Control Flow,简称 ECP, 又称Trap)
    • 不在程序的控制范围之内
    • exception
    • interrupt

RISC-V Trap处理中涉及的寄存器

八个控制状态寄存器(CSR)是机器模式下异常处理的必要部分:

  • mtvec(Machine Trap Vector)它保存发生异常时处理器需要跳转到的地址。
  • mepc(Machine Exception PC)它指向发生异常的指令。
  • mcause(Machine Exception Cause)它指示发生异常的种类。
  • mie(Machine Interrupt Enable)它指出处理器目前能处理和必须忽略的中断。
  • mip(Machine Interrupt Pending)它列出目前正准备处理的中断。
  • mtval(Machine Trap Value)它保存了陷入(trap)的附加信息:地址例外中出错
  • 的地址、发生非法指令例外的指令本身,对于其他异常,它的值为 0。
  • mscratch(Machine Scratch)它暂时存放一个字大小的数据。
  • mstatus(Machine Status)它保存全局中断使能,以及许多其他的状态,如图

mtvec (Machine Trap-Vector Base-Address)

  • BASE: trap入口函数的及地址,必须保证四字节对其
  • MODE: 进一步用于控制入口函数的地址配置方式
    • Direct: 所有的exception和interrupt发生后pc都跳转到BASE指定的地址处。其实就是一个中断处理函数。
    • Vectored: exception处理方式同Direct;但interrupt的入口地址以数组方式排列。其实就是多向量指向不同的中断处理函数。


mepc (Machine Exception Program Counter)

  • 当trap发生时,pc会被替换为mtvec设定的地址,同时hart会设置mepc为当前指令或者下一条指令的地址(如果是异常则设置当前指令,如果是中断则设置下一条指令的地址),当我们需要退出trap时可以调用特殊的mret指令,该指令会将mepc中的值恢复到pc中(实现返回的效果)。
  • 在处理trap的程序中我们可以修改mepc的值达到改变mret返回地址的目的。

mcause (Machine Cause)

  • 当trap发生时,hart会设置该寄存器通知我们trap发生的原因。
  • 最高位Interrupt为1时标识了当前trap为interrupt,否则是exception。通过此标识能快速分辨发生了中断还是异常。
  • 剩余的Exception Code用于标识具体的interrupt或者exception的种类。
  • WLRL(Write/Read Only Legal Values)

mstatus (Machine Status)

  • MIE: 分别用于打开(1)或者关闭(0) M/S/U模式下的全局中断。当trap发生时,hart会自动将MIE设置为0。
  • MPIE: 当trap发生时用于保存trap发生之前的MIE值。
  • MPP: 当trap发生时用于保存trap发生之前的权限级别值。M/S/U三种模式用两个bit表示。

中断与异常含义

RISC-V Trap处理流程

Trap初始化(设置入口地址等)-> Trap的Top Half(硬件处理过程)-> Trap的Bottom Half(软件逻辑部分)-> 从Trap返回

Top Half(Trap发生时,Hart自动执行流)

  • 先把 mstatus 的MIE值复制到MPIE中,清除 mstatus 中的MIE标志位,效果是中断被禁止。(这就是硬件上不支持中断嵌套,但可以手动将中断再次打开实现中断嵌套)
  • 设置 mepc,同时PC被设置为 mtvec。(需要注意的是,对于 exception, mepc 指向导致异常的指令;对于 interrupt,它指向被中断的指令的下一条指令。)
  • 根据 trap 的种类设置 mcausem,并根据需要为 mtval 设置附加信息。
  • 将 trap发生之前的权限模式保存在 mstatus 的 MPP 域中,再把 hart 权限模式更改为M(也就是说无论在任何 Level 下触发 trap, hart首先切换到 Machine 模式)

Bottom Half(软件需要做的事情)

  • 保存(save) 当前控制流的上下文信息,是指保存x1~x31寄存器的值。(利用 mscratch)
  • 调用C语言的trap handler
  • 中断C程序执行完毕之后从trap handler函数返回,mepc的值可能需要调整。
  • 恢复 (restore)上下文的信息。
  • 执行 MRET指令返回到trap之前的状态。

退出 trap:编程调用 MRET 指令

  • 针对不同权限级别下有各自退出trap的返回指令xRET (x=M/S/U)
  • 以在M模式下指令mret指令为例,会执行开中断(mstatus.MIE = mstatus.MPIE; mstatus.MPIE = 1),然后返回进入trap之前的指令,如果是中断的话返回进入trap之前的下一条指令。(pc = mepc)

portASM.S /*-----------------------------------------------------------*/.section .text.freertos_risc_v_trap_handler .align 8 freertos_risc_v_trap_handler:portcontextSAVE_CONTEXT_INTERNALcsrr a0, mcausecsrr a1, mepcbge a0, x0, synchronous_exceptionasynchronous_interrupt:store_x a1, 0( sp ) /* Asynchronous interrupt so save unmodified exception return address. */load_x sp, xISRStackTop /* Switch to ISR stack. */j handle_interruptsynchronous_exception:addi a1, a1, 4 /* Synchronous so update exception return address to the instruction after the instruction that generated the exeption. */store_x a1, 0( sp ) /* Save updated exception return address. */load_x sp, xISRStackTop /* Switch to ISR stack. */j handle_exceptionhandle_interrupt: #if( portasmHAS_MTIME != 0 )test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */addi t0, x0, 1slli t0, t0, __riscv_xlen - 1 /* LSB is already set, shift into MSB. Shift 31 on 32-bit or 63 on 64-bit cores. */addi t1, t0, 7 /* 0x8000[]0007 == machine timer interrupt. */bne a0, t1, application_interrupt_handlerportUPDATE_MTIMER_COMPARE_REGISTERcall xTaskIncrementTickbeqz a0, processed_source /* Don't switch context if incrementing tick didn't unblock a task. */call vTaskSwitchContextj processed_source#endif /* portasmHAS_MTIME */application_interrupt_handler:call freertos_risc_v_application_interrupt_handlerj processed_sourcehandle_exception:/* a0 contains mcause. */li t0, 11 /* 11 == environment call. */bne a0, t0, application_exception_handler /* Not an M environment call, so some other exception. */call vTaskSwitchContextj processed_sourceapplication_exception_handler:call freertos_risc_v_application_exception_handlerj processed_source /* No other exceptions handled yet. */processed_source:portcontextRESTORE_CONTEXT /*-----------------------------------------------------------*/

总结

以上是生活随笔为你收集整理的【RISC-V】Trap和Exception的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。