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.

RTC will sometimes miss waking from hibernate

I am using the LX4F120H5QRF based Stellaris launchpad development board to prototype a data-logger at this stage the only external device that is being communicated to is an SD card via SPI. I am making using the FatFs library as shown in one of the stellarisware examples for one of the other dev boards to manage the filesystem.

I have written software that will wake up, read values from a few of the ADC channels and a GPIO port save them to the SD card, set the RTC match register to some time in the future and go back into hibernate.

This is working "mostly", it sits and does its thing logging but every now and again it will will not wake back up from hibernation and will just sit there, I do know the RTC is still functioning though because if I use the wake pin to resume from hibernation when it has got stuck the times logged are correct.

I have tried to look at the log files to determine if there is some particular cause but have been unable to locate anything that looks suspect.

Is anyone able to help me with some ideas on what might cause the RTC match to not wake up the controller, or even a good way to debug the problem as I am at a bit of a loss as to how to debug the issue properly because of how CCS will just freeze up and quit any time you try to debug a project that goes into hibernate mode.

  • Hi Hugh,

        Provide your code, in order for TIers and TI helpers, to help better.

    -kel

  • It is a work project and I am not entirely sure on our rules on releasing code, but in the interest of getting this unusual problem sorted out, and trying to prevent anyone else from wasting so much time trying to solve the same issue I have attached the code. [WRONG VERSION REMOVED]

    Out of chance I have also noticed that this issue is not occurring when the sd card is removed, to me this suggests some kind of interaction with the sysTick timer or SSI Peripheral but I am unsure how to proceed on debugging the issue as I have not, had to work with low power modes where the CPU is shut off before.

     - Hugh

  • Hugh Powell said:
    some kind of interaction with the sysTick timer or SSI Peripheral

    Might this suggest that you disable the SSI Peripheral - just prior to ordering, "Hibernate?"   Upon "wake-up" - enable that SSI. 

    Don't know how or if RTC relies upon SysTick Timer - but if no or minimal issue is introduced - you may, "disable & reenable SysTick" similarly.  (attempt this only after you've confirmed that this SysTick disable does not impact your RTC operation...)

  • I have modified my "shutdown" function to turn off all peripherals and interrupts, and the problem is still existing, I have also told it to turn on the red led if it gets into the infinite loops after Hibernate request is called, and this does not occur, so I am able to confirm it is getting into hibernate mode.

    I am just not sure why it will not wake up.

    Edit: I have just realized the version of code I provided was out of date I will upload the latest version when I get back to the office this afternoon.

  • Sorry for the delay here is the current version I am working with.

    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_gpio.h"
    #include "driverlib/fpu.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/adc.h"
    #include "driverlib/timer.h"
    #include "driverlib/hibernate.h"
    #include "driverlib/uart.h"
    #include "fatfs/src/ff.h"
    #include "fatfs/src/diskio.h"
    #include "util/uartstdio.h"
    
    #ifdef DEBUG
    void__error__(char *pcFilename, unsigned long ulLine)
    {
    }
    #endif
    
    static FATFS g_sFatFs;
    static DIR g_sDirObject;
    static FILINFO g_sFileInfo;
    static FIL g_sFileObject;
    
    #define SHORT_SAMPLE_FREQUENCY 100 // Hertz
    #define LONG_SAMPLE_TIME 2 // Seconds
    
    #define RED_LED   GPIO_PIN_1
    #define BLUE_LED  GPIO_PIN_2
    #define GREEN_LED GPIO_PIN_3
    
    #define A1SCALE 6.283
    #define A2SCALE 6.224
    
    #define FILENAME "log"
    
    char filename[32] = "";
    
    char* itoa(int value, char* result, int base);
    char* uitoa(unsigned int value, char* result, int base);
    int string_size(char* string);
    
    //*****************************************************************************
    //
    // The following are data structures used by FatFs.
    //
    //*****************************************************************************
    static FATFS g_sFatFs;
    static DIR g_sDirObject;
    static FILINFO g_sFileInfo;
    static FIL g_sFileObject;
    
    //*****************************************************************************
    //
    // A structure that holds a mapping between an FRESULT numerical code, and a
    // string representation.  FRESULT codes are returned from the FatFs FAT file
    // system driver.
    //
    //*****************************************************************************
    typedef struct
    {
    	FRESULT iFResult;
    	char *pcResultStr;
    }
    tFResultString;
    
    // Define f_size and f_tell as in fatfs docs
    #define f_size(fp) ((fp)->fsize)
    #define f_tell(fp) ((fp)->fptr)
    
    // A macro to make it easy to add result codes to the table.
    #define FRESULT_ENTRY(f)        { (f), (#f) }
    
    // A table that holds a mapping between the numerical FRESULT code and it's
    // name as a string.  This is used for looking up error codes for printing to
    // the console.
    tFResultString g_psFResultStrings[] =
    {
    		FRESULT_ENTRY(FR_OK),
    		FRESULT_ENTRY(FR_NOT_READY),
    		FRESULT_ENTRY(FR_NO_FILE),
    		FRESULT_ENTRY(FR_NO_PATH),
    		FRESULT_ENTRY(FR_INVALID_NAME),
    		FRESULT_ENTRY(FR_INVALID_DRIVE),
    		FRESULT_ENTRY(FR_DENIED),
    		FRESULT_ENTRY(FR_EXIST),
    		FRESULT_ENTRY(FR_RW_ERROR),
    		FRESULT_ENTRY(FR_WRITE_PROTECTED),
    		FRESULT_ENTRY(FR_NOT_ENABLED),
    		FRESULT_ENTRY(FR_NO_FILESYSTEM),
    		FRESULT_ENTRY(FR_INVALID_OBJECT),
    		FRESULT_ENTRY(FR_MKFS_ABORTED)
    };
    
    // A macro that holds the number of result codes.
    #define NUM_FRESULT_CODES       (sizeof(g_psFResultStrings) /                 \
    		sizeof(tFResultString))
    
    //*****************************************************************************
    //
    // This function returns a string representation of an error code that was
    // returned from a function call to FatFs.  It can be used for printing human
    // readable error messages.
    //
    //*****************************************************************************
    const char *
    StringFromFResult(FRESULT iFResult)
    {
    	uint_fast8_t ui8Idx;
    
    	//
    	// Enter a loop to search the error code table for a matching error code.
    	//
    	for(ui8Idx = 0; ui8Idx < NUM_FRESULT_CODES; ui8Idx++)
    	{
    		//
    		// If a match is found, then return the string name of the error code.
    		//
    		if(g_psFResultStrings[ui8Idx].iFResult == iFResult)
    		{
    			return(g_psFResultStrings[ui8Idx].pcResultStr);
    		}
    	}
    
    	//
    	// At this point no matching code was found, so return a string indicating
    	// an unknown error.
    	//
    	return("UNKNOWN ERROR CODE");
    }
    
    // This is the handler for this SysTick interrupt.  FatFs requires a timer tick
    // every 10 ms for internal timing purposes.
    
    void SysTickHandler(void)
    {
    	// Call the FatFs tick timer.
    	disk_timerproc();
    }
    
    void ConfigureUART(void)
    {
    	// Enable the GPIO Peripheral used by the UART.
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
    	// Enable UART0
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
    	// Configure GPIO Pins for UART mode.
    	GPIOPinConfigure(GPIO_PA0_U0RX);
    	GPIOPinConfigure(GPIO_PA1_U0TX);
    	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);
    }
    
    void next_log_file(void){ // Returns into a global variable
    	FRESULT result = FR_OK;
    	char temp[16] = "";
    	unsigned int count = 0;
    	while (result != FR_NO_FILE){
    		strcpy(filename,FILENAME);
    		uitoa(++count,temp,10);
    		strcat(filename,temp);
    		strcat(filename,".csv");
    		UARTprintf("Testing for: %s\n", filename);
    		result = f_open(&g_sFileObject,filename,FA_READ);
    		f_close(&g_sFileObject);
    	}
    }
    
    void pack_string(unsigned long* data_out, char* data_in){ //Packs 32 bytes into 8 unsigned longs
    	int i;
    	for (i=0;i<8;i++){
    		data_out[i] = data_in[i] + (((unsigned long)data_in[i+1]) << 8) + (((unsigned long)data_in[i+2]) << 16) + (((unsigned long)data_in[i+3]) << 24);
    	}
    }
    
    void unpack_string(unsigned long* data_in, char* data_out){
    	int i;
    	for (i=0;i<8;i++){
    		data_out[i] = data_in[i]&255;
    		data_out[i+1] = (data_in[i]>>8)&255;
    		data_out[i+2] = (data_in[i]>>16)&255;
    		data_out[i+3] = (data_in[i]>>24)&255;
    	}
    }
    
    void OpenLogfile(void){
    	FRESULT iFResult;
    	iFResult = f_open(&g_sFileObject, filename, FA_WRITE | FA_OPEN_ALWAYS);
    	// If there was some problem opening the file, then return an error.
    	if(iFResult != FR_OK)
    	{
    		UARTprintf("Command returned error code %s\n",
    				StringFromFResult(iFResult));
    	}
    
    	// Move to end to file
    	iFResult = f_lseek( &g_sFileObject, f_size(&g_sFileObject));
    	if(iFResult != FR_OK)
    	{
    		UARTprintf("Command returned error code %s\n",
    				StringFromFResult(iFResult));
    	}
    }
    
    void CloseLogfile(void){
    	f_close(&g_sFileObject);
    }
    
    void TakeSample(void){
    	FRESULT iFResult;
    	ADCIntClear(ADC0_BASE, 1);
    	ADCProcessorTrigger(ADC0_BASE, 1);
    
    	unsigned long ADC0Values[4];
    	unsigned long A1, A2;
    	unsigned int dig1, dig2;
    	unsigned long uptime = HibernateRTCGet();
    	unsigned long uptimesub = HibernateRTCSSGet()/32.768;//Partial uptime ms
    
    	char data_string[128] = "";
    	char temp[32] = "";
    	WORD bytes_written;
    
    	while(!ADCIntStatus(ADC0_BASE, 1, false));
    
    	ADCSequenceDataGet(ADC0_BASE, 1, ADC0Values);
    
    	A1 = ADC0Values[1]*A1SCALE;
    	A2 = ADC0Values[3]*A2SCALE;
    
    	dig1 = GPIOPinRead(GPIO_PORTE_BASE, 255);
    	dig2 = GPIOPinRead(GPIO_PORTC_BASE, 255) >> 4;
    
    	uitoa(uptime,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, ".");
    	uitoa(uptimesub,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, "\t");
    	uitoa(A1,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, "\t");
    	uitoa(A2,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, "\t");
    	uitoa(dig1,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, "\t");
    	uitoa(dig2,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, "\n");
    	UARTprintf(data_string);
    
    	// write to the file
    	iFResult = f_write (&g_sFileObject,          /* [IN] Pointer to the file object structure */
    			data_string, /* [IN] Pointer to the data to be written */
    			strlen(data_string),         /* [IN] Number of bytes to write */
    			&bytes_written          /* [OUT] Pointer to the variable to return number of bytes written */
    	);
    	if(iFResult != FR_OK)
    	{
    		UARTprintf("Command returned error code %s\n",
    				StringFromFResult(iFResult));
    	}
    }
    
    void Shutdown(void){
    	UARTprintf("Shutting Down\n");
    /*
    	SysCtlPeripheralDisable(SYSCTL_PERIPH_SSI0);
    	SysCtlPeripheralDisable(SYSCTL_PERIPH_ADC0);
    	SysCtlPeripheralDisable(SYSCTL_PERIPH_TIMER0);
    
    	// Disable interrupts as they might have been causing issues with going back to sleep.
    	SysTickDisable();
    	SysTickIntDisable();
    	IntMasterDisable();
    /*
    	//unsigned long temp;
    	temp = HibernateRTCGet();
    	UARTprintf("%u\t%u\t%u\n",temp,temp+LONG_SAMPLE_TIME,HibernateRTCSSGet());
    	HibernateRTCSet(0);
    	//HibernateRTCMatch0Set(temp+LONG_SAMPLE_TIME); // Set the time to wake up in the future
    	HibernateRTCMatch0Set(LONG_SAMPLE_TIME); // Set the time to wake up in the future
    */
    	UARTprintf("%u\t%u\t%u\t%u\t%u\n",HibernateIsActive(), HibernateIntStatus(0), HibernateWakeGet(), HibernateRTCGet(),HibernateRTCMatch0Get(),HibernateRTCSSGet());
    	SysCtlDelay(SysCtlClockGet()/20); // Give serial 0.05s to finish
    
    	GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, 0x0); // Turn off lights
    
    	HibernateRequest();
    
    	SysCtlDelay(SysCtlClockGet()/4); // Give it way more than it needs to shut down before telling us it is broken;
    	GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, RED_LED); // Turn on red led to show somthing is wrong
    	while(1); //Trap
    }
    
    void Timer0IntHandler(void)
    {
    	// Clear the timer interrupt a bit risky doing it here instead of after sample if you use a fast sample rate
    	TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    	TakeSample();
    }
    
    int main(void)
    {
    	FRESULT iFResult;
    
    	// Enable lazy stacking for interrupt handlers.  This allows floating-point
    	// instructions to be used within interrupt handlers, but at the expense of
    	// extra stack usage.
    	FPULazyStackingEnable();
    
    	// Set the system clock to run at 50MHz from the PLL.
    	SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, 255);
    	GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, 255-127);
    	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED);
    
    	// Needed to unlock PF0 from an alternate function (found this was needed in buttons.c
    	HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY_DD;
    	HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;
    	HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0;
    
    	// Set as a pullup
    	GPIODirModeSet(GPIO_PORTF_BASE, 1, GPIO_DIR_MODE_IN);
    	GPIOPadConfigSet(GPIO_PORTF_BASE, 1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    
    	// Enable the peripherals used by this example.
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    
    	TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER);
    	TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet()/SHORT_SAMPLE_FREQUENCY);
    
    	// Configure ADC
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    	GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_0|GPIO_PIN_1);
    	SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS);
    	ADCHardwareOversampleConfigure(ADC0_BASE, 64);
    
    	// Setup ADC Sequence
    	ADCSequenceDisable(ADC0_BASE, 1);
    	ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH7);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH7);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH6);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH6 | ADC_CTL_IE | ADC_CTL_END);
    	ADCSequenceEnable(ADC0_BASE, 1);
    
    	// Configure SysTick for a 100Hz interrupt.  The FatFs driver wants a 10 ms tick
    	SysTickPeriodSet(SysCtlClockGet() / 100);
    	SysTickEnable();
    	SysTickIntEnable();
    
    	// Enable Interrupts
    	IntMasterEnable();
    
    	ConfigureUART();
    
    	UARTprintf("\n\nIm Awake\n");
    	//UARTprintf("\033[2J\033[HIm Awake\n");
    
    	// Mount the file system, using logical disk 0.
    	iFResult = f_mount(0, &g_sFatFs);
    
    	if(iFResult != FR_OK)
    	{
    		while (1); // Trap the CPU for debug
    	} else {
    		UARTprintf("Opened Filesystem\n");
    	}
    
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
    
    	HibernateEnableExpClk(SysCtlClockGet());
    
    	if(HibernateIsActive() && (HibernateIntStatus(0) & (HIBERNATE_INT_RTC_MATCH_0 | HIBERNATE_INT_PIN_WAKE)))
    	{
    		HibernateIntClear(HibernateIntStatus(0));
    
    		GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, GREEN_LED);
    		UARTprintf("Woke from hibernate\n");
    
    
    		// Load the name of the current logfile from VBAT
    		unsigned long packed_filename[8];
    		HibernateDataGet(packed_filename,8);
    		unpack_string(packed_filename,filename);
    		UARTprintf("Using Log file: %s\n",filename);
    
    		OpenLogfile();
    
    		TakeSample();
    
    		if (!GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0)){
    			GPIOPinWrite(GPIO_PORTF_BASE, RED_LED, RED_LED);
    
    			IntEnable(INT_TIMER0A);
    			TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    			TimerEnable(TIMER0_BASE, TIMER_A);
    
    			while (!GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0)); // Trap until button released, will look at doing some deep sleep stuff here in the future
    
    			IntDisable(INT_TIMER0A);
    			TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    			TimerDisable(TIMER0_BASE, TIMER_A);
    
    			GPIOPinWrite(GPIO_PORTF_BASE, RED_LED, 0x0);
    		}
    
    		CloseLogfile();
    
    		HibernateRTCMatch0Set(HibernateRTCGet()+LONG_SAMPLE_TIME);
    
    		Shutdown();
    	}
    	else {
    		GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, BLUE_LED);
    
    		HibernateGPIORetentionEnable();
    		HibernateRTCSet(0);
    		HibernateRTCEnable();
    		HibernateRTCMatch0Set(5);
    		HibernateWakeSet(HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC);
    		UARTprintf("Configured hibernate\n");
    		next_log_file();
    		// Restore the filename in the power down memory
    		unsigned long packed_filename[8];
    		pack_string(packed_filename,filename);
    		HibernateDataSet(packed_filename,8);
    
    		UARTprintf("Set logfile name %s\nsleeping for 5 seconds\n",filename);
    
    		Shutdown();
    	}
    	// Should never get here
    	while (1) UARTprintf("I'm Broken\n");
    }
    
    
    
    // Two functions to convert an integer to a string, not written by me (http://www.strudel.org.uk/itoa/)
    char* itoa(int value, char* result, int base) {
    	// check that the base if valid
    	if (base < 2 || base > 36) { *result = '\0'; return result; }
    
    	char* ptr = result, *ptr1 = result, tmp_char;
    	int tmp_value;
    
    	do {
    		tmp_value = value;
    		value /= base;
    		*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
    	} while ( value );
    
    	// Apply negative sign
    	if (tmp_value < 0) *ptr++ = '-';
    	*ptr-- = '\0';
    	while(ptr1 < ptr) {
    		tmp_char = *ptr;
    		*ptr--= *ptr1;
    		*ptr1++ = tmp_char;
    	}
    	return result;
    }
    char* uitoa(unsigned int value, char* result, int base) {
    	// check that the base if valid
    	if (base < 2 || base > 36) { *result = '\0'; return result; }
    
    	char* ptr = result, *ptr1 = result, tmp_char;
    	int tmp_value;
    
    	do {
    		tmp_value = value;
    		value /= base;
    		*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
    	} while ( value );
    
    	*ptr-- = '\0';
    	while(ptr1 < ptr) {
    		tmp_char = *ptr;
    		*ptr--= *ptr1;
    		*ptr1++ = tmp_char;
    	}
    	return result;
    }
    

    Am getting quite frustrated with the project as sometimes it will run for hours without problem, if it is going to stop waking up it appears to happen within the first half hour of being powered on.

    Another thought that occurred to me is that there is some kind of fault that happens to occur with some numbers that causes the processor to reset before the next RTC wakeup has been set, but still not too much idea what could be causing this.

  • Hugh Powell said:
    Sorry for the delay here is the current version I am working with.
    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_gpio.h"
    #include "driverlib/fpu.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/adc.h"
    #include "driverlib/timer.h"
    #include "driverlib/hibernate.h"
    #include "driverlib/uart.h"
    #include "fatfs/src/ff.h"
    #include "fatfs/src/diskio.h"
    #include "util/uartstdio.h"
    
    #ifdef DEBUG
    void__error__(char *pcFilename, unsigned long ulLine)
    {
    }
    #endif
    
    static FATFS g_sFatFs;
    static DIR g_sDirObject;
    static FILINFO g_sFileInfo;
    static FIL g_sFileObject;
    
    #define SHORT_SAMPLE_FREQUENCY 100 // Hertz
    #define LONG_SAMPLE_TIME 2 // Seconds
    
    #define RED_LED   GPIO_PIN_1
    #define BLUE_LED  GPIO_PIN_2
    #define GREEN_LED GPIO_PIN_3
    
    #define A1SCALE 6.283
    #define A2SCALE 6.224
    
    #define FILENAME "log"
    
    char filename[32] = "";
    
    char* itoa(int value, char* result, int base);
    char* uitoa(unsigned int value, char* result, int base);
    int string_size(char* string);
    
    //*****************************************************************************
    //
    // The following are data structures used by FatFs.
    //
    //*****************************************************************************
    static FATFS g_sFatFs;
    static DIR g_sDirObject;
    static FILINFO g_sFileInfo;
    static FIL g_sFileObject;
    
    //*****************************************************************************
    //
    // A structure that holds a mapping between an FRESULT numerical code, and a
    // string representation.  FRESULT codes are returned from the FatFs FAT file
    // system driver.
    //
    //*****************************************************************************
    typedef struct
    {
    	FRESULT iFResult;
    	char *pcResultStr;
    }
    tFResultString;
    
    // Define f_size and f_tell as in fatfs docs
    #define f_size(fp) ((fp)->fsize)
    #define f_tell(fp) ((fp)->fptr)
    
    // A macro to make it easy to add result codes to the table.
    #define FRESULT_ENTRY(f)        { (f), (#f) }
    
    // A table that holds a mapping between the numerical FRESULT code and it's
    // name as a string.  This is used for looking up error codes for printing to
    // the console.
    tFResultString g_psFResultStrings[] =
    {
    		FRESULT_ENTRY(FR_OK),
    		FRESULT_ENTRY(FR_NOT_READY),
    		FRESULT_ENTRY(FR_NO_FILE),
    		FRESULT_ENTRY(FR_NO_PATH),
    		FRESULT_ENTRY(FR_INVALID_NAME),
    		FRESULT_ENTRY(FR_INVALID_DRIVE),
    		FRESULT_ENTRY(FR_DENIED),
    		FRESULT_ENTRY(FR_EXIST),
    		FRESULT_ENTRY(FR_RW_ERROR),
    		FRESULT_ENTRY(FR_WRITE_PROTECTED),
    		FRESULT_ENTRY(FR_NOT_ENABLED),
    		FRESULT_ENTRY(FR_NO_FILESYSTEM),
    		FRESULT_ENTRY(FR_INVALID_OBJECT),
    		FRESULT_ENTRY(FR_MKFS_ABORTED)
    };
    
    // A macro that holds the number of result codes.
    #define NUM_FRESULT_CODES       (sizeof(g_psFResultStrings) /                 \
    		sizeof(tFResultString))
    
    //*****************************************************************************
    //
    // This function returns a string representation of an error code that was
    // returned from a function call to FatFs.  It can be used for printing human
    // readable error messages.
    //
    //*****************************************************************************
    const char *
    StringFromFResult(FRESULT iFResult)
    {
    	uint_fast8_t ui8Idx;
    
    	//
    	// Enter a loop to search the error code table for a matching error code.
    	//
    	for(ui8Idx = 0; ui8Idx < NUM_FRESULT_CODES; ui8Idx++)
    	{
    		//
    		// If a match is found, then return the string name of the error code.
    		//
    		if(g_psFResultStrings[ui8Idx].iFResult == iFResult)
    		{
    			return(g_psFResultStrings[ui8Idx].pcResultStr);
    		}
    	}
    
    	//
    	// At this point no matching code was found, so return a string indicating
    	// an unknown error.
    	//
    	return("UNKNOWN ERROR CODE");
    }
    
    // This is the handler for this SysTick interrupt.  FatFs requires a timer tick
    // every 10 ms for internal timing purposes.
    
    void SysTickHandler(void)
    {
    	// Call the FatFs tick timer.
    	disk_timerproc();
    }
    
    void ConfigureUART(void)
    {
    	// Enable the GPIO Peripheral used by the UART.
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
    	// Enable UART0
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
    	// Configure GPIO Pins for UART mode.
    	GPIOPinConfigure(GPIO_PA0_U0RX);
    	GPIOPinConfigure(GPIO_PA1_U0TX);
    	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);
    }
    
    void next_log_file(void){ // Returns into a global variable
    	FRESULT result = FR_OK;
    	char temp[16] = "";
    	unsigned int count = 0;
    	while (result != FR_NO_FILE){
    		strcpy(filename,FILENAME);
    		uitoa(++count,temp,10);
    		strcat(filename,temp);
    		strcat(filename,".csv");
    		UARTprintf("Testing for: %s\n", filename);
    		result = f_open(&g_sFileObject,filename,FA_READ);
    		f_close(&g_sFileObject);
    	}
    }
    
    void pack_string(unsigned long* data_out, char* data_in){ //Packs 32 bytes into 8 unsigned longs
    	int i;
    	for (i=0;i<8;i++){
    		data_out[i] = data_in[i] + (((unsigned long)data_in[i+1]) << 8) + (((unsigned long)data_in[i+2]) << 16) + (((unsigned long)data_in[i+3]) << 24);
    	}
    }
    
    void unpack_string(unsigned long* data_in, char* data_out){
    	int i;
    	for (i=0;i<8;i++){
    		data_out[i] = data_in[i]&255;
    		data_out[i+1] = (data_in[i]>>8)&255;
    		data_out[i+2] = (data_in[i]>>16)&255;
    		data_out[i+3] = (data_in[i]>>24)&255;
    	}
    }
    
    void OpenLogfile(void){
    	FRESULT iFResult;
    	iFResult = f_open(&g_sFileObject, filename, FA_WRITE | FA_OPEN_ALWAYS);
    	// If there was some problem opening the file, then return an error.
    	if(iFResult != FR_OK)
    	{
    		UARTprintf("Command returned error code %s\n",
    				StringFromFResult(iFResult));
    	}
    
    	// Move to end to file
    	iFResult = f_lseek( &g_sFileObject, f_size(&g_sFileObject));
    	if(iFResult != FR_OK)
    	{
    		UARTprintf("Command returned error code %s\n",
    				StringFromFResult(iFResult));
    	}
    }
    
    void CloseLogfile(void){
    	f_close(&g_sFileObject);
    }
    
    void TakeSample(void){
    	FRESULT iFResult;
    	ADCIntClear(ADC0_BASE, 1);
    	ADCProcessorTrigger(ADC0_BASE, 1);
    
    	unsigned long ADC0Values[4];
    	unsigned long A1, A2;
    	unsigned int dig1, dig2;
    	unsigned long uptime = HibernateRTCGet();
    	unsigned long uptimesub = HibernateRTCSSGet()/32.768;//Partial uptime ms
    
    	char data_string[128] = "";
    	char temp[32] = "";
    	WORD bytes_written;
    
    	while(!ADCIntStatus(ADC0_BASE, 1, false));
    
    	ADCSequenceDataGet(ADC0_BASE, 1, ADC0Values);
    
    	A1 = ADC0Values[1]*A1SCALE;
    	A2 = ADC0Values[3]*A2SCALE;
    
    	dig1 = GPIOPinRead(GPIO_PORTE_BASE, 255);
    	dig2 = GPIOPinRead(GPIO_PORTC_BASE, 255) >> 4;
    
    	uitoa(uptime,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, ".");
    	uitoa(uptimesub,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, "\t");
    	uitoa(A1,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, "\t");
    	uitoa(A2,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, "\t");
    	uitoa(dig1,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, "\t");
    	uitoa(dig2,temp,10);
    	strcat(data_string, temp);
    	strcat(data_string, "\n");
    	UARTprintf(data_string);
    
    	// write to the file
    	iFResult = f_write (&g_sFileObject,          /* [IN] Pointer to the file object structure */
    			data_string, /* [IN] Pointer to the data to be written */
    			strlen(data_string),         /* [IN] Number of bytes to write */
    			&bytes_written          /* [OUT] Pointer to the variable to return number of bytes written */
    	);
    	if(iFResult != FR_OK)
    	{
    		UARTprintf("Command returned error code %s\n",
    				StringFromFResult(iFResult));
    	}
    }
    
    void Shutdown(void){
    	UARTprintf("Shutting Down\n");
    /*
    	SysCtlPeripheralDisable(SYSCTL_PERIPH_SSI0);
    	SysCtlPeripheralDisable(SYSCTL_PERIPH_ADC0);
    	SysCtlPeripheralDisable(SYSCTL_PERIPH_TIMER0);
    
    	// Disable interrupts as they might have been causing issues with going back to sleep.
    	SysTickDisable();
    	SysTickIntDisable();
    	IntMasterDisable();
    /*
    	//unsigned long temp;
    	temp = HibernateRTCGet();
    	UARTprintf("%u\t%u\t%u\n",temp,temp+LONG_SAMPLE_TIME,HibernateRTCSSGet());
    	HibernateRTCSet(0);
    	//HibernateRTCMatch0Set(temp+LONG_SAMPLE_TIME); // Set the time to wake up in the future
    	HibernateRTCMatch0Set(LONG_SAMPLE_TIME); // Set the time to wake up in the future
    */
    	UARTprintf("%u\t%u\t%u\t%u\t%u\n",HibernateIsActive(), HibernateIntStatus(0), HibernateWakeGet(), HibernateRTCGet(),HibernateRTCMatch0Get(),HibernateRTCSSGet());
    	SysCtlDelay(SysCtlClockGet()/20); // Give serial 0.05s to finish
    
    	GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, 0x0); // Turn off lights
    
    	HibernateRequest();
    
    	SysCtlDelay(SysCtlClockGet()/4); // Give it way more than it needs to shut down before telling us it is broken;
    	GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, RED_LED); // Turn on red led to show somthing is wrong
    	while(1); //Trap
    }
    
    void Timer0IntHandler(void)
    {
    	// Clear the timer interrupt a bit risky doing it here instead of after sample if you use a fast sample rate
    	TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    	TakeSample();
    }
    
    int main(void)
    {
    	FRESULT iFResult;
    
    	// Enable lazy stacking for interrupt handlers.  This allows floating-point
    	// instructions to be used within interrupt handlers, but at the expense of
    	// extra stack usage.
    	FPULazyStackingEnable();
    
    	// Set the system clock to run at 50MHz from the PLL.
    	SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, 255);
    	GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, 255-127);
    	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED);
    
    	// Needed to unlock PF0 from an alternate function (found this was needed in buttons.c
    	HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY_DD;
    	HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;
    	HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0;
    
    	// Set as a pullup
    	GPIODirModeSet(GPIO_PORTF_BASE, 1, GPIO_DIR_MODE_IN);
    	GPIOPadConfigSet(GPIO_PORTF_BASE, 1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    
    	// Enable the peripherals used by this example.
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    
    	TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER);
    	TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet()/SHORT_SAMPLE_FREQUENCY);
    
    	// Configure ADC
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    	GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_0|GPIO_PIN_1);
    	SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS);
    	ADCHardwareOversampleConfigure(ADC0_BASE, 64);
    
    	// Setup ADC Sequence
    	ADCSequenceDisable(ADC0_BASE, 1);
    	ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH7);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH7);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH6);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH6 | ADC_CTL_IE | ADC_CTL_END);
    	ADCSequenceEnable(ADC0_BASE, 1);
    
    	// Configure SysTick for a 100Hz interrupt.  The FatFs driver wants a 10 ms tick
    	SysTickPeriodSet(SysCtlClockGet() / 100);
    	SysTickEnable();
    	SysTickIntEnable();
    
    	// Enable Interrupts
    	IntMasterEnable();
    
    	ConfigureUART();
    
    	UARTprintf("\n\nIm Awake\n");
    	//UARTprintf("\033[2J\033[HIm Awake\n");
    
    	// Mount the file system, using logical disk 0.
    	iFResult = f_mount(0, &g_sFatFs);
    
    	if(iFResult != FR_OK)
    	{
    		while (1); // Trap the CPU for debug
    	} else {
    		UARTprintf("Opened Filesystem\n");
    	}
    
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
    
    	HibernateEnableExpClk(SysCtlClockGet());
    
    	if(HibernateIsActive() && (HibernateIntStatus(0) & (HIBERNATE_INT_RTC_MATCH_0 | HIBERNATE_INT_PIN_WAKE)))
    	{
    		HibernateIntClear(HibernateIntStatus(0));
    
    		GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, GREEN_LED);
    		UARTprintf("Woke from hibernate\n");
    
    
    		// Load the name of the current logfile from VBAT
    		unsigned long packed_filename[8];
    		HibernateDataGet(packed_filename,8);
    		unpack_string(packed_filename,filename);
    		UARTprintf("Using Log file: %s\n",filename);
    
    		OpenLogfile();
    
    		TakeSample();
    
    		if (!GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0)){
    			GPIOPinWrite(GPIO_PORTF_BASE, RED_LED, RED_LED);
    
    			IntEnable(INT_TIMER0A);
    			TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    			TimerEnable(TIMER0_BASE, TIMER_A);
    
    			while (!GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0)); // Trap until button released, will look at doing some deep sleep stuff here in the future
    
    			IntDisable(INT_TIMER0A);
    			TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    			TimerDisable(TIMER0_BASE, TIMER_A);
    
    			GPIOPinWrite(GPIO_PORTF_BASE, RED_LED, 0x0);
    		}
    
    		CloseLogfile();
    
    		HibernateRTCMatch0Set(HibernateRTCGet()+LONG_SAMPLE_TIME);
    
    		Shutdown();
    	}
    	else {
    		GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, BLUE_LED);
    
    		HibernateGPIORetentionEnable();
    		HibernateRTCSet(0);
    		HibernateRTCEnable();
    		HibernateRTCMatch0Set(5);
    		HibernateWakeSet(HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC);
    		UARTprintf("Configured hibernate\n");
    		next_log_file();
    		// Restore the filename in the power down memory
    		unsigned long packed_filename[8];
    		pack_string(packed_filename,filename);
    		HibernateDataSet(packed_filename,8);
    
    		UARTprintf("Set logfile name %s\nsleeping for 5 seconds\n",filename);
    
    		Shutdown();
    	}
    	// Should never get here
    	while (1) UARTprintf("I'm Broken\n");
    }
    
    
    
    // Two functions to convert an integer to a string, not written by me (http://www.strudel.org.uk/itoa/)
    char* itoa(int value, char* result, int base) {
    	// check that the base if valid
    	if (base < 2 || base > 36) { *result = '\0'; return result; }
    
    	char* ptr = result, *ptr1 = result, tmp_char;
    	int tmp_value;
    
    	do {
    		tmp_value = value;
    		value /= base;
    		*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
    	} while ( value );
    
    	// Apply negative sign
    	if (tmp_value < 0) *ptr++ = '-';
    	*ptr-- = '\0';
    	while(ptr1 < ptr) {
    		tmp_char = *ptr;
    		*ptr--= *ptr1;
    		*ptr1++ = tmp_char;
    	}
    	return result;
    }
    char* uitoa(unsigned int value, char* result, int base) {
    	// check that the base if valid
    	if (base < 2 || base > 36) { *result = '\0'; return result; }
    
    	char* ptr = result, *ptr1 = result, tmp_char;
    	int tmp_value;
    
    	do {
    		tmp_value = value;
    		value /= base;
    		*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
    	} while ( value );
    
    	*ptr-- = '\0';
    	while(ptr1 < ptr) {
    		tmp_char = *ptr;
    		*ptr--= *ptr1;
    		*ptr1++ = tmp_char;
    	}
    	return result;
    }
    

    The attached
    //*****************************************************************************
    //
    // qs-rgb.c - Quickstart for the EK-TM4C123GXL.
    //
    // Copyright (c) 2012-2013 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 1.0 of the EK-TM4C123GXL Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include <math.h>
    #include <time.h>
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_hibernate.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.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "utils/cmdline.h"
    #include "drivers/rgb.h"
    #include "drivers/buttons.h"
    #include "rgb_commands.h"
    #include "qs-rgb.h"
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>EK-TM4C123GXL Quickstart Application (qs-rgb)</h1>
    //!
    //! A demonstration of the Tiva C Series LaunchPad (EK-TM4C123GXL)
    //! capabilities.
    //!
    //! Press and/or hold the left button to traverse towards the red end of the
    //! ROYGBIV color spectrum.  Press and/or hold the right button to traverse
    //! toward the violet end of the ROYGBIV color spectrum.
    //!
    //! If no input is received for 5 seconds, the application will start
    //! automatically changing the color displayed.
    //!
    //! Press and hold both left and right buttons for 3 seconds to enter
    //! hibernation.  During hibernation, the last color displayed will blink
    //! for 0.5 seconds every 3 seconds.
    //!
    //! The system can also be controlled via a command line provided via the UART.
    //! Configure your host terminal emulator for 115200, 8-N-1 to access this
    //! feature.
    //!
    //! - Command 'help' generates a list of commands and helpful information.
    //! - Command 'hib' will place the device into hibernation mode.
    //! - Command 'rand' will initiate the pseudo-random color sequence.
    //! - Command 'intensity' followed by a number between 0 and 100 will set the
    //! brightness of the LED as a percentage of maximum brightness.
    //! - Command 'rgb' followed by a six character hex value will set the color.
    //! For example 'rgb FF0000' will produce a red color.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Entry counter to track how int32_t to stay in certain staging states before
    // making transition into hibernate.
    //
    //*****************************************************************************
    static volatile uint32_t ui32HibModeEntryCount;
    
    //*****************************************************************************
    //
    // Array of pre-defined colors for use when buttons cause manual color steps.
    //
    //*****************************************************************************
    static float fManualColors[7] = {0.0f, .214f, .428f, .642f, .856f, 1.07f,
                                     1.284f};
    
    //*****************************************************************************
    //
    // Input buffer for the command line interpreter.
    //
    //*****************************************************************************
    static char g_cInput[APP_INPUT_BUF_SIZE];
    
    //*****************************************************************************
    //
    // Application state structure.  Gets stored to hibernate memory for
    // preservation across hibernate events.
    //
    //*****************************************************************************
    volatile tAppState g_sAppState;
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    
    //*****************************************************************************
    //
    // Handler to manage the button press events and state machine transitions
    // that result from those button events.
    //
    // This function is called by the SysTickIntHandler if a button event is
    // detected. Function will determine which button was pressed and tweak various
    // elements of the global state structure accordingly.
    //
    //*****************************************************************************
    void
    AppButtonHandler(void)
    {
        static uint32_t ui32TickCounter;
    
        ui32TickCounter++;
    
        //
        // Switch statement to adjust the color wheel position based on buttons
        //
        switch(g_sAppState.ui32Buttons & ALL_BUTTONS)
        {
    
        case LEFT_BUTTON:
    
            //
            // Check if the button has been held int32_t enough to peform another
            // color wheel increment.
            //
            if((ui32TickCounter % APP_BUTTON_POLL_DIVIDER) == 0)
            {
                //
                // Perform the increment and index wrap around.
                //
                g_sAppState.ui32ManualIndex++;
                if(g_sAppState.ui32ManualIndex >= APP_NUM_MANUAL_COLORS)
                {
                    g_sAppState.ui32ManualIndex = 0;
                }
                g_sAppState.fColorWheelPos = APP_PI *
                                          fManualColors[g_sAppState.ui32ManualIndex];
            }
    
            //
            // Reset some state counts and system mode so that we know the user
            // is present and actively engaging with the application.
            //
            ui32HibModeEntryCount = 0;
            g_sAppState.ui32ModeTimer = 0;
            g_sAppState.ui32Mode = APP_MODE_NORMAL;
            break;
    
        case RIGHT_BUTTON:
    
            //
            // Check if the button has been held int32_t enough to perform another
            // color wheel decrement.
            //
            if((ui32TickCounter % APP_BUTTON_POLL_DIVIDER) == 0)
            {
                //
                // Perform the decrement and index wrap around.
                //
                if(g_sAppState.ui32ManualIndex == 0)
                {
                    //
                    // set to one greater than the last color so that we decrement
                    // back into range with next instruction.
                    //
                    g_sAppState.ui32ManualIndex = APP_NUM_MANUAL_COLORS;
                }
                g_sAppState.ui32ManualIndex--;
                g_sAppState.fColorWheelPos = APP_PI *
                                          fManualColors[g_sAppState.ui32ManualIndex];
            }
            //
            // Reset some state counts and system mode so that we know the user
            // is present and actively engaging with the application.
            //
            ui32HibModeEntryCount = 0;
            g_sAppState.ui32ModeTimer = 0;
            g_sAppState.ui32Mode = APP_MODE_NORMAL;
            break;
    
        case ALL_BUTTONS:
    
            //
            // Both buttons for int32_ter than debounce time will cause hibernation
            //
            if(ui32HibModeEntryCount < APP_HIB_BUTTON_DEBOUNCE)
            {
                ui32HibModeEntryCount++;
                g_sAppState.ui32Mode = APP_MODE_NORMAL;
            }
            else
            {
                g_sAppState.ui32Mode = APP_MODE_HIB;
            }
            g_sAppState.ui32ModeTimer = 0;
            break;
    
        default:
            if(g_sAppState.ui32Mode == APP_MODE_HIB_FLASH)
            {
                //
                // Waking from hibernate RTC just do a quick flash then back to
                // hibernation.
                //
                if(ui32HibModeEntryCount < APP_HIB_FLASH_DURATION)
                {
                    ui32HibModeEntryCount++;
                }
                else
                {
                    g_sAppState.ui32Mode = APP_MODE_HIB;
                }
            }
            else
            {
                //
                // Normal or remote mode and no user action will cause transition
                // to automatic scrolling mode.
                //
                ui32HibModeEntryCount = 0;
                if(g_sAppState.ui32ModeTimer < APP_AUTO_MODE_TIMEOUT)
                {
                    g_sAppState.ui32ModeTimer++;
                }
                else
                {
                    g_sAppState.ui32Mode = APP_MODE_AUTO;
                }
    
                //
                // reset the tick counter when no buttons are pressed
                // this makes the first button reaction speed quicker
                //
                ui32TickCounter = APP_BUTTON_POLL_DIVIDER - 1;
            }
            break;
        }
    }
    
    //*****************************************************************************
    //
    // Uses the fColorWheelPos variable to update the color mix shown on the RGB
    //
    // ui32ForceUpdate when set forces a color update even if a color change
    // has not been detected.  Used primarily at startup to init the color after
    // a hibernate.
    //
    // This function is called by the SysTickIntHandler to update the colors on
    // the RGB LED whenever a button or timeout event has changed the color wheel
    // position.  Color is determined by a series of sine functions and conditions
    //
    //*****************************************************************************
    void
    AppRainbow(uint32_t ui32ForceUpdate)
    {
        static float fPrevPos;
        float fCurPos;
        float fTemp;
        volatile uint32_t * pui32Colors;
    
        pui32Colors = g_sAppState.ui32Colors;
        fCurPos = g_sAppState.fColorWheelPos;
    
    
        if((fCurPos != fPrevPos) || ui32ForceUpdate)
        {
            //
            // Preserve the new color wheel position
            //
            fPrevPos = fCurPos;
    
            //
            // Adjust the BLUE value based on the control state
            //
            fTemp = 65535.0f * sinf(fCurPos);
            if(fTemp < 0)
            {
                pui32Colors[GREEN] = 0;
            }
            else
            {
                pui32Colors[GREEN] = (uint32_t) fTemp;
            }
    
    
            //
            // Adjust the RED value based on the control state
            //
            fTemp = 65535.0f * sinf(fCurPos - APP_PI / 2.0f);
            if(fTemp < 0)
            {
                pui32Colors[BLUE] = 0;
            }
            else
            {
                pui32Colors[BLUE] = (uint32_t) fTemp;
            }
    
    
            //
            // Adjust the GREEN value based on the control state
            //
            if(fCurPos < APP_PI)
            {
                fTemp = 65535.0f * sinf(fCurPos + APP_PI * 0.5f);
            }
            else
            {
                fTemp = 65535.0f * sinf(fCurPos + APP_PI);
            }
            if(fTemp < 0)
            {
                pui32Colors[RED] = 0;
            }
            else
            {
                pui32Colors[RED] = (uint32_t) fTemp;
            }
    
            //
            // Update the actual LED state
            //
            RGBColorSet(pui32Colors);
        }
    
    }
    
    //*****************************************************************************
    //
    // Called by the NVIC as a result of SysTick Timer rollover interrupt flag
    //
    // Checks buttons and calls AppButtonHandler to manage button events.
    // Tracks time and auto mode color stepping.  Calls AppRainbow to implement
    // RGB color changes.
    //
    //*****************************************************************************
    void
    SysTickIntHandler(void)
    {
    
        static float x;
    
        g_sAppState.ui32Buttons = ButtonsPoll(0,0);
        AppButtonHandler();
    
        //
        // Auto increment the color wheel if in the AUTO mode. AUTO mode is when
        // device is active but user interaction has timed out.
        //
        if(g_sAppState.ui32Mode == APP_MODE_AUTO)
        {
            g_sAppState.fColorWheelPos += APP_AUTO_COLOR_STEP;
        }
    
        //
        // Provide wrap around of the control variable from 0 to 1.5 times PI
        //
        if(g_sAppState.fColorWheelPos > (APP_PI * 1.5f))
        {
            g_sAppState.fColorWheelPos = 0.0f;
        }
        if(x < 0.0f)
        {
            g_sAppState.fColorWheelPos = APP_PI * 1.5f;
        }
    
        //
        //    Set the RGB Color based on current control variable value.
        //
        AppRainbow(0);
    
    
    }
    
    //*****************************************************************************
    //
    // Uses the fColorWheelPos variable to update the color mix shown on the RGB
    //
    // This function is called when system has decided it is time to enter
    // Hibernate.  This will prepare the hibernate peripheral, save the system
    // state and then enter hibernate mode.
    //
    //*****************************************************************************
    void
    AppHibernateEnter(void)
    {
    	uint32_t wakeTime = HibernateRTCGet() + 2;
        //
        // Alert UART command line users that we are going to hibernate
        //
        UARTprintf("Entering Hibernate with wakeTime=0x%x HIB_RTCC=0x%x HIB_RTCSS(count)=0x%x\nHIB_RTCM0=0x%x HIB_RTCSS=0x%x HIB_RTCT=0x%x\n",
        		   wakeTime, HibernateRTCGet(), HibernateRTCSSGet(),
        		   HibernateRTCMatchGet(0), HibernateRTCSSMatchGet(0),
        		   HibernateRTCTrimGet ());
    
        //
        // Prepare Hibernation Module
        //
        HibernateGPIORetentionEnable();
    //    HibernateRTCSet(0);
        HibernateRTCEnable();
        HibernateRTCMatchSet(0, wakeTime);
        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);
    
        //
        // Disable the LED for 100 milliseconds to let user know we are
        // ready for hibernate and will hibernate on relase of buttons
        //
        RGBDisable();
        SysCtlDelay(SysCtlClockGet()/3/10);
        RGBEnable();
    
        //
        // Wait for wake button to be released prior to going into hibernate
        //
        while(g_sAppState.ui32Buttons & RIGHT_BUTTON)
        {
            //
            //Delay for about 300 clock ticks to allow time for interrupts to
            //sense that button is released
            //
            SysCtlDelay(100);
        }
    
        //
        // Disable the LED for power savings and go to hibernate mode
        //
        RGBDisable();
        HibernateRequest();
    
    
    }
    
    //*****************************************************************************
    //
    // Configure the UART and its pins.  This must be called before UARTprintf().
    //
    //*****************************************************************************
    void
    ConfigureUART(void)
    {
        //
        // Enable the GPIO Peripheral used by the UART.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Enable UART0
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Configure GPIO Pins for UART mode.
        //
        ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
        ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
        ROM_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);
    }
    
    //*****************************************************************************
    //
    // Main function performs init and manages system.
    //
    // Called automatically after the system and compiler pre-init sequences.
    // Performs system init calls, restores state from hibernate if needed and
    // then manages the application context duties of the system.
    //
    //*****************************************************************************
    int
    main(void)
    {
        uint32_t ui32Status;
        uint32_t ui32ResetCause;
        int32_t i32CommandStatus;
    
        //
        // Enable stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        ROM_FPUEnable();
        ROM_FPUStackingEnable();
    
        //
        // Set the system clock to run at 40Mhz off PLL with external crystal as
        // reference.
        //
        ROM_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
                           SYSCTL_OSC_MAIN);
    
        //
        // Enable the hibernate module
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
    
        //
        // Enable and Initialize the UART.
        //
        ConfigureUART();
    
        UARTprintf("Welcome to the Tiva C Series TM4C123G LaunchPad!\n");
        UARTprintf("Type 'help' for a list of commands\n");
        UARTprintf("> ");
    
        //
        // Determine why system reset occurred and respond accordingly.
        //
        ui32ResetCause = SysCtlResetCauseGet();
        SysCtlResetCauseClear(ui32ResetCause);
        if(ui32ResetCause == SYSCTL_CAUSE_POR)
        {
            if(HibernateIsActive())
            {
                //
                // Read the status bits to see what caused the wake.
                //
                ui32Status = HibernateIntStatus(0);
                HibernateIntClear(ui32Status);
    
                //
                // Wake was due to the push button.
                //
                if(ui32Status & HIBERNATE_INT_PIN_WAKE)
                {
                    UARTprintf("Hibernate Wake Pin Wake Event\n");
                    UARTprintf("> ");
    
                    //
                    // Recover the application state variables from battery backed
                    // hibernate memory.  Set ui32Mode to normal.
                    //
                    HibernateDataGet((uint32_t*) &g_sAppState,
                                     sizeof(tAppState) / 4 + 1);
                    g_sAppState.ui32Mode = APP_MODE_NORMAL;
                }
    
                //
                // Wake was due to RTC match
                //
                else if(ui32Status & HIBERNATE_INT_RTC_MATCH_0)
                {
                    UARTprintf("Hibernate RTC Wake Event\n");
                    UARTprintf("> ");
                    //
                    // Recover the application state variables from battery backed
                    // hibernate memory. Set ui32Mode to briefly flash the RGB.
                    //
                    HibernateDataGet((uint32_t*) &g_sAppState,
                                    sizeof(tAppState) / 4 + 1);
                    g_sAppState.ui32Mode = APP_MODE_HIB_FLASH;
                }
            }
    
            else
            {
                //
                // Reset was do to a cold first time power up.
                //
                UARTprintf("Power on reset. Hibernate not active.\n");
                UARTprintf("> ");
    
                g_sAppState.ui32Mode = APP_MODE_NORMAL;
                g_sAppState.fColorWheelPos = 0;
                g_sAppState.fIntensity = APP_INTENSITY_DEFAULT;
                g_sAppState.ui32Buttons = 0;
            }
        }
        else
        {
            //
            // External Pin reset or other reset event occured.
            //
            UARTprintf("External or other reset\n");
            UARTprintf("> ");
    
            //
            // Treat this as a cold power up reset without restore from hibernate.
            //
            g_sAppState.ui32Mode = APP_MODE_NORMAL;
            g_sAppState.fColorWheelPos = APP_PI;
            g_sAppState.fIntensity = APP_INTENSITY_DEFAULT;
            g_sAppState.ui32Buttons = 0;
    
        //
            // colors get a default initialization later when we call AppRainbow.
            //
        }
    
        //
        // Initialize clocking for the Hibernate module
        //
        HibernateEnableExpClk(SysCtlClockGet());
    
        //
        // Initialize the RGB LED. AppRainbow typically only called from interrupt
        // context. Safe to call here to force initial color update because
        // interrupts are not yet enabled.
        //
        RGBInit(0);
        RGBIntensitySet(g_sAppState.fIntensity);
        AppRainbow(1);
        RGBEnable();
    
        //
        // Initialize the buttons
        //
        ButtonsInit();
    
        //
        // Initialize the SysTick interrupt to process colors and buttons.
        //
        SysTickPeriodSet(SysCtlClockGet() / APP_SYSTICKS_PER_SEC);
        SysTickEnable();
        SysTickIntEnable();
        IntMasterEnable();
    
        //
        // spin forever and wait for carriage returns or state changes.
        //
        while(1)
        {
    
            UARTprintf("\n>");
    
    
            //
            // Peek to see if a full command is ready for processing
            //
            while(UARTPeek('\r') == -1)
            {
                //
                // millisecond delay.  A SysCtlSleep() here would also be OK.
                //
                SysCtlDelay(SysCtlClockGet() / (1000 / 3));
    
                //
                // Check for change of mode and enter hibernate if requested.
                // all other mode changes handled in interrupt context.
                //
                if(g_sAppState.ui32Mode == APP_MODE_HIB)
                {
                    AppHibernateEnter();
                }
            }
    
            //
            // a '\r' was detected get the line of text from the user.
            //
            UARTgets(g_cInput,sizeof(g_cInput));
    
            //
            // Pass the line from the user to the command processor.
            // It will be parsed and valid commands executed.
            //
            i32CommandStatus = CmdLineProcess(g_cInput);
    
            //
            // Handle the case of bad command.
            //
            if(i32CommandStatus == CMDLINE_BAD_CMD)
            {
                UARTprintf("Bad command!\n");
            }
    
            //
            // Handle the case of too many arguments.
            //
            else if(i32CommandStatus == CMDLINE_TOO_MANY_ARGS)
            {
                UARTprintf("Too many arguments for command processor!\n");
            }
        }
    }
    
    is a modified version of the TivaWare qs-rgb example, where the AppHibernateEnter function has been changed to set a wake up time of HibernateRTCGet() + 2 seconds. qs-rgb.c operates the same way as your main.c for setting the wake-up time in that the RTC Match Seconds count is advanced by 2 seconds, and the RTC Match SubSeconds count isn't set.

    The qs-rgb.c also has the problem that sometimes it doesn't wake-up automatically from a hibernation on a RTC match, but would wake up manually using the Wake button.

    Example diagnostic output for when qs-rgb.c didn't wake automatically on a RTC match (last line is going in hibernation from which didn't wake up):

    HIB_RTCM0=0x16b9 HIB_RTCSS=0x0 HIB_RTCT=0x2040
    Welcome to the Tiva C Series TM4C123G LaunchPad!
    Type 'help' for a list of commands
    > Hibernate RTC Wake Event
    >
    >Entering Hibernate with wakeTime=0x16bd HIB_RTCC=0x16bb HIB_RTCSS(count)=0x1175

    HIB_RTCM0=0x16bb HIB_RTCSS=0x0 HIB_RTCT=0x2040
    Welcome to the Tiva C Series TM4C123G LaunchPad!
    Type 'help' for a list of commands
    > Hibernate RTC Wake Event
    >
    >Entering Hibernate with wakeTime=0x16bf HIB_RTCC=0x16bd HIB_RTCSS(count)=0x1175

    HIB_RTCM0=0x16bd HIB_RTCSS=0x0 HIB_RTCT=0x2040
    Welcome to the Tiva C Series TM4C123G LaunchPad!
    Type 'help' for a list of commands
    > Hibernate RTC Wake Event
    >
    >Entering Hibernate with wakeTime=0x16c1 HIB_RTCC=0x16bf HIB_RTCSS(count)=0x1174

    HIB_RTCM0=0x16bf HIB_RTCSS=0x0 HIB_RTCT=0x2040

    Analysis of the diagnostic output, LM4F120H5QR datasheet and LM4F120H5QR errata shows:

    1) The Hibernation RTC Trim (HIBRTCT) register has the value of 0x2040, rather reset value of 0x7FFF. The code isn't writing to HIBRTCT, but due to errata 3.1 Some Hibernation module registers may not have the correct value in two situations, the HIBRTCT register value gets corrupted. See RTC counting too fast on lm4f120xl launchpad for some more investigation into this errata.

    2) The RTC Sub Seconds Match is set to zero, which is the reset value.

    3) When failed to wake up on a RTC match the 6 least significant bits of the Hibernation RTC Match 0 register were set to 0x01 (and the RTC Sub Seconds Match is zero as above). Since the RTC Trim value of 0x2040 is less that 0x7FFF, as explained by the RTC Trim section of the datasheet when least 6 significant bits of RTCC (seconds count) change from 0x00 to 0x01 the RTCSSC (sub seconds count) will skip the value zero (and other values). Therefore, the RTC wake event doesn't happen because the RTC Sub Seconds Match condition isn't met.

    Therefore suggest:

    a) Displaying the value of HibernateRTCTrimGet () in the UARTprintf diagnostic output in the Shutdown function. if you post the diagnostic output prior to not waking up from hibernation that will show if your program hits the timing conditions where the RTC match isn't met (due to the RTC trim not having the default value).

    b) After a), add the work-around for errata 3.1 in your hibernation initialisation code to see if that fixes the problem.

  • Thankyou for the detailed explantation, this was the cause and was able to be correct by adding the below lines after configuring the Hibernate clock

    HibernateRTCTrimSet (0x7FFF);
    HibernateIntDisable (HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_LOW_BAT | HIBERNATE_INT_RTC_MATCH_0 | HIBERNATE_INT_WR_COMPLETE);

    Also as per my first question is there any good way of using ccs as a debugger in projects that utilize hibernate mode.

  • Hugh Powell said:
    Also as per my first question is there any good way of using ccs as a debugger in projects that utilize hibernate mode.

    With CCS 5.4 running on Windows XP SP3 I haven't had any success in debugging a LM4F120H5QR which has entered hibernate mode:

    1) If the LM4F enters hinberate mode while the debugger is already attached, then errors are reported by CCS that it can no longer read the target (didn't make a note of the error messages). The only option is then to terminate the debug session. After the debug session has been terminated CCS crashes.

    2) If attempt to attach the debugger to a LM4F in hibernate mode then get an error reported by CCS (again didn't make a note of the error messages). After had cancelled the failed debug attach CCS crashes.

    I tried enabling the CCS Project Properties -> Debug -> Misc/Other Options -> Allow power transitions while running if supported (low power mode) option. However, that didn't change the behaviour.

    Suggest you post on the Code Composer Studio forum for the problem about being unable to debug a LM4F which has entered hibernate mode.

  • Quite good.   W/out using/knowing CCS - suspect (guess) that hibernate may cause MCU to disable JTAG internal pull-up R's. 

    Perhaps the temporary attachment of pull-up R's to JTAG lines may aid debug attempt during hibernate.

    (as past M3's - since discarded - had less than stellar "hibernate capability" - have no related LM experience to report...)