zoukankan      html  css  js  c++  java
  • riscv 开发之S模式ecall调用

    我们知道有些寄存器只能在m模式下设置和访问,如果s模式想要使用某个功能,只能先回到m模式然后再进行相应的设置。OpenSBI定义了s模式和m模式之间功能调用的接口,s模式通过执行“ecall”指令回到m模式使用相关功能,在本章节和下一章节我们将通过类似的方式来学习s模式下如何使用ecall和m模式下如何处理来自s模式的ecall异常。

    首先我们将ecall指令封装成宏来使用,如下所示。

    #ifndef _ASM_RISCV_ECALL_H
    #define _ASM_RISCV_ECALL_H
    #define RISCV_ECALL(which, arg0, arg1, arg2) ({            \
        register unsigned long a0 asm ("a0") = (unsigned long)(arg0);   \
        register unsigned long a1 asm ("a1") = (unsigned long)(arg1);   \
        register unsigned long a2 asm ("a2") = (unsigned long)(arg2);   \
        register unsigned long a7 asm ("a7") = (unsigned long)(which);  \
        asm volatile ("ecall"                   \
                  : "+r" (a0)               \
                  : "r" (a1), "r" (a2), "r" (a7)        \
                  : "memory");              \
        a0;                         \
    })
    #define RISCV_ECALL_0(which) RISCV_ECALL(which, 0, 0, 0)
    #endif

    这个宏的封装方式也是参考了Linux下的“sbi.h”,which表示调用号,按照OpenSBI的规范,调用号是存放在a7寄存器中,其他的参数从a0寄存器开始存放。当然在测试中我们不会去检测a7寄存器的,在实际的OpenSBI代码中,会通过a7寄存器判断是何种ecall调用然后进行不同的处理。在“main”中调用ecall宏发起一个ecall调用,如下所示。

    static void main(void)
    {
        printf("%s %d.\r\n", __func__, __LINE__);
        supervisor_trap_init();
        RISCV_ECALL_0(0);
        while(1);
    }

    在m模式的异常处理中,我们先对s模式的ecall异常不做任何处理,如下所示。

    static char *interrupt_cause[] = {
        "Reserved",
        "Supervisor software interrupt",
        "Reserved",
        "Machine software interrupt",
        "Reserved",
        "Supervisor timer interrupt",
        "Reserved",
        "Machine timer interrupt",
        "Reserved",
        "Supervisor external interrupt",
        "Reserved",
        "Machine external interrupt",
        "Reserved",
        "Reserved",
        "Reserved",
        "Reserved"
    };
    
    static char *exception_cause[] = {
        "Instruction address misaligned",
        "Instruction access fault",
        "Illegal instruction",
        "Breakpoint",
        "Load address misaligned",
        "Load access fault",
        "Store/AMO address misaligned",
        "Store/AMO access fault",
        "Environment call from U-mode",
        "Environment call from S-mode",
        "Reserved",
        "Environment call from M-mode",
        "Instruction page fault",
        "Load page fault",
        "Reserved",
        "Store/AMO page fault"
    };
    void machine_trap(void)
    { 
        unsigned long cause = mcause_get();
        unsigned long mepc  = mepc_get();
        unsigned long tval  = mtval_get();
        int is_int = (cause & (1l << 63l)) ? 1 : 0;
        int mcode = cause & 0xff;
        if (mcode >= 16) {
            printf("%s : %s.\r\n", is_int ? "Interrupt" : "Exception", "Unknown code");
            return;
        }
        if (is_int) {
            printf("Interrupt : %s.\r\n", interrupt_cause[mcode]); 
            switch (mcode) {
            case M_SOFT_INT:
                msoftint_clear();
                break;
            case M_TIMER_INT:
                timer_set(timer_get() + TIMER_CLK_RATE);
                // raise a supervisor software interrupt.
                //sip_set(SIP_SSIP);
                break;
            }
        } else {
            printf("Exception : %s.\r\n", exception_cause[mcode]); 
            switch (mcode) {
            case ILLEGAL_INSTRUCTION:
                printf("tval = %p\r\n", tval);
                printf("mepc = %p\r\n", mepc);
                break;
            case ECALL_FROM_SMODE:
                break;
            }
            mepc_set(mepc + 4);
        }
        return;
    }

     

  • 相关阅读:
    NVIC
    ONE WIRE
    对话框
    STM32_USART
    [Java]eclipse的使用
    [转] Android资源管理框架(Asset Manager)简要介绍和学习计划
    [其他]网站收录
    [Java]Java简介
    [网络技术]网关 路由器 OSI
    [安卓]安卓模拟器(Android Emulator)
  • 原文地址:https://www.cnblogs.com/dream397/p/15686532.html
Copyright © 2011-2022 走看看