0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

opensbi下的riscv64裸机编程:中断与异常

嵌入式IoT 来源:嵌入式IoT 作者:嵌入式IoT 2021-01-07 10:30 次阅读

opensbi下的riscv64裸机编程2(中断与异常)

1.本文说明

2.riscv特权模式下的异常

2.1 CSPs

2.2 异常开关的寄存器

2.3 与中断相关的指令

3.中断测试

3.1 设置中断向量表

3.2 开启中断设置

3.3 初始化timer

3.4 开启中断

3.5 中断处理

4.测试及校验

5.总结

1.本文说明

任何时候,中断和异常的产生都是十分值得关注的,这些将破坏程序原有的执行逻辑。按照芯片的设计来说,中断和异常大致上可以分为三类异常(Exception)、陷入(Trap)、外部中断(Interrupt)。

异常(Exception)

在一条指令执行的过程中发生了错误,可以通过异常处理函数进行处理,最常见的异常包括无效的内存地址访问、非法指令异常、缺页异常等等。当发生这些异常后可以进行处理。

陷入(Trap)

主动的让其进入异常处理函数,常见的是系统调用syscall。而在riscv上为ecall或者进入断点的ebreak。

外部中断(Interrupt)

一般由外部事件触发,比如定时器中断、GPIO中断等。这些异常是不可预知的。

对于一般的中断处理流程,进入中断后需要进行上下文的保存与恢复。

2.riscv特权模式下的异常

涉及到中断和异常,RISCV的特权模式是不能绕开的。在RISCV中,无论在任何模式发生的异常,硬件线程都会将控制权交给M-Mode的异常处理程序。然而对于类Unix的操作系统来说,异常都是由操作系统来处理。而操着系统运行的模式是S-Mode,所以RISCV也可以选择将异常重新导向到S-Mode,也支持异常委托机制(Machine Interrupt Delegaintion)将异常直接通过S-Mode进行处理,这样可以大大的增加操作系统的灵活性。

33788338-5074-11eb-8b86-12bb97331649.png

一般来说M-Mode是必须实现的,S-Mode也一般会有,而U-Mode是选择性扩展的。目前的RISCV芯片中例如蜂鸟的E203与K210都只支持了RISCV架构中的Machine Mode。

2.1 CSPs

实际上RISCV在实现系统指令集的时候,是支持多种模式的扩展的,这一系列的指令集通过Control and Status Registers (CSRs)来进行控制。

CSR地址是扩展了12位,也就是可以设计最大4096个指令。

33cd0dae-5074-11eb-8b86-12bb97331649.png

通过下面的网站可以看到当前CSRs的实现状态。

http://www.five-embeddev.com/quickref/csrs.html

这里只针对S-Mode下的异常处理进行分析,M-Mode下的异常处理类似。

Name Number Feature/Extensions Description
sepc 0x0141 supervisor Supervisor Exception Program Counter
scause 0x0142 supervisor Supervisor Exception Cause
stval 0x0143 supervisor Supervisor bad address or instruction.
stvec 0x0105 supervisor Supervisor Trap Vector Base Address
sstatus 0x0100 supervisor Supervisor Status

Supervisor Exception Program Counter (sepc)

当中断发生时,存放需要跳转的PC值。这里需要利用stvec提供中断向量表的基地址。

341d7fc8-5074-11eb-8b86-12bb97331649.png

该寄存器的值是在32位下是4字节对齐的。

Supervisor Cause Register (scause)

该寄存器表示中断发生的原因。下面的表格中表述了中断的发生原因:

