我对裸金属编程和中断处理都非常陌生,但我一直在使用基于RISC-V FE310-G002 SOC电源的开发板进行学习。
我一直在研究RISC-V WFI(等待中断)指令,并从手册中了解到,它似乎不能保证使核心真正进入睡眠状态。相反,它只是建议执行可以停止到系统,该指令应被视为NOP。然而,这对我来说似乎相当无用。请考虑以下汇编程序片段:
wfi_loop:
WFI
J wfi_loop
由于WFI是不可靠的,因此需要采取措施。但是,从中断处理程序返回时,您仍然会被困在循环中。因此,您必须将其设置为与全局变量相关联,该全局变量的值在中断处理程序中更新,并且必须具有条件性。这似乎非常混乱。
此外,如果您的实现实际上确实遵守了WFI指令,并且在执行WFI指令之前触发了中断,则整个核心将停止运行,直到触发其他中断为止,因为它将在WFI指令之前返回。
似乎唯一正确的使用方法是在内核调度程序中使用该指令,当没有任务要执行时。但即使是这样,我认为您也永远不会想要从中断处理程序返回到这样的代码中,而是要重新启动调度程序算法。但这也是一个问题,因为您必须以某种方式回滚堆栈等等...
我一直在脑海中来回思考这个问题,但似乎无法找到安全的用途。也许,如果您使用CSRRS原子地启用中断,然后立即调用WFI,就可以解决问题:
CSRRSI zero, mie, 0x80
wfi_loop:
WFI
J wfi_loop
NOP
NOP
在中断处理程序中调用MRET之前,请确保将mepc寄存器增加8个字节。在返回之前,还必须在中断处理程序内部的mie寄存器中再次禁用中断。这种解决方案仅在WFI、J和NOP被编码为4字节指令时才是安全的,无论是否使用压缩指令。它还取决于程序计数器在CSRRSI指令启用中断后到达WFI指令之前,以使中断能够在代码的安全位置触发,并以打破等待它的循环的方式返回。
我想我只是想了解硬件的行为,因此如何正确地调用和返回中断并使用WFI指令?
hlt
。它会“停止”直到下一个硬件中断请求(IRQ)发生。然而,它经常被误解为永久“停机”。因此,wfi
是更好的助记符选择。 - ecmsti
\hlt
作为最后一次尝试让机器处于空闲状态。在等待按键输入时(在检测到没有可用的按键之后),它会在此处被调用(https://hg.ulukai.org/ecm/ldebug/file/d6c84ad50855/source/lineio.asm#l1042)。我们不关心发生哪个中断请求,唯一需要的是如果按下键(IRQ 1),它将恢复。本质上,这是在等待时进行轮询和睡眠。(86-DOS应用程序假定它们是唯一的前台任务。) - ecmhlt
引起的睡眠可能很短(特别是在虚拟机或类似环境中运行时),但对于忙碌循环而言,我们认为很短的时间对于机器来说已经非常长了。适当地空闲可以使CPU在易于>95%的时间内降频和睡眠。我想wfi
在这些情况下与hlt
相同。 - ecm