Estou pensando em desenvolver software alimentado por bateria usando os controladores EFM Gekko (http://energymicro.com/) e gostaria que o controlador estivesse dormindo sempre que não houvesse nada útil para ele fazer. A instrução WFI (Wait For Interrupt) é usada para esse fim; colocará o processador em suspensão até que ocorra uma interrupção.
Se o sono estivesse comprometido armazenando algo em algum lugar, seria possível usar operações de carregamento exclusivo / armazenamento exclusivo para fazer algo como:
// dont_sleep é carregado com 2 sempre que algo acontece // deve forçar o loop principal a alternar pelo menos uma vez. Se uma interrupção // ocorre que faz com que seja redefinido para 2 durante a seguinte instrução, // o comportamento será como se a interrupção tivesse acontecido depois dele. loja_exclusiva (carga_exclusiva (não dorme) >> 1); while (! dont_sleep) { // Se ocorrer uma interrupção entre a próxima instrução e store_exclusive, não durma load_exclusive (SLEEP_TRIGGER); if (! dont_sleep) loja_exclusiva (SLEEP_TRIGGER); }
Se uma interrupção ocorrer entre as operações load_exclusive e store_exclusive, o efeito seria pular a store_exclusive, fazendo com que o sistema execute o loop mais uma vez (para ver se a interrupção havia definido dont_sleep). Infelizmente, o Gekko usa uma instrução WFI em vez de um endereço de gravação para acionar o modo de suspensão; escrevendo código como
if (! dont_sleep) WFI ();
correria o risco de que uma interrupção pudesse ocorrer entre o 'if' e o 'wfi' e definir dont_sleep, mas o wfi iria em frente e seria executado de qualquer maneira. Qual é o melhor padrão para evitar isso? Defina PRIMASK como 1 para impedir que as interrupções interrompam o processador antes de executar o WFI e limpe-o imediatamente depois? Ou existe algum truque melhor?
EDITAR
Eu estou pensando sobre o bit Event. Pela descrição geral, ele gostaria que fosse destinado ao suporte a vários processadores, mas estava se perguntando se algo como o seguinte poderia funcionar:
if (não dorme) SEV (); / * Tornará o seguinte sinalizador de evento claro do WFE, mas não será interrompido * / WFE ();
Cada interrupção que define não_sleep também deve executar uma instrução SEV; portanto, se a interrupção ocorrer após o teste "se", o WFE limpará o sinalizador de evento, mas não entrará no modo de suspensão. Isso soa como um bom paradigma?