Add a basic power management framework
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3936 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
1f217f57ab
commit
4e92683ab3
@ -2051,3 +2051,4 @@
|
||||
-print-libgcc-file-name.
|
||||
* lib/time/lib_gmtimer.c: Correct several calculations that could lead
|
||||
to errors in dates.
|
||||
* drivers/pm: Add the beginnings of a NuttX power management sub-system.
|
||||
|
@ -47,6 +47,7 @@
|
||||
|
||||
#include <nuttx/init.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/pm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
@ -60,6 +61,16 @@ static jmp_buf sim_abort;
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
/* Power management should be initialized early in the (simulated) boot
|
||||
* sequence.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
pm_initialize();
|
||||
#endif
|
||||
|
||||
/* Then start NuttX */
|
||||
|
||||
if (setjmp(sim_abort) == 0)
|
||||
{
|
||||
os_start();
|
||||
|
@ -40,7 +40,10 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/pm.h>
|
||||
|
||||
#include "up_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -103,6 +106,24 @@ void up_idle(void)
|
||||
uipdriver_loop();
|
||||
#endif
|
||||
|
||||
/* Fake some power management stuff for testing purposes */
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
{
|
||||
static enum pm_state_e state = PM_NORMAL;
|
||||
enum pm_state_e newstate;
|
||||
|
||||
newstate = pm_checkstate();
|
||||
if (newstate != state)
|
||||
{
|
||||
if (pm_changestate(newstate) == OK)
|
||||
{
|
||||
state = newstate;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Wait a bit so that the sched_process_timer() is called close to the
|
||||
* correct rate.
|
||||
*/
|
||||
|
@ -56,6 +56,7 @@ include mmcsd/Make.defs
|
||||
include mtd/Make.defs
|
||||
include net/Make.defs
|
||||
include pipes/Make.defs
|
||||
include pm/Make.defs
|
||||
include sensors/Make.defs
|
||||
include serial/Make.defs
|
||||
include usbdev/Make.defs
|
||||
|
50
drivers/pm/Make.defs
Executable file
50
drivers/pm/Make.defs
Executable file
@ -0,0 +1,50 @@
|
||||
############################################################################
|
||||
# drivers/pm/Make.defs
|
||||
#
|
||||
# Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
# Has power management support been initialized?
|
||||
|
||||
ifeq ($(CONFIG_PM),y)
|
||||
|
||||
# Include power management sources
|
||||
|
||||
CSRCS += pm_activity.c pm_changestate.c pm_checkstate.c pm_initialize.c pm_register.c pm_update.c
|
||||
|
||||
# Include power management in the build
|
||||
|
||||
DEPPATH += --dep-path pm
|
||||
VPATH += :pm
|
||||
CFLAGS += ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/pm}
|
||||
endif
|
||||
|
166
drivers/pm/pm_activity.c
Normal file
166
drivers/pm/pm_activity.c
Normal file
@ -0,0 +1,166 @@
|
||||
/****************************************************************************
|
||||
* drivers/pm/pm_activity.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/pm.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include "pm_internal.h"
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_activity
|
||||
*
|
||||
* Description:
|
||||
* This function is called by a device driver to indicate that it is
|
||||
* performing meaningful activities (non-idle). This increment an activty
|
||||
* cound and/or will restart a idle timer and prevent entering IDLE
|
||||
* power states.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priority - activity priority, range 0-9. Larger values correspond to
|
||||
* higher priorities. Higher priority activity can prevent the system
|
||||
* fromentering reduced power states for a longer period of time.
|
||||
*
|
||||
* As an example, a button press might be higher priority activity because
|
||||
* it means that the user is actively interacting with the device.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function may be called from an interrupt handler (this is the ONLY
|
||||
* PM function that may be called from an interrupt handler!).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void pm_activity(int priority)
|
||||
{
|
||||
uint32_t now;
|
||||
uint32_t accum;
|
||||
irqstate_t flags;
|
||||
|
||||
/* Just increment the activity count in the current time slice. The priority
|
||||
* is simply the number of counts that are added.
|
||||
*/
|
||||
|
||||
if (priority > 0)
|
||||
{
|
||||
/* Add the priority to the accumulated counts in a critical section. */
|
||||
|
||||
flags = irqsave();
|
||||
accum = (uint32_t)g_pmglobals.accum + priority;
|
||||
|
||||
/* Make sure that we do not overflow the underlying uint16_t representation */
|
||||
|
||||
if (accum > UINT16_MAX)
|
||||
{
|
||||
accum = UINT16_MAX;
|
||||
}
|
||||
|
||||
/* Save the updated count */
|
||||
|
||||
g_pmglobals.accum = accum;
|
||||
|
||||
/* Check the elapsed time. In periods of low activity, time slicing is
|
||||
* controlled by IDLE loop polling; in periods of higher activity, time
|
||||
* slicing is controlled by driver activity. In either case, the duration
|
||||
* of the time slice is only approximate; during times of heavy activity,
|
||||
* time slices may be become longer and the activity level may be over-
|
||||
* estimated.
|
||||
*/
|
||||
|
||||
now = clock_systimer();
|
||||
if (now - g_pmglobals.stime >= TIME_SLICE_TICKS)
|
||||
{
|
||||
uint16_t tmp;
|
||||
|
||||
/* Sample the count, reset the time and count, and assess the PM
|
||||
* state. This is an atomic operation because interrupts are
|
||||
* still disabled.
|
||||
*/
|
||||
|
||||
tmp = g_pmglobals.accum;
|
||||
g_pmglobals.stime = now;
|
||||
g_pmglobals.accum = 0;
|
||||
|
||||
/* Reassessing the PM state may require some computation. However,
|
||||
* the work will actually be performed on a worker thread at a user-
|
||||
* controlled priority.
|
||||
*/
|
||||
|
||||
(void)pm_update(accum);
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
223
drivers/pm/pm_changestate.c
Normal file
223
drivers/pm/pm_changestate.c
Normal file
@ -0,0 +1,223 @@
|
||||
/****************************************************************************
|
||||
* drivers/pm/pm_changestate.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/pm.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include "pm_internal.h"
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_prepall
|
||||
*
|
||||
* Description:
|
||||
* Prepare every driver for the state change.
|
||||
*
|
||||
* Input Parameters:
|
||||
* newstate - Idenfifies the new PM state
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 (OK) means that the callback function for all registered drivers
|
||||
* returned OK (meaning that they accept the state change). Non-zero
|
||||
* means that one of the drivers refused the state change. In this case,
|
||||
* the system will revert to the preceding state.
|
||||
*
|
||||
* Assumptions:
|
||||
* Interrupts are disabled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int pm_prepall(enum pm_state_e newstate)
|
||||
{
|
||||
FAR sq_entry_t *entry;
|
||||
int ret = OK;
|
||||
|
||||
/* Visit each registered callback structure. */
|
||||
|
||||
for (entry = sq_peek(&g_pmglobals.registry);
|
||||
entry && ret == OK;
|
||||
entry = sq_next(entry))
|
||||
{
|
||||
/* Is the prepare callback supported? */
|
||||
|
||||
FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry;
|
||||
if (cb->prepare)
|
||||
{
|
||||
/* Yes.. prepare the driver */
|
||||
|
||||
ret = cb->prepare(cb, newstate);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_changeall
|
||||
*
|
||||
* Description:
|
||||
* Inform all drivers of the state change.
|
||||
*
|
||||
* Input Parameters:
|
||||
* newstate - Idenfifies the new PM state
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* Interrupts are disabled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void pm_changeall(enum pm_state_e newstate)
|
||||
{
|
||||
FAR sq_entry_t *entry;
|
||||
|
||||
/* Visit each registered callback structure. */
|
||||
|
||||
for (entry = sq_peek(&g_pmglobals.registry); entry; entry = sq_next(entry))
|
||||
{
|
||||
/* Is the notification callback supported? */
|
||||
|
||||
FAR struct pm_callback_s *cb = (FAR struct pm_callback_s *)entry;
|
||||
if (cb->notify)
|
||||
{
|
||||
/* Yes.. notify the driver */
|
||||
|
||||
(void)cb->notify(cb, newstate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_changestate
|
||||
*
|
||||
* Description:
|
||||
* This function is used to platform-specific power managmeent logic. It
|
||||
* will announce the power management power management state change to all
|
||||
* drivers that have registered for power management event callbacks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* newstate - Idenfifies the new PM state
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 (OK) means that the callback function for all registered drivers
|
||||
* returned OK (meaning that they accept the state change). Non-zero
|
||||
* means that one of the drivers refused the state change. In this case,
|
||||
* the system will revert to the preceding state.
|
||||
*
|
||||
* Assumptions:
|
||||
* It is assumed that interrupts are disabled when this function is
|
||||
* called. This function is probably called from the IDLE loop... the
|
||||
* lowest priority task in the system. Changing driver power management
|
||||
* states may result in renewed system activity and, as a result, can
|
||||
* suspend the IDLE thread before it completes the entire state change
|
||||
* unless interrupts are disabled throughout the state change.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int pm_changestate(enum pm_state_e newstate)
|
||||
{
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
/* Disable interrupts throught this operation... changing driver states
|
||||
* could cause additional driver activity that might interfere with the
|
||||
* state change. When the state change is complete, interrupts will be
|
||||
* re-enabled.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
|
||||
/* First, prepare the drivers for the state change. In this phase,
|
||||
* drivers may refuse the state state change.
|
||||
*/
|
||||
|
||||
ret = pm_prepall(newstate);
|
||||
if (ret != OK)
|
||||
{
|
||||
/* One or more drivers is not ready for this state change. Revert to
|
||||
* the preceding state.
|
||||
*/
|
||||
|
||||
newstate = g_pmglobals.state;
|
||||
(void)pm_prepall(newstate);
|
||||
}
|
||||
|
||||
/* All drivers have agreed to the state change (or, one or more have
|
||||
* disagreed and the state has been reverted). Set the new state.
|
||||
*/
|
||||
|
||||
pm_changeall(newstate);
|
||||
g_pmglobals.state = newstate;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
161
drivers/pm/pm_checkstate.c
Normal file
161
drivers/pm/pm_checkstate.c
Normal file
@ -0,0 +1,161 @@
|
||||
/****************************************************************************
|
||||
* drivers/pm/pm_checkstate.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/pm.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include "pm_internal.h"
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_checkstate
|
||||
*
|
||||
* Description:
|
||||
* This function is called from the MCU-specific IDLE loop to monitor the
|
||||
* the power management conditions. This function returns the "recommended"
|
||||
* power management state based on the PM configuration and activity
|
||||
* reported in the last sampling periods. The power management state is
|
||||
* not automatically changed, however. The IDLE loop must call
|
||||
* pm_changestate() in order to make the state change.
|
||||
*
|
||||
* These two steps are separated because the plaform-specific IDLE loop may
|
||||
* have additional situational information that is not available to the
|
||||
* the PM sub-system. For example, the IDLE loop may know that the
|
||||
* battery charge level is very low and may force lower power states
|
||||
* even if there is activity.
|
||||
*
|
||||
* NOTE: That these two steps are separated in time and, hence, the IDLE
|
||||
* could be suspended for a long period of time between calling
|
||||
* pm_checkstate() and pm_changestate(). There it is recommended that
|
||||
* the IDLE loop make these calls atomic by either disabling interrupts
|
||||
* until the state change is completed.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* The recommended power management state.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
enum pm_state_e pm_checkstate(void)
|
||||
{
|
||||
uint32_t now;
|
||||
irqstate_t flags;
|
||||
|
||||
/* Check for the end of the current time slice. This must be performed
|
||||
* with interrupts disabled so that it does not conflict with the similar
|
||||
* logic in pm_activity().
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
|
||||
/* Check the elapsed time. In periods of low activity, time slicing is
|
||||
* controlled by IDLE loop polling; in periods of higher activity, time
|
||||
* slicing is controlled by driver activity. In either case, the duration
|
||||
* of the time slice is only approximate; during times of heavy activity,
|
||||
* time slices may be become longer and the activity level may be over-
|
||||
* estimated.
|
||||
*/
|
||||
|
||||
now = clock_systimer();
|
||||
if (now - g_pmglobals.stime >= TIME_SLICE_TICKS)
|
||||
{
|
||||
uint16_t accum;
|
||||
|
||||
/* Sample the count, reset the time and count, and assess the PM
|
||||
* state. This is an atomic operation because interrupts are
|
||||
* still disabled.
|
||||
*/
|
||||
|
||||
accum = g_pmglobals.accum;
|
||||
g_pmglobals.stime = now;
|
||||
g_pmglobals.accum = 0;
|
||||
|
||||
/* Reassessing the PM state may require some computation. However,
|
||||
* the work will actually be performed on a worker thread at a user-
|
||||
* controlled priority.
|
||||
*/
|
||||
|
||||
(void)pm_update(accum);
|
||||
}
|
||||
irqrestore(flags);
|
||||
|
||||
/* Return the recommended state. Assuming that we are called from the
|
||||
* IDLE thread at the lowest priority level, any updates scheduled on the
|
||||
* worker thread above should have already been peformed and the recommended
|
||||
* state should be current:
|
||||
*/
|
||||
|
||||
return g_pmglobals.recommended;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
112
drivers/pm/pm_initialize.c
Normal file
112
drivers/pm/pm_initialize.c
Normal file
@ -0,0 +1,112 @@
|
||||
/****************************************************************************
|
||||
* drivers/pm/pm_initialize.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <semaphore.h>
|
||||
|
||||
#include <nuttx/pm.h>
|
||||
|
||||
#include "pm_internal.h"
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/* All PM global data: */
|
||||
|
||||
struct pm_global_s g_pmglobals;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_initialize
|
||||
*
|
||||
* Description:
|
||||
* This function is called by MCU-specific one-time at power on reset in
|
||||
* order to initialize the power management capabilities. This function
|
||||
* must be called *very* early in the intialization sequence *before* any
|
||||
* other device drivers are initialize (since they may attempt to register
|
||||
* with the power management subsystem).
|
||||
*
|
||||
* Input parameters:
|
||||
* None.
|
||||
*
|
||||
* Returned value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void pm_initialize(void)
|
||||
{
|
||||
/* Initialize the registry and the PM global data structures. The PM
|
||||
* global data structure resides in .bss which is zeroed at boot time. So
|
||||
* it is only required to initialize non-zero elements of the PM global
|
||||
* data structure here.
|
||||
*/
|
||||
|
||||
sq_init(&g_pmglobals.registry);
|
||||
sem_init(&g_pmglobals.regsem, 0, 1);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
210
drivers/pm/pm_internal.h
Normal file
210
drivers/pm/pm_internal.h
Normal file
@ -0,0 +1,210 @@
|
||||
/****************************************************************************
|
||||
* drivers/pm/pm_internal.h
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __DRIVERS_PM_PM_INTERNAL_H
|
||||
#define __DRIVERS_PM_PM_INTERNAL_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <semaphore.h>
|
||||
#include <queue.h>
|
||||
|
||||
#include <nuttx/pm.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#ifndef CONFIG_SCHED_WORKQUEUE
|
||||
# warning "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)"
|
||||
#endif
|
||||
|
||||
/* Convert the time slice interval into system clock ticks.
|
||||
*
|
||||
* CONFIG_PM_SLICEMS provides the duration of one time slice in milliseconds.
|
||||
* CLOCKS_PER_SEC provides the number of timer ticks in one second.
|
||||
*
|
||||
* slice ticks = (CONFIG_PM_SLICEMS msec / 1000 msec/sec) /
|
||||
* (CLOCKS_PER_SEC ticks/sec)
|
||||
*/
|
||||
|
||||
#define TIME_SLICE_TICKS ((CONFIG_PM_SLICEMS * CLOCKS_PER_SEC) / 1000)
|
||||
|
||||
/* Function-like macros *****************************************************/
|
||||
/****************************************************************************
|
||||
* Name: pm_lock
|
||||
*
|
||||
* Descripton:
|
||||
* Lock the power management registry. NOTE: This function may return
|
||||
* an error if a signal is received while what (errno == EINTR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define pm_lock() sem_wait(&g_pmglobals.regsem);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_unlock
|
||||
*
|
||||
* Descripton:
|
||||
* Unlock the power management registry.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define pm_unlock() sem_post(&g_pmglobals.regsem);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
/* This structure encapsulates all of the global data used by the PM module */
|
||||
|
||||
struct pm_global_s
|
||||
{
|
||||
/* state - The current state (as determined by an explicit call to
|
||||
* pm_changestate()
|
||||
* recommended - The recommended state based on the PM algorithm in
|
||||
* function pm_update().
|
||||
* mndex - The index to the next slot in the memory[] arry to use.
|
||||
* mcnt - A tiny counter used only at start up. The actual
|
||||
* algorithm cannot be applied until CONFIG_PM_MEMORY
|
||||
* samples have been collected.
|
||||
*/
|
||||
|
||||
uint8_t state;
|
||||
uint8_t recommended;
|
||||
uint8_t mndx;
|
||||
uint8_t mcnt;
|
||||
|
||||
/* accum - The accumulated counts in this time interval
|
||||
* thrcnt - The number of below threshold counts seen.
|
||||
*/
|
||||
|
||||
uint16_t accum;
|
||||
uint16_t thrcnt;
|
||||
|
||||
/* This is the averaging "memory." The averaging algorithm is simply:
|
||||
* Y = (An*X + SUM(Ai*Yi))/SUM(Aj), where i = 1..n-1 and j= 1..n, n is the
|
||||
* length of the "memory", Ai is the weight applied to each value, and X is
|
||||
* the current activity.
|
||||
*
|
||||
* CONFIG_PM_MEMORY provides the memory for the algorithm. Default: 2
|
||||
* CONFIG_PM_COEFn provides weight for each sample. Default: 1
|
||||
*/
|
||||
|
||||
#if CONFIG_PM_MEMORY > 1
|
||||
uint16_t memory[CONFIG_PM_MEMORY-1];
|
||||
#endif
|
||||
|
||||
/* stime - The time (in ticks) at the start of the current time slice */
|
||||
|
||||
uint32_t stime;
|
||||
|
||||
/* This semaphore manages mutually exclusive access to the power management
|
||||
* registry. It must be initialized to the value 1.
|
||||
*/
|
||||
|
||||
sem_t regsem;
|
||||
|
||||
/* For work that has been deferred to the worker thread */
|
||||
|
||||
struct work_s work;
|
||||
|
||||
/* registry is a singly-linked list of registered power management
|
||||
* callback structures. To ensure mutually exclusive access, this list
|
||||
* must be locked by calling pm_lock() before it is accessed.
|
||||
*/
|
||||
|
||||
sq_queue_t registry;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
# define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
# define EXTERN extern
|
||||
#endif
|
||||
|
||||
/* All PM global data: */
|
||||
|
||||
EXTERN struct pm_global_s g_pmglobals;
|
||||
|
||||
/************************************************************************************
|
||||
* Public Function Prototypes
|
||||
************************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_update
|
||||
*
|
||||
* Description:
|
||||
* This internal function is called at the end of a time slice in order to
|
||||
* update driver activity metrics and recommended states.
|
||||
*
|
||||
* Input Parameters:
|
||||
* accum - The value of the activity accumulator at the end of the time
|
||||
* slice.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function may be called from a driver, perhaps even at the interrupt
|
||||
* level. It may also be called from the IDLE loop at the lowest possible
|
||||
* priority level. To reconcile these various conditions, all work is
|
||||
* performed on the worker thread at a user-selectable priority.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void pm_update(uint16_t accum);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
#endif /* #define __DRIVERS_PM_PM_INTERNAL_H */
|
112
drivers/pm/pm_register.c
Normal file
112
drivers/pm/pm_register.c
Normal file
@ -0,0 +1,112 @@
|
||||
/****************************************************************************
|
||||
* drivers/pm/pm_register.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <queue.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/pm.h>
|
||||
|
||||
#include "pm_internal.h"
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_register
|
||||
*
|
||||
* Description:
|
||||
* This function is called by a device driver in order to register to
|
||||
* receive power management event callbacks.
|
||||
*
|
||||
* Input parameters:
|
||||
* callbacks - An instance of struct pm_callback_s providing the driver
|
||||
* callback functions.
|
||||
*
|
||||
* Returned value:
|
||||
* Zero (OK) on success; otherwise a negater errno value is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int pm_register(FAR struct pm_callback_s *callbacks)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(callbacks);
|
||||
|
||||
/* Add the new entry to the end of the list of registered callbacks */
|
||||
|
||||
ret = pm_lock();
|
||||
if (ret == OK)
|
||||
{
|
||||
sq_addlast(&callbacks->entry, &g_pmglobals.registry);
|
||||
pm_unlock();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
287
drivers/pm/pm_update.c
Normal file
287
drivers/pm/pm_update.c
Normal file
@ -0,0 +1,287 @@
|
||||
/****************************************************************************
|
||||
* drivers/pm/pm_update.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/pm.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
|
||||
#include "pm_internal.h"
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
/* CONFIG_PM_MEMORY is the total number of time slices (including the current
|
||||
* time slice. The histor or previous values is then CONFIG_PM_MEMORY-1.
|
||||
*/
|
||||
|
||||
#if CONFIG_PM_MEMORY > 1
|
||||
static const uint16_t g_pmcoeffs[CONFIG_PM_MEMORY-1] =
|
||||
{
|
||||
CONFIG_PM_COEF1
|
||||
#if CONFIG_PM_MEMORY > 2
|
||||
, CONFIG_PM_COEF2
|
||||
#endif
|
||||
#if CONFIG_PM_MEMORY > 3
|
||||
, CONFIG_PM_COEF3
|
||||
#endif
|
||||
#if CONFIG_PM_MEMORY > 4
|
||||
, CONFIG_PM_COEF4
|
||||
#endif
|
||||
#if CONFIG_PM_MEMORY > 5
|
||||
, CONFIG_PM_COEF5
|
||||
#endif
|
||||
#if CONFIG_PM_MEMORY > 6
|
||||
# warning "This logic needs to be extended"
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
static const uint16_t g_pmthresh[3] =
|
||||
{
|
||||
CONFIG_PM_IDLEENTER_THRESH,
|
||||
CONFIG_PM_STANDBYENTER_THRESH,
|
||||
CONFIG_PM_SLEEPENTER_THRESH
|
||||
};
|
||||
|
||||
static const uint16_t g_pmcount[3] =
|
||||
{
|
||||
CONFIG_PM_IDLEENTER_COUNT,
|
||||
CONFIG_PM_STANDBYENTER_COUNT,
|
||||
CONFIG_PM_SLEEPENTER_COUNT
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_worker
|
||||
*
|
||||
* Description:
|
||||
* This worker function is queue at the end of a time slice in order to
|
||||
* update driver activity metrics and recommended states.
|
||||
*
|
||||
* Input Parameters:
|
||||
* arg - The value of the activity accumulator at the end of the time
|
||||
* slice.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function runs on the worker thread.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void pm_worker(FAR void *arg)
|
||||
{
|
||||
uint16_t accum = (uint16_t)((uintptr_t)arg);
|
||||
uint32_t Y;
|
||||
|
||||
#if CONFIG_PM_MEMORY > 1
|
||||
uint32_t denom;
|
||||
int i, j;
|
||||
|
||||
/* We won't bother to do anything until we have accumulated
|
||||
* CONFIG_PM_MEMORY-1 samples.
|
||||
*/
|
||||
|
||||
if (g_pmglobals.mcnt < CONFIG_PM_MEMORY-1)
|
||||
{
|
||||
g_pmglobals.memory[g_pmglobals.mcnt] = accum;
|
||||
g_pmglobals.mcnt++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* The averaging algorithm is simply: Y = (An*X + SUM(Ai*Yi))/SUM(Aj), where
|
||||
* i = 1..n-1 and j= 1..n, n is the length of the "memory", Ai is the
|
||||
* weight applied to each value, and X is the current activity.
|
||||
*
|
||||
* CONFIG_PM_MEMORY provides the memory for the algorithm. Default: 2
|
||||
* CONFIG_PM_COEFn provides weight for each sample. Default: 1
|
||||
*
|
||||
* First, calclate Y = An*X
|
||||
*/
|
||||
|
||||
Y = CONFIG_PM_COEFN * accum;
|
||||
denom = CONFIG_PM_COEFN;
|
||||
|
||||
/* Then calculate Y += SUM(Ai*Yi), i = 1..n-1. The oldest sample will
|
||||
* reside at g_pmglobals.mndx (and this is the value that we will overwrite
|
||||
* with the new value).
|
||||
*/
|
||||
|
||||
for (i = 0, j = g_pmglobals.mndx; i < CONFIG_PM_MEMORY-1; i++, j++)
|
||||
{
|
||||
if (j >= CONFIG_PM_MEMORY-1)
|
||||
{
|
||||
j = 0;
|
||||
}
|
||||
|
||||
Y += g_pmcoeffs[i] * g_pmglobals.memory[j];
|
||||
denom += g_pmcoeffs[i];
|
||||
}
|
||||
|
||||
/* Compute and save the new activity value */
|
||||
|
||||
Y /= denom;
|
||||
g_pmglobals.memory[g_pmglobals.mndx] = Y;
|
||||
g_pmglobals.mndx++;
|
||||
if (g_pmglobals.mndx >= CONFIG_PM_MEMORY-1)
|
||||
{
|
||||
g_pmglobals.mndx = 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* No smoothing */
|
||||
|
||||
Y = accum;
|
||||
|
||||
#endif
|
||||
|
||||
/* Now, compare this new activity level to the thresholds and counts for
|
||||
* the next state. Determine if it is appropriate to switch to a new,
|
||||
* lower power consumption state.
|
||||
*
|
||||
* If we are already in the SLEEP state, then there is nothing more to be
|
||||
* done (in fact, I would be surprised to be executing!).
|
||||
*/
|
||||
|
||||
if (g_pmglobals.state < PM_SLEEP)
|
||||
{
|
||||
unsigned int nextstate;
|
||||
int index;
|
||||
|
||||
/* Get the next state and the table index for the next state (which will
|
||||
* be the current state)
|
||||
*/
|
||||
|
||||
index = g_pmglobals.state;
|
||||
nextstate = g_pmglobals.state + 1;
|
||||
|
||||
/* Has the threshold for the next state been exceeded? */
|
||||
|
||||
if (Y > g_pmthresh[index])
|
||||
{
|
||||
/* No... reset the count and recommend the current state */
|
||||
|
||||
g_pmglobals.thrcnt = 0;
|
||||
g_pmglobals.recommended = g_pmglobals.state;
|
||||
}
|
||||
|
||||
/* Yes.. have we already recommended this state? If so, do nothing */
|
||||
|
||||
else if (g_pmglobals.recommended < nextstate)
|
||||
{
|
||||
/* No.. increment the count. Has is passed the the count required
|
||||
* for a state transition?
|
||||
*/
|
||||
|
||||
if (++g_pmglobals.thrcnt >= g_pmcount[index])
|
||||
{
|
||||
/* Yes, recommend the new state and set up for the next
|
||||
* transition.
|
||||
*/
|
||||
|
||||
g_pmglobals.thrcnt = 0;
|
||||
g_pmglobals.recommended = nextstate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_update
|
||||
*
|
||||
* Description:
|
||||
* This internal function is called at the end of a time slice in order to
|
||||
* update driver activity metrics and recommended states.
|
||||
*
|
||||
* Input Parameters:
|
||||
* accum - The value of the activity accumulator at the end of the time
|
||||
* slice.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function may be called from a driver, perhaps even at the interrupt
|
||||
* level. It may also be called from the IDLE loop at the lowest possible
|
||||
* priority level. To reconcile these various conditions, all work is
|
||||
* performed on the worker thread at a user-selectable priority. This will
|
||||
* also serialize all of the updates and eliminate any need for additional
|
||||
* protection.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void pm_update(uint16_t accum)
|
||||
{
|
||||
/* The work will be performed on the worker thread */
|
||||
|
||||
DEBUGASSERT(g_pmglobals.work.worker == NULL);
|
||||
(void)work_queue(&g_pmglobals.work, pm_worker, (FAR void*)((uintptr_t)accum), 0);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
@ -37,22 +37,28 @@
|
||||
* have various names and are sometimes used in conflicting ways. In the
|
||||
* PM logic, we will use the following terminology:
|
||||
*
|
||||
* NORMAL - The normal, full power operating mode.
|
||||
* REDUCED - This is still basically normal operational mode, but with some
|
||||
* simple changes to reduce power consumption. Perhaps this just
|
||||
* means just dimming the backlight.
|
||||
* STANDBY - Standby is a very low power consumption mode. It is the lowest
|
||||
* power from which the system can recover quickly.
|
||||
* SLEEP - The lowest power consumption mode. It may require some time
|
||||
* to get back to normal operation from SLEEP (some parts may
|
||||
* even require going through reset).
|
||||
* NORMAL - The normal, full power operating mode.
|
||||
* IDLE - This is still basically normal operational mode, the system is,
|
||||
* however, IDLE and some simple simple steps to reduce power
|
||||
* consumption provided that they do not interfere with normal
|
||||
* Operation. Simply dimming the a backlight might be an example
|
||||
* somethat that would be done when the system is idle.
|
||||
* STANDBY - Standby is a lower power consumption mode that may involve more
|
||||
* extensive power management steps such has disabling clocking or
|
||||
* setting the processor into reduced power consumption modes. In
|
||||
* this state, the system should still be able to resume normal
|
||||
* activity almost immediately.
|
||||
* SLEEP - The lowest power consumption mode. The most drastic power
|
||||
* reduction measures possible should be taken in this state. It
|
||||
* may require some time to get back to normal operation from
|
||||
* SLEEP (some MCUs may even require going through reset).
|
||||
*
|
||||
* State changes always proceed from higher to lower power usage:
|
||||
*
|
||||
* NORMAL->REDUCED->STANDBY->SLEEP
|
||||
* ^ | | |
|
||||
* | V V V
|
||||
* +-------+---------+--------+
|
||||
* NORMAL->IDLE->STANDBY->SLEEP
|
||||
* ^ | | |
|
||||
* | V V V
|
||||
* +-------+------+--------+
|
||||
*/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_PM_H
|
||||
@ -64,28 +70,112 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <queue.h>
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-Processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* Time slices */
|
||||
/* Time slices. The power management module collects activity counts in
|
||||
* time slices. At the end of the time slice, the count accumulated during
|
||||
* that interval is applied to an averaging algorithm to determine the
|
||||
* activity level.
|
||||
*
|
||||
* CONFIG_PM_SLICEMS provides the duration of that time slice. Default: 100
|
||||
* Milliseconds
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_PM_SLICEMS
|
||||
# define CONFIG_PM_SLICEMS 100 /* Default is 100 msec */
|
||||
# define CONFIG_PM_SLICEMS 100 /* Default is 100 msec */
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PM_NREDUCED
|
||||
# define CONFIG_PM_NREDUCED 30 /* Thiry IDLE slices to enter reduced mode */
|
||||
/* The averaging algorithm is simply: Y = (An*X + SUM(Ai*Yi))/SUM(Aj), where
|
||||
* i = 1..n-1 and j= 1..n, n is the length of the "memory", Ai is the
|
||||
* weight applied to each value, and X is the current activity.
|
||||
*
|
||||
* CONFIG_PM_MEMORY provides the memory for the algorithm. Default: 2
|
||||
* CONFIG_PM_COEFn provides weight for each sample. Default: 1
|
||||
*
|
||||
* Setting CONFIG_PM_MEMORY=1 disables all smoothing.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_PM_MEMORY
|
||||
# define CONFIG_PM_MEMORY 2
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PM_NSTANDBY
|
||||
# define CONFIG_PM_NSTANDBY 80 /* Eight IDLE slices to enter standby mode */
|
||||
#ifndef CONFIG_PM_MEMORY < 1
|
||||
# error "CONFIG_PM_MEMORY must be >= 1"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PM_NSLEEP
|
||||
# define CONFIG_PM_NSLEEP 150 /* 150 IDLE slices to enter standby mode */
|
||||
#ifndef CONFIG_PM_COEFN
|
||||
# define CONFIG_PM_COEFN 1
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_MEMORY > 1 && !defined(CONFIG_PM_COEF1)
|
||||
# define CONFIG_PM_COEF1 1
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_MEMORY > 2 && !defined(CONFIG_PM_COEF2)
|
||||
# define CONFIG_PM_COEF2 1
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_MEMORY > 3 && !defined(CONFIG_PM_COEF3)
|
||||
# define CONFIG_PM_COEF3 1
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_MEMORY > 4 && !defined(CONFIG_PM_COEF4)
|
||||
# define CONFIG_PM_COEF4 1
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_MEMORY > 5 && !defined(CONFIG_PM_COEF5)
|
||||
# define CONFIG_PM_COEF5 1
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_MEMORY > 6
|
||||
# warning "This logic needs to be extended"
|
||||
#endif
|
||||
|
||||
/* State changes then occur when the weight activity account crosses
|
||||
* threshold values for certain periods of time (time slice count).
|
||||
*
|
||||
* CONFIG_PM_xxxENTER_THRESH is the threshold value for entering state xxx.
|
||||
* CONFIG_PM_xxxENTER_COUNT is the count for entering state xxx.
|
||||
*
|
||||
* Resuming to normal state, on the other hand, is usually immediate and
|
||||
* controlled by wakeup conditions established by the platform. The PM
|
||||
* module only recommends reduced power states.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_PM_IDLEENTER_THRESH
|
||||
# define CONFIG_PM_IDLEENTER_THRESH 1 /* Essentially no activity */
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PM_IDLEENTER_COUNT
|
||||
# define CONFIG_PM_IDLEENTER_COUNT 30 /* Thirty IDLE slices to enter
|
||||
* IDLE mode from normal
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PM_STANDBYENTER_THRESH
|
||||
# define CONFIG_PM_STANDBYENTER_THRESH 1 /* Essentially no activity */
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PM_STANDBYENTER_COUNT
|
||||
# define CONFIG_PM_STANDBYENTER_COUNT 50 /* Fifty IDLE slices to enter
|
||||
* STANDBY mode from IDLE
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PM_SLEEPENTER_THRESH
|
||||
# define CONFIG_PM_SLEEPENTER_THRESH 1 /* Essentially no activity */
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PM_SLEEPENTER_COUNT
|
||||
# define CONFIG_PM_SLEEPENTER_COUNT 70 /* 70 IDLE slices to enter SLEEP
|
||||
* mode from STANDBY
|
||||
*/
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@ -98,30 +188,38 @@
|
||||
|
||||
enum pm_state_e
|
||||
{
|
||||
PM_REDUCED = 0, /* Drivers will receive periodic this indications if it is
|
||||
* appropriate to enter a simple reduced power state. This
|
||||
* would include simple things such as displaying display back-
|
||||
* lighting. The driver should essentially be ready to resume
|
||||
* normal activity instantly.
|
||||
PM_NORMAL = 0, /* Normal full power operating mode. If the driver is in
|
||||
* a reduced power usage mode, it should immediately re-
|
||||
* initialize for normal operatin.
|
||||
*
|
||||
* PM_REDUCED may be followed by PM_STANDBY or PM_RESUME.
|
||||
* PM_NORMAL may be followed by PM_IDLE.
|
||||
*/
|
||||
PM_STANDBY, /* The system is entering standby mode. The driver should
|
||||
* already be prepared for this mode.
|
||||
PM_IDLE, /* Drivers will receive this state change if it is
|
||||
* appropriate to enter a simple IDLE power state. This
|
||||
* would include simple things such as reducing display back-
|
||||
* lighting. The driver should be ready to resume normal
|
||||
* activity instantly.
|
||||
*
|
||||
* PM_STANDBY may be followed PM_SLEEP or by PM_RESUME
|
||||
* PM_IDLE may be followed by PM_STANDBY or PM_NORMAL.
|
||||
*/
|
||||
PM_SLEEP, /* The system is entering deep sleep mode. The driver should
|
||||
* already be prepared for this mode.
|
||||
PM_STANDBY, /* The system is entering standby mode. Standby is a lower
|
||||
* power consumption mode that may involve more extensive
|
||||
* power management steps such has disabling clocking or
|
||||
* setting the processor into reduced power consumption
|
||||
* modes. In this state, the system should still be able
|
||||
* to resume normal activity almost immediately.
|
||||
*
|
||||
* PM_SLEEP may be following by PM_RESUME
|
||||
* PM_STANDBY may be followed PM_SLEEP or by PM_NORMAL
|
||||
*/
|
||||
PM_RESUME, /* The system is resuming normal operation. The driver should
|
||||
* reinitialize for normal operation.
|
||||
PM_SLEEP, /* The system is entering deep sleep mode. The most drastic
|
||||
* power reduction measures possible should be taken in this
|
||||
* state. It may require some time to get back to normal
|
||||
* operation from SLEEP (some MCUs may even require going
|
||||
* through reset).
|
||||
*
|
||||
* PM_RESUME may be followed by PM_REDUCED.
|
||||
* PM_SLEEP may be following by PM_NORMAL
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
/* This structure contain pointers callback functions in the driver. These
|
||||
* callback functions can be used to provide power management information
|
||||
@ -130,7 +228,7 @@ enum pm_state_e
|
||||
|
||||
struct pm_callback_s
|
||||
{
|
||||
struct pm_callback_s *flink; /* Supports a singly linked list */
|
||||
struct sq_entry_s entry; /* Supports a singly linked list */
|
||||
|
||||
/**************************************************************************
|
||||
* Name: prepare
|
||||
@ -173,12 +271,14 @@ struct pm_callback_s
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 (OK) means the event was successfully processed. Non-zero means
|
||||
* means that the driver failed to enter the power mode.
|
||||
* means that the driver failed to enter the lower power consumption
|
||||
* mode. Drivers are not permitted to return non-zero values when
|
||||
* reverting to higher power consumption modes!
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
int (*notify)(FAR struct pm_callback_s *cb, enum pm_state_e pmstate);
|
||||
}
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
@ -196,6 +296,26 @@ extern "C" {
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
* Name: pm_initialize
|
||||
*
|
||||
* Description:
|
||||
* This function is called by MCU-specific one-time at power on reset in
|
||||
* order to initialize the power management capabilities. This function
|
||||
* must be called *very* early in the intialization sequence *before* any
|
||||
* other device drivers are initialize (since they may attempt to register
|
||||
* with the power management subsystem).
|
||||
*
|
||||
* Input parameters:
|
||||
* None.
|
||||
*
|
||||
* Returned value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void pm_initialize(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_register
|
||||
*
|
||||
@ -214,6 +334,67 @@ extern "C" {
|
||||
|
||||
EXTERN int pm_register(FAR struct pm_callback_s *callbacks);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_activity
|
||||
*
|
||||
* Description:
|
||||
* This function is called by a device driver to indicate that it is
|
||||
* performing meaningful activities (non-idle). This increment an activty
|
||||
* cound and/or will restart a idle timer and prevent entering IDLE
|
||||
* power states.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priority - activity priority, range 0-9. Larger values correspond to
|
||||
* higher priorities. Higher priority activity can prevent the system
|
||||
* fromentering reduced power states for a longer period of time.
|
||||
*
|
||||
* As an example, a button press might be higher priority activity because
|
||||
* it means that the user is actively interacting with the device.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function may be called from an interrupt handler (this is the ONLY
|
||||
* PM function that may be called from an interrupt handler!).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void pm_activity(int priority);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_checkstate
|
||||
*
|
||||
* Description:
|
||||
* This function is called from the MCU-specific IDLE loop to monitor the
|
||||
* the power management conditions. This function returns the "recommended"
|
||||
* power management state based on the PM configuration and activity
|
||||
* reported in the last sampling periods. The power management state is
|
||||
* not automatically changed, however. The IDLE loop must call
|
||||
* pm_changestate() in order to make the state change.
|
||||
*
|
||||
* These two steps are separated because the plaform-specific IDLE loop may
|
||||
* have additional situational information that is not available to the
|
||||
* the PM sub-system. For example, the IDLE loop may know that the
|
||||
* battery charge level is very low and may force lower power states
|
||||
* even if there is activity.
|
||||
*
|
||||
* NOTE: That these two steps are separated in time and, hence, the IDLE
|
||||
* could be suspended for a long period of time between calling
|
||||
* pm_checkstate() and pm_changestate(). There it is recommended that
|
||||
* the IDLE loop make these calls atomic by either disabling interrupts
|
||||
* until the state change is completed.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* The recommended power management state.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN enum pm_state_e pm_checkstate(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_changestate
|
||||
*
|
||||
@ -223,52 +404,25 @@ EXTERN int pm_register(FAR struct pm_callback_s *callbacks);
|
||||
* drivers that have registered for power management event callbacks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* pmstate - Idenfifies the new PM state
|
||||
* newstate - Idenfifies the new PM state
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 (OK) means that the callback function for all registered drivers
|
||||
* returned OK (meaning that they accept the state change).
|
||||
* returned OK (meaning that they accept the state change). Non-zero
|
||||
* means that one of the drivers refused the state change. In this case,
|
||||
* the system will revert to the preceding state.
|
||||
*
|
||||
* Assumptions:
|
||||
* It is assumed that interrupts are disabled when this function is
|
||||
* called. This function is probably called from the IDLE loop... the
|
||||
* lowest priority task in the system. Changing driver power management
|
||||
* states may result in renewed system activity and, as a result, can
|
||||
* suspend the IDLE thread before it completes the entire state change
|
||||
* unless interrupts are disabled throughout the state change.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN int pm_changestate(enum pm_event_s pmstate);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_activity
|
||||
*
|
||||
* Description:
|
||||
* This function is called by a device driver to indicate that it is
|
||||
* performing meaningful activities (non-idle). This increment an activty
|
||||
* cound and/or will restart a idle timer and prevent entering reduced
|
||||
* power states.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* The current activity count.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN int pm_activity(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pm_checkactivity
|
||||
*
|
||||
* Description:
|
||||
* Return the activity count accumulated since the last time this function
|
||||
* was called. A count of zero will indicate that no meaningful activity
|
||||
* occurred since the last time this function was called.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* The current activity count.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN int pm_checkactivity(void);
|
||||
EXTERN int pm_changestate(enum pm_state_e newstate);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
|
Loading…
x
Reference in New Issue
Block a user