PM update

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4932 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2012-07-11 23:21:16 +00:00
parent a4426d194e
commit 4f1e53b492
4 changed files with 135 additions and 16 deletions

View File

@ -607,6 +607,7 @@ int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
{
struct rtc_regvals_s regvals;
irqstate_t flags;
uint16_t cr;
int ret = -EBUSY;
/* Is there already something waiting on the ALARM? */
@ -621,6 +622,12 @@ int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
up_rtc_breakout(tp, &regvals);
/* Enable RTC alarm */
cr = getreg16(STM32_RTC_CRH);
cr |= RTC_CRH_ALRIE;
putreg16(cr, STM32_RTC_CRH);
/* The set the alarm */
flags = irqsave();
@ -635,3 +642,44 @@ int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
return ret;
}
#endif
/************************************************************************************
* Name: up_rtc_cancelalarm
*
* Description:
* Cancel a pending alarm alarm
*
* Input Parameters:
* none
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
#ifdef CONFIG_RTC_ALARM
int up_rtc_cancelalarm(void)
{
irqstate_t flags;
int ret = -ENODATA;
if (g_alarmcb != NULL)
{
/* Cancel the global callback function */
g_alarmcb = NULL;
/* Unset the alarm */
flags = irqsave();
stm32_rtc_beginwr();
putreg16(0xffff, STM32_RTC_ALRH);
putreg16(0xffff, STM32_RTC_ALRL);
stm32_rtc_endwr();
irqrestore(flags);
ret = OK;
}
return ret;
}
#endif

View File

@ -44,6 +44,7 @@
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <nuttx/clock.h>
#include <nuttx/power/pm.h>
#include <debug.h>
@ -74,7 +75,7 @@
/* Values for the RTC Alarm to wake up from the PM_STANDBY mode */
#ifndef CONFIG_PM_ALARM_SEC
# define CONFIG_PM_ALARM_SEC 1
# define CONFIG_PM_ALARM_SEC 3
#endif
#ifndef CONFIG_PM_ALARM_NSEC
@ -85,7 +86,9 @@
* Private Data
****************************************************************************/
#ifdef CONFIG_PM
static void up_alarmcb(void);
#endif
/****************************************************************************
* Private Functions
@ -128,12 +131,10 @@ static void up_idlepm(void)
/* The new state change failed, revert to the preceding state */
(void)pm_changestate(oldstate);
}
else
{
/* Save the new state */
oldstate = newstate;
/* No state change... */
goto errout;
}
/* Then perform board-specific, state-dependent logic here */
@ -141,16 +142,27 @@ static void up_idlepm(void)
switch (newstate)
{
case PM_NORMAL:
{
/* Cancel the alarm that was set in PM_STANDBY */
if (oldstate == PM_STANDBY)
{
ret = up_rtc_cancelalarm();
if (ret < 0)
{
lldbg("Warning: Cancel alarm failed\n");
}
}
}
break;
case PM_IDLE:
{
{
/* Check if the buttons have already been registered */
up_unregisterbuttons();
/* Initialize the buttoms to wake up the system from the idle
/* Initialize the buttons to wake up the system from the idle
* mode
*/
@ -168,26 +180,53 @@ static void up_idlepm(void)
up_pmbuttons();
(void)up_rtc_gettime(&alarmtime);
/* Configure the RTC alarm to Auto Wake the system */
alarmtime.tv_sec = CONFIG_PM_ALARM_SEC;
alarmtime.tv_nsec = CONFIG_PM_ALARM_NSEC;
alarmtime.tv_sec += CONFIG_PM_ALARM_SEC;
alarmtime.tv_nsec += CONFIG_PM_ALARM_NSEC;
/* The tv_nsec value must not exceed 1,000,000,000. That
* would be an invalid time.
*/
if (alarmtime.tv_nsec >= NSEC_PER_SEC)
{
/* Carry to the seconds */
alarmtime.tv_sec++;
alarmtime.tv_nsec -= NSEC_PER_SEC;
}
/* Set the alarm */
ret = up_rtc_setalarm(&alarmtime, &up_alarmcb);
if (ret < 0)
{
lldbg("The alarm is already set to %d seconds \n",
alarmtime.tv_sec);
lldbg("Warning: The alarm is already set.\n");
}
/* Call the STM32 stop mode */
stm32_pmstop(true);
/* We have been re-awakened by some even: A button press?
* An alarm? Cancel any pending alarm and resume the normal
* operation.
*/
up_rtc_cancelalarm();
pm_changestate(PM_NORMAL);
}
break;
case PM_SLEEP:
{
/* We should not return from standby mode. The only way out
* of standby is via the reset path.
*/
(void)stm32_pmstandby();
}
break;
@ -196,6 +235,11 @@ static void up_idlepm(void)
break;
}
/* Save the new state */
oldstate = newstate;
errout:
irqrestore(flags);
}
}
@ -203,7 +247,6 @@ static void up_idlepm(void)
# define up_idlepm()
#endif
/************************************************************************************
* Name: up_alarmcb
*
@ -212,9 +255,16 @@ static void up_idlepm(void)
*
************************************************************************************/
#ifdef CONFIG_PM
static void up_alarmcb(void)
{
/* This alarm occurs because there wasn't any EXTI interrupt during the
* PM_STANDBY period. So just go to sleep.
*/
pm_changestate(PM_SLEEP);
}
#endif
/****************************************************************************
* Public Functions

View File

@ -273,8 +273,11 @@ static const struct button_info_s g_buttoninfo[NUM_PMBUTTONS] =
#ifdef CONFIG_ARCH_IRQBUTTONS
static void button_handler(int id, int irq)
{
/* At this point the MCU should have already awakened. Just report some
* activity in order to drive the rest of the system to the PM_NORMAL state
/* At this point the MCU should have already awakened. The state
* change will be handled in the IDLE loop when the system is re-awakened
* The button interrupt handler should be totally ignorant of the PM
* activities and should report button activity as if nothing
* special happened.
*/
pm_activity(CONFIG_PM_BUTTON_ACTIVITY);

View File

@ -6,7 +6,7 @@
*
* With extensions, modifications by:
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregroy Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -256,6 +256,24 @@ EXTERN int up_rtc_settime(FAR const struct timespec *tp);
EXTERN int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback);
#endif
/************************************************************************************
* Name: up_rtc_cancelalarm
*
* Description:
* Cancel a pending alarm alarm
*
* Input Parameters:
* none
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
#ifdef CONFIG_RTC_ALARM
EXTERN int up_rtc_cancelalarm(void);
#endif
#undef EXTERN
#if defined(__cplusplus)
}