RISCV------内核及汇编
小狼@http://blog.csdn.net/xiaolangyangyang
1、寄存器组(ABI)

2、异常及中断

- mie:中断开关
- mip:中断状态
- mstatus.mie:全局中断开关
RISCV异常及中断向量有两种方式:一是全部异常及中断使用同一个入口,二是使用向量表,D1s芯片使用的是第一种方式,全部异常及中断使用同一入口,再通过scause判断是异常还是中断,以及异常或中断编号,如下图所示:



3、特权模式



4、启动代码分析
/* linker.ld */
/* 起始地址是0x27000 */
SECTIONS
{
/*
* 设置benos的加载入口地址为0x27000
*
* 这里"."表示location counter,当前位置
*/
. = 0x27000,
/*
* 这里是第一个段text.boot,起始地址就是0x27000
* 这个段存放了benos的第一条指令
*/
_text_boot = .;
.text.boot : { *(.text.boot) }
_etext_boot = .;
/*
* text代码段
*/
. = ALIGN(8);
_text = .;
_stext = .;
.text :
{
*(.text)
}
. = ALIGN(8);
_etext = .;
/*
* 只读数据段
*/
_rodata = .;
.rodata : { *(.rodata) }
_erodata = .;
/*
* 数据段
*/
_data = .;
.data : { *(.data) }
_edata = .;
/*
* bss段
*
* ALIGN(8)表示8个字节对齐
* bss_begin的起始地址以8字节对齐
*/
. = ALIGN(0x8);
_bss = .;
.bss : { *(.bss*) }
_ebss = .;
}
/* boot.S */
/* 启动代码,需要设置SP指针 */
.section ".text.boot"
.globl _start
_start:
/* 关闭中断 */
csrw sie, zero
call __init_uart
call print_asm
/* 设置栈, 栈的大小为4KB */
la sp, stacks_start
li t0, 4096
add sp, sp, t0
/* 跳转到C语言 */
tail kernel_main
print_asm:
/*此时SP栈空间还没分配,把返回地址ra保存到临时寄存器中*/
mv s1, ra
la a0, boot_string
call put_string_uart
/*恢复返回地址ra*/
mv ra, s1
ret
.section .data
.align 12
.global stacks_start
stacks_start:
.skip 4096
.section .rodata
.align 3
.globl boot_string
boot_string:
.string "\r\nBooting at asm\r\n"
/* entry.S */
/* 主要定义了异常及中断入口 */
#include "asm/asm-offsets.h"
#include "asm/csr.h"
.macro kernel_entry
addi sp, sp, -(PT_SIZE)
sd x1, PT_RA(sp)
sd x3, PT_GP(sp)
sd x5, PT_T0(sp)
sd x6, PT_T1(sp)
sd x7, PT_T2(sp)
sd x8, PT_S0(sp)
sd x9, PT_S1(sp)
sd x10, PT_A0(sp)
sd x11, PT_A1(sp)
sd x12, PT_A2(sp)
sd x13, PT_A3(sp)
sd x14, PT_A4(sp)
sd x15, PT_A5(sp)
sd x16, PT_A6(sp)
sd x17, PT_A7(sp)
sd x18, PT_S2(sp)
sd x19, PT_S3(sp)
sd x20, PT_S4(sp)
sd x21, PT_S5(sp)
sd x22, PT_S6(sp)
sd x23, PT_S7(sp)
sd x24, PT_S8(sp)
sd x25, PT_S9(sp)
sd x26, PT_S10(sp)
sd x27, PT_S11(sp)
sd x28, PT_T3(sp)
sd x29, PT_T4(sp)
sd x30, PT_T5(sp)
sd x31, PT_T6(sp)
csrr s1, sstatus
sd s1, PT_SSTATUS(sp)
/*保存sepc*/
csrr s2, sepc
sd s2, PT_SEPC(sp)
/*保存sbadaddr*/
csrr s3, sbadaddr
sd s3, PT_SBADADDR(sp)
/*保存scause*/
csrr s4, scause
sd s4, PT_SCAUSE(sp)
/*保存ssratch*/
csrr s5, sscratch
sd s5, PT_TP(sp)
/*保存SP*/
addi s0, sp, PT_SIZE
sd s0, PT_SP(sp)
.endm
.macro kernel_exit
ld a0, PT_SSTATUS(sp)
csrw sstatus, a0
ld a2, PT_SEPC(sp)
csrw sepc, a2
ld x1, PT_RA(sp)
ld x3, PT_GP(sp)
ld x4, PT_TP(sp)
ld x5, PT_T0(sp)
ld x6, PT_T1(sp)
ld x7, PT_T2(sp)
ld x8, PT_S0(sp)
ld x9, PT_S1(sp)
ld x10, PT_A0(sp)
ld x11, PT_A1(sp)
ld x12, PT_A2(sp)
ld x13, PT_A3(sp)
ld x14, PT_A4(sp)
ld x15, PT_A5(sp)
ld x16, PT_A6(sp)
ld x17, PT_A7(sp)
ld x18, PT_S2(sp)
ld x19, PT_S3(sp)
ld x20, PT_S4(sp)
ld x21, PT_S5(sp)
ld x22, PT_S6(sp)
ld x23, PT_S7(sp)
ld x24, PT_S8(sp)
ld x25, PT_S9(sp)
ld x26, PT_S10(sp)
ld x27, PT_S11(sp)
ld x28, PT_T3(sp)
ld x29, PT_T4(sp)
ld x30, PT_T5(sp)
ld x31, PT_T6(sp)
ld x2, PT_SP(sp)
.endm
/*
do_exception_vector必须4字节对齐
否则写入stvec寄存器会不成功
*/
.align 2
.global do_exception_vector
do_exception_vector:
kernel_entry
csrw sscratch, x0
la ra, ret_from_exception
mv a0, sp /* pt_regs */
mv a1, s4
tail do_exception
ret_from_exception:
restore_all:
kernel_exit
sret
.global trigger_load_access_fault
trigger_load_access_fault:
li a0, 0x100001
ld a0, (a0)
ret
5、调试
《T-HEAD+CPU调试技巧.pdf》
6、各特权态的指令
- 各个特权级都拥有的指令:
ECALL:U态陷入S态,S态陷入M态
EBREAK:产生断点异常
FENCE.I:产生一个内存读写屏障
SRET/URET:M太返回S态,S态返回U态
- S态引入的指令:
SFENCE.VMA:主要用于刷新页表
- M态引入的指令:
WFI:让当前处理器核心进入睡眠状态
7、各特权态的CSR
- CSR寄存器有自己的一套独立的地址空间,访问CSR需要使用专用的指令
- 每一个处理器核心都有自己一套独立的4K CSR,这4K CSR分别对应到4个特权态(U\S\V\M),对于每个特权态,最多有1024个CSR可使用
- 访问没有权限的CSR会Trap,访问不存在的CSR会Trap,写只读CSR会Trap,对于可选寄存器的操作会被忽略
【百问网DongshanPI-D1S开发板体验】2环境搭建
全志D1s开发板裸机开发之坏境搭建
DongshanPi-D1s快速上手 | 开发环境搭建
韦东山D1S板子------xfel工具无法烧写bin文件到spi norFlash问题解决
RISC-V 架构 - 精讲