RISCV基础开发(十三)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2021年8月21日13:16:41 评论 776

QEMU裸机开发之S模式中断设置

1. 中断初始化

S模式下的中断初始化和M模式基本类似,只不过操作的是S模式下的CSR寄存器,如下所示。

static void supervisor_trap_init(void)
{
    //this stack is used for supervisor_trap_entry in entry.S
    sscratch_set((unsigned long)(__stack_start + 4096 * 3));

    // set the supervisor trap handler.
    stvec_set((unsigned long)supervisor_trap_entry);

    // enable supervisor interrupts.
    sstatus_set(sstatus_get() | SSTATUS_SIE);

    // enable supervisor timer and soft interrupts.
    sie_set(sie_get() | SIE_STIE | SIE_SSIE);
}

static void main(void)
{
    printf("%s %d.\r\n", __func__, __LINE__);

    supervisor_trap_init();

    while(1);
}

唯一不同的是S模式的中断栈使用的是__stack_start往上第三个4KB的空间,其余的和m模式下都差不多,这里就不在赘述了。

2. 中断处理

2.1 中断入口

在“entry.S”中,我们需要实现s模式中断和异常处理的入口,如下所示。

#
# supervisor trap entry.
#
.globl supervisor_trap_entry
.align 4
supervisor_trap_entry:

    # sscratch holds smode trap stack address,
    # swap current sp and smode trap stack address
    csrrw sp, sscratch, sp

    // call the C trap handler in trap.c
    call supervisor_trap

    # restore old sp value
    csrrw sp, sscratch, sp

    sret

处理逻辑也和m模式下一样,就是设置好栈地址后,然后调用“supervisor_trap”C函数进行处理。

2.2 中断C函数处理

S模式的C处理函数和m模式同样基本类似,只不过将相关CSR寄存器换成S模式下的,如下所示。

void supervisor_trap(void)
{ 
    unsigned long tval = stval_get();
    unsigned long sepc = sepc_get();
    unsigned long cause = scause_get();

    int is_int = (cause & (1l << 63l)) ? 1 : 0;
    int scode = cause & 0xff;

    if (scode >= 16) {
        printf("%s : %s.\r\n", is_int ? "Interrupt" : "Exception", "Unknown code");
        return;
    }

    if (is_int) {
        printf("Interrupt : %s.\r\n", interrupt_cause[scode]); 
        switch (scode) {
        case S_SOFT_INT:
            break;
        case S_TIMER_INT:
            break;
        }
    } else {
        printf("Exception : %s.\r\n", exception_cause[scode]); 
        switch (scode) {
        case ILLEGAL_INSTRUCTION:
            printf("tval = %p\r\n", tval);
            printf("sepc = %p\r\n", sepc);
            break;
        }

        sepc_set(sepc + 4);
    }

    return;
}

这里只预留了空位,在后续章节会添加相关的处理代码。

3. 测试

由于需要触发中断才能测试中断处理是不是真的被执行了,所以本章节只是准备好这些设置和处理,在下一章节中,通过S模式软中断来一起验证和测试。

4. 工程源码

链接:https://pan.baidu.com/s/1TnTYr7mywdKj5bxpdmWnyA,提取码:q772,见lesson8。

gewenbin
  • 本文由 发表于 2021年8月21日13:16:41
  • 转载请务必保留本文链接:http://www.databusworld.cn/10539.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: