WFI(Wait For Interrupt)指令是ARM中的一个Hint 指令,内核执行hint指令的时候不需要依赖额外的处理操作。WFI指令可以让CPU进入standby 模式,即低功耗模式,此时内核会暂停其他活动,一直等待中断事件的发生,检测到中断发生后,WFI指令执行完成,CPU退出standby模式。
本文将从ARM hint指令、WFI的用途以及WFI的唤醒事件等三个角度解释WFI指令。
一、ARM Hint 指令
HINT 指令可以合法地被视为 NOP指令,但它们可以具有特定于实现的效果,常见的HINT指令有:
- NOP // No operation,无操作, 不保证CPU会花时间去执行
- YIELD // 提示当前线程正在执行可以换出的任务
- WFE // Wait for Event,进入low power状态,直到等待的事件发生
- WFI // Wait for interrupt,进入low power状态,直到等待的中断或与中断类似的操作发生
- SEV // Send Event,发送事件,与WFE对应
- SEVL // Send Event Local,发送本地事件,与WFE对应
ARM 汇编语言中包含可用于让core进入低功耗状态(low-power state)的指令:WFI或WFE。ARM架构将这些指令定义为hint指令,这意味着core在执行它们时不需要采取任何特定操作。然而,在 Cortex-A 处理器系列中,这些指令的实现方式是关闭几乎所有内核部分的时钟。这意味着内核的功耗显着降低,仅消耗静态漏电流,没有动态功耗。
二、WFI指令的用途
WFI指令的主要目的就是使core进入standby模式,直到中断或者类似中断的事件发送,才退出,core继续工作。
standby 模式- 待机模式
在待机模式下,core保持上电状态,但其大部分时钟停止或者进入时钟门限。这意味着core的绝大部分都处于static state,唯一消耗的功率是用于寻找中断唤醒条件的泄漏电流和少量逻辑时钟。
使用 WFI(等待中断)或 WFE(等待事件)指令可以进入此模式。ARM 建议在 WFI 或 WFE 之前使用数据同步屏障 (Data Synchronization Barrier ,DSB) 指令,以确保待处理的内存事务在更改状态之前完成。
core进入待机状态后,会停止执行,直到检测到唤醒事件。唤醒条件取决于进入指令。对于 WFI,需要中断事件或外部调试请求来唤醒core。对于 WFE,存在许多指定的事件,包括cluster中执行 SEV 指令的另一个core。
WFI 指令广泛用于电池供电的系统。例如,手机可以每秒多次将core置于待机模式,同时等待用户按下按钮才唤醒core,从而可以节省功耗。
WFE 类似于 WFI。core暂停执行,直到发生事件。这可以是列出的事件条件之一,也可以是cluster中另一个core发出的事件信号。其他core可以通过执行 SEV 指令来发出事件信号。SEV 向所有core发送一个事件信号。还可以对generic timer通用定时器进行编程,以触发将core从 WFE 唤醒的周期性事件。
总而言之,WFI 指令可以提示hint core在接收到中断或类似的exception之前无需执行任何操作,具体来说有两部分:
- 强制暂停core的运行以及所有相关的总线活动。
- 暂停处理器执行指令。
三、WFI指令的唤醒事件
WFI可以使core进入待机状态,而将core从待机状态中唤醒,则需要中断事件或者类似中断事件的exception(debug事件):
- 物理的IRQ中断,但是忽略 CPSR寄存器的 I 位.
- 物理的FIQ中断,但是忽略 CPSR寄存器的 F 位.
- 物理的异步abort,但是忽略 CPSR寄存器的 A 位.
- 异步的调试事件(debug event),当启用侵入式调试(invasive debug)并允许调试事件时,比如Trace 32中的 break 操作,也会将core唤醒.
- 包括其他实现定义的硬件机制来生成 WFI 唤醒事件.
四、WFI使用注意事项
- 在WFI指令之前使用 DSB 、DMB等内存屏障指令,使得core在进入待机模式之前,完成内存交互。
- 当硬件检测到WFI唤醒事件后,WFI指令才算执行完成。
- WFI唤醒事件不能被CPSR中的相关掩码(I F A)等bit 位屏蔽,即忽略CPSR中的IFA相关bit 位。
- ARM架构并未定义低功耗状态的确切性质,但 WFI 指令的执行不得导致内存一致性遭受破坏。
- 如果是为了测试中断事件而使用WFI,注意在中断发生和WFI之间不应有耗时事件(如大量的printf打印),否则有可能导致中断丢失,即中断已经处理完成了才执行WFI指令,此时中断已经消失了,但是WFI还在一直等中断。use case如下:
当检测到中断时,WFI指令才算完成,才会唤醒处理器,假设有这样一个use case:
Timer(10); // 假设这是个timer,10秒后将发起中断,中断handler在其他地方定义
WFI(); //如果处理器没有接收到中断,WFI指令将没有完成,一直处于休眠状态,下一条printf也不会被执行
printf("中断发生,WFI检测到中断");
正常情况下是可以看到打印的,但是,在timer和WFI之间加入一个耗时事件:
Timer(10); // 10秒后将发起中断
WasteTime(20); // 执行这个函数需要20秒
WFI(); //从中断发生,到处理完成中断用不了10秒,执行到WFI时,中断已经消失了,所以CPU会一直处于休眠状态,下面的printf也不会被执行
printf("中断发生,WFI检测到中断");
文章转自CSDN,作者:SOC罗三炮,文章已获得原创作者授权
作者:lvy
文章来源:Arm精选
推荐阅读
- PMU : TrustedFirmware运行时的性能数据的统计方法
- CoreLink NIC-400:适用于可穿戴设备和入门级智能手机的出色互连
- 2023年Arm最新处理器架构分析——X4、A720和A520
欢迎关注ARM精选专栏, 欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。