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

    文章

    3614

    浏览量

    93686
  • 裸机
    +关注

    关注

    0

    文章

    39

    浏览量

    6372
  • RISC-V
    +关注

    关注

    45

    文章

    2270

    浏览量

    46130

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

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

收藏 人收藏

    评论

    相关推荐

    如何快速入门HAL库编程 HAL库与裸机编程的比较

    如何快速入门HAL库编程 要快速入门HAL库编程,可以遵循以下步骤: 了解基础知识 : 掌握C语言编程基础,包括变量、数据类型、函数、指针等。 了解嵌入式系统的基本概念,如微控制器、中断
    的头像 发表于 12-02 11:39 260次阅读

    【「RISC-V体系结构编程与实践」阅读体验】-- SBI及NEMU环境

    。 我觉得这也是本书的一个亮点,从最底层最简单的裸机开始,一步步对其扩展和完善,而不是直接从OpenSBI开始,这样更容易理解底层的一些细节。 NEMU环境介绍及搭建 RISCV-V的实验环境搭建
    发表于 11-26 09:37

    ARM处理器的异常中断响应过程

    ARM处理器的异常中断响应是嵌入式系统设计中一个至关重要的环节,它确保了系统在面对内部或外部事件时能够稳定、可靠地运行。
    的头像 发表于 09-10 11:18 903次阅读

    freertos和裸机有什么区别

    FreeRTOS 和裸机编程是两种不同的嵌入式系统开发方法,它们在设计理念、资源使用、功能实现等方面有着显著的差异。 1. 基本概念 1.1 FreeRTOS FreeRTOS 是一个小型的、可裁剪
    的头像 发表于 09-02 14:13 1334次阅读

    TI C64x+ DSP内核异常处理机制的应用

    电子发烧友网站提供《TI C64x+ DSP内核异常处理机制的应用.pdf》资料免费下载
    发表于 08-28 11:54 0次下载
    TI C<b class='flag-5'>64</b>x+ DSP内核<b class='flag-5'>异常</b>处理机制的应用

    嵌入式C编程常用的异常错误处理

    。 3. 中断服务程序 (Interrupt Service Routines, ISR) 在嵌入式系统中,中断是处理异常情况的常用方法。ISR用于处理硬件中断,并确保系统在
    发表于 08-06 14:32

    在ubuntu 24.04尝试使用riscv64-linux-musleabi_for_x86_64-pc-linux-gnu工具链编译cv1800大核出现报错的原因?

    在ubuntu 24.04尝试使用riscv64-linux-musleabi_for_x86_64-pc-linux-gnu工具链编译cv1800大核,结果出现如下报错: /home
    发表于 07-16 08:20

    谷歌安卓系统即将取消对RISC-V架构的支持

    负责安卓Linux核心分支开发的谷歌高级工程师向AOSP提交了一系列补丁,其中显示“已去除ACK对riscv64的支持”。这些补丁详细描述指出“对risc64 GKI内核的支持已停止”。
    的头像 发表于 04-30 15:40 1534次阅读

    国产riscv芯片大汇总?

    请问有统计国产的riscv芯片的吗?能汇总一吗?
    发表于 04-27 11:53

    RISCV soft JTAG调试_v1.2

    因为目前软件的限制,RISCV的逻辑不能同时共用JTAG,所以如果想要同时去调试逻辑和RISCV的话,可以通过RISCV的soft Jtag来实现。soft Jtag就是通过GPIO来实现的软件
    的头像 发表于 04-23 08:38 1057次阅读

    全志D1s开发板裸机开发之坏境搭建

    使用 7-Zip 解压。 解压成功后,可以看到 riscv64-unknown-elf-gcc.exe 文件,如下图所示: 需要把 riscv64-unknown-elf-gcc.exe 文件所在目录
    发表于 03-06 13:54

    RISCV soft JTAG调试_v1.1

    因为目前软件的限制,RISCV的逻辑不能同时共用JTAG,所以如果想要同时去调试逻辑和RISCV的话,可以通过RISCV的soft Jtag来实现。soft Jtag就是通过GPIO来实现的软件
    的头像 发表于 02-23 16:16 653次阅读
    <b class='flag-5'>RISCV</b> soft JTAG调试_v1.1

    聊聊KUKA机器人高级编程:中断

    最大数量/BRAKE最多可以同时声明64中断中断的声明可以随时被新的声明覆盖。可以选择使用BRAKE声明中断。BRAKE语句在检测到声明的中断
    发表于 01-25 15:16 6528次阅读
    聊聊KUKA机器人高级<b class='flag-5'>编程</b>:<b class='flag-5'>中断</b>

    TOM0 channel5中断异常的原因?

    正常情况ADC中断和TOM0 channel5中断都是正常的,当出现异常时,ADC中断正常,TOM0 channel5
    发表于 01-25 06:33

    arm中断是怎么实现的

    ARM中断的实现是通过中断控制器和异常模式实现的。ARM处理器通过中断控制器来接收和处理外部的中断信号,而
    的头像 发表于 01-05 15:18 892次阅读