Zastanawiam się nad stworzeniem oprogramowania zasilanego bateryjnie za pomocą kontrolerów EFM Gekko (http://energymicro.com/) i chciałbym, aby kontroler zasnął, ilekroć nie ma w tym nic użytecznego. W tym celu wykorzystywana jest instrukcja WFI (Wait For Interrupt); spowoduje przejście procesora w tryb uśpienia do momentu wystąpienia przerwania.
Gdyby sen był zaangażowany poprzez przechowywanie czegoś w innym miejscu, można użyć operacji wyłączających ładowanie / wyłączających przechowywanie, aby wykonać coś takiego:
// dont_sleep zostanie załadowane 2 za każdym razem, gdy coś się stanie // powinien zmusić główną pętlę do cyklowania przynajmniej raz. Jeśli przerwanie // występuje, że powoduje zresetowanie go do 2 podczas następującej instrukcji, // zachowanie będzie wyglądało tak, jakby przerwanie nastąpiło po nim. store_exclusive (load_exclusive (dont_sleep) >> 1); while (! dont_sleep) { // Jeśli wystąpi przerwanie między kolejną instrukcją a wyjątkiem store_exlusive, nie śpij load_exclusive (SLEEP_TRIGGER); if (! dont_sleep) store_exclusive (SLEEP_TRIGGER); }
Jeśli wystąpiłoby przerwanie między operacjami load_exclusive i store_exclusive, efektem byłoby pominięcie opcji store_exclusive, co spowodowałoby, że system ponownie uruchomiłby pętlę (aby sprawdzić, czy przerwanie ustawiło dont_sleep). Niestety Gekko używa instrukcji WFI zamiast adresu zapisu, aby uruchomić tryb uśpienia; pisanie kodu jak
if (! dont_sleep) WFI ();
naraziłoby się na ryzyko, że może wystąpić przerwa między „if” a „wfi” i ustawi dont_sleep, ale wfi i tak wykona polecenie. Jaki jest najlepszy wzór, aby temu zapobiec? Ustaw PRIMASK na 1, aby zapobiec przerwaniu przez procesor procesora tuż przed wykonaniem WFI, i wyczyść go natychmiast po? Czy jest jakaś lepsza sztuczka?
EDYTOWAĆ
Zastanawiam się nad bitem zdarzenia. Według ogólnego opisu, chciałby, aby był przeznaczony do obsługi wieloprocesorowej, ale zastanawiał się, czy może działać coś takiego:
if (dont_sleep) SEV (); / * Powoduje usunięcie flagi zdarzenia WFE, ale nie uśpienie * / WFE ();
Każde przerwanie, które ustawia Don't_sleep, powinno również wykonać instrukcję SEV, więc jeśli przerwanie nastąpi po teście „if”, WFE wyczyści flagę zdarzenia, ale nie przejdzie w tryb uśpienia. Czy to brzmi jak dobry paradygmat?