Sto cercando di sviluppare software alimentato a batteria utilizzando i controller Gekko EFM (http://energymicro.com/) e vorrei che il controller si addormentasse ogni volta che non c'è nulla di utile da fare. L'istruzione WFI (Wait For Interrupt) viene utilizzata per questo scopo; metterà il processore in standby fino a quando si verifica un interrupt.
Se il sonno fosse impegnato memorizzando qualcosa da qualche parte, si potrebbero usare operazioni di esclusione del carico / esclusive del negozio per fare qualcosa del tipo:
// dont_sleep viene caricato con 2 ogni volta che succede qualcosa // dovrebbe forzare il ciclo principale a scorrere almeno una volta. Se un interrupt // si verifica che provoca il ripristino su 2 durante la seguente istruzione, // il comportamento sarà come se l'interruzione avvenisse dopo di esso. store_exclusive (load_exclusive (dont_sleep) >> 1); while (! dont_sleep) { // Se si verifica l'interruzione tra la prossima istruzione e store_exclusive, non dormire load_exclusive (SLEEP_TRIGGER); if (! dont_sleep) store_exclusive (SLEEP_TRIGGER); }
Se dovesse verificarsi un interrupt tra le operazioni load_exclusive e store_exclusive, l'effetto sarebbe quello di saltare store_exclusive, facendo in modo che il sistema esegua il ciclo ancora una volta (per vedere se l'interrupt aveva impostato dont_sleep). Sfortunatamente, Gekko utilizza un'istruzione WFI anziché un indirizzo di scrittura per attivare la modalità di sospensione; scrivere codice come
if (! dont_sleep) WFI ();
correrebbe il rischio che si verifichi un'interruzione tra 'if' e 'wfi' e imposti dont_sleep, ma il wfi andrebbe avanti ed eseguirà comunque. Qual è il modello migliore per impedirlo? Impostare PRIMASK su 1 per impedire agli interrupt di interrompere il processore prima di eseguire WFI e cancellarlo immediatamente dopo? O c'è qualche trucco migliore?
MODIFICARE
Mi chiedo il bit dell'evento. Secondo la descrizione generale, vorrebbe che fosse destinato al supporto di più processori, ma si chiedeva se potesse funzionare qualcosa di simile al seguente:
if (dont_sleep) SEV (); / * Renderanno il seguente flag di evento WFE chiaro ma non inattivo * / WFE ();
Ogni interrupt che imposta Don't_sleep dovrebbe anche eseguire un'istruzione SEV, quindi se l'interrupt si verifica dopo il test "if", il WFE cancellerebbe il flag di evento ma non andrebbe in sospensione. Suona come un buon paradigma?