Interrupt Exception Code Description
1 0 Reserved
1 1 Supervisor software interrupt
1 2–4 Reserved
1 5 Supervisor timer interrupt
1 6–8 Reserved
1 9 Supervisor external interrupt
1 10–15 Reserved
1 ≥16 Designated for platform use
0 0 Instruction address misaligned
0 1 Instruction access fault
0 2 Illegal instruction
0 3 Breakpoint
0 4 Load address misaligned
0 5 Load access fault
0 6 Store/AMO address misaligned
0 7 Store/AMO access fault
0 8 Environment call from U-mode
0 9 Environment call from S-mode
0 10–11 Reserved
0 12 Instruction page fault
0 13 Load page fault
0 14 Reserved
0 15 Store/AMO page fault
0 16–23 Reserved
0 24–31 Designated for custom use
0 32–47 Reserved
0 48–63 Designated for custom use
0 ≥64 Reserved

Supervisor Trap Value (stval) Register

由于scause不足以表示异常发生的所有信息,比如发生了缺页异常,就会将stavl设置成需要访问但是不在内存中的地址。以便于操作系统将这个地址加载进来。

Supervisor Trap Vector Base Address Register (stvec)

设置中断处理的基地址,同时设置模式

345c5ce8-5074-11eb-8b86-12bb97331649.png

对于基地址的模式有如下两种:

Value Name Description
0 Direct All exceptions set pc to BASE.
1 Vectored Asynchronous interrupts set pc to BASE+4×cause.
≥2 Reserved

Direct:顾名思义,当异常发生的时候,每次都会跳转到这个地址,然后通过这个地址的中断处理程序去判断哪种中断。

Vectored:在这种模式下,会跳转到BASE + 4 * cause 进行处理流程。每种异常的cause都不一样。

Supervisor Status Register (sstatus)

控制中断的状态等等,也可以控制全局中断的时能等等。

351940c4-5074-11eb-8b86-12bb97331649.png

SIE域表示全局中断使能。当该MIE域值为1时,表示所有中断的全局开关打开,当MIE域的值为0时候,表示全局关闭所有中断。

SPIE用于保存进入异常之前MIE域的值。

2.2 异常开关的寄存器

对于S-Mode中断的Enable与Pending,还需要关注两个寄存器。sie与sip。

Supervisor Interrupt Enable(sie)

353dac16-5074-11eb-8b86-12bb97331649.png

Supervisor Interrupt Pending(sip)

358046fc-5074-11eb-8b86-12bb97331649.png

可以看到有三种类型的中断,由芯片厂家进行自定义设计。

Supervisor software interrupt

Supervisor timer interrupt

Supervisor external interrupt

2.3 与中断相关的指令

CSR Read Write(csrrw)

csrrw dst, csr, src:将指定的CSR寄存器写入dst,同时将src的值写入CSR。

CSR Read(csrr)

csrr dst,csr:读一个CSR寄存器到dst。

CSR Clear(csrc)

csrc(i) csr, rs1:将指定的位清零。

CSR Set(csrs)

csrs(i) csr, rs1:将指定的位置一。

3.中断测试

由于在qemu上,中断的产生可以通过定时器来发生,所以需要理解riscv上对timer的使用。timer又需要通过sbi的接口进行访问。

相关的代码文件可以参考:

https://github.com/bigmagic123/riscv64_opensbi_baremetal/tree/master/03_interrupt

已经实现了timer中断的产生过程。

3.1 设置中断向量表

本程序需要设置中断向量表,前面提到过,中断向量的跳转有两种模式:Direct与Vectored。Direct可以直接转到固定的pc地址,然后由统一的入口进行处理,这种比较容易实现,所以设置为这种模式。

.globaltable_val_set table_val_set: lat0,trap_entry csrwstvec,t0 jrra

直接将trap_entry函数的入口写到stvec的寄存器中。由于函数地址4字节对其,所以设置后模式为Direct。

3.2 开启中断设置

要开启时钟中断,这样才能产生时钟,而根据手册,开启时钟中断实际上是设置Supervisor Interrupt Enable(sie),也就是设置SIE的寄存器开启。

353dac16-5074-11eb-8b86-12bb97331649.png

所以只需要设置即可。

voidenable_timer_interrupt(void) { w_sie(r_sie()|SIE_STIE); }

3.3 初始化timer

