¿Cómo me despierto del modo de suspensión en PIC10F200 a través del perro guardián?

Hasta ahora he trabajado con muchos otros microcontroladores pero no con la familia PIC. Tengo problemas para despertarme del modo de suspensión mediante el mecanismo de vigilancia en un PIC10F200. Lo estoy programando en C usando MPLAB X IDE v2.35. Todas las funciones y macros son parte de las bibliotecas de referencia del microchip para el procesador.

Aquí hay un ejemplo mínimo de cuál es mi problema:

#include <xc.h>
#pragma config CP    = OFF   // Code protection off
#pragma config MCLRE = OFF   // GP3/MCLR pin fuction is digital I/O
#pragma config WDTE  = ON    // Watchdog Timer enabled
#define _XTAL_FREQ 4000000

void main(void) {
    OPTION = 0 | nGPWU | nGPPU & ~T0CS & ~T0SE | PSA | PS2 | PS1 | PS0;    // bits: 7: no wake-up on pin change; 6: no weak pullups; 5: internal clock; 4: incremnt low to high; 3: prescale on wdt (Timer0 if cleared); 2-0: clock division by 128
    TRISGPIO = 0b00000000; // set all to output

    while(1) {
        GP0 = 1;   GP1 = 1;   GP2 = 1;   SLEEP();  // set all high and sleep a bit
        GP0 = 0;   GP1 = 0;   GP2 = 0;   SLEEP();  // set all low  and sleep a bit
    }
}

Básicamente, este es un ejemplo clásico de pin de palanca (LED parpadeante) que usa el perro guardián. Solo los pines están altos todo el tiempo. ¿Qué hice mal?

Hay demasiadas cosas en capas aquí. ¿Realmente necesita un compilador en una máquina que solo tiene 255 ubicaciones de instrucciones utilizables? Por ejemplo, no sabemos qué hace realmente SLEEP().
SLEEP es una función integrada y parte de MPLAB X. Llama a la instrucción del ensamblador del mismo nombre. El PIC10F200 no tiene comparador y no define el registro. Estoy acostumbrado a C y no hay ninguna razón para que aprenda la variante de ensamblador de PIC. Gracias por sus comentarios.
Por lo general, cuando se produce un perro guardián, reinicia el programa desde el principio. Por lo tanto, nunca llegará a la segunda llamada SLEEP().
De los AVR, estoy acostumbrado a continuar el programa, donde lo dejó, pero tendría que configurar el perro guardián en el modo de interrupción en lugar del modo de reinicio. Estaba buscando algo similar en el PIC y pensé en la hoja de datos que sería el comportamiento predeterminado: "Algunos registros no se restablecen de ninguna manera [...] No se ven afectados por un restablecimiento de WDT durante la suspensión o un restablecimiento de MCLR durante Dormir, ya que estos restablecimientos se consideran como la reanudación del funcionamiento normal". ¿De qué sirve un temporizador de vigilancia con modo de suspensión si no hay forma de retener datos entre sueños?
Nunca suponga nada cuando cambie de proveedor. Una vez, Intel hizo una reducción de troquel en la serie 8051 de micros... El rendimiento cambió lo suficiente como para romper algunos diseños de PCB. Entonces, incluso el mismo proveedor puede arruinarlo. (La solución fue 20k pullups para aquellos que necesitan saber).

Respuestas (1)

La respuesta finalmente me llegó en forma de Howardlong. De hecho, el perro guardián provoca un reinicio cada vez que se ingresa al modo de suspensión. Sin embargo, uno puede conservar las variables entre reinicios después de dormir usando la persistentpalabra clave en la declaración de variables.

El problema es que, de esta manera, la variable no se puede inicializar de la manera normal. Para darle un valor inicial, la mejor manera es detectar un reinicio de encendido e inicializarlo únicamente desde el reinicio. Inicializarlo normalmente conduciría a un tipo de problema de huevo y gallina, en el que desea conservar el valor, pero configurarlo en un reinicio. Tenga en cuenta que algunos registros también se restablecen mediante un restablecimiento WDT y, por lo tanto, deben configurarse cada vez.

Aquí hay un ejemplo:

#include <xc.h>
#include <stdbool.h>
#pragma config CP    = OFF   // Code protection off
#pragma config MCLRE = OFF   // Master Clear Enable (GP3/MCLR pin fuction is digital I/O, MCLR internally tied to VDD)
#pragma config WDTE  = ON   // Watchdog Timer enabled
#define _XTAL_FREQ 40000000

static persistent bool _bState; // Persistent so the C startup code doesn't initialise

void main(void) {   
    // Check STATUS bits for type of reset
    if ( ! ( GPWUF==0 && nPD==0 && nTO==0 ) ) {
        // NOT a WDT wakeup from sleep, so treat as a power on reset
        _bState=false;
        OSCCALbits.FOSC4=0;
    }
    // These SFRs must be re-written after every reset
    OPTION = 0b11001100; // WDT is div-by-32 prescaled
    TRISGPIO = 0b1011;   // GP2 output

    GP2=_bState;
    _bState=!_bState;
    SLEEP();                
}
Adicionalmente quiero expresar mi descontento con uno de los comentarios sobre mi pregunta inicial. Cuestionar por qué quiero usar C y mostrar una falta de conocimiento de las funciones básicas no es realmente constructivo. Si crees que una pregunta es estúpida, debería ser fácil de responder. Si no quieres perder el tiempo, ignóralo.