⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hibernate.c

📁 最新版IAR FOR ARM(EWARM)5.11中的代码例子
💻 C
字号:
//*****************************************************************************
//
// hibernate.c - Hibernation example.
//
// Copyright (c) 2007 Luminary Micro, Inc.  All rights reserved.
// 
// Software License Agreement
// 
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
// 
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws.  All rights are reserved.  You may not combine
// this software with "viral" open-source software in order to form a larger
// program.  Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
// 
// THIS SOFTWARE IS PROVIDED "AS IS".  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.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 1952 of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************

#include "../../../hw_types.h"
#include "../../../hw_memmap.h"
#include "../../../src/debug.h"
#include "../../../src/sysctl.h"
#include "../../../src/systick.h"
#include "../../../src/hibernate.h"
#include "../../../src/gpio.h"
#include "../../../utils/ustdlib.h"
#include "../../../utils/diag.h"
#include "../rit128x96x4.h"

//*****************************************************************************
//
//! \addtogroup ek_lm3s1968_list
//! <h1>Hibernate Example (hibernate)</h1>
//!
//! An example to demonstrate the use of the Hibernation module.  The user
//! can put the microcontroller in hibernation by pressing the select
//! button.  The microcontroller will then wake on its own after 5 seconds,
//! or immediately if the user presses the select button again.  The program
//! keeps a count of the number of times it has entered hibernation.  The
//! value of the counter is stored in the battery backed memory of the
//! Hibernation module so that it can be retrieved when the microcontroller
//! wakes.
//
//*****************************************************************************

//*****************************************************************************
//
// Macros to convert character based display rows and columns into the pixel
// based X and Y coordinates needed for display drawing functions.
//
//*****************************************************************************
#define COL(c) ((c) * 6)
#define ROW(r) ((r) * 8)

//*****************************************************************************
//
// A counter that counts the number of ticks of the SysTick interrupt.
//
//*****************************************************************************
volatile unsigned long g_ulSysTickCount = 0;

//*****************************************************************************
//
// A buffer to hold character strings that will be printed to the display.
//
//*****************************************************************************
static char cBuf[40];

//*****************************************************************************
//
// A buffer that holds one display line of dashes.
//
//*****************************************************************************
static char cDashLine[] = "---------------------";

//*****************************************************************************
//
// Text that will be displayed if there is an error.
//
//*****************************************************************************
static char *cErrorText[] =
{
    "The controller did",
    "not enter hib mode.",
    "This could occur if",
    "the button were held",
    "down when trying to",
    "hibernate.",
    "---------------------",
    "   PRESS BUTTON",
    "    TO RESTART",
    0
};

//*****************************************************************************
//
// A flag to indicate the select button was pressed.
//
//*****************************************************************************
static volatile unsigned char bSelectPressed = 0;

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, unsigned long ulLine)
{
}
#endif

//*****************************************************************************
//
// Delay a certain number of SysTick timer ticks.
//
//*****************************************************************************
void
SysTickWait(unsigned long ulTicks)
{
    ulTicks += g_ulSysTickCount;
    while(g_ulSysTickCount <= ulTicks)
    {
    }
}

//*****************************************************************************
//
// The SysTick handler.  Increments a tick counter and debounces the push
// button.
//
//*****************************************************************************
void
SysTickHandler(void)
{
    static unsigned char ucSwitches = 0x80;
    static unsigned char ucSwitchClockA = 0;
    static unsigned char ucSwitchClockB = 0;
    unsigned long ulData, ulDelta;

    //
    // Increment the tick counter.
    //
    g_ulSysTickCount++;

    //
    // Read the state of the select button.
    //
    ulData = (GPIOPinRead(GPIO_PORTG_BASE, GPIO_PIN_7));

    //
    // Determine the switches that are at a different state than the debounced
    // state.
    //
    ulDelta = ulData ^ ucSwitches;

    //
    // Increment the clocks by one.
    //
    ucSwitchClockA ^= ucSwitchClockB;
    ucSwitchClockB = ~ucSwitchClockB;

    //
    // Reset the clocks corresponding to switches that have not changed state.
    //
    ucSwitchClockA &= ulDelta;
    ucSwitchClockB &= ulDelta;

    //
    // Get the new debounced switch state.
    //
    ucSwitches &= ucSwitchClockA | ucSwitchClockB;
    ucSwitches |= (~(ucSwitchClockA | ucSwitchClockB)) & ulData;

    //
    // Determine the switches that just changed debounced state.
    //
    ulDelta ^= (ucSwitchClockA | ucSwitchClockB);

    //
    // See if the select button was just pressed.
    //
    if((ulDelta & 0x80) && !(ucSwitches & 0x80))
    {
        //
        // Set a flag to indicate that the select button was just pressed.
        //
        bSelectPressed = 1;
    }

    //
    // Else, see if the select button was just released.
    //
    if((ulDelta & 0x80) && (ucSwitches & 0x80))
    {
        //
        // Clear the button pressed flag.
        //
        bSelectPressed = 0;
    }
}

