www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式IoT

opensbi下的riscv64裸機(jī)編程2(中斷與異常)

  • 1.本文說明

  • 2.riscv特權(quán)模式下的異常

    • 2.1 CSPs

    • 2.2 異常開關(guān)的寄存器

    • 2.3 與中斷相關(guān)的指令

  • 3.中斷測(cè)試

    • 3.1 設(shè)置中斷向量表

    • 3.2 開啟中斷設(shè)置

    • 3.3 初始化timer

    • 3.4 開啟中斷

    • 3.5 中斷處理

  • 4.測(cè)試及校驗(yàn)

  • 5.總結(jié)

1.本文說明

任何時(shí)候,中斷和異常的產(chǎn)生都是十分值得關(guān)注的,這些將破壞程序原有的執(zhí)行邏輯。按照芯片的設(shè)計(jì)來說,中斷和異常大致上可以分為三類異常(Exception)、陷入(Trap)、外部中斷(Interrupt)。

  • 異常(Exception)

在一條指令執(zhí)行的過程中發(fā)生了錯(cuò)誤,可以通過異常處理函數(shù)進(jìn)行處理,最常見的異常包括無效的內(nèi)存地址訪問、非法指令異常、缺頁(yè)異常等等。當(dāng)發(fā)生這些異常后可以進(jìn)行處理。

  • 陷入(Trap)

主動(dòng)的讓其進(jìn)入異常處理函數(shù),常見的是系統(tǒng)調(diào)用syscall。而在riscv上為ecall或者進(jìn)入斷點(diǎn)的ebreak。

  • 外部中斷(Interrupt)

一般由外部事件觸發(fā),比如定時(shí)器中斷、GPIO中斷等。這些異常是不可預(yù)知的。

對(duì)于一般的中斷處理流程,進(jìn)入中斷后需要進(jìn)行上下文的保存與恢復(fù)。

2.riscv特權(quán)模式下的異常

涉及到中斷和異常,RISCV的特權(quán)模式是不能繞開的。在RISCV中,無論在任何模式發(fā)生的異常,硬件線程都會(huì)將控制權(quán)交給M-Mode的異常處理程序。然而對(duì)于類Unix的操作系統(tǒng)來說,異常都是由操作系統(tǒng)來處理。而操著系統(tǒng)運(yùn)行的模式是S-Mode,所以RISCV也可以選擇將異常重新導(dǎo)向到S-Mode,也支持異常委托機(jī)制(Machine Interrupt Delegaintion)將異常直接通過S-Mode進(jìn)行處理,這樣可以大大的增加操作系統(tǒng)的靈活性。

一般來說M-Mode是必須實(shí)現(xiàn)的,S-Mode也一般會(huì)有,而U-Mode是選擇性擴(kuò)展的。目前的RISCV芯片中例如蜂鳥的E203與K210都只支持了RISCV架構(gòu)中的Machine Mode。

2.1 CSPs

實(shí)際上RISCV在實(shí)現(xiàn)系統(tǒng)指令集的時(shí)候,是支持多種模式的擴(kuò)展的,這一系列的指令集通過Control and Status Registers (CSRs)來進(jìn)行控制。

CSR地址是擴(kuò)展了12位,也就是可以設(shè)計(jì)最大4096個(gè)指令。

通過下面的網(wǎng)站可以看到當(dāng)前CSRs的實(shí)現(xiàn)狀態(tài)。

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

這里只針對(duì)S-Mode下的異常處理進(jìn)行分析,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)

當(dāng)中斷發(fā)生時(shí),存放需要跳轉(zhuǎn)的PC值。這里需要利用stvec提供中斷向量表的基地址。

該寄存器的值是在32位下是4字節(jié)對(duì)齊的。

Supervisor Cause Register (scause)

該寄存器表示中斷發(fā)生的原因。下面的表格中表述了中斷的發(fā)生原因:

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不足以表示異常發(fā)生的所有信息,比如發(fā)生了缺頁(yè)異常,就會(huì)將stavl設(shè)置成需要訪問但是不在內(nèi)存中的地址。以便于操作系統(tǒng)將這個(gè)地址加載進(jìn)來。

Supervisor Trap Vector Base Address Register (stvec)

設(shè)置中斷處理的基地址,同時(shí)設(shè)置模式

對(duì)于基地址的模式有如下兩種:

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

Direct:顧名思義,當(dāng)異常發(fā)生的時(shí)候,每次都會(huì)跳轉(zhuǎn)到這個(gè)地址,然后通過這個(gè)地址的中斷處理程序去判斷哪種中斷。

Vectored:在這種模式下,會(huì)跳轉(zhuǎn)到BASE + 4 * cause進(jìn)行處理流程。每種異常的cause都不一樣。

Supervisor Status Register (sstatus)

控制中斷的狀態(tài)等等,也可以控制全局中斷的時(shí)能等等。

SIE域表示全局中斷使能。當(dāng)該MIE域值為1時(shí),表示所有中斷的全局開關(guān)打開,當(dāng)MIE域的值為0時(shí)候,表示全局關(guān)閉所有中斷。

SPIE用于保存進(jìn)入異常之前MIE域的值。

2.2 異常開關(guān)的寄存器