对于timer的填充,其实就是设置中断的值。当timer达到设定的值后会产生中断。

voidset_timer(uint64stime_value) { SBI_TIMER(stime_value); } //getcurrenttime uint64get_cycle() { returnr_time(); } voidclock_set_next_event() { set_timer(get_cycle()+TIMEBASE); }

函数填充了下一个tick的值。

3.4 开启中断

中断的开启通过sstatus全局的状态寄存器设置。

351940c4-5074-11eb-8b86-12bb97331649.png

通过设置SIE位就可以达到使能或者关闭中断的作用。

voidinterrupt_enable(void) { w_sstatus(r_sstatus()|SSTATUS_SIE); }

3.5 中断处理

中断处理需要保存当前的上下文寄存器(寄存器压栈操作),然后跳转到中断处理函数去处理具体的中断。当处理完成之后返回现场(寄存器出栈)。

这里先不做这么复杂的工作,中断产生后直接跳转到中断处理函数中,只执行一次。

.globaltrap_entry trap_entry: csrra0,scause csrrca1,stval,zero csrra2,sepc mva3,s0 /*scause,stval,sepc,sp*/ callhandle_trap

其中a0为第一个参数,保存中断发生的原因。

a1是中断发生的具体信息。

a2表示了中断异常返回值。

然后进入hande_trap。

uintptr_thandle_trap(uintptr_tscause,uintptr_tstval,uintptr_tsepc,uintptr_tsp) { tfp_printf("handle_trap%08lx:%08lx:%08lx:%08lx ",scause,stval,sepc,sp); while(1); return0; }

4.测试及校验

因为工程文件的增加,所以使用了Makefile进行工程的构建工作。

%.o:%.c%.s $(CC)$(CFLAGS)-c$< -o $@

Makefile的语法规则基本

TARGET…:DEPENDENCIES… COMMAND

这里也不过多的涉及了。

输入make后,在fw_bin目录下执行run.sh脚本即可。

最后可以看到中断的原因

最高位是8,相应的中断描述为Supervisor timer interrupt。

5.总结

riscv的异常和中断的处理模式在M-Mode或者S-Mode下都可以设计,具体要看芯片的设计方式,如果设计在M-Mode,对于操作系统来说,可以通过转发或者代理给S-Mode的操作系统,如果S-Mode存在中断处理,那么处于S-Mode的系统可以直接处理,这样比较简洁。

责任编辑:xj

原文标题:opensbi下的riscv64裸机编程2(中断与异常)

文章出处:【微信公众号:嵌入式IoT】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编程
    +关注

    关注

    88

    文章

    3439

    浏览量

    92377
  • 裸机
    +关注

    关注

    0

    文章

    37

    浏览量

    6151
  • RISC-V
    +关注

    关注

    41

    文章

    1899

    浏览量

    45044

原文标题:opensbi下的riscv64裸机编程2(中断与异常)

