Цитата(ataradov @ Mar 29 2016, 02:12)

Это все верно если ждем прерывания от внутренних источников, да и то не всегда.
Вам тут уже ответили об общем принципе:
WFI должна выполняться только тогда, когда выполнена вся запланированная работа и нет работы, которую надо выполнить.
Т.е. (в случае наличия ОС) задача самого нижнего приоритета (фоновая) должна выполнять простой цикл с всего одной инструкцией: WFI (или WFE).
Вся остальная работа - в ISR-ах или задачах ОС более высокого приоритета.
Всё моё ПО именно так и построено, вне зависимости от того - надо экономить энергию или нет - выполнение WFI в фоновом процессе - это просто правило хорошего тона если хотите

Когда нужно установить Ваш флаг, ставите его (хоть в ISR, хоть в любой задаче) и какой-то объект синхронизации ОС (мэйлбокс например) переводите в состояние "готов'.
Далее - у Вас есть задача, ожидающая этот мэйлбокс. Как только мэйлбокс перешёл в сост. "готов" и нет более приоритетных задач, задача получает управление и обрабатывает его.
Любая установка готовности любому объекту синхронизации ОС - это вызов диспетчера ОС, который просмотрит список задач и переведёт те из них, которые готовы к выполнению, в состояние "готова".
Если окажется, что текущая задача ОС имеет приоритет ниже, чем новая готовая задача, то будет вызван переключатель контекста ОС. Вызов переключателя контекста ОС - это собственно программное возбуждение прерывания PendSV, имеющего самый низший приоритет из всех прерываний (ниже любого аппаратного IRQ).
Соответственно в ISR PendSV управление войдёт:
а) или сразу, если выполняется какая-то задача ОС (с более низким приоритетом, чем активизируемая);
б) или после завершения всех текущих ISR, если выполняется любой ISR.
Даже если Вы не используете ОС и у Вас всего одна полезная задача, всё равно лучше построить ПО по тому-же принципу: процедура установки Вашего флага, после его установки, возбуждает PendSV, которое переключит контекст с фоновой на полезную задачу (если уже не выполняется полезная), которая, сделав всю работу (и проверив в конце что флаг опять не установился), вызовет переключатель контекста на фоновую задачу.
Таким образом - как только возникает прерывание, ISR которого ставит флаг, управление находится в ISR-ах до тех пор, пока управление не получит полезная задача и не обработает флаг. И WFI может выполниться только тогда, когда флаг сброшен. И никакие гонки в принципе невозможны.
Цитата(ataradov @ Mar 29 2016, 01:23)

1. Спим
2. Прерывание
3. Установили флаг
4. Работаем
5. Сбросили флаг
6. Готовимся ко сну
7. Спим
Но теперь если произойдет 6a - Прерывание, то мы успешно установим флаг и уйдем в сон.
6а - прерывание, установившее флаг и мэйлбокс (либо просто активировавшее PendSV если без ОС).
6б - сразу после завершения ISR вход в ISR PendSV (если без ОС); если с ОС - вход в PendSV только если выполнялась менее приоритетная задача, если более приоритетная - вход в PendSV после перехода её в сост. ожидания.
В любом случае после прерывания 6а и
до пункта 7, будет выполнено PendSV (сразу или не сразу), которое переключит контекст на задачу обрабатывающую флаг. И управление дойдёт до пункта 7 только когда флаг уже будет обработан.
Запрет прерываний тут нигде не нужен. Хотя можно и запретить если сильно хочется - WFI вроде игнорит маску PRIMASK.
Можете, если без ОС, собственно сам обработчик PendSV сделать полезной задачей, обрабатывающей Ваш флаг. Тогда вся полезная работа у Вас всегда будет выполняться только в ISR-ах, установка Вашего флага будет всегда вызывать установку запроса PendSV.