summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-07-11 23:21:16 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-07-11 23:21:16 +0000
commitf2f04aeaa1ad971b4de143731e8a53912e638ffa (patch)
tree2fa53e1bfd0e4ea2254a5036f0e4936185c87cf0
parent25694ca4c649d667e7baa519434fae2d885cc6b7 (diff)
downloadnuttx-f2f04aeaa1ad971b4de143731e8a53912e638ffa.tar.gz
nuttx-f2f04aeaa1ad971b4de143731e8a53912e638ffa.tar.bz2
nuttx-f2f04aeaa1ad971b4de143731e8a53912e638ffa.zip
PM update
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4932 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c48
-rw-r--r--nuttx/configs/stm3210e-eval/src/up_idle.c76
-rw-r--r--nuttx/configs/stm3210e-eval/src/up_pmbuttons.c7
-rw-r--r--nuttx/include/nuttx/rtc.h20
4 files changed, 135 insertions, 16 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c b/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c
index 03be0ee3f..203f45450 100644
--- a/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c
+++ b/nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c
@@ -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
diff --git a/nuttx/configs/stm3210e-eval/src/up_idle.c b/nuttx/configs/stm3210e-eval/src/up_idle.c
index 456a92db8..05ae64bad 100644
--- a/nuttx/configs/stm3210e-eval/src/up_idle.c
+++ b/nuttx/configs/stm3210e-eval/src/up_idle.c
@@ -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
diff --git a/nuttx/configs/stm3210e-eval/src/up_pmbuttons.c b/nuttx/configs/stm3210e-eval/src/up_pmbuttons.c
index 62dc45f1e..ab7fd549e 100644
--- a/nuttx/configs/stm3210e-eval/src/up_pmbuttons.c
+++ b/nuttx/configs/stm3210e-eval/src/up_pmbuttons.c
@@ -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);
diff --git a/nuttx/include/nuttx/rtc.h b/nuttx/include/nuttx/rtc.h
index b9bd020c9..007617a0e 100644
--- a/nuttx/include/nuttx/rtc.h
+++ b/nuttx/include/nuttx/rtc.h
@@ -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)
}