對(duì)于S-Mode中斷的Enable與Pending,還需要關(guān)注兩個(gè)寄存器。sie與sip。

Supervisor Interrupt Enable(sie)

Supervisor Interrupt Pending(sip)

可以看到有三種類型的中斷,由芯片廠家進(jìn)行自定義設(shè)計(jì)。

  • Supervisor software interrupt
  • Supervisor timer interrupt
  • Supervisor external interrupt

2.3 與中斷相關(guān)的指令

  • CSR Read Write(csrrw)

csrrw dst, csr, src:將指定的CSR寄存器寫入dst,同時(shí)將src的值寫入CSR。

  • CSR Read(csrr)

csrr dst,csr:讀一個(gè)CSR寄存器到dst。

  • CSR Clear(csrc)

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

  • CSR Set(csrs)

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

3.中斷測(cè)試

由于在qemu上,中斷的產(chǎn)生可以通過定時(shí)器來發(fā)生,所以需要理解riscv上對(duì)timer的使用。timer又需要通過sbi的接口進(jìn)行訪問。

相關(guān)的代碼文件可以參考:

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

已經(jīng)實(shí)現(xiàn)了timer中斷的產(chǎn)生過程。

3.1 設(shè)置中斷向量表

本程序需要設(shè)置中斷向量表,前面提到過,中斷向量的跳轉(zhuǎn)有兩種模式:Direct與Vectored。Direct可以直接轉(zhuǎn)到固定的pc地址,然后由統(tǒng)一的入口進(jìn)行處理,這種比較容易實(shí)現(xiàn),所以設(shè)置為這種模式。

.global table_val_set
table_val_set:
 la t0, trap_entry
 csrw stvec, t0
 jr ra

直接將trap_entry函數(shù)的入口寫到stvec的寄存器中。由于函數(shù)地址4字節(jié)對(duì)其,所以設(shè)置后模式為Direct。

3.2 開啟中斷設(shè)置

要開啟時(shí)鐘中斷,這樣才能產(chǎn)生時(shí)鐘,而根據(jù)手冊(cè),開啟時(shí)鐘中斷實(shí)際上是設(shè)置Supervisor Interrupt Enable(sie),也就是設(shè)置SIE的寄存器開啟。

所以只需要設(shè)置即可。

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

3.3 初始化timer

對(duì)于timer的填充,其實(shí)就是設(shè)置中斷的值。當(dāng)timer達(dá)到設(shè)定的值后會(huì)產(chǎn)生中斷。

void set_timer(uint64 stime_value)
{
 SBI_TIMER(stime_value);
}

// get current time
uint64 get_cycle()
{ return r_time();
}

void clock_set_next_event()
{
 set_timer(get_cycle() + TIMEBASE);
}

函數(shù)填充了下一個(gè)tick的值。

3.4 開啟中斷

中斷的開啟通過sstatus全局的狀態(tài)寄存器設(shè)置。

通過設(shè)置SIE位就可以達(dá)到使能或者關(guān)閉中斷的作用。

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

3.5 中斷處理

中斷處理需要保存當(dāng)前的上下文寄存器(寄存器壓棧操作),然后跳轉(zhuǎn)到中斷處理函數(shù)去處理具體的中斷。當(dāng)處理完成之后返回現(xiàn)場(chǎng)(寄存器出棧)。

這里先不做這么復(fù)雜的工作,中斷產(chǎn)生后直接跳轉(zhuǎn)到中斷處理函數(shù)中,只執(zhí)行一次。

.global trap_entry
trap_entry:
 csrr a0, scause
 csrrc a1, stval, zero
 csrr  a2, sepc
 mv    a3, s0
 /* scause, stval, sepc, sp */
 call  handle_trap

其中a0為第一個(gè)參數(shù),保存中斷發(fā)生的原因。

a1是中斷發(fā)生的具體信息。

a2表示了中斷異常返回值。

然后進(jìn)入hande_trap。

uintptr_t handle_trap(uintptr_t scause, uintptr_t stval, uintptr_t sepc, uintptr_t sp)
{
 tfp_printf("handle_trap %08lx:%08lx:%08lx:%08lx\n", scause, stval, sepc, sp); while (1); return 0;
}

4.測(cè)試及校驗(yàn)

因?yàn)楣こ涛募脑黾?,所以使用了Makefile進(jìn)行工程的構(gòu)建工作。

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

Makefile的語(yǔ)法規(guī)則基本

TARGET … : DEPENDENCIES …
 COMMAND

這里也不過多的涉及了。

輸入make后,在fw_bin目錄下執(zhí)行run.sh腳本即可。

最后可以看到中斷的原因

最高位是8,相應(yīng)的中斷描述為Supervisor timer interrupt。

5.總結(jié)

riscv的異常和中斷的處理模式在M-Mode或者S-Mode下都可以設(shè)計(jì),具體要看芯片的設(shè)計(jì)方式,如果設(shè)計(jì)在M-Mode,對(duì)于操作系統(tǒng)來說,可以通過轉(zhuǎn)發(fā)或者代理給S-Mode的操作系統(tǒng),如果S-Mode存在中斷處理,那么處于S-Mode的系統(tǒng)可以直接處理,這樣比較簡(jiǎn)潔。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