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?