WFE和WFI的区别

ARM核中的WFI与WFE:低功耗指令解析

1. 概念:

WFI(Wait for interrupt)和WFE(Wait for event)是两个让ARM核进入low-power standby模式的指令,由ARM architecture定义,由ARM core实现。

2. WFI和WFE

2.1 相同点

WFI和WFE的功能非常类似,以ARMv8-A为例(参考DDI0487A_d_armv8_arm.pdf的描述),主要是“将ARMv8-A PE(Processing Element, 处理单元)设置为low-power standby state”。

需要说明的是,ARM architecture并没有规定“low-power standby state”的具体形式,因而可以由ARM core自行发挥,根据ARM的建议,一般可以实现为standby(关闭clock、保持供电)、dormant、shutdown等等。但有个原则,不能造成内存一致性的问题。

Cortex-A57 ARM core为例,它把WFI和WFE实现为“put the core in a low-power state by disabling the clocks in the core while keeping the core powered up”,即我们通常所说的standby模式,保持供电,关闭clock。

2.2 不同点

那它们的区别体现在哪呢?主要体现进入和退出的方式上。

对WFI来说,执行WFI指令后,ARM core会立即进入low-power standby state,直到有WFI Wakeup events发生。

而WFE则稍微不同,执行WFE指令后,根据Event Register(一个单bit的寄存器,每个PE一个)的状态,有两种情况:

  • 如果Event Register为1,该指令会把它清零,然后执行完成(不会standby);

  • 如果Event Register为0,和WFI类似,进入low-power standby state,直到有WFE Wakeup events发生。

2.3 使用场景

WFI

WFI一般用于cpuidle。

WFE

WFE的一个典型使用场景,是用在spinlock中(可参考arch_spin_lock,对arm64来说,位于arm64/include/asm/spinlock.h中)。

spinlock的功能,是在不同CPU core之间,保护共享资源。使用WFE的流程是:

  • a)资源空闲
  • b)Core1访问资源,acquire lock,获得资源
  • c)Core2访问资源,此时资源不空闲,执行WFE指令,让core进入low-power state
  • d)Core1释放资源,release lock,释放资源,同时执行SEV指令,唤醒Core2
  • e)Core2获得资源

以往的spinlock,在获得不到资源时,让Core进入busy loop,而通过插入WFE指令,可以节省功耗,也算是因祸(损失了性能)得福(降低了功耗)吧。

参考资料:
https://www.cnblogs.com/linhaostudy/p/9398798.html

在STM32中,**WFI(Wait For Interrupt)****WFE(Wait For Event)**是两种低功耗模式的进入指令,均用于暂停CPU执行以降低功耗,但触发条件适用场景不同。以下是它们的详细对比及标准库中的使用方法: --- ### **1. WFI(Wait For Interrupt)** - **触发条件**: 通过执行`__WFI()`指令进入低功耗模式,**仅能被中断(IRQ)唤醒**。 - 适用于需要精确控制唤醒源的场景(如定时器中断、外部中断)。 - 唤醒后需手动清除中断标志。 - **标准库使用**: ```c #include "stm32f0xx.h" void Enter_WFI_Mode(void) { // 配置中断(如EXTI) EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; // 启用SYSCFGGPIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); // 配置PA0为外部中断(示例) GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(GPIOA, &GPIO_InitStruct); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); EXTI_InitStruct.EXTI_Line = EXTI_Line0; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStruct); NVIC_InitStruct.NVIC_IRQChannel = EXTI0_1_IRQn; NVIC_InitStruct.NVIC_IRQChannelPriority = 0x00; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); // 进入WFI模式 __WFI(); // CPU暂停,等待中断唤醒 } ``` --- ### **2. WFE(Wait For Event)** - **触发条件**: 通过执行`__WFE()`指令进入低功耗模式,**可被事件(Event)或中断唤醒**。 - 事件来源: - 外部信号通过`EXTI`配置为事件模式(非中断)。 - 内部外设事件(如DMA完成、定时器更新)。 - 适用于低功耗场景下需要灵活唤醒的场景(如传感器数据就绪事件)。 - 唤醒后无需清除标志(事件自动清除)。 - **标准库使用**: ```c #include "stm32f0xx.h" void Enter_WFE_Mode(void) { // 配置事件(如EXTI事件) EXTI_InitTypeDef EXTI_InitStruct; // 启用SYSCFGGPIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); // 配置PA0为事件输入(非中断) GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(GPIOA, &GPIO_InitStruct); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); EXTI_InitStruct.EXTI_Line = EXTI_Line0; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Event; // 关键:配置为事件模式 EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStruct); // 进入WFE模式 __WFE(); // CPU暂停,等待事件或中断唤醒 } ``` --- ### **3. 关键区别** | **特性** | **WFI** | **WFE** | |------------------|----------------------------------|----------------------------------| | **唤醒源** | 仅中断(IRQ) | 中断或事件(Event) | | **标志清除** | 需手动清除中断标志 | 事件自动清除 | | **功耗** | 略高(需检测中断) | 略低(事件检测更高效) | | **适用场景** | 定时唤醒、外部中断 | 传感器事件、DMA完成等 | | **指令** | `__WFI()` | `__WFE()` | --- ### **4. 实际应用建议** - **WFI**: - 适用于需要精确时序的场景(如RTC闹钟唤醒)。 - 示例:低功耗定时采集数据,通过定时器中断唤醒。 - **WFE**: - 适用于异步事件唤醒(如GPIO电平变化、DMA传输完成)。 - 示例:等待外部设备发送数据就绪信号(通过EXTI事件唤醒)。 --- ### **5. 注意事项** 1. **时钟配置**: 进入低功耗模式前需正确配置时钟(如HSI),唤醒后需重新初始化。 2. **外设状态**: 部分外设(如UART)在低功耗模式下可能停止工作,需在唤醒后重新配置。 3. **调试**: 使用WFE时,若调试器连接可能导致意外唤醒(需禁用调试接口的低功耗模式)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值