Я занимаюсь разработкой программного обеспечения с питанием от батареи с использованием контроллеров EFM Gekko (http://energymicro.com/) и хотел бы, чтобы контроллер спал всякий раз, когда для него нет ничего полезного. Для этого используется инструкция WFI (Wait For Interrupt); он переводит процессор в спящий режим до тех пор, пока не произойдет прерывание.
Если бы сна были заняты хранением чего-либо, можно было бы использовать операции исключая загрузку / исключая хранилище, чтобы сделать что-то вроде:
// dont_sleep загружается с 2 каждый раз, когда происходит что-то // должен заставить основной цикл цикл как минимум один раз. Если прерывание // происходит, что приводит к его сбросу до 2 во время следующего оператора, // поведение будет таким, как будто прерывание произошло после него. store_exclusive (load_exclusive (dont_sleep) >> 1); в то время как (! dont_sleep) { // Если между следующим оператором и store_exclusive происходит прерывание, не спим load_exclusive (SLEEP_TRIGGER); если (! dont_sleep) store_exclusive (SLEEP_TRIGGER); }
Если между операциями load_exclusive и store_exclusive должно произойти прерывание, эффект будет состоять в том, чтобы пропустить store_exclusive, что приведет к повторному прохождению системы через цикл (чтобы проверить, не было ли установлено прерывание dont_sleep). К сожалению, Gekko использует инструкцию WFI, а не адрес записи для запуска спящего режима; писать код как
если (! dont_sleep) ВДИ ();
рискует, что между «if» и «wfi» может произойти прерывание, и установит dont_sleep, но wfi все равно будет выполняться и выполняться. Какой лучший способ предотвратить это? Установите PRIMASK в 1, чтобы прерывания не прерывали процессор непосредственно перед выполнением WFI, и очистите его сразу после? Или есть какой-то лучший трюк?
РЕДАКТИРОВАТЬ
Мне интересно немного о событии. По общему описанию, он хотел бы, чтобы он был предназначен для поддержки многопроцессорных систем, но ему было интересно, может ли работать что-то вроде следующего:
если (dont_sleep) СЕВ (); / * После WFE очистит флаг события, но не перейдет в режим сна * / WFE ();
Каждое прерывание, которое устанавливает not_sleep, должно также выполнять инструкцию SEV, поэтому, если прерывание произойдет после теста «if», WFE очистит флаг события, но не перейдет в спящий режим. Это звучит как хорошая парадигма?