Suspensión de baja potencia con activación WDT en PIC32MM

1

Estoy tratando de poner un PIC32MM0256GPM028 en modo de reposo y que el temporizador de vigilancia del modo de suspensión lo despierte (digamos 1/4 de segundo más tarde, ajustable por SWDTPS). Una vez que se pone en reposo (caídas actuales), simplemente permanece allí.

Esta publicación parece ser la más cercana modo de suspensión PIC32 con un despertador de vigilancia que falla , pero parece que se trata de un restablecimiento que se produce en lugar de una activación.

Tengo esto como una función independiente:

void sleep(uint32_t t){                     //sleep for t WDT periods 
    static uint32_t oldRCON=0;
    SYSKEY = 0x0;
    SYSKEY = 0xAA996655;                    //unlock
    SYSKEY = 0x556699AA;
    //OSCCONbits.SLPEN=0;                     //enable idle
    OSCCONbits.SLPEN=1;                     //enable sleep
    SYSKEY = 0x0;                           //lock
    while(t){
        WDTCONbits.ON=1;                    //enable
        WDTCONbits.WDTCLRKEY=0x5743;        //magic sequence to reset WDT
        oldRCON=RCON;                       //dummy read
        RCONCLR=0xDF;                       //clear all reset reason flags
        __builtin_disable_interrupts();      //disable interrupts

        asm volatile( "wait" );             //sleep/idle as per SLPEN

        Nop();
        WDTCONbits.ON=0;                    //disable
        t--;
    }
}

Fusibles WDT (PS4096 es 4096ms, etc., se desaceleró para que pueda ver lo que hace):

// FWDT
//#pragma config SWDTPS = PS1024       // Sleep Mode Watchdog Timer Postscale Selection bits ~in milliseconds
#pragma config SWDTPS = PS4096       // Sleep Mode Watchdog Timer Postscale Selection bits ~in milliseconds
#pragma config FWDTWINSZ = PS25_0       // Watchdog Timer Window Size bits (Watchdog timer window size is 25%)
#pragma config WINDIS = OFF             // Windowed Watchdog Timer Disable bit (Watchdog timer is in non-window mode)
#pragma config RWDTPS = PS1048576       // Run Mode Watchdog Timer Postscale Selection bits (1:1048576)
#pragma config RCLKSEL = LPRC           // Run Mode Watchdog Timer Clock Source Selection bits (Clock source is LPRC (same as for sleep mode))
#pragma config FWDTEN = OFF             // Watchdog Timer Enable bit 
//#pragma config FWDTEN = ON             // Watchdog Timer Enable bit 

La sección Modos de ahorro de energía (61130) del manual de PIC32 ofrece un fragmento de código (ejemplo 10-1) que es incluso menor que el que tengo (por ejemplo, este código no hace el desbloqueo de syskey):

// Code example to put the Device in sleep and then wake the device using
// the WDT
OSCCONSET = 0x10; // set Power-Saving mode to Sleep
WDTCONCLR = 0x0002; // Disable WDT window mode
WDTCONSET = 0x8000; // Enable WDT
// WDT time-out period is set in the device
// configuration
... user code ...
WDTCONSET = 0x01; // service the WDT
asm volatile( “wait” ); // put device in selected power-saving mode
// code execution will resume here after wake
... user code ...
// The following code fragment is at the beginning of the ‘C’ start-up code
// to find whether the wake from Sleep is due to the WDT
if ( RCON & 0x18 ) // The WDT caused a wake from Sleep
{
asm volatile( “eret” ); // return from interrupt
}

Tengo el código eret en mi controlador reset y nmi y al inicio de main, pero ni siquiera se está reiniciando. No estoy desactivando el modo de ventana porque está desactivado en los fusibles, y no debería impedir que el WDT se dispare de todos modos.

La mayoría de los ejemplos, etc., parecen ser para variantes de MX / MZ, así que me pregunto si hay una diferencia sutil que no haya notado.

¿Cómo consigo que el PIC32MM se ponga en suspensión y se reanude en WDT?

    
pregunta user85471

1 respuesta

0

Parece que la clave está borrando el indicador WDTS en RNMICON. De acuerdo con la hoja de datos, esto debería ser cero en el reinicio, por lo que la función debería funcionar una vez (pero no parece que lo haga).

El código siguiente funciona (es decir, sleep (1); sleeps durante 1 período WDT), aunque aún puede tener algunas líneas innecesarias.

void sleep(uint32_t t){
    SYSKEY = 0x0;
    SYSKEY = 0xAA996655;                    //unlock
    SYSKEY = 0x556699AA;
    //OSCCONbits.SLPEN=0;                     //enable idle
    OSCCONbits.SLPEN=1;                     //enable sleep
    SYSKEY = 0x0;                           //lock
    while(t){
        RCONCLR=0xDF;                       //clear all reset reason flags
        __builtin_disable_interrupts();
        SYSKEY = 0x0;
        SYSKEY = 0xAA996655;
        SYSKEY = 0x556699AA;
        RNMICONbits.WDTS=0;                 //clear sleep WDT flag
        SYSKEY = 0x0;
        WDTCONbits.WDTCLRKEY=0x5743;        //magic sequence to reset WDT
        WDTCONbits.ON=1;                    //enable
        asm volatile( "wait" );             //sleep/idle as per SLPEN
        Nop();
        WDTCONbits.ON=0;                    //disable
        t--;
    }
}
    
respondido por el user85471

Lea otras preguntas en las etiquetas