Estoy buscando desarrollar software alimentado por batería usando los controladores EFM Gekko (http://energymicro.com/) y me gustaría que el controlador esté dormido cada vez que no haya nada útil para hacerlo. La instrucción WFI (Wait For Interrupt) se utiliza para este propósito; pondrá el procesador en suspensión hasta que ocurra una interrupción.
Si el sueño se activara almacenando algo en algún lugar, uno podría usar operaciones exclusivas de carga / exclusivas de tienda para hacer algo como:
// dont_sleep se carga con 2 cada vez que sucede algo que // debería forzar al ciclo principal a circular al menos una vez. Si una interrupción // ocurre que hace que se restablezca a 2 durante la siguiente declaración, // el comportamiento será como si la interrupción ocurriera después. store_exclusive (load_exclusive (dont_sleep) >> 1); mientras que (! dont_sleep) { // Si se produce una interrupción entre la siguiente instrucción y store_exclusive, no duermas load_exclusive (SLEEP_TRIGGER); si (! dont_sleep) store_exclusive (SLEEP_TRIGGER); }
Si ocurriera una interrupción entre las operaciones load_exclusive y store_exclusive, el efecto sería omitir store_exclusive, haciendo que el sistema se ejecute a través del ciclo una vez más (para ver si la interrupción había establecido dont_sleep). Desafortunadamente, Gekko utiliza una instrucción WFI en lugar de una dirección de escritura para activar el modo de suspensión; escribir código como
si (! dont_sleep) WFI ();
correría el riesgo de que se produzca una interrupción entre el 'if' y el 'wfi' y establezca dont_sleep, pero el wfi continuará y se ejecutará de todos modos. ¿Cuál es el mejor patrón para evitar eso? Establezca PRIMASK en 1 para evitar que las interrupciones interrumpan el procesador justo antes de ejecutar el WFI, y bórrelo inmediatamente después. ¿O hay algún truco mejor?
EDITAR
Me pregunto sobre el bit del evento. Según la descripción general, desearía que fuera compatible con varios procesadores, pero se preguntaba si algo como lo siguiente podría funcionar:
if (no dormir) SEV (); / * Hará que la siguiente marca de evento WFE sea clara pero no duerma * / WFE ();
Cada interrupción que establezca don't_sleep también debe ejecutar una instrucción SEV, por lo que si la interrupción ocurre después de la prueba "if", el WFE borrará el indicador de evento pero no se irá a dormir. ¿Suena eso como un buen paradigma?