【问题标题】:RISC-V jump to interrupt handlerRISC-V 跳转到中断处理程序
【发布时间】:2020-01-12 04:07:56
【问题描述】:

您好,我正在编写一个小内核以更好地理解 RISC-V。到目前为止,我设法使用 UART 并设置了一个简单的内存管理器。为了能够解析用户输入,我设置了一个中断处理程序并将其地址设置为 MTVEC。然后我在 MSTATUS 和 MIE 中启用了中断。之后,我通过 mmio 寄存器设置 MTIMECMP 并使用 WFI 永远循环(RISC-V 等待中断指令)。然后我注意到 MIP 包含预期的 0x8 (这意味着机器模式计时器中断挂起)。唯一的问题是我的代码没有跳转到 MTVEC。我做错了什么?最好的问候,Serge Teodori

来源:

void mtrap(){
    uint8_t txt[0x100];
    struct uart_t uart = { .reg = (uint32_t*) 0x10013000 };

    stringFormat(txt, 0x100, "machine trap\r\n");
    uart_write(&uart, txt, 0x100);
}

void main(){
    uint8_t txt[0x100];
    uint64_t mvendorid, marchid, mimpid, mhartid, mstatus, misa, mtvec, mie, mip, mcause;
    struct clint_t clint = { .addr = 0x2000000 };
    struct plic_t plic = { .reg = (uint32_t*) 0x0c000000 };
    struct uart_t uart = { .reg = (uint32_t*) 0x10013000 };

    asm volatile ("csrr %[reg], mvendorid" : [reg] "=r" (mvendorid));
    asm volatile ("csrr %[reg], marchid" : [reg] "=r" (marchid));
    asm volatile ("csrr %[reg], mimpid" : [reg] "=r" (mimpid));
    asm volatile ("csrr %[reg], mhartid" : [reg] "=r" (mhartid));
    asm volatile ("csrr %[reg], misa" : [reg] "=r" (misa));

    // block all harts except hart 0
    if(mhartid)
        for(;;){ asm volatile ("wfi"); }

    mm_init(0x84000000, 0x1bffe000); // addr: 2GB + 64MB & size: 512MB - 64MB - 8KB
    uart_init(&uart);

    stringFormat(txt, 0x100, "mvendorid=%x, marchid=%x, mimpid=%x, mhartid=%x, misa=%x\r\n", mvendorid, marchid, mimpid, mhartid, misa);
    uart_write(&uart, txt, 0x100);

    // check if pending interrupt
    asm volatile ("csrr %[reg], mie" : [reg] "=r" (mie));
    asm volatile ("csrr %[reg], mip" : [reg] "=r" (mip));
    asm volatile ("csrr %[reg], mstatus" : [reg] "=r" (mstatus));
    asm volatile ("csrr %[reg], mcause" : [reg] "=r" (mcause));
    stringFormat(txt, 0x100, "mie=%x, mip=%x, mstatus=%x, mcause=%x\r\n", mie, mip, mstatus, mcause);
    uart_write(&uart, txt, 0x100);

    // set interrupt function or vector
    asm volatile ("csrw mtvec, %[reg]" : : [reg] "r" (riscv_mtrap));
    asm volatile ("csrr %[reg], mtvec" : [reg] "=r" (mtvec));
    stringFormat(txt, 0x100, "mtvec=%x\r\n", mtvec);
    uart_write(&uart, txt, 0x100);

    // enable machine mode interrupts
    asm volatile ("csrs mstatus, 0x8");

    // enable interrupts
    asm volatile ("csrs mie, 0x8");

    // check if pending interrupt
    asm volatile ("csrr %[reg], mie" : [reg] "=r" (mie));
    asm volatile ("csrr %[reg], mip" : [reg] "=r" (mip));
    asm volatile ("csrr %[reg], mstatus" : [reg] "=r" (mstatus));
    asm volatile ("csrr %[reg], mcause" : [reg] "=r" (mcause));
    stringFormat(txt, 0x100, "mie=%x, mip=%x, mstatus=%x, mcause=%x\r\n", mie, mip, mstatus, mcause);
    uart_write(&uart, txt, 0x100);

    // enable timer and wait for x cycles
    clint_set_hart_timer(&clint, mhartid, 10);
    for(mip = 0; mip < 0x100; mip++){}

    // check if pending interrupt
    asm volatile ("csrr %[reg], mie" : [reg] "=r" (mie));
    asm volatile ("csrr %[reg], mip" : [reg] "=r" (mip));
    asm volatile ("csrr %[reg], mstatus" : [reg] "=r" (mstatus));
    asm volatile ("csrr %[reg], mcause" : [reg] "=r" (mcause));
    stringFormat(txt, 0x100, "mie=%x, mip=%x, mstatus=%x, mcause=%x\r\n", mie, mip, mstatus, mcause);
    uart_write(&uart, txt, 0x100);

    for(;;){ asm volatile ("wfi"); }
}

asm:

    .align 4
    .globl riscv_mtrap
    .type riscv_mtrap, @function
riscv_mtrap:
    j mtrap
    mret

输出:

mvendorid=0, marchid=0, mimpid=0, mhartid=0, misa=800000000014112d
mie=0, mip=0, mstatus=0, mcause=0
mtvec=80000010
mie=8, mip=0, mstatus=8, mcause=0
mie=8, mip=80, mstatus=8, mcause=0

【问题讨论】:

  • 你能提供一些汇编代码来理解为什么吗?
  • 是的,我明天会发布。我的做法是对的还是我错过了什么?
  • asm volatile ("csrw mtvec, %[reg]" : : [reg] "r" (riscv_mtrap));是不是忘了给r加等号,所以看起来像asm volatile ("csrw mtvec, %[reg]" : : [reg] "=r" (riscv_mtrap));
  • 也就是说,将中断服务程序的地址,从一个寄存器写入CSR MTVEC。 “r”表示读取,“=r”表示写入,所以没有错误。
  • 当我添加 asm volatile ("j riscv_data1"); 其中 riscv_data1.data 部分中定义为 .long0xdeadc0de 在最后的 wfi 指令之前,处理器触发陷阱。 .. 所以无效或未对齐的指令会触发中断处理程序。也许没有运行间隔计时器......嗯必须检查qemu的文档。

标签: c riscv


【解决方案1】:

发现错误。 asm volatile ("csrs mie, 0x8"); 启用软件中断。我必须asm volatile ("csrw mie, 0x80");,现在它可以工作了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2016-03-26
    • 2020-04-29
    • 2021-03-28
    • 2022-08-17
    • 1970-01-01
    相关资源
    最近更新 更多