This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Hibernate code help

Other Parts Discussed in Thread: EK-TM4C123GXL

This code just isn't doing what I thought it would.

I'm trying to make it so that on reset, the LED flashes and then it hibernates. After it wakes from hibernation the LED flashes 5 times and hibernates again, this should happen forever. I'm not sure if my hibernation configuration is out of order or if I'm missing something entirely.

#include <stdint.h>
#include "inc/tm4c123gh6pm.h"

#include <stdbool.h>
#include "driverlib/hibernate.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom_map.h"

uint32_t hibStatus;
uint32_t hibData[64];

void hibernateInterrupt(void);
void ledOn(void);
void ledOff(void);
int main(void);


void hibernate(void) {
    // Enable the hibernation peripheral
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);

    // Enable clocking to the hibernation module
    MAP_HibernateEnableExpClk(MAP_SysCtlClockGet());

    // delay here to allow crystal to power up and stabalize
    MAP_SysCtlDelay(5000);

    // Configure the clock source for Hibernation module, and enable the RTC
    // feature.
    MAP_HibernateClockConfig(HIBERNATE_OSC_LOWDRIVE);
    MAP_HibernateRTCEnable();

    // Initialize the RTC
    MAP_HibernateRTCSet(0);

    // Set the match 0 register for 10 seconds from now
    HibernateRTCMatchSet(0, MAP_HibernateRTCGet() + 10);

    // Clear any pending status
    hibStatus = MAP_HibernateIntStatus(false);
    MAP_HibernateIntClear(hibStatus);

    // Enable the interrupt sources
    MAP_HibernateIntEnable(HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_LOW_BAT
                           | HIBERNATE_INT_RTC_MATCH_0);

    // Save the program state information (not currently populated)
    MAP_HibernateDataSet(hibData, 64);

    // Configure to wake on RTC match, low battery or pin wake
    MAP_HibernateWakeSet(HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC
                         | HIBERNATE_WAKE_LOW_BAT);

    // Set the function to run on wake
    HibernateIntRegister(hibernateInterrupt);

    // Request to go into hibernation mode
    MAP_HibernateRequest();

    // It may take some time for power to be removed
    for (;;) {
    }

}

void hibernateInterrupt(void) {
    // Get the interrupt status
    hibStatus = MAP_HibernateIntStatus(true);

    // Clear the interrupt
    MAP_HibernateIntClear(hibStatus);

    uint8_t i;
    for (i=0; i<5; i++) {
        ledOn();
        MAP_SysCtlDelay(1500000);
        ledOff();
        MAP_SysCtlDelay(1500000);
    }


    // Process the RTC match 0 and wake pin interrupts
    if (hibStatus & (HIBERNATE_INT_RTC_MATCH_0 | HIBERNATE_INT_PIN_WAKE)) {
        // RTC match 0 interrupt actions here

    }

    // Process the low battery interrupt
    if (hibStatus & HIBERNATE_INT_LOW_BAT) {

    }

    hibernate();
}

void configureLED(void) {
    volatile uint32_t loop;

    // Enable the GPIO port that is used for the on-board LED.
    SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF;

    // Do a dummy read to insert a few cycles after enabling the peripheral.
    loop = SYSCTL_RCGC2_R;

    // Enable the GPIO pin for the LED (PF3).  Set the direction as output, and
    // enable the GPIO pin for digital function.
    GPIO_PORTF_DIR_R = 0x08;
    GPIO_PORTF_DEN_R = 0x08;
}

void ledOn(void) {
    // Turn on the LED.
    GPIO_PORTF_DATA_R |= 0x08;
}

void ledOff(void) {
    // Turn off the LED.
    GPIO_PORTF_DATA_R &= ~(0x08);
}


int main (void) {
    configureLED();

    ledOn();

    MAP_SysCtlDelay(3000000);

    ledOff();

    hibernate();
}

