9
0
Fork 0
nuttx-bb/nuttx/include/nuttx/pm.h

480 lines
18 KiB
C

/****************************************************************************
* include/nuttx/pm.h
* NuttX Power Management Interfaces
*
* 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.
*
****************************************************************************/
/* Definition of terms. Various "sleep" and low power consumption states
* 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.
* 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->IDLE->STANDBY->SLEEP
* ^ | | |
* | V V V
* +-------+------+--------+
*/
#ifndef __INCLUDE_NUTTX_PM_H
#define __INCLUDE_NUTTX_PM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <queue.h>
#ifdef CONFIG_PM
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* 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 */
#endif
/* 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. These weights
* may be negative and a limited to the range of int16_t.
*
* 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_MEMORY < 1
# error "CONFIG_PM_MEMORY must be >= 1"
#endif
#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 /* <=1: Essentially no activity */
#endif
#ifndef CONFIG_PM_IDLEEXIT_THRESH
# define CONFIG_PM_IDLEEXIT_THRESH 2 /* >=2: Active */
#endif
#if CONFIG_PM_IDLEENTER_THRESH >= CONFIG_PM_IDLEEXIT_THRESH
# error "Must have CONFIG_PM_IDLEENTER_THRESH < CONFIG_PM_IDLEEXIT_THRESH
#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 /* <=1: Essentially no activity */
#endif
#ifndef CONFIG_PM_STANDBYEXIT_THRESH
# define CONFIG_PM_STANDBYEXIT_THRESH 2 /* >=2: Active */
#endif
#if CONFIG_PM_STANDBYENTER_THRESH >= CONFIG_PM_STANDBYEXIT_THRESH
# error "Must have CONFIG_PM_STANDBYENTER_THRESH < CONFIG_PM_STANDBYEXIT_THRESH
#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 /* <=1: Essentially no activity */
#endif
#ifndef CONFIG_PM_SLEEPEXIT_THRESH
# define CONFIG_PM_SLEEPEXIT_THRESH 2 /* >=2: Active */
#endif
#if CONFIG_PM_SLEEPENTER_THRESH >= CONFIG_PM_SLEEPEXIT_THRESH
# error "Must have CONFIG_PM_SLEEPENTER_THRESH < CONFIG_PM_SLEEPEXIT_THRESH
#endif
#ifndef CONFIG_PM_SLEEPENTER_COUNT
# define CONFIG_PM_SLEEPENTER_COUNT 70 /* 70 IDLE slices to enter SLEEP
* mode from STANDBY
*/
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/* This enumeration provides all power management states. Receipt of the
* state indication is the state transition event.
*/
enum pm_state_e
{
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_NORMAL may be followed by PM_IDLE.
*/
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_IDLE may be followed by PM_STANDBY or PM_NORMAL.
*/
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_STANDBY may be followed PM_SLEEP or by PM_NORMAL
*/
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_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
* to the driver.
*/
struct pm_callback_s
{
struct sq_entry_s entry; /* Supports a singly linked list */
/**************************************************************************
* Name: prepare
*
* Description:
* Request the driver to prepare for a new power state. This is a
* warning that the system is about to enter into a new power state. The
* driver should begin whatever operations that may be required to enter
* power state. The driver may abort the state change mode by returning
* a non-zero value from the callback function
*
* Input Parameters:
* cb - Returned to the driver. The driver version of the callback
* strucure may include additional, driver-specific state
* data at the end of the structure.
* pmstate - Identifies the new PM state
*
* Returned Value:
* 0 (OK) means the event was successfully processed and that the driver
* is prepared for the PM state change. Non-zero means that the driver
* is not prepared to perform the tasks needed achieve this power setting
* and will cause the state change to be aborted. NOTE: The prepare
* method will also be recalled when reverting from lower back to higher
* power consumption modes (say because another driver refused a lower
* power state change). Drivers are not permitted to return non-zero
* values when reverting back to higher power consumption modes!
*
**************************************************************************/
int (*prepare)(FAR struct pm_callback_s *cb, enum pm_state_e pmstate);
/**************************************************************************
* Name: notify
*
* Description:
* Notify the driver of new power state. This callback is called after
* all drivers have had the opportunity to prepare for the new power
* state.
*
* Input Parameters:
* cb - Returned to the driver. The driver version of the callback
* strucure may include additional, driver-specific state
* data at the end of the structure.
* pmstate - Identifies the new PM state
*
* Returned Value:
* None. The driver already agreed to transition to the low power
* consumption state when when it returned OK to the prepare() call.
*
**************************************************************************/
int (*notify)(FAR struct pm_callback_s *cb, enum pm_state_e pmstate);
};
/****************************************************************************
* Public Data
****************************************************************************/
#ifndef __ASSEMBLY__
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C" {
#else
#define EXTERN extern
#endif
/****************************************************************************
* 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
*
* 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.
*
****************************************************************************/
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
* count and/or will restart a idle timer and prevent entering reduced
* power states.
*
* Input Parameters:
* priority - Activity priority, range 0-9. Larger values correspond to
* higher priorities. Higher priority activity can prevent the system
* from entering 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
* loop could be suspended for a long period of time between calling
* pm_checkstate() and pm_changestate(). The IDLE loop may need to 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
*
* 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 - Identifies 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.
*
****************************************************************************/
EXTERN int pm_changestate(enum pm_state_e newstate);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
/****************************************************************************
* Stubs
****************************************************************************/
#else /* CONFIG_PM */
/* Stubbed out versions of all of PM interface functions that may be used to
* avoid so much conditional compilation in driver code when PM is disabled:
*/
# define pm_initialize()
# define pm_register(cb) (0)
# define pm_activity(prio)
# define pm_checkstate() (0)
# define pm_changestate(state)
#endif /* CONFIG_PM */
#endif /* __INCLUDE_NUTTX_PM_H */