小编Ech*_*Ray的帖子

处理中断和使用 WFI risc-v cpu 指令的预期/正确方法是什么?

我对裸机编程非常陌生,以前从未接触过中断,但我一直在 RISC-V FE310-G002 SOC 供电的开发板上学习。

我一直在阅读有关 RISC-V WFI(等待中断)指令的内容,并且从手册中来看,听起来您不能依靠它来实际休眠核心。相反,它仅建议系统可以停止执行,并且应该将指令视为 NOP。然而,这对我来说似乎毫无用处。考虑以下 ASM 程序片段:

wfi_loop:
WFI
J wfi_loop
Run Code Online (Sandbox Code Playgroud)

由于不能依赖 WFI,因此必须执行此操作。然而,从中断处理程序中执行 MRET 后,您仍然会陷入循环中。因此,您必须使其以全局变量为条件,该全局变量的值在中断处理程序中更新。这看起来非常混乱。

此外,如果您的实现实际上遵循 WFI 指令,并且在执行 WFI 指令之前触发了中断,则整个内核将停止运行,直到触发其他中断,因为它将在 WFI 指令之前返回。

当没有工作要做时,该指令的唯一正确用法似乎是在内核调度程序内部。但即便如此,我认为您也不会想从中断处理程序返回到此类代码,而是从头开始重新启动调度程序算法。但这也会是一个问题,因为你必须以某种方式回滚堆栈,等等......

我一直在脑子里思考这个问题,但似乎无法找到安全的用途。也许,如果您以原子方式使用 CSRRS 启用中断,然后立即调用 WFI,如下所示:

CSRRSI zero, mie, 0x80
wfi_loop:
WFI
J wfi_loop
NOP
NOP
Run Code Online (Sandbox Code Playgroud)

然后确保在从中断处理程序调用 MRET 之前将 mepc 寄存器增加 8 个字节。在返回之前,还必须在中断处理程序内部的 mie 寄存器中再次禁用中断。只有当 WFI、J 和 NOP 都编码为 4 字节指令时,无论是否使用压缩指令,该解决方案才是安全的。它还取决于在 CSRRSI 指令启用后,程序计数器在可能触发中断之前到达 WFI 指令。然后,这将允许在代码中的安全位置触发中断,并以中断等待它的循环的方式返回。

我想我只是想了解我可以从硬件中获得什么行为,以及如何正确调用中断并返回并使用 WFI 指令?

assembly interrupt interrupt-handling riscv riscv32

7
推荐指数
2
解决办法
5838
查看次数

如何从汇编调用 C 函数以及如何静态链接它?

我正在玩弄并试图了解计算机和程序的低级操作。为此,我正在尝试链接 Assembly 和 C。

我有2个程序文件:

“callee.c”中的一些C代码:

#include <unistd.h>

void my_c_func() {
  write(1, "Hello, World!\n", 14);
  return;
}
Run Code Online (Sandbox Code Playgroud)

我在“caller.asm”中还有一些 GAS x86_64 程序集:

.text

.globl my_entry_pt

my_entry_pt:
  # call my c function
  call my_c_func # this function has no parameters and no return data

  # make the 'exit' system call
  mov $60, %rax # set the syscall to the index of 'exit' (60)
  mov $0, %rdi # set the single parameter, the exit code to 0 for normal exit
  syscall
Run Code Online (Sandbox Code Playgroud)

我可以像这样构建和执行程序:

$ …
Run Code Online (Sandbox Code Playgroud)

c linux assembly gcc x86-64

4
推荐指数
1
解决办法
220
查看次数

标签 统计

assembly ×2

c ×1

gcc ×1

interrupt ×1

interrupt-handling ×1

linux ×1

riscv ×1

riscv32 ×1

x86-64 ×1