文章出处:【微信号:Embeded_IoT,微信公众号:嵌入式IoT】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    ARM中的异常中断是如何实现进入中断程序的?如何进入呢?

    ARM中的异常中断是如何实现进入中断程序的?如何进入呢? 在计算机系统中,异常中断是两个常见的概念。 在ARM中,异常
    的头像 发表于 10-19 16:36 561次阅读

    arm处理器有哪些中断源?arm处理器对异常中断的响应过程

    arm处理器有哪些中断源?arm处理器对异常中断的响应过程  ARM处理器是一种广泛使用的嵌入式处理器,运行着各种不同类型的应用程序。为了保证应用程序的稳定性和正确性,ARM处理器需要在遇到异常
    的头像 发表于 10-19 16:35 813次阅读

    RT-Smart riscv64汇编注释

    以rt-smart在全志D1上的代码为例,主要注释了rt-smart在riscv64上的系统初始化和异常处理的代码
    的头像 发表于 10-12 17:26 339次阅读
    RT-Smart <b class='flag-5'>riscv64</b>汇编注释

    RISC-V Linux运行时OpenSBI配置和编译

    配置和编译 OpenSBI的配置选项位于不同平台下的 config.mk 文件,例如 platform/generic/config.mk : # Blobs to build
    的头像 发表于 10-08 14:24 611次阅读

    OpenSBI固件类型介绍

    OpenSBI固件类型 在介绍OpenSBI固件类型前,我们需要知道一点RISC-V Linux的启动过程: 启动流程:ZSBL-->FSBL-->OpenSBI-->u-boot-->Linux
    的头像 发表于 10-08 14:11 362次阅读
    <b class='flag-5'>OpenSBI</b>固件类型介绍

    异常、陷阱和中断有什么区别呢?

    异常中断会暂停程序以响应硬件或软件中的意外事件。中断是异步事件,异常是同步事件,但是中断异常
    的头像 发表于 09-14 15:20 1107次阅读
    <b class='flag-5'>异常</b>、陷阱和<b class='flag-5'>中断</b>有什么区别呢?

    Debian12桌面异常卡是为什么?

    riscv64 202306 镜像,然后upgrade了系统。 不是版本2带GPU了吗,是没有适配GPU吗,桌面基本跑不动,点一鼠标要四五秒才有反应,版本1没有GPU的体验还好点勉强能用,版本2完全不可用。
    发表于 09-12 07:05

    【昉·星光 2 高性能RISC-V单板计算机体验】三:基于RISC-V交叉编译工具链的OpenCV库编译

    \\\\_depend –share 修改Makefile: CC=riscv64\\\\-unknown\\\\-linux\\\\-gnu\\\\-gcc AR=riscv64\\\\-unknown
    发表于 09-02 22:10

    【昉·星光 2 高性能RISC-V单板计算机体验】利用VF2部署一个网络摄像头

    Linux starfive 5.15.0-starfive #1 SMP Sun Jun 11 07:48:39 UTC 2023 riscv64 GNU/Linux 就是因为文件名上带
    发表于 08-22 00:28

    d1哪吒开发板的启动流程分析

    志D1芯片的启动流程最底层的分析来看,和其他全志产品线的芯片的启动流程基本类似,主要需要理解的是fel模式对SRAM,DDR等操作,这样在做裸机开发的时候,才能将程序下载进去。有了这些理解,在做riscv的底层
    发表于 08-16 08:16

    riscv实现自定义指令并用qemu运行的过程

    qemu模拟硬件平台,实现特定指令解析,同时写裸机代码来测试该指令的运行情况。当然,如果实现的很好,是需要修改riscv的gcc的,让自己的扩展指令加入。这里不做修改,后面会详细描述细节。 自定义指令
    发表于 08-16 07:27

    全志D1开发板RISCV64开箱评测

    的生态建设远远没有arm强大,但是也在开源思想的引领,开始逐步走向大众的视野。 这块哪吒 RISCV64的板子,从主要的核的特性上来看,与目前市面上可见的riscv开发板相比,特性主要有以下几点: 1.
    发表于 08-16 07:05

    嵌入式编程中为什么使用qemu?qemu的实际应用

    aarch64编程,采用qemu,运行自己写的裸机代码,能够非常方便的进行各种实验。 在进行rtos的开发过程中,经常会采用qemu作为调试工具,进行龙芯、树莓派、riscv相关的开发
    发表于 08-16 06:44

    RISCV的生态里有没有可以离线分析MCU运行异常的工具?

    大家好, 请教一大家在RISCV的生态里有没有可以离线(不接开发板)分析MCU运行异常的工具; 具体的流程: MCU运行过程发生异常,主动上报Assert,程序将
    发表于 08-12 07:33

    RT-Thread BSP qemu-virt64-riscv的编译环境搭建

    qemu-virt64-riscv   下载 RT-Thread   这里使用 gitee 的 RT-Thread 仓库,先通过 fork 的方式,把 RT-Thread fork 到自己的账号   ubuntu 中安装
    发表于 05-16 10:37