我正在研究使用 EFM Gekko 控制器 (http://energymicro.com/) 开发电池供电的软件,并且希望控制器在没有任何用处时处于睡眠状态。WFI(等待中断)指令用于此目的;它将使处理器进入睡眠状态,直到发生中断。
如果睡眠是通过在某个地方存储某些东西来进行的,则可以使用 load-exclusive/store-exclusive 操作来执行以下操作:
// dont_sleep 会在任何时候加载 2 // 应该强制主循环至少循环一次。如果一个中断 // 发生导致它在以下语句中重置为 2, // 行为就像中断发生在它之后一样。 store_exclusive(load_exclusive(dont_sleep) >> 1); 而(!dont_sleep) { // 如果在 next 语句和 store_exclusive 之间发生中断,不要休眠 load_exclusive(SLEEP_TRIGGER); 如果(!dont_sleep) store_exclusive(SLEEP_TRIGGER); }
如果在 load_exclusive 和 store_exclusive 操作之间发生中断,效果将是跳过 store_exclusive,从而导致系统再循环一次(查看中断是否设置了 dont_sleep)。不幸的是,Gekko 使用 WFI 指令而不是写地址来触发睡眠模式;像这样写代码
如果(!dont_sleep) WFI();
会冒在“if”和“wfi”之间发生中断并设置 dont_sleep 的风险,但 wfi 会继续执行。防止这种情况的最佳模式是什么?将 PRIMASK 设置为 1 以防止在执行 WFI 之前中断中断处理器,并在之后立即清除它?还是有什么更好的技巧?
编辑
我想知道事件位。根据一般描述,它希望它适用于多处理器支持,但想知道以下内容是否可行:
如果 (dont_sleep) SEV(); /* 将使以下 WFE 清除事件标志但不休眠 */ WFE();
每个设置 don't_sleep 的中断也应该执行一条 SEV 指令,所以如果中断发生在“if”测试之后,WFE 将清除事件标志但不会进入睡眠状态。这听起来像是一个很好的范例吗?