From f2f04aeaa1ad971b4de143731e8a53912e638ffa Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 11 Jul 2012 23:21:16 +0000 Subject: PM update git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4932 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/arch/arm/src/stm32/stm32f10xxx_rtc.c | 48 ++++++++++++++++ nuttx/configs/stm3210e-eval/src/up_idle.c | 76 +++++++++++++++++++++----- nuttx/configs/stm3210e-eval/src/up_pmbuttons.c | 7 ++- nuttx/include/nuttx/rtc.h | 20 ++++++- 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, ®vals); + /* 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 #include +#include #include #include @@ -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 * * 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) } -- cgit v1.2.3