//*****************************************************************************
//
// 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)
{
    unsigned long ulIdx;
    unsigned long ulStatus = 0;
    unsigned long ulHibernateCount = 0;

    //
    // Set the clocking to run directly from the crystal.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_8MHZ);

    //
    // Initialize the OLED display, and print title message.
    //
    RIT128x96x4Init(1000000);
    RIT128x96x4StringDraw("Hibernate Example", COL(2), ROW(0), 15);
    RIT128x96x4StringDraw(cDashLine, COL(0), ROW(1), 15);

    //
    // Initialize the GPIO needed for the button.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
    GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_7);
    GPIOPadConfigSet(GPIO_PORTG_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA,
                     GPIO_PIN_TYPE_STD_WPU);

    //
    // Set up systick to generate interrupts at 100 Hz.
    //
    SysTickPeriodSet(SysCtlClockGet() / 100);
    SysTickIntEnable();
    SysTickEnable();

    //
    // Check for presence of Hibernate module.
    //
    if(SysCtlPeripheralPresent(SYSCTL_PERIPH_HIBERNATE))
    {
        //
        // Enable the Hibernation module in system control.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
    }
    else
    {
        //
        // No Hibernation module is present.  Print an error message and quit.
        //
        RIT128x96x4StringDraw("No Hib Module!", COL(3), ROW(2), 15);
        DiagExit(-1);
    }

    //
    // Print wake cause message on display.
    //
    RIT128x96x4StringDraw("Last wake due to:", COL(1), ROW(3), 15);

    //
    // Per an erratum, sometimes on wake the Hibernation module control
    // register will be cleared when it should not be.  As a workaround a
    // location in the non-volatile data area can be read instead.  This data
    // area is cleared to 0 on reset, so if the first location is non-zero then
    // the Hibernation module is in use.  In this case, re-enable the
    // Hibernation module which will ensure that the control register bits have
    // the proper value.
    //
    HibernateDataGet(&ulHibernateCount, 1);
    if(ulHibernateCount)
    {
        HibernateEnableExpClk(SysCtlClockGet());
        HibernateClockSelect(HIBERNATE_CLOCK_SEL_DIV128);
    }

    //
    // 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.
        //
        ulStatus = HibernateIntStatus(0);

        //
        // Wake was due to the push button.
        //
        if(ulStatus & HIBERNATE_INT_PIN_WAKE)
        {
            RIT128x96x4StringDraw("BUTTON", COL(7), ROW(4), 15);
        }

        //
        // Wake was due to RTC match
        //
        else if(ulStatus & HIBERNATE_INT_RTC_MATCH_0)
        {
            RIT128x96x4StringDraw("TIMEOUT", COL(6), ROW(4), 15);
        }

        //
        // Wake is due to neither button nor RTC, so it must have been a hard
        // reset.
        //
        else
        {
            RIT128x96x4StringDraw("RESET", COL(7), ROW(4), 15);
        }

        //
        // If the wake is due to button or RTC, then read the first location
        // from the battery backed memory, as the hibernation count.
        //
        if(ulStatus & (HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_RTC_MATCH_0))
        {
            HibernateDataGet(&ulHibernateCount, 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(SysCtlClockGet());

    //
    // If the wake was not due to button or RTC match, then it was a reset.
    //
    if(!(ulStatus & (HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_RTC_MATCH_0)))
    {
        //
        // Configure the module clock source.
        //
        HibernateClockSelect(HIBERNATE_CLOCK_SEL_DIV128);

        //
        // Finish the wake cause message.
        //
        RIT128x96x4StringDraw("RESET", COL(7), ROW(4), 15);

        //
        // 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(cBuf, sizeof(cBuf), "Hib count=%4u", ulHibernateCount);
    RIT128x96x4StringDraw(cBuf, COL(3), ROW(2), 15);

    //
    // Print messages on the screen about hibernation.
    //
    RIT128x96x4StringDraw("Press Select to", COL(3), ROW(6), 15);
    RIT128x96x4StringDraw("hibernate.", COL(6), ROW(7), 15);
    RIT128x96x4StringDraw("Will wake in 5 secs,", COL(0), ROW(9), 15);
    RIT128x96x4StringDraw("or press Select for", COL(0), ROW(10), 15);
    RIT128x96x4StringDraw("immediate wake.", COL(2), ROW(11), 15);
    RIT128x96x4StringDraw(cDashLine, COL(0), ROW(5), 15);
    RIT128x96x4StringDraw(cDashLine, COL(0), ROW(8), 15);

    //
    // 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.
    //
    RIT128x96x4StringDraw("  Release the   ", COL(3), ROW(6), 15);
    RIT128x96x4StringDraw(" button.      ", COL(6), ROW(7), 15);

    //
    // Wait for user to release the button.
    //
    while(bSelectPressed)
    {
    }

    //
    // Increment the hibernation count, and store it in the battery backed
    // memory.
    //
    ulHibernateCount++;
    HibernateDataSet(&ulHibernateCount, 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();
    HibernateRTCMatch0Set(5);
    HibernateRTCMatch1Set(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.
    //
    RIT128x96x4Clear();
    ulIdx = 0;
    while(cErrorText[ulIdx])
    {
        RIT128x96x4StringDraw(cErrorText[ulIdx], COL(0), ROW(ulIdx), 15);
        ulIdx++;
    }

    //
    // Wait for the user to press the button, then restart the app.
    //
    bSelectPressed = 0;
    while(!bSelectPressed)
    {
    }

    //
    // Reset the processor.
    //
    SysCtlReset();

    //
    // Exit.
    //
    DiagExit(0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -