/***************************************************** * Function: init_Hibernation * Description: Initialize hibernation module * Input: NONE * Output: NONE *****************************************************/ void init_Hibernation(void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE); // Enable hibernation module HibernateEnableExpClk(SysCtlClockGet()); // Enable clocking to the hibernation module HibernateClockConfig(HIBERNATE_OSC_LOWDRIVE); // Configure the clock source for hibernation module HibernateGPIORetentionEnable(); // Retain GPIO state during hibernation // HibernateRTCEnable(); // Enable the RTC // HibernateRTCSet(0); // Clear the RTC time //HibernateRTCMatchSet(0, HibernateRTCGet() + 5); // Set the match 0 register for 5 seconds from now HibernateWakeSet(HIBERNATE_WAKE_PIN); // Configure to wake on button press or RTC match // HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC // Clear any pending status. // int status = HibernateIntStatus(0); // Clear any pending status HibernateIntClear(status); }
//***************************************************************************** // //! This is the hibernate module handler. //! When the RTC timer expires, an interrupt is generated and the the GPS //! data is parsed and logged. //! //! If the Wake button is pressed, low power mode is disabled. //! A reset/power cycle is required to re-enable low power mode after Wake has //! been pressed. // //***************************************************************************** void lowPowerMode(int delaySeconds) { uint32_t ui32Status; // // Set the RTC to 0 or an initial value. The RTC can be set once when the // system is initialized after the cold startup and then left to run. Or // it can be initialized before every hibernate. // HibernateRTCSet(0); // // Set the match 0 register for 30 seconds from now. // HibernateRTCMatchSet(0, HibernateRTCGet() + delaySeconds); // // Clear any pending status. // ui32Status = HibernateIntStatus(0); HibernateIntClear(ui32Status); // // Save the program state information. The state information is stored in // the pui32NVData[] array. It is not necessary to save the full 16 words // of data, only as much as is actually needed by the program. // HibernateDataSet(&lowPowerOn, 1); // // Configure to wake on RTC match or when wake button is pressed. // HibernateWakeSet(HIBERNATE_WAKE_RTC | HIBERNATE_WAKE_PIN); // // Request hibernation. The following call may return because it takes a // finite amount of time for power to be removed. // HibernateRequest(); // // Spin here to wait for the power to be removed. // for(;;) { } } // End function lowPowerMode
//***************************************************************************** // // Initialize and operate the data logger. // //***************************************************************************** int main(void) { tContext sDisplayContext, sBufferContext; uint32_t ui32HibIntStatus, ui32SysClock, ui32LastTickCount; bool bSkipSplash; uint8_t ui8ButtonState, ui8ButtonChanged; uint_fast8_t ui8X, ui8Y; // // 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. // MAP_FPULazyStackingEnable(); // // Set the clocking to run at 50 MHz. // MAP_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); ui32SysClock = MAP_SysCtlClockGet(); // // Initialize locals. // bSkipSplash = false; ui32LastTickCount = 0; // // Initialize the data acquisition module. This initializes the ADC // hardware. // AcquireInit(); // // Enable access to the hibernate peripheral. If the hibernate peripheral // was already running then this will have no effect. // MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE); // // Check to see if the hiberate module is already active and if so then // read the saved configuration state. If both are okay, then proceed // to check and see if we are logging data using sleep mode. // if(HibernateIsActive() && !GetSavedState(&g_sConfigState)) { // // Read the status of the hibernate module. // ui32HibIntStatus = HibernateIntStatus(1); // // If this is a pin wake, that means the user pressed the select // button and we should terminate the sleep logging. In this case // we will fall out of this conditional section, and go through the // normal startup below, but skipping the splash screen so the user // gets immediate response. // if(ui32HibIntStatus & HIBERNATE_INT_PIN_WAKE) { // // Clear the interrupt flag so it is not seen again until another // wake. // HibernateIntClear(HIBERNATE_INT_PIN_WAKE); bSkipSplash = true; } // // Otherwise if we are waking from hibernate and it was not a pin // wake, then it must be from RTC match. Check to see if we are // sleep logging and if so then go through an abbreviated startup // in order to collect the data and go back to sleep. // else if(g_sConfigState.ui32SleepLogging && (ui32HibIntStatus & HIBERNATE_INT_RTC_MATCH_0)) { // // Start logger and pass the configuration. The logger should // configure itself to take one sample. // AcquireStart(&g_sConfigState); g_iLoggerState = eSTATE_LOGGING; // // Enter a forever loop to run the acquisition. This will run // until a new sample has been taken and stored. // while(!AcquireRun()) { } // // Getting here means that a data acquisition was performed and we // can now go back to sleep. Save the configuration and then // activate the hibernate. // SetSavedState(&g_sConfigState); // // Set wake condition on pin-wake or RTC match. Then put the // processor in hibernation. // HibernateWakeSet(HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC); HibernateRequest(); // // Hibernating takes a finite amount of time to occur, so wait // here forever until hibernate activates and the processor // power is removed. // for(;;) { } } // // Otherwise, this was not a pin wake, and we were not sleep logging, // so just fall out of this conditional and go through the normal // startup below. // } else { // // In this case, either the hibernate module was not already active, or // the saved configuration was not valid. Initialize the configuration // to the default state and then go through the normal startup below. // GetDefaultState(&g_sConfigState); } // // Enable the Hibernate module to run. // HibernateEnableExpClk(SysCtlClockGet()); // // The hibernate peripheral trim register must be set per silicon // erratum 2.1 // HibernateRTCTrimSet(0x7FFF); // // Start the RTC running. If it was already running then this will have // no effect. // HibernateRTCEnable(); // // In case we were sleep logging and are now finished (due to user // pressing select button), then disable sleep logging so it doesnt // try to start up again. // g_sConfigState.ui32SleepLogging = 0; SetSavedState(&g_sConfigState); // // Initialize the display driver. // CFAL96x64x16Init(); // // Initialize the buttons driver. // ButtonsInit(); // // Pass the restored state to the menu system. // MenuSetState(&g_sConfigState); // // Enable the USB peripheral // MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0); // // Configure the required pins for USB operation. // MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); MAP_GPIOPinConfigure(GPIO_PG4_USB0EPEN); MAP_GPIOPinTypeUSBDigital(GPIO_PORTG_BASE, GPIO_PIN_4); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL); MAP_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6 | GPIO_PIN_7); MAP_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1); // // Erratum workaround for silicon revision A1. VBUS must have pull-down. // if(CLASS_IS_BLIZZARD && REVISION_IS_A1) { HWREG(GPIO_PORTB_BASE + GPIO_O_PDR) |= GPIO_PIN_1; } // // Initialize the USB stack mode and pass in a mode callback. // USBStackModeSet(0, eUSBModeOTG, ModeCallback); // // Initialize the stack to be used with USB stick. // USBStickInit(); // // Initialize the stack to be used as a serial device. // USBSerialInit(); // // Initialize the USB controller for dual mode operation with a 2ms polling // rate. // USBOTGModeInit(0, 2000, g_pui8HCDPool, HCD_MEMORY_SIZE); // // Initialize the menus module. This module will control the user // interface menuing system. // MenuInit(WidgetActivated); // // Configure SysTick to periodically interrupt. // g_ui32TickCount = 0; MAP_SysTickPeriodSet(ui32SysClock / CLOCK_RATE); MAP_SysTickIntEnable(); MAP_SysTickEnable(); // // Initialize the display context and another context that is used // as an offscreen drawing buffer for display animation effect // GrContextInit(&sDisplayContext, &g_sCFAL96x64x16); GrContextInit(&sBufferContext, &g_sOffscreenDisplayA); // // Show the splash screen if we are not skipping it. The only reason to // skip it is if the application was in sleep-logging mode and the user // just waked it up with the select button. // if(!bSkipSplash) { const uint8_t *pui8SplashLogo = g_pui8Image_TI_Black; // // Draw the TI logo on the display. Use an animation effect where the // logo will "slide" onto the screen. Allow select button to break // out of animation. // for(ui8X = 0; ui8X < 96; ui8X++) { if(ButtonsPoll(0, 0) & SELECT_BUTTON) { break; } GrImageDraw(&sDisplayContext, pui8SplashLogo, 95 - ui8X, 0); } // // Leave the logo on the screen for a long duration. Monitor the // buttons so that if the user presses the select button, the logo // display is terminated and the application starts immediately. // while(g_ui32TickCount < 400) { if(ButtonsPoll(0, 0) & SELECT_BUTTON) { break; } } // // Extended splash sequence // if(ButtonsPoll(0, 0) & UP_BUTTON) { for(ui8X = 0; ui8X < 96; ui8X += 4) { GrImageDraw(&sDisplayContext, g_ppui8Image_Splash[(ui8X / 4) & 3], (int32_t)ui8X - 96L, 0); GrImageDraw(&sDisplayContext, pui8SplashLogo, ui8X, 0); MAP_SysCtlDelay(ui32SysClock / 12); } MAP_SysCtlDelay(ui32SysClock / 3); pui8SplashLogo = g_ppui8Image_Splash[4]; GrImageDraw(&sDisplayContext, pui8SplashLogo, 0, 0); MAP_SysCtlDelay(ui32SysClock / 12); } // // Draw the initial menu into the offscreen buffer. // SlideMenuDraw(&g_sMenuWidget, &sBufferContext, 0); // // Now, draw both the TI logo splash screen (from above) and the initial // menu on the screen at the same time, moving the coordinates so that // the logo "slides" off the display and the menu "slides" onto the // display. // for(ui8Y = 0; ui8Y < 64; ui8Y++) { GrImageDraw(&sDisplayContext, pui8SplashLogo, 0, -ui8Y); GrImageDraw(&sDisplayContext, g_pui8OffscreenBufA, 0, 63 - ui8Y); } } // // Add the menu widget to the widget tree and send an initial paint // request. // WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sMenuWidget); WidgetPaint(WIDGET_ROOT); // // Set the focus handle to the menu widget. Any button events will be // sent to this widget // g_ui32KeyFocusWidgetHandle = (uint32_t)&g_sMenuWidget; // // Forever loop to run the application // while(1) { // // Each time the timer tick occurs, process any button events. // if(g_ui32TickCount != ui32LastTickCount) { // // Remember last tick count // ui32LastTickCount = g_ui32TickCount; // // Read the debounced state of the buttons. // ui8ButtonState = ButtonsPoll(&ui8ButtonChanged, 0); // // Pass any button presses through to the widget message // processing mechanism. The widget that has the button event // focus (probably the menu widget) will catch these button events. // if(BUTTON_PRESSED(SELECT_BUTTON, ui8ButtonState, ui8ButtonChanged)) { SendWidgetKeyMessage(WIDGET_MSG_KEY_SELECT); } if(BUTTON_PRESSED(UP_BUTTON, ui8ButtonState, ui8ButtonChanged)) { SendWidgetKeyMessage(WIDGET_MSG_KEY_UP); } if(BUTTON_PRESSED(DOWN_BUTTON, ui8ButtonState, ui8ButtonChanged)) { SendWidgetKeyMessage(WIDGET_MSG_KEY_DOWN); } if(BUTTON_PRESSED(LEFT_BUTTON, ui8ButtonState, ui8ButtonChanged)) { SendWidgetKeyMessage(WIDGET_MSG_KEY_LEFT); } if(BUTTON_PRESSED(RIGHT_BUTTON, ui8ButtonState, ui8ButtonChanged)) { SendWidgetKeyMessage(WIDGET_MSG_KEY_RIGHT); } } // // Tell the OTG library code how much time has passed in milliseconds // since the last call. // USBOTGMain(GetTickms()); // // Call functions as needed to keep the host or device mode running. // if(g_iCurrentUSBMode == eUSBModeDevice) { USBSerialRun(); } else if(g_iCurrentUSBMode == eUSBModeHost) { USBStickRun(); } // // If in the logging state, then call the logger run function. This // keeps the data acquisition running. // if((g_iLoggerState == eSTATE_LOGGING) || (g_iLoggerState == eSTATE_VIEWING)) { if(AcquireRun() && g_sConfigState.ui32SleepLogging) { // // If sleep logging is enabled, then at this point we have // stored the first data item, now save the state and start // hibernation. Wait for the power to be cut. // SetSavedState(&g_sConfigState); HibernateWakeSet(HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC); HibernateRequest(); for(;;) { } } // // If viewing instead of logging then request a repaint to keep // the viewing window updated. // if(g_iLoggerState == eSTATE_VIEWING) { WidgetPaint(WIDGET_ROOT); } } // // If in the saving state, then save data from flash storage to // USB stick. // if(g_iLoggerState == eSTATE_SAVING) { // // Save data from flash to USB // FlashStoreSave(); // // Return to idle state // g_iLoggerState = eSTATE_IDLE; } // // If in the erasing state, then erase the data stored in flash. // if(g_iLoggerState == eSTATE_ERASING) { // // Save data from flash to USB // FlashStoreErase(); // // Return to idle state // g_iLoggerState = eSTATE_IDLE; } // // If in the flash reporting state, then show the report of the amount // of used and free flash memory. // if(g_iLoggerState == eSTATE_FREEFLASH) { // // Report free flash space // FlashStoreReport(); // // Return to idle state // g_iLoggerState = eSTATE_IDLE; } // // If we are exiting the clock setting widget, that means that control // needs to be given back to the menu system. // if(g_iLoggerState == eSTATE_CLOCKEXIT) { // // Give the button event focus back to the menu system // g_ui32KeyFocusWidgetHandle = (uint32_t)&g_sMenuWidget; // // Send a button event to the menu widget that means the left // key was pressed. This signals the menu widget to deactivate // the current child widget (which was the clock setting wigdet). // This will cause the menu widget to slide the clock set widget // off the screen and resume control of the display. // SendWidgetKeyMessage(WIDGET_MSG_KEY_LEFT); g_iLoggerState = eSTATE_IDLE; } // // Process any new messages that are in the widget queue. This keeps // the user interface running. // WidgetMessageQueueProcess(); } }
//***************************************************************************** // // Run the hibernate example. Use a loop to put the microcontroller into // hibernate mode, and to wake up based on time. Also allow the user to cause // it to hibernate and/or wake up based on button presses. // //***************************************************************************** int main(void) { uint32_t ui32Idx; uint32_t ui32Status = 0; uint32_t ui32HibernateCount = 0; tContext sContext; tRectangle sRect; // // 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. // ROM_FPULazyStackingEnable(); // // Set the clocking to run directly from the crystal. // ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Initialize the UART. // ConfigureUART(); // // Initialize the OLED display // CFAL96x64x16Init(); // // Initialize the graphics context. // GrContextInit(&sContext, &g_sCFAL96x64x16); // // Fill the top 24 rows of the screen with blue to create the banner. // sRect.i16XMin = 0; sRect.i16YMin = 0; sRect.i16XMax = GrContextDpyWidthGet(&sContext) - 1; sRect.i16YMax = 9; GrContextForegroundSet(&sContext, ClrDarkBlue); GrRectFill(&sContext, &sRect); // // Change foreground for white text. // GrContextForegroundSet(&sContext, ClrWhite); // // Put the application name in the middle of the banner. // GrContextFontSet(&sContext, g_psFontFixed6x8); GrStringDrawCentered(&sContext, "hibernate", -1, GrContextDpyWidthGet(&sContext) / 2, 4, 0); // // Initialize the buttons driver // ButtonsInit(); // // Set up systick to generate interrupts at 100 Hz. // ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / 100); ROM_SysTickIntEnable(); ROM_SysTickEnable(); // // Enable the Hibernation module. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE); // // Print wake cause message on display. // GrStringDrawCentered(&sContext, "Wake due to:", -1, GrContextDpyWidthGet(&sContext) / 2, Row(2) + 4, true); // // Check to see if Hibernation module is already active, which could mean // that the processor is waking from a hibernation. // 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) { GrStringDrawCentered(&sContext, "BUTTON", -1, GrContextDpyWidthGet(&sContext) / 2, Row(3) + 4, true); } // // Wake was due to RTC match // else if(ui32Status & HIBERNATE_INT_RTC_MATCH_0) { GrStringDrawCentered(&sContext, "TIMEOUT", -1, GrContextDpyWidthGet(&sContext) / 2, Row(3) + 4, true); } // // Wake is due to neither button nor RTC, so it must have been a hard // reset. // else { GrStringDrawCentered(&sContext, "RESET", -1, GrContextDpyWidthGet(&sContext) / 2, Row(3) + 4, true); } // // If the wake is due to button or RTC, then read the first location // from the battery backed memory, as the hibernation count. // if(ui32Status & (HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_RTC_MATCH_0)) { HibernateDataGet(&ui32HibernateCount, 1); } } // // Enable the Hibernation module. This should always be called, even if // the module was already enabled, because this function also initializes // some timing parameters. // HibernateEnableExpClk(ROM_SysCtlClockGet()); // // If the wake was not due to button or RTC match, then it was a reset. // if(!(ui32Status & (HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_RTC_MATCH_0))) { // // Configure the module clock source. // HibernateClockConfig(HIBERNATE_OSC_LOWDRIVE); // // Finish the wake cause message. // GrStringDrawCentered(&sContext, "RESET", -1, GrContextDpyWidthGet(&sContext) / 2, Row(3) + 4, true); // // Wait a couple of seconds in case we need to break in with the // debugger. // SysTickWait(3 * 100); // // Allow time for the crystal to power up. This line is separated from // the above to make it clear this is still needed, even if the above // delay is removed. // SysTickWait(15); } // // Print the count of times that hibernate has occurred. // usnprintf(g_pcBuf, sizeof(g_pcBuf), "Hib count=%4u", ui32HibernateCount); GrStringDrawCentered(&sContext, g_pcBuf, -1, GrContextDpyWidthGet(&sContext) / 2, Row(1) + 4, true); // // Print messages on the screen about hibernation. // GrStringDrawCentered(&sContext, "Select to Hib", -1, GrContextDpyWidthGet(&sContext) / 2, Row(4) + 4, true); GrStringDrawCentered(&sContext, "Wake in 5 s,", -1, GrContextDpyWidthGet(&sContext) / 2, Row(5) + 4, true); GrStringDrawCentered(&sContext, "or press Select", -1, GrContextDpyWidthGet(&sContext) / 2, Row(6) + 4, true); GrStringDrawCentered(&sContext, "for immed. wake.", -1, GrContextDpyWidthGet(&sContext) / 2, Row(7) + 4, true); // // Clear the button pressed flag, in case it was held down at the // beginning. // bSelectPressed = 0; // // Wait for user to press the button. // while(!bSelectPressed) { // // Wait a bit before looping again. // SysTickWait(10); } // // Tell user to release the button. // GrStringDrawCentered(&sContext, " ", -1, GrContextDpyWidthGet(&sContext) / 2, Row(4) + 4, true); GrStringDrawCentered(&sContext, " ", -1, GrContextDpyWidthGet(&sContext) / 2, Row(5) + 4, true); GrStringDrawCentered(&sContext, " ", -1, GrContextDpyWidthGet(&sContext) / 2, Row(6) + 4, true); GrStringDrawCentered(&sContext, " ", -1, GrContextDpyWidthGet(&sContext) / 2, Row(7) + 4, true); GrStringDrawCentered(&sContext, "Release the", -1, GrContextDpyWidthGet(&sContext) / 2, Row(5) + 4, true); GrStringDrawCentered(&sContext, "button.", -1, GrContextDpyWidthGet(&sContext) / 2, Row(6) + 4, true); GrStringDrawCentered(&sContext, " ", -1, GrContextDpyWidthGet(&sContext) / 2, Row(7) + 4, true); // // Wait for user to release the button. // while(bSelectPressed) { } // // If hibernation count is very large, it may be that there was already // a value in the hibernate memory, so reset the count. // ui32HibernateCount = (ui32HibernateCount > 10000) ? 0 : ui32HibernateCount; // // Increment the hibernation count, and store it in the battery backed // memory. // ui32HibernateCount++; HibernateDataSet(&ui32HibernateCount, 1); // // Clear and enable the RTC and set the match registers to 5 seconds in the // future. Set both to same, though they could be set differently, the // first to match will cause a wake. // HibernateRTCSet(0); HibernateRTCEnable(); HibernateRTCMatchSet(0, 5); // // Set wake condition on pin or RTC match. Board will wake when 5 seconds // elapses, or when the button is pressed. // HibernateWakeSet(HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC); // // Request hibernation. // HibernateRequest(); // // Give it time to activate, it should never get past this wait. // SysTickWait(100); // // Should not have got here, something is wrong. Print an error message to // the user. // sRect.i16XMin = 0; sRect.i16XMax = 95; sRect.i16YMin = 0; sRect.i16YMax = 63; GrContextForegroundSet(&sContext, ClrBlack); GrRectFill(&sContext, &sRect); GrContextForegroundSet(&sContext, ClrWhite); ui32Idx = 0; while(g_pcErrorText[ui32Idx]) { GrStringDraw(&sContext, g_pcErrorText[ui32Idx], -1, Col(0), Row(ui32Idx), true); ui32Idx++; } // // Wait for the user to press the button, then restart the app. // bSelectPressed = 0; while(!bSelectPressed) { } // // Reset the processor. // ROM_SysCtlReset(); // // Finished. // while(1) { } }
//***************************************************************************** // // This function is called to start an acquisition running. It determines // which channels are to be logged, enables the ADC sequencers, and computes // the first RTC match value. This will start the acquisition running. // //***************************************************************************** void AcquireStart(tConfigState *psConfig) { uint32_t ui32Idx, pui32RTC[2], ui32SelectedMask; // // Check the parameters // ASSERT(psConfig); if(!psConfig) { return; } // // Update the config state pointer, save the selected item mask // g_psConfigState = psConfig; ui32SelectedMask = psConfig->ui16SelectedMask; // // Get the logging period from the logger configuration. Split the // period into seconds and subseconds pieces and save for later use in // generating RTC match values. // g_pui32MatchPeriod[0] = psConfig->ui32Period >> 8; g_pui32MatchPeriod[1] = (psConfig->ui32Period & 0xFF) << 8; // // Determine how many channels are to be logged // ui32Idx = ui32SelectedMask; g_ui32NumItems = 0; while(ui32Idx) { if(ui32Idx & 1) { g_ui32NumItems++; } ui32Idx >>= 1; } // // Initialize the strip chart manager for a new run. Don't bother with // the strip chart if we are using viewer mode, or sleep-logging. // if((psConfig->ui8Storage != CONFIG_STORAGE_VIEWER) && !psConfig->ui32SleepLogging) { StripChartMgrInit(); StripChartMgrConfigure(ui32SelectedMask); } // // Configure USB for memory stick if USB storage is chosen // if(psConfig->ui8Storage == CONFIG_STORAGE_USB) { USBStickOpenLogFile(0); } else if(psConfig->ui8Storage == CONFIG_STORAGE_FLASH) { // // Flash storage is to be used, prepare the flash storage module. // If already sleep-logging, then pass in the saved flash address // so it does not need to be searched. // if(psConfig->ui32SleepLogging) { FlashStoreOpenLogFile(psConfig->ui32FlashStore); } else { // // Otherwise not sleep logging, so just initialize the flash store, // this will cause it to search for the starting storage address. // FlashStoreOpenLogFile(0); } } // // Enable the ADC sequencers // MAP_ADCSequenceEnable(ADC0_BASE, 0); MAP_ADCSequenceEnable(ADC1_BASE, 0); // // Flush the ADC sequencers to be sure there is no lingering data. // MAP_ADCSequenceDataGet(ADC0_BASE, 0, g_pui32ADCData); MAP_ADCSequenceDataGet(ADC1_BASE, 0, g_pui32ADCData); // // Enable ADC interrupts // MAP_ADCIntClear(ADC0_BASE, 0); MAP_ADCIntClear(ADC1_BASE, 0); MAP_ADCIntEnable(ADC0_BASE, 0); MAP_IntEnable(INT_ADC0SS0); // // If we are not already sleep-logging, then initialize the RTC match. // If we are sleep logging then this does not need to be set up. // if(!psConfig->ui32SleepLogging) { // // Get the current RTC value // do { pui32RTC[0] = HibernateRTCGet(); pui32RTC[1] = HibernateRTCSSGet(); } while(pui32RTC[0] != HibernateRTCGet()); // // Set an initial next match value. Start with the subseconds always // 0 so the first match value will always be an even multiple of the // subsecond match. Add 2 seconds to the current RTC just to be clear // of an imminent rollover. This means that the first match will occur // between 1 and 2 seconds from now. // g_pui32NextMatch[0] = pui32RTC[0] + 2; g_pui32NextMatch[1] = 0; // // Now set the match value // HibernateRTCMatchSet(0, g_pui32NextMatch[0]); HibernateRTCSSMatchSet(0, g_pui32NextMatch[1]); } // // If we are configured to sleep, but not sleeping yet, then enter sleep // logging mode if allowed. // if(psConfig->bSleep && !psConfig->ui32SleepLogging) { // // Allow sleep logging if storing to flash at a period of 1 second // or greater. // if((psConfig->ui8Storage == CONFIG_STORAGE_FLASH) && (psConfig->ui32Period >= 0x100)) { psConfig->ui32SleepLogging = 1; } } // // Enable the RTC interrupts from the hibernate module // HibernateIntClear(HibernateIntStatus(0)); HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0 | HIBERNATE_INT_PIN_WAKE); MAP_IntEnable(INT_HIBERNATE); // // Logging data should now start running // }
//***************************************************************************** // // This is the handler for the RTC interrupt from the hibernate peripheral. // It occurs on RTC match. This handler will initiate an ADC acquisition, // which will run all of the ADC sequencers. Then it computes the next // match value and sets it in the RTC. // //***************************************************************************** void RTCHandler(void) { uint32_t ui32Status, ui32Seconds; // // Increment RTC interrupt counter // g_pui32RTCInts++; // // Clear the RTC interrupts (this can be slow for hib module) // ui32Status = HibernateIntStatus(1); HibernateIntClear(ui32Status); // // Read and save the current value of the seconds counter. // ui32Seconds = HibernateRTCGet(); // // If we are sleep logging, then there will be no remembered value for // the next match value, which is also used as the time stamp when // data is collected. In this case we will just use the current // RTC seconds. This is safe because if sleep-logging is used, it // is only with periods of whole seconds, 1 second or longer. // if(g_psConfigState->ui32SleepLogging) { g_pui32NextMatch[0] = ui32Seconds; g_pui32NextMatch[1] = 0; } // // If we are logging data to PC and using a period greater than one // second, then use special handling. For PC logging, if no data is // collected, then we must send a keep-alive packet once per second. // if((g_psConfigState->ui8Storage == CONFIG_STORAGE_HOSTPC) && (g_pui32MatchPeriod[0] > 1)) { // // If the current seconds count is less than the match value, that // means we got the interrupt due to one-second keep alive for the // host PC. // if(ui32Seconds < g_pui32NextMatch[0]) { // // Set the next match for one second ahead (next keep-alive) // HibernateRTCMatchSet(0, ui32Seconds + 1); // // Set flag to indicate that a keep alive packet is needed // g_bNeedKeepAlive = true; // // Nothing else to do except wait for next keep alive or match // return; } // // Else, this is a real match so proceed to below to do a normal // acquisition. // } // // Kick off the next ADC acquisition. When these are done they will // cause an ADC interrupt. // MAP_ADCProcessorTrigger(ADC1_BASE, 0); MAP_ADCProcessorTrigger(ADC0_BASE, 0); // // Set the next RTC match. Add the match period to the previous match // value. We are making an assumption here that there is enough time from // when the match interrupt occurred, to this point in the code, that we // are still setting the match time in the future. If the period is too // long, then we could miss a match and never get another RTC interrupt. // g_pui32NextMatch[0] += g_pui32MatchPeriod[0]; g_pui32NextMatch[1] += g_pui32MatchPeriod[1]; if(g_pui32NextMatch[1] > 32767) { // // Handle subseconds rollover // g_pui32NextMatch[1] &= 32767; g_pui32NextMatch[0]++; } // // If logging to host PC at greater than 1 second period, then set the // next RTC wakeup for 1 second from now. This will cause a keep alive // packet to be sent to the PC // if((g_psConfigState->ui8Storage == CONFIG_STORAGE_HOSTPC) && (g_pui32MatchPeriod[0] > 1)) { HibernateRTCMatchSet(0, ui32Seconds + 1); } else { // // Otherwise this is a normal match and the next match should also be a // normal match, so set the next wakeup to the calculated match time. // HibernateRTCMatchSet(0, g_pui32NextMatch[0]); HibernateRTCSSMatchSet(0, g_pui32NextMatch[1]); } // // Toggle the LED on the board so the user can see that the acquisition // is running. // MAP_GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_2, ~MAP_GPIOPinRead(GPIO_PORTG_BASE, GPIO_PIN_2)); // // Now exit the int handler. The ADC will trigger an interrupt when // it is finished, and the RTC is set up for the next match. // }
//***************************************************************************** // // 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"); } } }
void HibernateInterrupt() { HibernateIntClear(HibernateIntStatus(1)); //Always need to clear the interrupts. }
int main(void) { // Status of Hibernation module uint32_t ui32Status = 0; // Length of time to hibernate uint32_t hibernationTime = 600; g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); //************************************************************************* //! I/O config and setup //************************************************************************* SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); // UART SysCtlPeripheralEnable(SYSCTL_PERIPH_UART7); // UART SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // UART0 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); // UART7 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); // SSI SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); // GPIO SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2); // SSI SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK); // GPIO SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);// Hibernation // UART0 and UART7 GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PC4_U7RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinConfigure(GPIO_PC5_U7TX); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5); // LED indicators GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1); // // SD Card Detect (PK3) and GPS Pulse Per Second (PK2) // GPIOPinTypeGPIOInput(GPIO_PORTK_BASE, GPIO_PIN_2|GPIO_PIN_3); // Pulse Per Second input pin config as weak pull-down GPIOPadConfigSet(GPIO_PORTK_BASE,GPIO_PIN_2,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPD); // Pulse Per Second input pin config as rising edge triggered interrupt GPIOIntTypeSet(GPIO_PORTK_BASE,GPIO_PIN_2,GPIO_RISING_EDGE); // Register Port K as interrupt GPIOIntRegister(GPIO_PORTK_BASE, PortKIntHandler); // Enable Port K pin 2 interrupt GPIOIntEnable(GPIO_PORTK_BASE, GPIO_INT_PIN_2); // // Disable PPS pin interrupt by default // if(IntIsEnabled(INT_GPIOK)) { IntDisable(INT_GPIOK); } GPIOPinConfigure(GPIO_PD0_SSI2XDAT1); GPIOPinConfigure(GPIO_PD1_SSI2XDAT0); GPIOPinConfigure(GPIO_PD2_SSI2FSS); GPIOPinConfigure(GPIO_PD3_SSI2CLK); // SD Card Detect (CD) - weak pull-up input GPIOPadConfigSet(GPIO_PORTK_BASE, GPIO_PIN_3, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); // Debug UART output config UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); // GPS UART input config UARTConfigSetExpClk(UART7_BASE, g_ui32SysClock, 9600, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); // // Configure SysTick for a 100Hz interrupt. // SysTickPeriodSet(g_ui32SysClock / 100); SysTickIntEnable(); SysTickEnable(); // // Floating point enable // FPUEnable(); FPULazyStackingEnable(); // // Clear user LEDs // GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1, 0x00); //************************************************************************* //! Hibernation mode checks and setup //************************************************************************* // // Check to see if Hibernation module is already active, which could mean // that the processor is waking from a hibernation. // if(HibernateIsActive()) { // // Read the status bits to see what caused the wake. Clear the wake // source so that the device can be put into hibernation again. // ui32Status = HibernateIntStatus(0); HibernateIntClear(ui32Status); // // Wake was due to RTC match. // if(ui32Status & HIBERNATE_INT_RTC_MATCH_0) { // // TODO: add IMU check // } // // Wake was due to the External Wake pin. // else if(ui32Status & HIBERNATE_INT_PIN_WAKE) { // // Switch off low power mode // lowPowerOn = 0; } } // // Configure Hibernate module clock. // HibernateEnableExpClk(g_ui32SysClock); // // If the wake was not due to the above sources, then it was a system // reset. // if(!(ui32Status & (HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_RTC_MATCH_0))) { // // Configure the module clock source. // HibernateClockConfig(HIBERNATE_OSC_LOWDRIVE); } // // Enable PPS for a single data log. Interrupt on next PPS logic high. // ppsDataLog(); // // Enable RTC mode. // HibernateRTCEnable(); // // Loop forever // while(1) { // // If low power mode is set (default), hibernate again // If not, spin in nested while(1) for faster updates from PPS pin ints. // if(lowPowerOn) { lowPowerMode(hibernationTime); } else { if(!IntIsEnabled(INT_GPIOK)) { IntEnable(INT_GPIOK); } while(1) { } } } } // End function main