Looking through the peripheral driver library it wasn't clear to me where execution starts after returning from hibernation. If I don't set `HibernateIntRegister(hibernateInterrupt);` should I expect that main will be run when the interrupt occurs?

  • While waiting to hear back on this, I've been trying to use the hibernate function in other ways. Specifically I removed the hibernateInterrupt function and placed the reset differentiation in main however my project keeps failing when I call:

    HibernateEnableExpClk(SysCtlClockGet());

    I have a print statement before and after this line, the one after it is never printed.

    I found the example project 'ek-tm4c123gxl/qs-rgb' and went through the agony that is importing the project into CCS on linux because it uses hibernate in the same manor that I'm trying to use it now. This project also fails for me when it hits the `HibernateEnableExpClk()` line. I tried hard-coding the `SysCtlClockGet()` value but that didn't make a difference.

  • Here is the new code that is not working.

    
    #include <stdint.h>
    #include "inc/tm4c123gh6pm.h"
    
    #include <stdbool.h>
    //#include <stdint.h>
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/hibernate.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "inc/hw_hibernate.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "utils/uartstdio.h"
    
    uint32_t hibStatus;
    uint32_t hibData[64];
    
    void hibernateInterrupt(void);
    void ledOn(void);
    void ledOff(void);
    int main(void);
    
    
    #ifdef DEBUG
        void __error__(char *pcFilename, uint32_t ui32Line) {
            // The error routine that is called if the driver library encounters an error.
            // TODO: if the sdcard is enabled we could log this error or we could
            //       print it if the console is enabled
            UARTprintf("%s[%d]\n", pcFilename, ui32Line);
        }
    #endif
    
    void hibernate(void) {
        // Alert UART command line users that we are going to hibernate
        UARTprintf("Entering Hibernate...\n");
    
        // Prepare Hibernation Module
        HibernateGPIORetentionEnable();
        HibernateRTCSet(0);
        HibernateRTCEnable();
        HibernateRTCMatchSet(0, MAP_HibernateRTCGet() + 10);
        HibernateWakeSet(HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC);
    
        // Store state information to battery backed memory
        // since sizeof returns number of bytes we convert to words and force
        // a rounding up to next whole word.
        //HibernateDataSet((uint32_t*)&g_sAppState, sizeof(tAppState)/4+1);
    
        // Go to hibernate mode
        HibernateRequest();
    
        // It may take some time to enter hibernation, wait here
        while(1) {
        }
    }
    
    void configureLED(void) {
        volatile uint32_t loop;
    
        // Enable the GPIO port that is used for the on-board LED.
        SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF;
    
        // Do a dummy read to insert a few cycles after enabling the peripheral.
        loop = SYSCTL_RCGC2_R;
    
        // Enable the GPIO pin for the LED (PF3).  Set the direction as output, and
        // enable the GPIO pin for digital function.
        GPIO_PORTF_DIR_R = 0x08;
        GPIO_PORTF_DEN_R = 0x08;
    }
    
    void ledOn(void) {
        // Turn on the LED.
        GPIO_PORTF_DATA_R |= 0x08;
    }
    
    void ledOff(void) {
        // Turn off the LED.
        GPIO_PORTF_DATA_R &= ~(0x08);
    }
    
    void configureUART(void) {
        // Enable the GPIO Peripheral used by the UART.
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        // Enable UART0
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        // Configure GPIO Pins for UART mode.
        MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
        MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
        MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        // Use the internal 16MHz oscillator as the UART clock source.
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
        // Initialize the UART for console I/O.
        UARTStdioConfig(0, 115200, 16000000);
    }
    
    int main (void) {
        // Enable stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        MAP_FPUEnable();
        MAP_FPUStackingEnable();
    
        // Set the system clock to run at 40Mhz off PLL with external crystal as
        // reference.
        MAP_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
                           SYSCTL_OSC_MAIN);
    
        configureLED();
    
        // Enable the hibernate module
        SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
    
    
        configureUART();
    
        ledOn();
        MAP_SysCtlDelay(2000000);
        ledOff();
    
        UARTprintf("#Running\n");
    
        uint32_t resetCause = SysCtlResetCauseGet();
        SysCtlResetCauseClear(resetCause);
    
        UARTprintf("Reset cause: 0x%08x\n", resetCause);
    
        // Reset caused by power on
        if(resetCause == SYSCTL_CAUSE_POR) {
    
            if (HibernateIsActive()) {
    
                // Read the status bits to see what caused the wake
                hibStatus = HibernateIntStatus(false);
                HibernateIntClear(hibStatus);
    
                // Woke from pin interrupt
                if (hibStatus & HIBERNATE_INT_PIN_WAKE) {
                    UARTprintf("Hibernate Wake Pin Wake Event\n");
                }
    
                // Woke from hibernation timeout
                if (hibStatus & HIBERNATE_INT_RTC_MATCH_0) {
                    UARTprintf("Hibernate Wake Pin Wake Event\n");
                }
    
            } else {
                // Reset was due to a cold first time power up
                UARTprintf("Power on reset\n");
    
            }
        } else {
            // External pin reset or other reset event occurred
            UARTprintf("External or other reset\n");
    
        }
    
        UARTprintf("here1\n");
    
        // Initialize clocking for the Hibernate module
        HibernateEnableExpClk(SysCtlClockGet());
        //HibernateClockConfig(HIBERNATE_OSC_LOWDRIVE);
    
        UARTprintf("here2\n");
    
        uint8_t i = 1;
        while(1) {
            ledOn();
            MAP_SysCtlDelay(2000000);
            ledOff();
            MAP_SysCtlDelay(2000000);
            if ((i++) % 15 == 0) {
                UARTprintf("here3\n");
                hibernate();
            }
        }
    }
    
    

    Output from running this code after flashing the device:

    #Running
    Reset cause: 0x00000011
    External or other reset
    here1
    

    Output after hitting reset:

    #Running
    Reset cause: 0x00000001
    External or other reset
    here1

  • After rebooting my pc this morning the `HibernateEnableExpClk(SysCtlClockGet());` line mysteriously works.

    This is after cutting the power to the LaunchPad multiple times yesterday.

  • HI,

    Do you know the function SysCtlClockGet() has a bug inside (in latest TivaWare version) - (e.g. returns 66MHz instead 80) - did you checked that?

    I think I corrected mine, worth to search this forum - Amit posted the correction.

    Petrei

  • Hello Jamie,

    I think in the previous post I did mention if the VDD3ON or VDD3OFF mode is being used and the corresponding HW configuration set correctly? Still no details on the same.

    Regards

    Amit