OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/rtos/ecos-2.0/packages/services/power
    from Rev 27 to Rev 174
    Reverse comparison

Rev 27 → Rev 174

/common/v2_0/cdl/power.cdl
0,0 → 1,167
# ====================================================================
#
# power.cdl
#
# Generic power management support
#
# ====================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): bartv
# Original data: bartv
# Contributors:
# Date: 2001-06-12
#
#####DESCRIPTIONEND####
#
# ====================================================================
 
cdl_package CYGPKG_POWER {
display "Generic power management support"
doc ref/services-power.html
parent CYGPKG_IO
include_dir "cyg/power"
compile power.cxx
compile -library=libextras.a power_data.cxx
cdl_option CYGIMP_POWER_PROVIDE_STRINGS {
display "Provide a string for every power controller"
doc ref/power-info.html#POWER-MANAGEMENT-INFO_IDS
default_value 1
description "
Optionally each power controller can contain a string identifying
the hardware or functionality it is associated with. This string
is not required by the generic power management, but may be
useful when presenting the current state of each controller to
the user.
"
}
 
cdl_option CYGIMP_POWER_PROVIDE_POLICY_DATA {
display "Reserve space in each power controller for use by the policy manager"
doc ref/power-policy.html#POWER-POLICY-DATA
default_value 1
description "
Optionally each power controller can provide a word of data
for use by the policy manager, for example to store a pointer
to some data structure controlled by the policy manager. If
the policy manager has no need for such additional data this
option can be safely disabled, saving a small amount of memory.
"
}
cdl_component CYGPKG_POWER_THREAD {
display "Run a separate thread within the power management package"
doc ref/power-intro.html#POWER-INTRO-OPERATION
active_if CYGPKG_KERNEL
default_value 1
description "
Optionally the power management code can run in its own thread. This
can be useful if state changes can be requested from any code,
including DSRs. If on the other hand the power management policy code
runs in its own thread and is the only part of the system that
makes power management calls, a separate thread is redundant.
"
 
cdl_option CYGNUM_POWER_THREAD_STACKSIZE {
display "Stack size for the power management thread"
default_value { is_loaded(CYGNUM_LIBC_MAIN_DEFAULT_STACK_SIZE) ? CYGNUM_LIBC_MAIN_DEFAULT_STACK_SIZE :
(2 * CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE) }
flavor data
description "
If a separate power management thread is being used then this
option allows the stack size to be controlled. If any power
controllers require an unusually large amount of stack then
they may impose a lower bound on this value, or alternatively
the user may need to increase the stack.
"
}
 
cdl_option CYGNUM_POWER_THREAD_PRIORITY {
display "Thread priority to use"
active_if { CYGNUM_KERNEL_SCHED_PRIORITIES > 2 }
default_value 1
flavor data
description "
This is the priority for the power management thread.
Typically it defaults to a high priority, thus ensuring
that when the system wakes up from a sleep state all of
the power controllers are activated early on and by the
time other threads run they do not have to worry about
various devices still being asleep.
"
}
}
 
cdl_component CYGPKG_POWER_OPTIONS {
display "Power management build options"
flavor none
description "
Package specific build options including control over
compiler flags used only in building this package,
and details of which tests are built."
 
 
cdl_option CYGPKG_POWER_CFLAGS_ADD {
display "Additional compiler flags"
flavor data
no_define
default_value { "" }
description "
This option modifies the set of compiler flags for
building the power management package. These flags are
used in addition to the set of global flags."
}
 
cdl_option CYGPKG_POWER_CFLAGS_REMOVE {
display "Suppressed compiler flags"
flavor data
no_define
default_value { "" }
description "
This option modifies the set of compiler flags for
building the power management package. These flags are
removed from the set of global flags if present."
}
 
cdl_option CYGPKG_POWER_TESTS {
display "Power management tests"
flavor data
no_define
calculated { "tests/powertest" }
}
}
}
/common/v2_0/tests/powertest.cxx
0,0 → 1,369
//==========================================================================
//
// powertest.cxx
//
// Testcase for the power management support.
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): bartv
// Contributors: bartv
// Date: 2001-07-29
//
// This testcase checks most of the functionality of the power management
// package. The main exception is the POWER_CONTROLLER_CPU macro and
// the power_controller_cpu variable: that controller may or may not be
// provided by one of the HAL packages, so attempting to manipulate that
// HAL could cause link-time conflicts.
//
// The testcase is likely to fail if some package supplies a policy
// module that is making concurrent calls, for example if that module
// installs its own callback. For now there is no way of detecting
// that scenario, but also for now policy modules are assumed to be
// provided by the application rather than by any eCos package.
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <pkgconf/system.h>
#include <pkgconf/power.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_ass.h>
#include <cyg/infra/testcase.h>
#include <cyg/hal/hal_arch.h>
#include <cyg/power/power.h>
 
#ifdef CYGPKG_KERNEL
// Additional #include's to support the use of multiple threads.
#include <cyg/kernel/kapi.h>
#include <cyg/kernel/sched.hxx>
#endif
 
// Additional prototypes. These are builtins, but in some configurations
// the relevant headers may not be present.
extern "C" int strcmp(const char*, const char*);
 
// ----------------------------------------------------------------------------
// Define the various tests in the system. This allows the power controllers
// and the policy callback to take appropriate action as required.
enum PowerTest {
PowerTest_Presence,
PowerTest_Order,
PowerTest_InitialState,
PowerTest_Ids
} current_test;
 
// ----------------------------------------------------------------------------
// Statics.
#ifdef CYGPKG_KERNEL
static unsigned char policy_thread_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
static cyg_thread policy_thread;
static cyg_handle_t policy_thread_handle;
#endif
 
// ----------------------------------------------------------------------------
// Provide three power controllers at different priorities.
static void xyzzy_power_controller_fn(PowerController*, PowerMode, PowerModeChange);
static void wumpus_power_controller_fn(PowerController*, PowerMode, PowerModeChange);
static void erwin_power_controller_fn(PowerController*, PowerMode, PowerModeChange);
 
POWER_CONTROLLER(xyzzy_controller, PowerPri_Early, "xyzzy", &xyzzy_power_controller_fn);
POWER_CONTROLLER(wumpus_controller, PowerPri_Typical, "wumpus", &wumpus_power_controller_fn);
POWER_CONTROLLER(erwin_controller, PowerPri_Late, "erwin", &erwin_power_controller_fn);
 
// ----------------------------------------------------------------------------
// The test cases.
 
// Check that all three power controllers are actually present in the array.
static void
test_presence(void)
{
bool seen_xyzzy = false;
bool seen_wumpus = false;
bool seen_erwin = false;
PowerController* controller;
 
for (controller = &(__POWER__[0]); controller != &__POWER_END__; controller++) {
if (controller == &xyzzy_controller) {
CYG_ASSERTC(!seen_xyzzy);
seen_xyzzy = true;
} else if (controller == &wumpus_controller) {
CYG_ASSERTC(!seen_wumpus);
seen_wumpus = true;
} else if (controller == &erwin_controller) {
CYG_ASSERTC(!seen_erwin);
seen_erwin = true;
}
}
 
if (seen_xyzzy && seen_wumpus && seen_erwin) {
CYG_TEST_PASS("All expected controllers found");
} else {
CYG_TEST_FAIL_FINISH("Failed to find all the controllers that should be present");
}
}
 
// Now check that the controllers appear in the expected order.
static void
test_order(void)
{
int xyzzy_index = -1;
int wumpus_index = -1;
int erwin_index = -1;
int i;
 
for (i = 0; &(__POWER__[i]) != &__POWER_END__; i++) {
if (&__POWER__[i] == &xyzzy_controller) {
CYG_ASSERTC(-1 == xyzzy_index);
xyzzy_index = i;
} else if (&__POWER__[i] == &wumpus_controller) {
CYG_ASSERTC(-1 == wumpus_index);
wumpus_index = i;
} else if (&__POWER__[i] == &erwin_controller) {
CYG_ASSERTC(-1 == erwin_index);
erwin_index = i;
}
}
CYG_ASSERTC(-1 != xyzzy_index);
CYG_ASSERTC(-1 != wumpus_index);
CYG_ASSERTC(-1 != erwin_index);
 
if ((xyzzy_index < wumpus_index) && (wumpus_index < erwin_index)) {
CYG_TEST_PASS("The power controllers are in the correct order");
} else {
CYG_TEST_FAIL_FINISH("The power controllers are not in the correct order");
}
}
 
// Check the initial state of the system. Power controllers other than the ones
// defined by this testcase are ignored, since conceivably they might well come
// up in a mode other than active.
static void
test_initial_state(void)
{
bool test_ok = true;
// There have been no calls to change power mode, so the system should be active
if (PowerMode_Active != power_get_mode()) {
CYG_TEST_FAIL("Initial power mode not active");
test_ok = false;
}
if (PowerMode_Active != power_get_desired_mode()) {
CYG_TEST_FAIL("Initial desired power mode not active");
test_ok = false;
}
if ((void (*)(PowerController*, PowerMode, PowerMode, PowerMode, PowerMode)) 0 != power_get_policy_callback()) {
CYG_TEST_FAIL("A policy callback has already been installed");
test_ok = false;
}
 
if ((PowerMode_Active != power_get_controller_mode(&xyzzy_controller)) ||
(PowerMode_Active != power_get_controller_mode(&wumpus_controller)) ||
(PowerMode_Active != power_get_controller_mode(&erwin_controller))) {
CYG_TEST_FAIL("Not all power controllers initialized to active");
test_ok = false;
}
if ((PowerMode_Active != power_get_controller_desired_mode(&xyzzy_controller)) ||
(PowerMode_Active != power_get_controller_desired_mode(&wumpus_controller)) ||
(PowerMode_Active != power_get_controller_desired_mode(&erwin_controller))) {
CYG_TEST_FAIL("Not all power controllers initialized to desired active");
test_ok = false;
}
if (!power_get_controller_attached(&xyzzy_controller) ||
!power_get_controller_attached(&wumpus_controller) ||
!power_get_controller_attached(&erwin_controller)) {
CYG_TEST_FAIL("Some power controllers started off detached");
test_ok = false;
}
 
// The initial policy data is checked in a separate testcase
if (test_ok) {
CYG_TEST_PASS("Initial power management state is as expected");
}
}
 
// If the configuration involves per-controller id's, check them.
#ifdef CYGIMP_POWER_PROVIDE_STRINGS
static int test_ids_data = 0; // avoid problems with over-optimising
 
static void
test_ids(void)
{
// All of the power controllers should have a valid id, i.e. it
// should be possible to dereference the pointer. A SEGV here
// probably indicates that a HAL or device driver package has
// failed to supply a sensible string, which is a test failure
// albeit one in that package rather than the power management
// package.
PowerController* controller;
for (controller = &(__POWER__[0]); controller != &__POWER_END__; controller++) {
const char* id = power_get_controller_id(controller);
test_ids_data += id[0];
}
 
// In addition the id strings for the three known controllers are also known.
if ((0 == strcmp("xyzzy", power_get_controller_id(&xyzzy_controller))) &&
(0 == strcmp("wumpus", power_get_controller_id(&wumpus_controller))) &&
(0 == strcmp("erwin", power_get_controller_id(&erwin_controller)))) {
CYG_TEST_PASS("Controller id strings match up");
} else {
CYG_TEST_FAIL("Controller id strings fail to match");
}
}
#else
static void
test_ids(void)
{
CYG_TEST_NA("Unable to test controller ids - this functionaly has been configured out");
}
#endif
// ----------------------------------------------------------------------------
// The individual power controller functions. By default these just obey the
// requested mode change, but there are some special cases.
static void
xyzzy_power_controller_fn(PowerController* controller, PowerMode desired_mode, PowerModeChange change)
{
switch (current_test) {
default :
controller->mode = desired_mode;
break;
}
}
 
static void
wumpus_power_controller_fn(PowerController* controller, PowerMode desired_mode, PowerModeChange change)
{
switch (current_test) {
default :
controller->mode = desired_mode;
break;
}
}
 
static void
erwin_power_controller_fn(PowerController* controller, PowerMode desired_mode, PowerModeChange change)
{
switch (current_test) {
default :
controller->mode = desired_mode;
break;
}
}
 
// ----------------------------------------------------------------------------
// The main policy callback. Like the controller functions by default this
// does nothing, but for specific tests it has to take action.
static void
policy_callback(PowerController* controller, PowerMode old_mode, PowerMode current_mode, PowerMode old_desired_mode, PowerMode current_desired_mode)
{
}
 
// ----------------------------------------------------------------------------
// Utilities.
 
// Detach all controllers except the ones supplied by this package. It would
// be unfortunate if say the cpu stopped running because a test case decided
// to set the global mode to off.
static void
detach_all_controllers(void)
{
PowerController* controller;
for (controller = &(__POWER__[0]); controller != &__POWER_END__; controller++) {
if ((controller != &xyzzy_controller) && (controller != &wumpus_controller) && (controller != &erwin_controller)) {
power_set_controller_attached(controller, false);
}
}
}
 
// ----------------------------------------------------------------------------
// The main routine, which acts as the policy module. This either runs as
// a separate thread, if the kernel is present, or else it is called
// directly from cyg_start().
static void
powertest_main(CYG_ADDRWORD data)
{
CYG_ASSERT(0 == data, "No data should be supplied");
 
CYG_TEST_INIT();
current_test = PowerTest_Presence;
test_presence();
 
current_test = PowerTest_Order;
test_order();
 
current_test = PowerTest_InitialState;
test_initial_state();
 
current_test = PowerTest_Ids;
test_ids();
detach_all_controllers();
 
CYG_TEST_FINISH("All tests have been run");
}
 
// ----------------------------------------------------------------------------
// Test startup.
externC void
cyg_start(void)
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
 
#ifdef CYGPKG_KERNEL
cyg_thread_create(CYG_SCHED_DEFAULT_INFO,
&powertest_main,
(cyg_addrword_t) 0,
"Power policy thread",
policy_thread_stack,
CYGNUM_HAL_STACK_SIZE_TYPICAL,
&policy_thread_handle,
&policy_thread);
cyg_thread_resume(policy_thread_handle);
Cyg_Scheduler::start();
CYG_TEST_FAIL_FINISH("Not reached");
#else
powertest_main(0);
#endif
}
 
 
 
 
/common/v2_0/include/power.h
0,0 → 1,249
#ifndef CYGONCE_POWER_POWER_H
# define CYGONCE_POWER_POWER_H
//==========================================================================
//
// include/power.h
//
// Definitions of power management support
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): bartv
// Contributors: bartv
// Date: 2001-06-12
//
//
//####DESCRIPTIONEND####
//==========================================================================
 
#include <pkgconf/power.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/hal/hal_tables.h>
 
#ifdef CYGPKG_POWER_THREAD
#include <cyg/kernel/kapi.h> // CYGPKG_POWER_THREAD is active_if CYGPKG_KERNEL so
// the kernel's headers are guaranteed to be available.
#endif
 
#ifdef __cplusplus
extern "C" {
#endif
 
// The four defined modes of power operation.
#define PowerMode_Min 0
#define PowerMode_Active 0
#define PowerMode_Idle 1
#define PowerMode_Sleep 2
#define PowerMode_Off 3
#define PowerMode_Max 3
typedef cyg_uint8 PowerMode;
 
// Whether a mode change is initiated globally or per-controller
#define PowerModeChange_Controller 0
#define PowerModeChange_ControllerNow 1
#define PowerModeChange_Global 2
typedef cyg_uint32 PowerModeChange;
 
// Some priorities.
#define PowerPri_Early 1000
#define PowerPri_Typical 5000
#define PowerPri_Late 9000
typedef struct PowerController {
void (*change_mode)(struct PowerController*, PowerMode, PowerModeChange);
#ifdef CYGIMP_POWER_PROVIDE_STRINGS
char* id;
#endif
#ifdef CYGIMP_POWER_PROVIDE_POLICY_DATA
CYG_ADDRWORD policy_data;
#endif
PowerMode mode;
PowerMode desired_mode;
cyg_uint8 change_this;
cyg_uint8 attached;
} CYG_HAL_TABLE_TYPE PowerController;
 
// The table of power controllers, allowing application code
// to access all of them.
extern PowerController __POWER__[], __POWER_END__;
 
// There should always be a power controller for the cpu which can
// be accessed by any client.
extern PowerController power_controller_cpu;
 
// If a separate power management thread is being used, its handle
// is exported so that other code can e.g. manipulate its priority
#ifdef CYGPKG_POWER_THREAD
extern cyg_handle_t power_thread_handle;
#endif
// Inline functions and supporting data.
extern PowerMode __power_mode;
extern PowerMode __power_desired_mode;
typedef void (*__power_policy_callback_t)(PowerController*, PowerMode, PowerMode, PowerMode, PowerMode);
extern __power_policy_callback_t __power_policy_callback;
 
// This macro is overridden elsewhere in this package when defining linkable
// extern (i.e. non-inline) versions of these functions.
#ifndef POWER_INLINE
# define POWER_INLINE extern inline
#endif
 
POWER_INLINE PowerMode
power_get_mode(void)
{
return __power_mode;
}
 
POWER_INLINE PowerMode
power_get_desired_mode(void)
{
return __power_desired_mode;
}
 
POWER_INLINE PowerMode
power_get_controller_mode(PowerController* controller)
{
return controller->mode;
}
 
POWER_INLINE PowerMode
power_get_controller_desired_mode(PowerController* controller)
{
return controller->desired_mode;
}
 
POWER_INLINE void
power_set_policy_callback(__power_policy_callback_t new_callback)
{
__power_policy_callback = new_callback;
}
 
POWER_INLINE __power_policy_callback_t
power_get_policy_callback(void)
{
return __power_policy_callback;
}
 
#ifdef CYGIMP_POWER_PROVIDE_STRINGS
POWER_INLINE const char*
power_get_controller_id(PowerController* controller)
{
return controller->id;
}
#endif
 
#ifdef CYGIMP_POWER_PROVIDE_POLICY_DATA
POWER_INLINE void
power_set_controller_policy_data(PowerController* controller, CYG_ADDRWORD data)
{
controller->policy_data = data;
}
 
POWER_INLINE CYG_ADDRWORD
power_get_controller_policy_data(PowerController* controller)
{
return controller->policy_data;
}
#endif
 
POWER_INLINE cyg_bool
power_get_controller_attached(PowerController* controller)
{
return controller->attached;
}
 
POWER_INLINE void
power_set_controller_attached(PowerController* controller, cyg_bool new_value)
{
controller->attached = new_value;
}
 
POWER_INLINE void
power_set_controller_mode_now(PowerController* controller, PowerMode new_mode)
{
controller->desired_mode = new_mode;
if (controller->mode != controller->desired_mode) {
(*controller->change_mode)(controller, new_mode, PowerModeChange_ControllerNow);
}
}
 
// Now for the non-inline functions.
extern void power_set_controller_mode(PowerController*, PowerMode);
extern void power_set_mode(PowerMode);
 
// Implementation support.
#ifdef CYGIMP_POWER_PROVIDE_STRINGS
# define POWER_CONTROLLER_ID(_id_) id: _id_,
#else
# define POWER_CONTROLLER_ID(_id_)
#endif
#ifdef CYGIMP_POWER_PROVIDE_POLICY_DATA
# define POWER_CONTROLLER_POLICY_DATA policy_data: 0,
#else
# define POWER_CONTROLLER_POLICY_DATA
#endif
 
#define POWER_CONTROLLER(_name_, _pri_, _id_, _fn_) \
PowerController _name_ \
CYG_HAL_TABLE_QUALIFIED_ENTRY(power, _pri_) = { \
change_mode: _fn_, \
POWER_CONTROLLER_ID(_id_) \
POWER_CONTROLLER_POLICY_DATA \
mode: PowerMode_Active, \
desired_mode: PowerMode_Active, \
change_this: 0, \
attached: 1 \
}
 
#define POWER_CONTROLLER_CPU(_id_, _fn_) \
PowerController power_controller_cpu \
CYG_HAL_TABLE_EXTRA(power) = { \
change_mode: _fn_, \
POWER_CONTROLLER_ID(_id_) \
POWER_CONTROLLER_POLICY_DATA \
mode: PowerMode_Active, \
desired_mode: PowerMode_Active, \
change_this: 0, \
attached: 1, \
}
 
#ifdef __cplusplus
} // extern "C" {
#endif
 
#endif // CYGONCE_POWER_POWER_H
/common/v2_0/doc/power-controller.html
0,0 → 1,638
<!-- Copyright (C) 2001 Red Hat, Inc. -->
<!-- This material may be distributed only subject to the terms -->
<!-- and conditions set forth in the Open Publication License, v1.0 -->
<!-- or later (the latest version is presently available at -->
<!-- http://www.opencontent.org/openpub/). -->
<!-- Distribution of substantively modified versions of this -->
<!-- document is prohibited without the explicit permission of the -->
<!-- copyright holder. -->
<!-- Distribution of the work or derivative of the work in any -->
<!-- standard (paper) book form is prohibited unless prior -->
<!-- permission is obtained from the copyright holder. -->
<HTML
><HEAD
><TITLE
>Implementing a Power Controller</TITLE
><meta name="MSSmartTagsPreventParsing" content="TRUE">
<META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.64
"><LINK
REL="HOME"
TITLE="eCos Power Management Support"
HREF="services-power.html"><LINK
REL="PREVIOUS"
TITLE="Attached and Detached Controllers"
HREF="power-attached.html"></HEAD
><BODY
CLASS="REFENTRY"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>eCos Power Management Support</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="power-attached.html"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
>&nbsp;</TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><H1
><A
NAME="POWER-CONTROLLER"
>Implementing a Power Controller</A
></H1
><DIV
CLASS="REFNAMEDIV"
><A
NAME="AEN355"
></A
><H2
>Name</H2
>Implementing a Power Controller&nbsp;--&nbsp;adding power management support to device drivers and
other packages</DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN358"
></A
><H2
>Implementing a Power Controller</H2
><P
>A system will have some number of power controllers. Usually there
will be one power controller for the cpu,
<TT
CLASS="VARNAME"
>power_controller_cpu</TT
>, typically provided by one of
the HAL packages and responsible for managing the processor itself and
associated critical components such as memory. Some or all of the
device drivers will provide power controllers, allowing the power
consumption of the associated devices to be controlled. There may be
some arbitrary number of other controllers present in the system. The
power management package does not impose any restrictions on the
number or nature of the power controllers in the system, other than
insisting that at most one <TT
CLASS="VARNAME"
>power_controller_cpu</TT
> be
provided.</P
><P
>Each power controller involves a single data structure of type
<SPAN
CLASS="STRUCTNAME"
>PowerController</SPAN
>, defined in the header file
<TT
CLASS="FILENAME"
>cyg/power/power.h</TT
>. These data
structures should all be placed in the table
<TT
CLASS="LITERAL"
>__POWER__</TT
>, so that the power management package and
other code can easily locate all the controllers in the system. This
table is constructed at link-time, avoiding code-size or run-time
overheads. To facilitate this the package provides two macros which
should be used to define a power controller,
<TT
CLASS="LITERAL"
>POWER_CONTROLLER()</TT
> and
<TT
CLASS="LITERAL"
>POWER_CONTROLLER_CPU()</TT
>.</P
><P
>The macro <TT
CLASS="LITERAL"
>POWER_CONTROLLER</TT
> takes four arguments:</P
><P
></P
><OL
TYPE="1"
><LI
><P
>A variable name. This can be used to access the power controller
directly, as well as via the table.</P
></LI
><LI
><P
>A priority. The table of power controllers is sorted, such that power
controllers with a numerically lower priority come earlier in the
table. The special controller <TT
CLASS="VARNAME"
>power_controller_cpu</TT
>
always comes at the end of the table. When moving from a high-power
mode to a lower-powered mode, the power management package iterates
through the table from front to back. When moving to a higher-powered
mode the reverse direction is used. The intention is that the power
controller for a software-only package such as a TCP/IP stack should
appear near the start of the table, whereas the controllers for the
ethernet and similar devices would be near the end of the table. Hence
when the policy module initiates a mode change to a lower-powered mode
the TCP/IP stack gets a chance to cancel this mode change, before the
devices it depends on are powered down. Similarly when moving to a
higher-powered mode the devices will be re-activated before any
software that depends on those devices.</P
><P
>The header file <TT
CLASS="FILENAME"
>cyg/power/power.h</TT
> defines three
priorities <TT
CLASS="LITERAL"
>PowerPri_Early</TT
>,
<TT
CLASS="LITERAL"
>PowerPri_Typical</TT
> and
<TT
CLASS="LITERAL"
>PowerPri_Late</TT
>. For most controllers one of these
priorities, possibly with a small number added or subtracted, will
give sufficient control. If an application developer is uncertain
about the relative priorities of the various controllers, a simple
<A
HREF="power-info.html#POWER-INFO-IDS"
>test program</A
> that iterates over
the table will quickly eliminate any confusion.</P
></LI
><LI
><P
>A constant string identifier. If the system has been configured
without support for such identifiers
(<TT
CLASS="VARNAME"
>CYGIMP_POWER_PROVIDE_STRINGS</TT
>) then this identifer
will be discarded at compile-time. Otherwise it will be made available
to higher-level code using the function
<TT
CLASS="FUNCTION"
>power_get_controller_id</TT
>. </P
></LI
><LI
><P
>A function pointer. This will be invoked to perform actual mode
changes, as described below.</P
></LI
></OL
><P
>A typical example of the use of the
<TT
CLASS="LITERAL"
>POWER_CONTROLLER</TT
> macro would be as follows:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>#include &lt;pkgconf/system.h&gt;
 
#ifdef CYGPKG_POWER
# include &lt;cyg/power/power.h&gt;
 
static void
xyzzy_device_power_mode_change(
PowerController* controller,
PowerMode desired_mode,
PowerModeChange change)
{
// Do the work
}
 
static POWER_CONTROLLER(xyzzy_power_controller, \
PowerPri_Late, \
"xyzzy device", \
&amp;xyzzy_device_power_mode_change);
#endif</PRE
></TD
></TR
></TABLE
><P
>This creates a variable <TT
CLASS="VARNAME"
>xyzzy_power_controller</TT
>,
which is a power controller data structure that will end up near the
end of the table of power controllers. Higher-level code can
iterate through this table and report the string <TT
CLASS="LITERAL"
>"xyzzy
device"</TT
> to the user. Whenever there is a mode change
operation that affects this controller, the function
<TT
CLASS="FUNCTION"
>xyzzy_device_power_mode_change</TT
> will be invoked.
The variable is declared static so this controller cannot be
manipulated by name in any other code. Alternatively, if the variable
had not been declared static other code could manipulate this
controller by name as well as through the table, especially if the
package for the xyzzy device driver explicitly declared this
variable in an exported header file. Obviously exporting the variable
involves a slight risk of a name clash at link time.</P
><P
>The above code explicitly checks for the presence of the power
management package before including that package's header file or
providing any related functionality. Since power management
functionality is optional, such checks are recommended.</P
><P
>The macro <TT
CLASS="LITERAL"
>POWER_CONTROLLER_CPU</TT
> only takes two
arguments, a string identifier and a mode change function pointer.
This macro always instantiates a variable
<TT
CLASS="VARNAME"
>power_controller_cpu</TT
> so there is no need to provide
a variable name. The resulting power controller structure always
appears at the end of the table, so there is no need to specify a
priority. Typical usage of the <TT
CLASS="LITERAL"
>POWER_CONTROLLER_CPU</TT
>
macro would be:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>static void
wumpus_processor_power_mode_change(
PowerController* controller,
PowerMode desired_mode,
PowerModeChange change)
{
// Do the work
}
 
POWER_CONTROLLER_CPU("wumpus processor", \
&amp;wumpus_processor_power_mode_change);</PRE
></TD
></TR
></TABLE
><P
>This defines a power controller structure
<TT
CLASS="VARNAME"
>power_controller_cpu</TT
>. It should not be declared
static since higher-level code may well want to manipulate the cpu's
power mode directly, and the variable is declared by the power
management package's header file.</P
><P
>Some care has to be taken to ensure that the power controllers
actually end up in the final executable. If a power controller
variable ends up in an ordinary library and is never referenced
directly then typically the linker will believe that the variable is
not needed and it will not end up in the executable. For eCos packages
this can be achieved in the CDL, by specifying that the containing
source file should end up in <TT
CLASS="FILENAME"
>libextras.a</TT
> rather
than the default <TT
CLASS="FILENAME"
>libtarget.a</TT
>:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>cdl_package CYGPKG_HAL_WUMPUS_ARCH {
&#8230;
compile -library=libextras.a data.c
}</PRE
></TD
></TR
></TABLE
><P
>If the file <TT
CLASS="FILENAME"
>data.c</TT
> instantiates a power
controller this is now guaranteed to end up in the final executable,
as intended. Typically HAL and device driver packages will already
have some data that must not be eliminated by the linker, so they will
already contain a file that gets built into
<TT
CLASS="FILENAME"
>libextras.a</TT
>. For power controllers defined inside
application code it is important that the power controllers end up in
<TT
CLASS="FILENAME"
>.o</TT
> object files rather than in
<TT
CLASS="FILENAME"
>.a</TT
> library archive files.</P
><P
>All the real work of a power controller is done by the mode change
function. If the power management package has been configured to use a
separate thread then this mode change function will be invoked by that
thread (except for the special case of <A
HREF="power-change.html#POWER-CHANGE-CONTROLLER-NOW"
><TT
CLASS="FUNCTION"
>power_set_controller_mode_now</TT
></A
>).
If no separate thread is used then the mode change function will be
invoked directly by <TT
CLASS="FUNCTION"
>power_set_mode</TT
> or
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
>.</P
><P
>The mode change function will be invoked with three arguments. The
first argument identifies the power controller. Usually this argument
is not actually required since a given mode change function will only
ever be invoked for a single power controller. For example,
<TT
CLASS="FUNCTION"
>xyzzy_device_power_mode_change</TT
> will only ever be
used in conjunction with <TT
CLASS="VARNAME"
>xyzzy_power_controller</TT
>.
However there may be some packages which contain multiple controllers,
all of which can share a single mode change function, and in that case
it is essential to identify the specific controller. The second
argument specifies the mode the controller should switch to, if
possible: it will be one of <TT
CLASS="LITERAL"
>PowerMode_Active</TT
>,
<TT
CLASS="LITERAL"
>PowerMode_Idle</TT
>, <TT
CLASS="LITERAL"
>PowerMode_Sleep</TT
>
or <TT
CLASS="LITERAL"
>PowerMode_Off</TT
>. The final argument will be one of
<TT
CLASS="LITERAL"
>PowerModeChange_Controller</TT
>,
PowerModeChange_ControllerNow, or
<TT
CLASS="LITERAL"
>PowerModeChange_Global</TT
>, and identifies the call
that caused this invocation. For example, if the mode change function
was invoked because of a call to <TT
CLASS="FUNCTION"
>power_set_mode</TT
>
then this argument will be <TT
CLASS="LITERAL"
>PowerModeChange_Global</TT
>.
It is up to each controller to decide how to interpret this final
argument. A typical controller might reject a global request to switch
to <SPAN
CLASS="TYPE"
>off</SPAN
> mode if the associated device is still busy, but
if the request was aimed specifically at this controller then it could
instead abort any current I/O operations and switch off the device.</P
><P
>The <SPAN
CLASS="STRUCTNAME"
>PowerController</SPAN
> data structure contains
one field, <TT
CLASS="STRUCTFIELD"
><I
>mode</I
></TT
>, that needs to be updated
by the power mode change function. At all times it should indicate the
current mode for this controller. When a mode change is requested the
desired mode is passed as the second argument. The exact operation of
the power mode change function depends very much on what is being
controlled and the current circumstances, but some guidelines are
possible:</P
><P
></P
><OL
TYPE="1"
><LI
><P
>If the request can be satisfied without obvious detriment, do so and
update the <TT
CLASS="STRUCTFIELD"
><I
>mode</I
></TT
> field. Reducing the power
consumption of a device that is not currently being used is generally
harmless.</P
></LI
><LI
><P
>If a request is a no-op, for example if the system is switching
from <SPAN
CLASS="TYPE"
>idle</SPAN
> to <SPAN
CLASS="TYPE"
>sleep</SPAN
> mode and the controller
does not distinguish between these modes, simply act as if the request
was satisfied.</P
></LI
><LI
><P
>If a request is felt to be unsafe, for example shutting down a
device that is still in use, then the controller may decide
to reject this request. This is especially true if the request was a
global mode change as opposed to one intended specifically for this
controller: in the latter case the policy module should be given due
deference. There are a number of ways in which a request can be
rejected:</P
><P
></P
><OL
TYPE="a"
><LI
><P
>If the request cannot be satisfied immediately but may be feasible in
a short while, leave the <TT
CLASS="STRUCTFIELD"
><I
>mode</I
></TT
> field
unchanged. Higher-level code in the policy module can interpret this
as a hint to retry the operation a little bit later. This approach is
also useful if the mode change can be started but will take some time
to complete, for example shutting down a socket connection, and
additional processing will be needed later on.</P
></LI
><LI
><P
>If the request is felt to be inappropriate, for example switching off
a device that is still in use, the mode change function can
call <TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
> to reset the
desired mode for this controller back to the current mode.
Higher-level code can then interpret this as a hint that there is more
activity in the system than had been apparent.</P
></LI
><LI
><P
>For a global mode change, if the new mode is felt to be inappropriate
then the power controller can call <TT
CLASS="FUNCTION"
>power_set_mode</TT
>
to indicate this. An example of this would be the policy module
deciding to switch off the whole unit while there is still I/O
activity.</P
></LI
></OL
></LI
></OL
><P
>Mode change functions should not directly manipulate any other fields
in the <SPAN
CLASS="STRUCTNAME"
>PowerController</SPAN
> data structure. If it
is necessary to keep track of additional data then static variables
can be used.</P
><P
>It should be noted that the above are only guidelines. Their
application in any given situation may be unclear. In addition the
detailed requirements of specific systems will vary, so even if the
power controller for a given device driver follows the above
guidelines exactly it may turn out that slightly different behaviour
would be more appropriate for the actual system that is being
developed. Fortunately the open source nature of
<SPAN
CLASS="PRODUCTNAME"
>eCos</SPAN
> allows system developers to fine-tune
power controllers to meet their exact requirements.</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="power-attached.html"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="services-power.html"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>&nbsp;</TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Attached and Detached Controllers</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>&nbsp;</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>
/common/v2_0/doc/services-power.html
0,0 → 1,164
<!-- Copyright (C) 2001 Red Hat, Inc. -->
<!-- This material may be distributed only subject to the terms -->
<!-- and conditions set forth in the Open Publication License, v1.0 -->
<!-- or later (the latest version is presently available at -->
<!-- http://www.opencontent.org/openpub/). -->
<!-- Distribution of substantively modified versions of this -->
<!-- document is prohibited without the explicit permission of the -->
<!-- copyright holder. -->
<!-- Distribution of the work or derivative of the work in any -->
<!-- standard (paper) book form is prohibited unless prior -->
<!-- permission is obtained from the copyright holder. -->
<HTML
><HEAD
><TITLE
>eCos Power Management Support</TITLE
><meta name="MSSmartTagsPreventParsing" content="TRUE">
<META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.64
"><LINK
REL="NEXT"
TITLE="Introduction"
HREF="power-intro.html"></HEAD
><BODY
CLASS="REFERENCE"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
>&nbsp;</TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="power-intro.html"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="REFERENCE"
><A
NAME="SERVICES-POWER"
></A
><DIV
CLASS="TITLEPAGE"
><H1
CLASS="TITLE"
>I. eCos Power Management Support</H1
><DIV
CLASS="TOC"
><DL
><DT
><B
>Table of Contents</B
></DT
><DT
><A
HREF="power-intro.html"
>Introduction</A
> &#8212; eCos support for Power Management</DT
><DT
><A
HREF="power-info.html"
>Power Management Information</A
> &#8212; finding out about the various power controllers in the system</DT
><DT
><A
HREF="power-change.html"
>Changing Power Modes</A
> &#8212; reducing or increasing power consumption as needed</DT
><DT
><A
HREF="power-policy.html"
>Support for Policy Modules</A
> &#8212; closer integration with higher-level code</DT
><DT
><A
HREF="power-attached.html"
>Attached and Detached Controllers</A
> &#8212; control which power controllers are affected by global changes</DT
><DT
><A
HREF="power-controller.html"
>Implementing a Power Controller</A
> &#8212; adding power management support to device drivers and
other packages</DT
></DL
></DIV
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="power-intro.html"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Introduction</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>
/common/v2_0/doc/power-change.html
0,0 → 1,453
<!-- Copyright (C) 2001 Red Hat, Inc. -->
<!-- This material may be distributed only subject to the terms -->
<!-- and conditions set forth in the Open Publication License, v1.0 -->
<!-- or later (the latest version is presently available at -->
<!-- http://www.opencontent.org/openpub/). -->
<!-- Distribution of substantively modified versions of this -->
<!-- document is prohibited without the explicit permission of the -->
<!-- copyright holder. -->
<!-- Distribution of the work or derivative of the work in any -->
<!-- standard (paper) book form is prohibited unless prior -->
<!-- permission is obtained from the copyright holder. -->
<HTML
><HEAD
><TITLE
>Changing Power Modes</TITLE
><meta name="MSSmartTagsPreventParsing" content="TRUE">
<META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.64
"><LINK
REL="HOME"
TITLE="eCos Power Management Support"
HREF="services-power.html"><LINK
REL="PREVIOUS"
TITLE="Power Management Information"
HREF="power-info.html"><LINK
REL="NEXT"
TITLE="Support for Policy Modules"
HREF="power-policy.html"></HEAD
><BODY
CLASS="REFENTRY"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>eCos Power Management Support</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="power-info.html"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="power-policy.html"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><H1
><A
NAME="POWER-CHANGE"
>Changing Power Modes</A
></H1
><DIV
CLASS="REFNAMEDIV"
><A
NAME="AEN171"
></A
><H2
>Name</H2
>Changing Power Modes&nbsp;--&nbsp;reducing or increasing power consumption as needed</DIV
><DIV
CLASS="REFSYNOPSISDIV"
><A
NAME="AEN174"
></A
><H2
>Synopsis</H2
><DIV
CLASS="FUNCSYNOPSIS"
><A
NAME="AEN175"
></A
><P
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="FUNCSYNOPSISINFO"
>#include &lt;cyg/power/power.h&gt;</PRE
></TD
></TR
></TABLE
><P
><CODE
><CODE
CLASS="FUNCDEF"
> void power_set_mode
</CODE
>( PowerMode new_mode
);</CODE
></P
><P
><CODE
><CODE
CLASS="FUNCDEF"
> void power_set_controller_mode
</CODE
>( PowerController* controller
, PowerMode new_mode
);</CODE
></P
><P
><CODE
><CODE
CLASS="FUNCDEF"
> void power_set_controller_mode_now
</CODE
>( PowerController* controller
, PowerMode new_mode
);</CODE
></P
><P
></P
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-CHANGE-GLOBAL"
></A
><H2
>Changing the Global Power Mode</H2
><P
>The primary functionality supported by the power management package is
to change the system's global power mode. This is achieved by calling
the function <TT
CLASS="FUNCTION"
>power_set_mode</TT
> with a single
argument, which should be one of <TT
CLASS="LITERAL"
>PowerMode_Active</TT
>,
<TT
CLASS="LITERAL"
>PowerMode_Idle</TT
>, <TT
CLASS="LITERAL"
>PowerMode_Sleep</TT
>
or <TT
CLASS="LITERAL"
>PowerMode_Off</TT
>. Typically this function will only
be invoked in certain scenarios:</P
><P
></P
><OL
TYPE="1"
><LI
><P
>A typical system will contain a policy module which is primarily
responsible for initiating power mode changes, and a thread inside the
power management package. The policy module will call
<TT
CLASS="FUNCTION"
>power_set_mode</TT
>, which has the effect of
manipulating some internal state in the power management package and
waking up its thread. When this thread gets scheduled to run (its
priority is controlled by a configuration option), it will iterate
over the power controllers and invoke each controller to change its
power mode. There is support for a <A
HREF="power-policy.html#POWER-POLICY-CALLBACK"
>callback function</A
>, and for
<A
HREF="power-attached.html"
>detached</A
> power controllers.</P
></LI
><LI
><P
>After a call to <TT
CLASS="FUNCTION"
>power_set_mode</TT
> but before the
power management thread has had a chance to iterate over all the
controllers, or even before the thread has been rescheduled at all,
the policy module may decide that a different power mode would be more
appropriate for the current situation and calls
<TT
CLASS="FUNCTION"
>power_set_mode</TT
> again. This has the effect of
aborting the previous mode change, followed by the power management
thread iterating over the power controllers again for the new mode.</P
></LI
><LI
><P
>If there is no single policy module responsible for power mode
changes, any code can call <TT
CLASS="FUNCTION"
>power_set_mode</TT
>. If
there are multiple calls in quick succession, earlier calls will
be aborted and the system should end up in the power mode
corresponding to the last call</P
></LI
><LI
><P
>As a special case, it is possible for a power controller to call
<TT
CLASS="FUNCTION"
>power_set_mode</TT
> when invoked by the power
management thread. For example a power controller could decide that it
is inappropriate for the system to go to sleep because the device it
is associated with is still busy. The effect is as if the policy
module had called <TT
CLASS="FUNCTION"
>power_set_mode</TT
> again before
the mode change had completed.</P
></LI
></OL
><P
>If the power management package has been configured not to use a
separate thread then obviously the behaviour is somewhat different.
The call to <TT
CLASS="FUNCTION"
>power_set_mode</TT
> will now iterate over
the various power controllers immediately, rather than leaving this to
a separate thread, and the whole mode change completes before
<TT
CLASS="FUNCTION"
>power_set_mode</TT
> returns. If some other thread or a
DSR calls <TT
CLASS="FUNCTION"
>power_set_mode</TT
> concurrently the
behaviour of the system is undefined. However, it is still legal for a
power controller to call <TT
CLASS="FUNCTION"
>power_set_mode</TT
>:
effectively this is a recursive call; it is detected by the system,
and internal state is updated; the recursive
<TT
CLASS="FUNCTION"
>power_set_mode</TT
> call now returns, and when the
power controller returns back to the original
<TT
CLASS="FUNCTION"
>power_set_mode</TT
> call it detects what has happened,
aborts the previous mode change, and starts a new mode change as
requested by the controller.</P
><P
><TT
CLASS="FUNCTION"
>power_set_mode</TT
> is normally invoked from thread
context. If a separate power management thread is used it can be
invoked safely from DSR context. If the system is configured not to
use such a thread, it may or may not be safe to invoke this function
from DSR context: essentially the function just iterates through
the various power controllers, and the documentation or source code of
each controller present in the current system will have to be examined
to determine whether or not this can happen safely in DSR context.
<TT
CLASS="FUNCTION"
>power_set_mode</TT
> should never be invoked from
ISR context.</P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-CHANGE-CONTROLLER"
></A
><H2
>Manipulating an Individual Power Controller</H2
><P
>In some cases it is desirable to set the power mode of an individual
controller separately from the mode for the system as a whole. For
example if a device is not currently being used then the associated
power controller could be set to <TT
CLASS="LITERAL"
>PowerMode_Off</TT
>,
even while the system as a whole is still active. This can be achieved
by calling the function
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
>. It takes two
arguments: the first identifies a particular controller; the second
specifies the desired new power mode for that controller. The function
operates in much the same way as <TT
CLASS="FUNCTION"
>power_set_mode</TT
>,
for example if a separate power management thread is being used then
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
> operates by
manipulating some internal state and waking up that thread. The
limitations are also much the same as for
<TT
CLASS="FUNCTION"
>power_set_mode</TT
>, so for example
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
> should not be invoked
from inside ISRs.</P
><P
>Manipulating individual controllers is often used in conjunction with
the function <A
HREF="power-attached.html"
><TT
CLASS="FUNCTION"
>power_set_controller_attached</TT
></A
>,
allowing the policy module to specify which controllers are affected
by global mode changes.</P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-CHANGE-CONTROLLER-NOW"
></A
><H2
>Direct Manipulation of a Power Controller</H2
><P
>In exceptional circumstances it may be necessary to invoke a power
controller directly, bypassing the power management thread and
higher-level functionality such as <A
HREF="power-policy.html#POWER-POLICY-CALLBACK"
>callback functions</A
>. The
function <TT
CLASS="FUNCTION"
>power_set_controller_mode_now</TT
> allows
this. It takes two arguments, a controller and a mode, just like
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
>.</P
><P
>Use of <TT
CLASS="FUNCTION"
>power_set_controller_mode_now</TT
> is
dangerous. For example no attempt is made to synchronise with any
other power mode changes that might be happening concurrently. A
possible use is when the system gets woken up out of
<SPAN
CLASS="TYPE"
>sleep</SPAN
> mode: depending on the hardware, on which power
controllers are present, and on the application code it may be
necessary to wake up some power controllers immediately before the
system as a whole is ready to run again.</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="power-info.html"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="services-power.html"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="power-policy.html"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Power Management Information</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Support for Policy Modules</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>
/common/v2_0/doc/power-info.html
0,0 → 1,486
<!-- Copyright (C) 2001 Red Hat, Inc. -->
<!-- This material may be distributed only subject to the terms -->
<!-- and conditions set forth in the Open Publication License, v1.0 -->
<!-- or later (the latest version is presently available at -->
<!-- http://www.opencontent.org/openpub/). -->
<!-- Distribution of substantively modified versions of this -->
<!-- document is prohibited without the explicit permission of the -->
<!-- copyright holder. -->
<!-- Distribution of the work or derivative of the work in any -->
<!-- standard (paper) book form is prohibited unless prior -->
<!-- permission is obtained from the copyright holder. -->
<HTML
><HEAD
><TITLE
>Power Management Information</TITLE
><meta name="MSSmartTagsPreventParsing" content="TRUE">
<META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.64
"><LINK
REL="HOME"
TITLE="eCos Power Management Support"
HREF="services-power.html"><LINK
REL="PREVIOUS"
TITLE="Introduction"
HREF="power-intro.html"><LINK
REL="NEXT"
TITLE="Changing Power Modes"
HREF="power-change.html"></HEAD
><BODY
CLASS="REFENTRY"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>eCos Power Management Support</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="power-intro.html"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="power-change.html"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><H1
><A
NAME="POWER-INFO"
>Power Management Information</A
></H1
><DIV
CLASS="REFNAMEDIV"
><A
NAME="AEN97"
></A
><H2
>Name</H2
>Obtaining Power Management Information&nbsp;--&nbsp;finding out about the various power controllers in the system</DIV
><DIV
CLASS="REFSYNOPSISDIV"
><A
NAME="AEN100"
></A
><H2
>Synopsis</H2
><DIV
CLASS="FUNCSYNOPSIS"
><A
NAME="AEN101"
></A
><P
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="FUNCSYNOPSISINFO"
>#include &lt;cyg/power/power.h&gt;
 
extern PowerController __POWER__[], __POWER_END__;
extern PowerController power_controller_cpu;
extern cyg_handle_t power_thread_handle;</PRE
></TD
></TR
></TABLE
><P
><CODE
><CODE
CLASS="FUNCDEF"
> PowerMode power_get_mode
</CODE
>(void);</CODE
></P
><P
><CODE
><CODE
CLASS="FUNCDEF"
> PowerMode power_get_desired_mode
</CODE
>(void);</CODE
></P
><P
><CODE
><CODE
CLASS="FUNCDEF"
> PowerMode power_get_controller_mode
</CODE
>( PowerController* controller
);</CODE
></P
><P
><CODE
><CODE
CLASS="FUNCDEF"
> PowerMode power_get_controller_desired_mode
</CODE
>( PowerController* controller
);</CODE
></P
><P
><CODE
><CODE
CLASS="FUNCDEF"
> const char* power_get_controller_id
</CODE
>( PowerController* controller
);</CODE
></P
><P
></P
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-INFO-ACCESS"
></A
><H2
>Accessing Power Controllers</H2
><P
>All the power controllers in a system are held in a table, filled in
at link-time. The symbols <TT
CLASS="VARNAME"
>__POWER__</TT
> and
<TT
CLASS="VARNAME"
>__POWER_END</TT
> can be used to iterate through this
table, for example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>PowerController* controller;
for (controller = &#38;(__POWER__[0]);
controller != &#38;(__POWER_END__);
controller++) {
 
&#8230;
}</PRE
></TD
></TR
></TABLE
><P
>Each controller has an associated priority, controlling the order in
which they appear in the table. Typically a software-only component
such as a TCP/IP stack would use a small number for the priority, so
that it appears near the start of the table, whereas a device driver
would be nearer the back of the table. When switching to a
lower-powered mode the power management package will iterate through
this table from front to back, thus ensuring that for example the
TCP/IP stack gets a chance to shut down before the underlying ethernet
or other hardware that the stack depends on. Similarly when switching
to a higher-powered mode the power management package will iterate
through this table from back to front.</P
><P
>In most systems there will be one special controller,
<TT
CLASS="VARNAME"
>power_controller_cpu</TT
>, which should be provided by
one of the architectural, variant or platform HAL packages. This
controller will always be the last entry in the table. It is
responsible for the final power down operation when switching to
<SPAN
CLASS="TYPE"
>off</SPAN
> mode. Other packages such as device drivers may or
may not declare variable identifiers for their power controllers,
allowing those controllers to be accessed by name as well as by their
entries in the global table.</P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-INFO-GLOBAL"
></A
><H2
>Global Power Modes</H2
><P
>The function <TT
CLASS="FUNCTION"
>power_get_mode</TT
> can be called at any
time to determine the current power mode for the system as a whole.
The return value will be one of <TT
CLASS="LITERAL"
>PowerMode_Active</TT
>,
<TT
CLASS="LITERAL"
>PowerMode_Idle</TT
>, <TT
CLASS="LITERAL"
>PowerMode_Sleep</TT
>
or <TT
CLASS="LITERAL"
>PowerMode_Off</TT
>. In normal circumstances it is
unlikely that <TT
CLASS="LITERAL"
>PowerMode_Off</TT
> would be returned since
that mode generally means that the cpu is no longer running.</P
><P
>The function <TT
CLASS="FUNCTION"
>power_get_desired_mode</TT
> returns the
power mode that the system should be running at. Most of the time this
will be the same value as returned by
<TT
CLASS="FUNCTION"
>power_get_mode</TT
>. However a different value may be
returned when in the middle of changing power modes. For example, if
the current thread runs at a higher priority than the power management
thread then the latter may have been pre-empted in the middle of a
mode change: <TT
CLASS="FUNCTION"
>power_get_mode</TT
> will return the mode
the system was running at before the mode change started, and
<TT
CLASS="FUNCTION"
>power_get_desired_mode</TT
> will return the mode the
system should end up in when the mode change completes, barring
further calls to <TT
CLASS="FUNCTION"
>power_set_mode</TT
>.</P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-INFO-INDIVIDUAL"
></A
><H2
>Individual Controller Power Modes</H2
><P
>The power management package keeps track of the current and desired
modes for each power controller, as well as the modes for the system as
a whole. The function <TT
CLASS="FUNCTION"
>power_get_controller_mode</TT
>
takes a single argument, a pointer to a power controller, and returns
the power mode that controller is currently running at. Similarly
<TT
CLASS="FUNCTION"
>power_get_controller_desired_mode</TT
> returns the
power mode that controller should be running at. Most of the time the
current and desired modes for a given controller will be the same, and
will also be the same as the global power mode. However if the power
management thread is preeempted in the middle of a mode change then
some of the controllers will have been updated to the desired global
mode, whereas others will still be at the old mode. The power
management package also provides functionality for manipulating
<A
HREF="power-change.html#POWER-CHANGE-CONTROLLER"
>individual controllers</A
>, and for <A
HREF="power-attached.html"
>detaching</A
> controllers from
global mode changes.</P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-INFO-IDS"
></A
><H2
>Power Controller Identification</H2
><P
>In some scenarios the power management package will run completely
automated, and there is no need to identify individual power
controllers. Any form of identification such as a string
description would serve no purpose, but would still consume memory in
the final system. In other scenarios it may be very desirable to
provide some means of identification. For example, while still
debugging it may be useful to see a simple string when printing the
contents of a power controller structure. Alternatively, if the
application is expected to provide some sort of user interface that
gives control over which parts of the system are enabled or disabled,
a string identifier for each controller would be useful. To cope with
these scenarios the power management package provides a configuration
option <TT
CLASS="VARNAME"
>CYGIMP_POWER_PROVIDE_STRINGS</TT
>. When enabled,
each power controller will contain a pointer to a constant string
which can be accessed via a function
<TT
CLASS="FUNCTION"
>power_get_controller_id</TT
>. When disabled the system
will not contain these strings, and the function will not be provided.
The following code illustrates how to use this function.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>#include &lt;stdio.h&gt;
#include &lt;pkgconf/system.h&gt;
#ifndef CYGPKG_POWER
# error The power management package is not present.
#endif
#include &lt;pkgconf/power.h&gt;
#ifndef CYGIMP_POWER_PROVIDE_STRINGS
# error Power controller identifiers are not available.
#endif
#include &lt;cyg/power/power.h&gt;
 
static const char*
mode_to_string(PowerMode mode)
{
const char* result;
switch(mode) {
case PowerMode_Active : result = "active"; break;
case PowerMode_Idle : result = "idle"; break;
case PowerMode_Sleep : result = "sleep"; break;
case PowerMode_Off : result = "off"; break;
default : result = "&lt;unknown&gt;"; break;
}
return result;
}
 
int
main(int argc, char** argv)
{
PowerController* controller;
 
for (controller = &amp;(__POWER__[0]);
controller != &amp;(__POWER_END__);
controller++) {
printf("Controller @ %p: %s, %s\n", controller,
power_get_controller_id(controller),
mode_to_string(power_get_controller_mode(controller)));
}
return 0;
}</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-INFO-THREAD"
></A
><H2
>The Power Management Thread</H2
><P
>If the power management package is configured to use a separate thread
then a handle for that thread is made available to higher-level code
via the variable <TT
CLASS="VARNAME"
>power_thread_handle</TT
>. This handle
can be used for a variety of purposes, including manipulating that
thread's priority.</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="power-intro.html"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="services-power.html"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="power-change.html"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Introduction</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Changing Power Modes</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>
/common/v2_0/doc/power-intro.html
0,0 → 1,553
<!-- Copyright (C) 2001 Red Hat, Inc. -->
<!-- This material may be distributed only subject to the terms -->
<!-- and conditions set forth in the Open Publication License, v1.0 -->
<!-- or later (the latest version is presently available at -->
<!-- http://www.opencontent.org/openpub/). -->
<!-- Distribution of substantively modified versions of this -->
<!-- document is prohibited without the explicit permission of the -->
<!-- copyright holder. -->
<!-- Distribution of the work or derivative of the work in any -->
<!-- standard (paper) book form is prohibited unless prior -->
<!-- permission is obtained from the copyright holder. -->
<HTML
><HEAD
><TITLE
>Introduction</TITLE
><meta name="MSSmartTagsPreventParsing" content="TRUE">
<META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.64
"><LINK
REL="HOME"
TITLE="eCos Power Management Support"
HREF="services-power.html"><LINK
REL="PREVIOUS"
TITLE="eCos Power Management Support"
HREF="services-power.html"><LINK
REL="NEXT"
TITLE="Power Management Information"
HREF="power-info.html"></HEAD
><BODY
CLASS="REFENTRY"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>eCos Power Management Support</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="services-power.html"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="power-info.html"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><H1
><A
NAME="POWER-INTRO"
>Introduction</A
></H1
><DIV
CLASS="REFNAMEDIV"
><A
NAME="AEN6"
></A
><H2
>Name</H2
>Introduction&nbsp;--&nbsp;eCos support for Power Management</DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-INTRO-INTRO"
></A
><H2
>Introduction</H2
><P
>The eCos Power Management package provides a framework for
incorporating power management facilities in an embedded application.
However its functionality is deliberately limited.</P
><P
></P
><OL
TYPE="1"
><LI
><P
>The package does not contain any support for controlling the current
power mode of any given processor, device or board. Instead it is the
responsibility of the appropriate HAL or device driver package to
implement such support, by implementing <I
CLASS="FIRSTTERM"
>power
controllers</I
>. The power management package groups these
power controllers together and provides an interface for manipulating
them.</P
></LI
><LI
><P
>The package does not contain any power management policy support.
Specifically, including this package in an application does not by
itself ever cause the system to go into low-power mode. Instead it is
the responsibility of a separate policy module, provided by
higher-level application code or by some other package, to decide when
it would be appropriate to switch from one power mode to another. The
power management package then provides the mechanisms for making it
happen.</P
></LI
></OL
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-INTRO-INCLUDE"
></A
><H2
>Including Power Management</H2
><P
>The power management package is never included automatically in an
eCos configuration: it is not part of any target specification or of
any template. Instead it must be added explicitly to a configuration
if the intended application requires power management functionality.
When using the command-line <B
CLASS="COMMAND"
>ecosconfig</B
> tool this
can be achieved using a command such as:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
>$ ecosconfig add power</PRE
></TD
></TR
></TABLE
><P
>The generic eCos user documentation should be consulted for more
information on how to use the various tools. The functionality
provided by the power management package is defined in the header file
<TT
CLASS="FILENAME"
>cyg/power/power.h</TT
>. This header
file can be used by both C and C++ code.</P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-INTRO-MODES"
></A
><H2
>Power Modes</H2
><P
>There are four defined modes of operation:</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
>active</DT
><DD
><P
>The system is fully operational, and power consumption is expected to
be high.</P
></DD
><DT
>idle</DT
><DD
><P
>There has been little or no activity for a short period of time. It is
up to the policy module to determine what constitutes a short period
of time, but typically it will be some tenths of a second or some
small number of seconds. A possible action when entering idle mode is
to reduce the system's clock speed, thus reducing the power drawn by
the cpu.</P
><P
>Note that typically this power mode is not entered automatically
whenever the idle thread starts running. Instead it is entered when
the policy module discovers that for a certain period of time the
system has been spending most of its time in the idle thread.
Theoretically it is possible to implement a policy module that would
cause a switch to idle mode as soon as the idle thread starts running,
but that could result in a great many power mode changes for no
immediate benefit.</P
></DD
><DT
>sleep</DT
><DD
><P
>The system has been idle for a significant period of time, perhaps
some tens of seconds. It is desirable to shut down any hardware that
is drawing a significant amount of power, for example a screen
backlight.</P
></DD
><DT
>off</DT
><DD
><P
>The system is powered down. Power consumption should be minimized.
Some special action may be needed before the system comes back up, for
example the user may need to press a specific button.</P
></DD
></DL
></DIV
><P
>The exact transitions that will happen are decided by the policy
module. One policy module might include transitions from active to
idle, from idle to sleep, from sleep to off, and from any of idle,
sleep or off directly back to active. Another policy module might
only use the active and off states, bypassing the intermediate ones.</P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-INTRO-CONTROLLERS"
></A
><H2
>Power Controllers</H2
><P
>The power management package operates primarily on power controllers.
The main functionality provided by a power controller is to switch the
power mode for some part of the system, for example the lcd display or
the cpu. A power controller consists primarily of a function which
will be invoked to switch the power mode for the part of the overall
system being controlled, plus some auxiliary data. A typical system
will include a number of different power controllers:</P
><P
></P
><OL
TYPE="1"
><LI
><P
>Usually there will be one power controller
<TT
CLASS="VARNAME"
>power_controller_cpu</TT
> associated with the processor
or with the target platform, and provided by the corresponding HAL
package. It is this controller which is responsible for switching off
the system when entering the <SPAN
CLASS="TYPE"
>off</SPAN
> mode, which makes it
somewhat special: attempting to switch off the cpu before other
devices like the lcd display does not make sense because the cpu would
no longer be executing any instructions for the latter operation.
Therefore this power controller has to be invoked last when switching
to a lower-power mode, and similarly when switching back to a
higher-power mode it will be invoked first.</P
><P
>It should be noted that providing power management support is not a
hard requirement when porting eCos to a new processor or platform, and
many eCos ports predate the availability of power management support.
Therefore for any given platform it is distinctly possible that
<TT
CLASS="VARNAME"
>power_controller_cpu</TT
> is not yet provided, and if
full power management functionality is desired then the appropriate
HAL package would have to be extended first. System developers should
examine the relevant HAL documentation and sources to determine what
is actually available.</P
></LI
><LI
><P
>Some or all of the device drivers will supply their own power
controllers, as part of the device driver package. It is not required
that all device drivers provide power controllers. In some cases,
especially for devices that are integrated with the processor,
<TT
CLASS="VARNAME"
>power_controller_cpu</TT
> will take care of the
integrated devices as a side effect. In other cases the hardware may
not provide any functionality that allows power consumption to be
controlled. For any given device driver it is also possible that no
power controller exists either because it was not required when the
driver was written, or because the driver predates the availability of
power management. Again the relevant documentation and sources should
be consulted for further information.</P
></LI
><LI
><P
>There may be power controllers which are not associated directly with
any specific hardware. For example a TCP/IP stack could provide a
power controller so that it gets informed when the system has been
reactivated: by looking at the system clock it can determine for how
long the system has been switched off; using this information it can
then recover from expired dhcp leases, or even to shut down any stream
connections that may have become invalid (although arguably the stack
should have refused to go to <SPAN
CLASS="TYPE"
>off</SPAN
> mode while there were
open connections).</P
></LI
></OL
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-INTRO-OPERATION"
></A
><H2
>Basic Operation</H2
><P
>By default the Power Management package creates a thread during
initialization. It is also possible for the package to be used without
such a thread, for example in configurations which do not include a
full kernel, and this alternative is described below. When a separate
thread is used the stacksize and priority for this thread can be
controlled by configuration options
<TT
CLASS="VARNAME"
>CYGNUM_POWER_THREAD_STACKSIZE</TT
> and
<TT
CLASS="VARNAME"
>CYGNUM_POWER_THREAD_PRIORITY</TT
>. Typically the thread
will just wait on a semaphore internal to the package, and will do
nothing until some other part of the system requests a change to the
power mode.</P
><P
>At some point the policy module will decide that the system should
move into a lower-power mode, for example from active to idle. This is
achieved by calling the function <TT
CLASS="FUNCTION"
>power_set_mode</TT
>,
provided by the power management package and declared in <TT
CLASS="FILENAME"
>cyg/power/power.h</TT
>, with a single
argument, <TT
CLASS="LITERAL"
>PowerMode_Idle</TT
>. This function manipulates
some internal state and posts the semaphore, thus waking up the power
management thread. Note that the function returns before the mode
change has completed, and in fact depending on thread priorities this
return may happen before any power controller has been invoked.</P
><P
>When the power management thread wakes up it examines the internal
state to figure out what it should be doing. In this case it is
supposed to change the global power mode, so it will iterate over all
the power controllers requesting each one to switch to the
<SPAN
CLASS="TYPE"
>idle</SPAN
> mode. It is up to each power controller to handle
this request appropriately. Optionally the thread will invoke a
callback function after processing each power controller, so that
higher-level code such as the policy module can more easily keep
track of the actual state of each controller. Once the thread has
iterated through all the power controllers it will again wait on the
internal semaphore for the next request to arrive.</P
><DIV
CLASS="NOTE"
><BLOCKQUOTE
CLASS="NOTE"
><P
><B
>Note: </B
>At present the power management thread always runs at a single
priority, which defaults to a low priority. A possible future
enhancement would be to support two separate priorities. When
switching to a lower-powered mode the thread would run at a low
priority as before, thus allowing other threads to run and get a
chance to cancel this mode change. When switching to a higher-powered
mode the thread would run at a high priority. This could be especially
important when moving out of the <SPAN
CLASS="TYPE"
>off</SPAN
> state: for example
it would ensure that all device drivers get a chance to wake up before
ordinary application threads get to run again and possibly attempt I/O
operations.</P
></BLOCKQUOTE
></DIV
><P
>Although usually calls to <TT
CLASS="FUNCTION"
>power_set_mode</TT
> will
come from just one place in the policy module, this is not a hard
requirement. It is possible for multiple threads to call this
function, with no need for any synchronization. If the power
management thread is in the middle of performing a mode change and a
new request comes in, the thread will detect this, abort the current
operation, and start iterating through the power controllers again
with the new mode. This check happens between every power controller
invocation. Usefully this makes it possible for power controllers
themselves to manipulate power modes: a power controller is invoked to
change mode; for some reason it determines that the new mode is
inappropriate; it calls <TT
CLASS="FUNCTION"
>power_set_mode</TT
> to move
the system back to another mode; when the power controller returns
this event will be detected; the power management thread will abort
the current mode change, and start the new one.</P
><P
>In addition to changing the power mode for the system as a whole,
individual controllers can be manipulated using the function
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
>. For example, while the
system as a whole might be in <SPAN
CLASS="TYPE"
>active</SPAN
> mode certain devices
might be kept in <SPAN
CLASS="TYPE"
>sleep</SPAN
> mode until they are explicitly
activated. It is possible to mix concurrent calls to
<TT
CLASS="FUNCTION"
>power_set_mode</TT
> and
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
>, and when a power
controller is invoked it may use
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
> to request further
changes to its own or to another controller's mode as required.</P
><P
>There are some scenarios where the power management package should not
use its own thread. One scenario is if the configuration is
specifically for a single-threaded application such as RedBoot.
Another scenario is if the policy module already involves a separate
thread: it may make more sense if the various power management
operations are synchronous with respect to the calling thread. The use
of a separate thread inside the power management package is controlled
by the configuration option <TT
CLASS="VARNAME"
>CYGPKG_POWER_THREAD</TT
>,
which is active only if the kernel package is present and enabled by
default.</P
><P
>If no separate power management thread is used then obviously the
implementations of <TT
CLASS="FUNCTION"
>power_set_mode</TT
> and
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
> will be somewhat
different: instead of waking up a separate thread to do the work,
these functions will now manipulate the power controllers directly. If
the system does still involve multiple threads then only one thread
may call <TT
CLASS="FUNCTION"
>power_set_mode</TT
> or
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
> at a time: the power
management package will not provide any synchronization, that must
happen at a higher level. However when a power controller is invoked
it can still call these functions as required.</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="services-power.html"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="services-power.html"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="power-info.html"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>eCos Power Management Support</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Power Management Information</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>
/common/v2_0/doc/power-attached.html
0,0 → 1,253
<!-- Copyright (C) 2001 Red Hat, Inc. -->
<!-- This material may be distributed only subject to the terms -->
<!-- and conditions set forth in the Open Publication License, v1.0 -->
<!-- or later (the latest version is presently available at -->
<!-- http://www.opencontent.org/openpub/). -->
<!-- Distribution of substantively modified versions of this -->
<!-- document is prohibited without the explicit permission of the -->
<!-- copyright holder. -->
<!-- Distribution of the work or derivative of the work in any -->
<!-- standard (paper) book form is prohibited unless prior -->
<!-- permission is obtained from the copyright holder. -->
<HTML
><HEAD
><TITLE
>Attached and Detached Controllers</TITLE
><meta name="MSSmartTagsPreventParsing" content="TRUE">
<META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.64
"><LINK
REL="HOME"
TITLE="eCos Power Management Support"
HREF="services-power.html"><LINK
REL="PREVIOUS"
TITLE="Support for Policy Modules"
HREF="power-policy.html"><LINK
REL="NEXT"
TITLE="Implementing a Power Controller"
HREF="power-controller.html"></HEAD
><BODY
CLASS="REFENTRY"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>eCos Power Management Support</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="power-policy.html"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="power-controller.html"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><H1
><A
NAME="POWER-ATTACHED"
>Attached and Detached Controllers</A
></H1
><DIV
CLASS="REFNAMEDIV"
><A
NAME="AEN321"
></A
><H2
>Name</H2
>Attached and Detached Controllers&nbsp;--&nbsp;control which power controllers are affected by global changes</DIV
><DIV
CLASS="REFSYNOPSISDIV"
><A
NAME="AEN324"
></A
><H2
>Synopsis</H2
><DIV
CLASS="FUNCSYNOPSIS"
><A
NAME="AEN325"
></A
><P
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="FUNCSYNOPSISINFO"
>#include &lt;cyg/power/power.h&gt;</PRE
></TD
></TR
></TABLE
><P
><CODE
><CODE
CLASS="FUNCDEF"
> cyg_bool power_get_controller_attached
</CODE
>( PowerController* controller
);</CODE
></P
><P
><CODE
><CODE
CLASS="FUNCDEF"
> void power_set_controller_attached
</CODE
>( PowerController* controller
, cyg_bool new_state
);</CODE
></P
><P
></P
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN339"
></A
><H2
>Detaching Power Controllers</H2
><P
>By default the global operation <TT
CLASS="FUNCTION"
>power_set_mode</TT
>
affects all power controllers. There may be circumstances when this is
not desirable. For example if a particular device is not currently
being used then it can be left switched off: the rest of the system
could be moving between <SPAN
CLASS="TYPE"
>active</SPAN
>, <SPAN
CLASS="TYPE"
>idle</SPAN
> and
<SPAN
CLASS="TYPE"
>sleep</SPAN
> modes, but there is no point in invoking the power
controller for the unused device. To support this the power management
package supports the concept of attached and detached controllers. By
default all controllers are attached, and hence will be affected by
global mode changes. A specific controller can be detached using the
function <TT
CLASS="FUNCTION"
>power_set_controller_attached</TT
>. This
function takes two arguments, one to specify a particular controller
and another to specify the desired new state.
<TT
CLASS="FUNCTION"
>power_get_controller_attached</TT
> can be used to
determine whether or not a specific controller is currently attached.</P
><P
>The attached or detached state of a controller only affects what
happens during a global mode change, in other words following a call
to <TT
CLASS="FUNCTION"
>power_set_mode</TT
>. It is still possible to
manipulate a detached controller using
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
> or
<TT
CLASS="FUNCTION"
>power_set_controller_mode_now</TT
>.</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="power-policy.html"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="services-power.html"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="power-controller.html"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Support for Policy Modules</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Implementing a Power Controller</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>
/common/v2_0/doc/power-policy.html
0,0 → 1,408
<!-- Copyright (C) 2001 Red Hat, Inc. -->
<!-- This material may be distributed only subject to the terms -->
<!-- and conditions set forth in the Open Publication License, v1.0 -->
<!-- or later (the latest version is presently available at -->
<!-- http://www.opencontent.org/openpub/). -->
<!-- Distribution of substantively modified versions of this -->
<!-- document is prohibited without the explicit permission of the -->
<!-- copyright holder. -->
<!-- Distribution of the work or derivative of the work in any -->
<!-- standard (paper) book form is prohibited unless prior -->
<!-- permission is obtained from the copyright holder. -->
<HTML
><HEAD
><TITLE
>Support for Policy Modules</TITLE
><meta name="MSSmartTagsPreventParsing" content="TRUE">
<META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.64
"><LINK
REL="HOME"
TITLE="eCos Power Management Support"
HREF="services-power.html"><LINK
REL="PREVIOUS"
TITLE="Changing Power Modes"
HREF="power-change.html"><LINK
REL="NEXT"
TITLE="Attached and Detached Controllers"
HREF="power-attached.html"></HEAD
><BODY
CLASS="REFENTRY"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>eCos Power Management Support</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="power-change.html"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="power-attached.html"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><H1
><A
NAME="POWER-POLICY"
>Support for Policy Modules</A
></H1
><DIV
CLASS="REFNAMEDIV"
><A
NAME="AEN255"
></A
><H2
>Name</H2
>Support for Policy Modules&nbsp;--&nbsp;closer integration with higher-level code</DIV
><DIV
CLASS="REFSYNOPSISDIV"
><A
NAME="AEN258"
></A
><H2
>Synopsis</H2
><DIV
CLASS="FUNCSYNOPSIS"
><A
NAME="AEN259"
></A
><P
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="FUNCSYNOPSISINFO"
>#include &lt;cyg/power/power.h&gt;</PRE
></TD
></TR
></TABLE
><P
><CODE
><CODE
CLASS="FUNCDEF"
> void power_set_policy_callback
</CODE
>( void (*)(PowerController*, PowerMode, PowerMode, PowerMode, PowerMode) callback
);</CODE
></P
><P
><CODE
><CODE
CLASS="FUNCDEF"
> void (*)(PowerController*, PowerMode, PowerMode, PowerMode, PowerMode) power_get_policy_callback
</CODE
>(void);</CODE
></P
><P
><CODE
><CODE
CLASS="FUNCDEF"
> CYG_ADDRWORD power_get_controller_policy_data
</CODE
>( PowerController* controller
);</CODE
></P
><P
><CODE
><CODE
CLASS="FUNCDEF"
> void power_set_controller_policy_data
</CODE
>( PowerController* controller
, CYG_ADDRWORD data
);</CODE
></P
><P
></P
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-POLICY-CALLBACK"
></A
><H2
>Policy Callbacks</H2
><P
>The use of a separate thread to perform power mode changes in typical
configurations can cause problems for some policy modules.
Specifically, the policy module can request a mode change for the
system as a whole or for an individual controller, but it does not
know when the power management thread actually gets scheduled to run
again and carry out the request. Although it would be possible for the
policy module to perform some sort of polling, in general that is
undesirable.</P
><P
>To avoid such problems the policy module can install a callback
function using <TT
CLASS="FUNCTION"
>power_set_policy_callback</TT
>. The
current callback function can be retrieved using
<TT
CLASS="FUNCTION"
>power_get_policy_callback</TT
>. If a callback function
has been installed then it will be called by the power management
package whenever a power controller has been invoked to perform a mode
change. The callback will be called in the context of the power
management thread, so usually it will have to make use of thread
synchronisation primitives to interact with the main policy module. It
is passed five arguments:</P
><P
></P
><OL
TYPE="1"
><LI
><P
>The power controller that has just been invoked to perform a mode
change. </P
></LI
><LI
><P
>The mode this controller was running at before the invocation.</P
></LI
><LI
><P
>The current mode this controller is now running at.</P
></LI
><LI
><P
>The desired mode before the power controller was invoked. Usually this
will be the same as the current mode, unless the controller has
decided for some reason that this was inappropriate.</P
></LI
><LI
><P
>The current desired mode. This will differ from the previous argument
only if there has was another call to
<TT
CLASS="FUNCTION"
>power_set_mode</TT
> or
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
> while the power
controller was being invoked, probably by the power controller itself.</P
></LI
></OL
><P
>A simple example of a policy callback function would be:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>static void
power_callback(
PowerController* controller,
PowerMode old_mode,
PowerMode new_mode,
PowerMode old_desired_mode,
powerMode new_desired_mode)
{
printf("Power mode change: %s, %s -&#62; %d\n",
power_get_controller_id(controller),
mode_to_string(old_mode),
mode_to_string(new_mode));
 
CYG_UNUSED_PARAM(PowerMode, old_desired_mode);
CYG_UNUSED_PARAM(PowerMode, new_desired_mode);
}
 
int
main(int argc, char** argv)
{
&#8230;
power_set_policy_callback(&amp;power_callback);
&#8230;
}</PRE
></TD
></TR
></TABLE
><P
>If <TT
CLASS="FUNCTION"
>power_set_controller_mode_now</TT
> is used to
manipulate an individual controller the policy callback will not be
invoked. This function may get called from any context including DSRs,
and even if there is already a call to the policy callback happening
in some other context, so invoking the callback would usually be
unsafe.</P
><P
>If the power management package has not been configured to use a
separate thread then <TT
CLASS="FUNCTION"
>power_set_mode</TT
> and
<TT
CLASS="FUNCTION"
>power_set_controller_mode</TT
> will manipulate the
power controllers immediately and invoke the policy callback
afterwards. Therefore the policy callback will typically run in the
same context as the main policy module.</P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="POWER-POLICY-DATA"
></A
><H2
>Policy-specific Controller Data</H2
><P
>Some policy modules may want to associate some additional data with
each power controller. This could be achieved by for example
maintaining a hash table or similar data structure, but for
convenience the power management package allows higher-level code,
typically the policy module, to store and retrieve one word of data in
each power controller. The function
<TT
CLASS="FUNCTION"
>power_set_controller_policy_data</TT
> takes two
arguments, a pointer to a power controller and a
<SPAN
CLASS="TYPE"
>CYG_ADDRWORD</SPAN
> of data: by appropriate use of casts this
word could be an integer or a pointer to some data structure. The
matching function
<TT
CLASS="FUNCTION"
>power_get_controller_policy_data</TT
> retrieves the
word previously installed, and can be cast back to an integer or
pointer. The default value for the policy data is 0.</P
><P
>For example the following code fragment stores a simple index value in
each power controller. This could then be retrieved by the policy
callback.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> unsigned int i = 0;
PowerController* controller;
 
for (controller = &amp;(__POWER__[0]);
controller != &amp;(__POWER_END__);
controller++) {
power_set_controller_policy_data(controller, (CYG_ADDRWORD) i++);
}</PRE
></TD
></TR
></TABLE
><P
>Not all policy modules will require per-controller data. The
configuration option
<TT
CLASS="VARNAME"
>CYGIMP_POWER_PROVIDE_POLICY_DATA</TT
> can be used to
control this functionality, thus avoiding wasting a small amount of
memory inside each power controller structure.</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="power-change.html"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="services-power.html"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="power-attached.html"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Changing Power Modes</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Attached and Detached Controllers</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>
/common/v2_0/doc/makefile
0,0 → 1,55
#=============================================================================
#
# makefile
#
# For building the power management package documentation
#
#=============================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
#=============================================================================
#####DESCRIPTIONBEGIN####
#
# Author(s): bartv
# Date: 2001-06-26
#####DESCRIPTIONEND####
#=============================================================================
 
TOPLEVEL := ../../../../..
MAIN_SGML := power.sgml
MAIN_HTML := services-power.html
MAIN_PDF := services-power.pdf
OTHER_SGML :=
PICTURES :=
 
include $(TOPLEVEL)/pkgconf/rules.doc
/common/v2_0/doc/power.sgml
0,0 → 1,1420
<!-- DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V3.1//EN" -->
 
<!-- {{{ Banner -->
 
<!-- =============================================================== -->
<!-- -->
<!-- power.sgml -->
<!-- -->
<!-- Generic power management documentation. -->
<!-- -->
<!-- =============================================================== -->
<!-- ####COPYRIGHTBEGIN#### -->
<!-- -->
<!-- =============================================================== -->
<!-- Copyright (C) 2001, 2002 Red Hat, Inc. -->
<!-- This material may be distributed only subject to the terms -->
<!-- and conditions set forth in the Open Publication License, v1.0 -->
<!-- or later (the latest version is presently available at -->
<!-- http://www.opencontent.org/openpub/) -->
<!-- Distribution of the work or derivative of the work in any -->
<!-- standard (paper) book form is prohibited unless prior -->
<!-- permission obtained from the copyright holder -->
<!-- =============================================================== -->
<!-- -->
<!-- ####COPYRIGHTEND#### -->
<!-- =============================================================== -->
<!-- #####DESCRIPTIONBEGIN#### -->
<!-- -->
<!-- Author(s): bartv -->
<!-- Contact(s): bartv -->
<!-- Date: 2001/06/26 -->
<!-- Version: 0.01 -->
<!-- -->
<!-- ####DESCRIPTIONEND#### -->
<!-- =============================================================== -->
 
<!-- }}} -->
<part id="services-power">
<!-- reference id="services-power" -->
<title>eCos Power Management Support</title>
 
<!-- {{{ Intro -->
 
<refentry id="power-intro">
<refmeta>
<refentrytitle>Introduction</refentrytitle>
</refmeta>
<refnamediv>
<refname>Introduction</refname>
<refpurpose>eCos support for Power Management</refpurpose>
</refnamediv>
 
<!-- {{{ Intro -->
 
<refsect1 id="power-intro-intro">
<title>Introduction</title>
<para>
The eCos Power Management package provides a framework for
incorporating power management facilities in an embedded application.
However its functionality is deliberately limited.
</para>
<orderedlist>
<listitem>
<para>
The package does not contain any support for controlling the current
power mode of any given processor, device or board. Instead it is the
responsibility of the appropriate HAL or device driver package to
implement such support, by implementing <firstterm>power
controllers</firstterm>. The power management package groups these
power controllers together and provides an interface for manipulating
them.
</para>
</listitem>
<listitem>
<para>
The package does not contain any power management policy support.
Specifically, including this package in an application does not by
itself ever cause the system to go into low-power mode. Instead it is
the responsibility of a separate policy module, provided by
higher-level application code or by some other package, to decide when
it would be appropriate to switch from one power mode to another. The
power management package then provides the mechanisms for making it
happen.
</para>
</listitem>
</orderedlist>
</refsect1>
 
<!-- }}} -->
<!-- {{{ including -->
 
<refsect1 id="power-intro-include">
<title>Including Power Management</title>
<para>
The power management package is never included automatically in an
eCos configuration: it is not part of any target specification or of
any template. Instead it must be added explicitly to a configuration
if the intended application requires power management functionality.
When using the command-line <command>ecosconfig</command> tool this
can be achieved using a command such as:
</para>
<screen>
$ ecosconfig add power
</screen>
<para>
The generic eCos user documentation should be consulted for more
information on how to use the various tools. The functionality
provided by the power management package is defined in the header file
<filename class="headerfile">cyg/power/power.h</filename>. This header
file can be used by both C and C++ code.
</para>
 
</refsect1>
 
<!-- }}} -->
<!-- {{{ modes -->
 
<refsect1 id="power-intro-modes">
<title>Power Modes</title>
<para>
There are four defined modes of operation:
</para>
<variablelist>
 
<varlistentry><term>active</term>
<listitem>
<para>
The system is fully operational, and power consumption is expected to
be high.
</para>
</listitem>
</varlistentry>
 
<varlistentry><term>idle</term>
<listitem>
<para>
There has been little or no activity for a short period of time. It is
up to the policy module to determine what constitutes a short period
of time, but typically it will be some tenths of a second or some
small number of seconds. A possible action when entering idle mode is
to reduce the system's clock speed, thus reducing the power drawn by
the cpu.
</para>
<para>
Note that typically this power mode is not entered automatically
whenever the idle thread starts running. Instead it is entered when
the policy module discovers that for a certain period of time the
system has been spending most of its time in the idle thread.
Theoretically it is possible to implement a policy module that would
cause a switch to idle mode as soon as the idle thread starts running,
but that could result in a great many power mode changes for no
immediate benefit.
</para>
</listitem>
</varlistentry>
 
<varlistentry><term>sleep</term>
<listitem>
<para>
The system has been idle for a significant period of time, perhaps
some tens of seconds. It is desirable to shut down any hardware that
is drawing a significant amount of power, for example a screen
backlight.
</para>
</listitem>
</varlistentry>
 
<varlistentry><term>off</term>
<listitem>
<para>
The system is powered down. Power consumption should be minimized.
Some special action may be needed before the system comes back up, for
example the user may need to press a specific button.
</para>
</listitem>
</varlistentry>
 
</variablelist>
 
<para>
The exact transitions that will happen are decided by the policy
module. One policy module might include transitions from active to
idle, from idle to sleep, from sleep to off, and from any of idle,
sleep or off directly back to active. Another policy module might
only use the active and off states, bypassing the intermediate ones.
</para>
 
</refsect1>
 
<!-- }}} -->
<!-- {{{ Power Controllers -->
 
<refsect1 id="power-intro-controllers">
<title>Power Controllers</title>
<para>
The power management package operates primarily on power controllers.
The main functionality provided by a power controller is to switch the
power mode for some part of the system, for example the lcd display or
the cpu. A power controller consists primarily of a function which
will be invoked to switch the power mode for the part of the overall
system being controlled, plus some auxiliary data. A typical system
will include a number of different power controllers:
</para>
<orderedlist>
<listitem>
<para>
Usually there will be one power controller
<varname>power_controller_cpu</varname> associated with the processor
or with the target platform, and provided by the corresponding HAL
package. It is this controller which is responsible for switching off
the system when entering the <type>off</type> mode, which makes it
somewhat special: attempting to switch off the cpu before other
devices like the lcd display does not make sense because the cpu would
no longer be executing any instructions for the latter operation.
Therefore this power controller has to be invoked last when switching
to a lower-power mode, and similarly when switching back to a
higher-power mode it will be invoked first.
</para>
<para>
It should be noted that providing power management support is not a
hard requirement when porting eCos to a new processor or platform, and
many eCos ports predate the availability of power management support.
Therefore for any given platform it is distinctly possible that
<varname>power_controller_cpu</varname> is not yet provided, and if
full power management functionality is desired then the appropriate
HAL package would have to be extended first. System developers should
examine the relevant HAL documentation and sources to determine what
is actually available.
</para>
</listitem>
<listitem>
<para>
Some or all of the device drivers will supply their own power
controllers, as part of the device driver package. It is not required
that all device drivers provide power controllers. In some cases,
especially for devices that are integrated with the processor,
<varname>power_controller_cpu</varname> will take care of the
integrated devices as a side effect. In other cases the hardware may
not provide any functionality that allows power consumption to be
controlled. For any given device driver it is also possible that no
power controller exists either because it was not required when the
driver was written, or because the driver predates the availability of
power management. Again the relevant documentation and sources should
be consulted for further information.
</para>
</listitem>
<listitem>
<para>
There may be power controllers which are not associated directly with
any specific hardware. For example a TCP/IP stack could provide a
power controller so that it gets informed when the system has been
reactivated: by looking at the system clock it can determine for how
long the system has been switched off; using this information it can
then recover from expired dhcp leases, or even to shut down any stream
connections that may have become invalid (although arguably the stack
should have refused to go to <type>off</type> mode while there were
open connections).
</para>
</listitem>
</orderedlist>
</refsect1>
 
<!-- }}} -->
<!-- {{{ Basic Operation -->
 
<refsect1 id="power-intro-operation">
<title>Basic Operation</title>
<para>
By default the Power Management package creates a thread during
initialization. It is also possible for the package to be used without
such a thread, for example in configurations which do not include a
full kernel, and this alternative is described below. When a separate
thread is used the stacksize and priority for this thread can be
controlled by configuration options
<varname>CYGNUM_POWER_THREAD_STACKSIZE</varname> and
<varname>CYGNUM_POWER_THREAD_PRIORITY</varname>. Typically the thread
will just wait on a semaphore internal to the package, and will do
nothing until some other part of the system requests a change to the
power mode.
</para>
<para>
At some point the policy module will decide that the system should
move into a lower-power mode, for example from active to idle. This is
achieved by calling the function <function>power_set_mode</function>,
provided by the power management package and declared in <filename
class="headerfile">cyg/power/power.h</filename>, with a single
argument, <literal>PowerMode_Idle</literal>. This function manipulates
some internal state and posts the semaphore, thus waking up the power
management thread. Note that the function returns before the mode
change has completed, and in fact depending on thread priorities this
return may happen before any power controller has been invoked.
</para>
<para>
When the power management thread wakes up it examines the internal
state to figure out what it should be doing. In this case it is
supposed to change the global power mode, so it will iterate over all
the power controllers requesting each one to switch to the
<type>idle</type> mode. It is up to each power controller to handle
this request appropriately. Optionally the thread will invoke a
callback function after processing each power controller, so that
higher-level code such as the policy module can more easily keep
track of the actual state of each controller. Once the thread has
iterated through all the power controllers it will again wait on the
internal semaphore for the next request to arrive.
</para>
<note>
<para>
At present the power management thread always runs at a single
priority, which defaults to a low priority. A possible future
enhancement would be to support two separate priorities. When
switching to a lower-powered mode the thread would run at a low
priority as before, thus allowing other threads to run and get a
chance to cancel this mode change. When switching to a higher-powered
mode the thread would run at a high priority. This could be especially
important when moving out of the <type>off</type> state: for example
it would ensure that all device drivers get a chance to wake up before
ordinary application threads get to run again and possibly attempt I/O
operations.
</para>
</note>
<para>
Although usually calls to <function>power_set_mode</function> will
come from just one place in the policy module, this is not a hard
requirement. It is possible for multiple threads to call this
function, with no need for any synchronization. If the power
management thread is in the middle of performing a mode change and a
new request comes in, the thread will detect this, abort the current
operation, and start iterating through the power controllers again
with the new mode. This check happens between every power controller
invocation. Usefully this makes it possible for power controllers
themselves to manipulate power modes: a power controller is invoked to
change mode; for some reason it determines that the new mode is
inappropriate; it calls <function>power_set_mode</function> to move
the system back to another mode; when the power controller returns
this event will be detected; the power management thread will abort
the current mode change, and start the new one.
</para>
<para>
In addition to changing the power mode for the system as a whole,
individual controllers can be manipulated using the function
<function>power_set_controller_mode</function>. For example, while the
system as a whole might be in <type>active</type> mode certain devices
might be kept in <type>sleep</type> mode until they are explicitly
activated. It is possible to mix concurrent calls to
<function>power_set_mode</function> and
<function>power_set_controller_mode</function>, and when a power
controller is invoked it may use
<function>power_set_controller_mode</function> to request further
changes to its own or to another controller's mode as required.
</para>
<para>
There are some scenarios where the power management package should not
use its own thread. One scenario is if the configuration is
specifically for a single-threaded application such as RedBoot.
Another scenario is if the policy module already involves a separate
thread: it may make more sense if the various power management
operations are synchronous with respect to the calling thread. The use
of a separate thread inside the power management package is controlled
by the configuration option <varname>CYGPKG_POWER_THREAD</varname>,
which is active only if the kernel package is present and enabled by
default.
</para>
<para>
If no separate power management thread is used then obviously the
implementations of <function>power_set_mode</function> and
<function>power_set_controller_mode</function> will be somewhat
different: instead of waking up a separate thread to do the work,
these functions will now manipulate the power controllers directly. If
the system does still involve multiple threads then only one thread
may call <function>power_set_mode</function> or
<function>power_set_controller_mode</function> at a time: the power
management package will not provide any synchronization, that must
happen at a higher level. However when a power controller is invoked
it can still call these functions as required.
</para>
</refsect1>
 
<!-- }}} -->
 
</refentry>
 
<!-- }}} -->
<!-- {{{ Power Management Info -->
 
<refentry id="power-info">
<refmeta>
<refentrytitle>Power Management Information</refentrytitle>
</refmeta>
<refnamediv>
<refname>Obtaining Power Management Information</refname>
<refpurpose>finding out about the various power controllers in the system</refpurpose>
</refnamediv>
 
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>
#include &lt;cyg/power/power.h&gt;
 
extern PowerController __POWER__[], __POWER_END__;
extern PowerController power_controller_cpu;
extern cyg_handle_t power_thread_handle;
</funcsynopsisinfo>
 
<funcprototype>
<funcdef>
PowerMode <function>power_get_mode</function>
</funcdef>
<void>
</funcprototype>
<funcprototype>
<funcdef>
PowerMode <function>power_get_desired_mode</function>
</funcdef>
<void>
</funcprototype>
<funcprototype>
<funcdef>
PowerMode <function>power_get_controller_mode</function>
</funcdef>
<paramdef>
PowerController* <parameter>controller</parameter>
</paramdef>
</funcprototype>
<funcprototype>
<funcdef>
PowerMode <function>power_get_controller_desired_mode</function>
</funcdef>
<paramdef>
PowerController* <parameter>controller</parameter>
</paramdef>
</funcprototype>
<funcprototype>
<funcdef>
const char* <function>power_get_controller_id</function>
</funcdef>
<paramdef>
PowerController* <parameter>controller</parameter>
</paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
 
<refsect1 id="power-info-access">
<title>Accessing Power Controllers</title>
<para>
All the power controllers in a system are held in a table, filled in
at link-time. The symbols <varname>__POWER__</varname> and
<varname>__POWER_END</varname> can be used to iterate through this
table, for example:
</para>
<programlisting>
PowerController* controller;
for (controller = &amp;(__POWER__[0]);
controller != &amp;(__POWER_END__);
controller++) {
 
&hellip;
}
</programlisting>
<para>
Each controller has an associated priority, controlling the order in
which they appear in the table. Typically a software-only component
such as a TCP/IP stack would use a small number for the priority, so
that it appears near the start of the table, whereas a device driver
would be nearer the back of the table. When switching to a
lower-powered mode the power management package will iterate through
this table from front to back, thus ensuring that for example the
TCP/IP stack gets a chance to shut down before the underlying ethernet
or other hardware that the stack depends on. Similarly when switching
to a higher-powered mode the power management package will iterate
through this table from back to front.
</para>
<para>
In most systems there will be one special controller,
<varname>power_controller_cpu</varname>, which should be provided by
one of the architectural, variant or platform HAL packages. This
controller will always be the last entry in the table. It is
responsible for the final power down operation when switching to
<type>off</type> mode. Other packages such as device drivers may or
may not declare variable identifiers for their power controllers,
allowing those controllers to be accessed by name as well as by their
entries in the global table.
</para>
</refsect1>
 
<refsect1 id="power-info-global">
<title>Global Power Modes</title>
<para>
The function <function>power_get_mode</function> can be called at any
time to determine the current power mode for the system as a whole.
The return value will be one of <literal>PowerMode_Active</literal>,
<literal>PowerMode_Idle</literal>, <literal>PowerMode_Sleep</literal>
or <literal>PowerMode_Off</literal>. In normal circumstances it is
unlikely that <literal>PowerMode_Off</literal> would be returned since
that mode generally means that the cpu is no longer running.
</para>
<para>
The function <function>power_get_desired_mode</function> returns the
power mode that the system should be running at. Most of the time this
will be the same value as returned by
<function>power_get_mode</function>. However a different value may be
returned when in the middle of changing power modes. For example, if
the current thread runs at a higher priority than the power management
thread then the latter may have been pre-empted in the middle of a
mode change: <function>power_get_mode</function> will return the mode
the system was running at before the mode change started, and
<function>power_get_desired_mode</function> will return the mode the
system should end up in when the mode change completes, barring
further calls to <function>power_set_mode</function>.
</para>
</refsect1>
 
<refsect1 id="power-info-individual">
<title>Individual Controller Power Modes</title>
<para>
The power management package keeps track of the current and desired
modes for each power controller, as well as the modes for the system as
a whole. The function <function>power_get_controller_mode</function>
takes a single argument, a pointer to a power controller, and returns
the power mode that controller is currently running at. Similarly
<function>power_get_controller_desired_mode</function> returns the
power mode that controller should be running at. Most of the time the
current and desired modes for a given controller will be the same, and
will also be the same as the global power mode. However if the power
management thread is preeempted in the middle of a mode change then
some of the controllers will have been updated to the desired global
mode, whereas others will still be at the old mode. The power
management package also provides functionality for manipulating
<link linkend="power-change-controller">
individual controllers</link>, and for <link
linkend="power-attached">detaching</link> controllers from
global mode changes.
</para>
</refsect1>
 
<refsect1 id="power-info-ids">
<title>Power Controller Identification</title>
<para>
In some scenarios the power management package will run completely
automated, and there is no need to identify individual power
controllers. Any form of identification such as a string
description would serve no purpose, but would still consume memory in
the final system. In other scenarios it may be very desirable to
provide some means of identification. For example, while still
debugging it may be useful to see a simple string when printing the
contents of a power controller structure. Alternatively, if the
application is expected to provide some sort of user interface that
gives control over which parts of the system are enabled or disabled,
a string identifier for each controller would be useful. To cope with
these scenarios the power management package provides a configuration
option <varname>CYGIMP_POWER_PROVIDE_STRINGS</varname>. When enabled,
each power controller will contain a pointer to a constant string
which can be accessed via a function
<function>power_get_controller_id</function>. When disabled the system
will not contain these strings, and the function will not be provided.
The following code illustrates how to use this function.
</para>
<programlisting>
#include &lt;stdio.h&gt;
#include &lt;pkgconf/system.h&gt;
#ifndef CYGPKG_POWER
# error The power management package is not present.
#endif
#include &lt;pkgconf/power.h&gt;
#ifndef CYGIMP_POWER_PROVIDE_STRINGS
# error Power controller identifiers are not available.
#endif
#include &lt;cyg/power/power.h&gt;
 
static const char*
mode_to_string(PowerMode mode)
{
const char* result;
switch(mode) {
case PowerMode_Active : result = "active"; break;
case PowerMode_Idle : result = "idle"; break;
case PowerMode_Sleep : result = "sleep"; break;
case PowerMode_Off : result = "off"; break;
default : result = "&lt;unknown&gt;"; break;
}
return result;
}
 
int
main(int argc, char** argv)
{
PowerController* controller;
 
for (controller = &amp;(__POWER__[0]);
controller != &amp;(__POWER_END__);
controller++) {
printf("Controller @ %p: %s, %s\n", controller,
power_get_controller_id(controller),
mode_to_string(power_get_controller_mode(controller)));
}
return 0;
}
</programlisting>
</refsect1>
<refsect1 id="power-info-thread">
<title>The Power Management Thread</title>
<para>
If the power management package is configured to use a separate thread
then a handle for that thread is made available to higher-level code
via the variable <varname>power_thread_handle</varname>. This handle
can be used for a variety of purposes, including manipulating that
thread's priority.
</para>
</refsect1>
 
</refentry>
 
<!-- }}} -->
<!-- {{{ Changing Power Modes -->
 
<refentry id="power-change">
<refmeta>
<refentrytitle>Changing Power Modes</refentrytitle>
</refmeta>
<refnamediv>
<refname>Changing Power Modes</refname>
<refpurpose>reducing or increasing power consumption as needed</refpurpose>
</refnamediv>
 
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>
#include &lt;cyg/power/power.h&gt;
</funcsynopsisinfo>
 
<funcprototype>
<funcdef>
void <function>power_set_mode</function>
</funcdef>
<paramdef>
PowerMode <parameter>new_mode</parameter>
</paramdef>
</funcprototype>
<funcprototype>
<funcdef>
void <function>power_set_controller_mode</function>
</funcdef>
<paramdef>
PowerController* <parameter>controller</parameter>
</paramdef>
<paramdef>
PowerMode <parameter>new_mode</parameter>
</paramdef>
</funcprototype>
<funcprototype>
<funcdef>
void <function>power_set_controller_mode_now</function>
</funcdef>
<paramdef>
PowerController* <parameter>controller</parameter>
</paramdef>
<paramdef>
PowerMode <parameter>new_mode</parameter>
</paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
 
<refsect1 id="power-change-global">
<title>Changing the Global Power Mode</title>
<para>
The primary functionality supported by the power management package is
to change the system's global power mode. This is achieved by calling
the function <function>power_set_mode</function> with a single
argument, which should be one of <literal>PowerMode_Active</literal>,
<literal>PowerMode_Idle</literal>, <literal>PowerMode_Sleep</literal>
or <literal>PowerMode_Off</literal>. Typically this function will only
be invoked in certain scenarios:
</para>
<orderedlist>
<listitem>
<para>
A typical system will contain a policy module which is primarily
responsible for initiating power mode changes, and a thread inside the
power management package. The policy module will call
<function>power_set_mode</function>, which has the effect of
manipulating some internal state in the power management package and
waking up its thread. When this thread gets scheduled to run (its
priority is controlled by a configuration option), it will iterate
over the power controllers and invoke each controller to change its
power mode. There is support for a <link
linkend="power-policy-callback">callback function</link>, and for
<link linkend="power-attached">detached</link> power controllers.
</para>
</listitem>
<listitem>
<para>
After a call to <function>power_set_mode</function> but before the
power management thread has had a chance to iterate over all the
controllers, or even before the thread has been rescheduled at all,
the policy module may decide that a different power mode would be more
appropriate for the current situation and calls
<function>power_set_mode</function> again. This has the effect of
aborting the previous mode change, followed by the power management
thread iterating over the power controllers again for the new mode.
</para>
</listitem>
<listitem>
<para>
If there is no single policy module responsible for power mode
changes, any code can call <function>power_set_mode</function>. If
there are multiple calls in quick succession, earlier calls will
be aborted and the system should end up in the power mode
corresponding to the last call
</para>
</listitem>
<listitem>
<para>
As a special case, it is possible for a power controller to call
<function>power_set_mode</function> when invoked by the power
management thread. For example a power controller could decide that it
is inappropriate for the system to go to sleep because the device it
is associated with is still busy. The effect is as if the policy
module had called <function>power_set_mode</function> again before
the mode change had completed.
</para>
</listitem>
</orderedlist>
<para>
If the power management package has been configured not to use a
separate thread then obviously the behaviour is somewhat different.
The call to <function>power_set_mode</function> will now iterate over
the various power controllers immediately, rather than leaving this to
a separate thread, and the whole mode change completes before
<function>power_set_mode</function> returns. If some other thread or a
DSR calls <function>power_set_mode</function> concurrently the
behaviour of the system is undefined. However, it is still legal for a
power controller to call <function>power_set_mode</function>:
effectively this is a recursive call; it is detected by the system,
and internal state is updated; the recursive
<function>power_set_mode</function> call now returns, and when the
power controller returns back to the original
<function>power_set_mode</function> call it detects what has happened,
aborts the previous mode change, and starts a new mode change as
requested by the controller.
</para>
<para>
<function>power_set_mode</function> is normally invoked from thread
context. If a separate power management thread is used it can be
invoked safely from DSR context. If the system is configured not to
use such a thread, it may or may not be safe to invoke this function
from DSR context: essentially the function just iterates through
the various power controllers, and the documentation or source code of
each controller present in the current system will have to be examined
to determine whether or not this can happen safely in DSR context.
<function>power_set_mode</function> should never be invoked from
ISR context.
</para>
</refsect1>
 
<refsect1 id="power-change-controller">
<title>Manipulating an Individual Power Controller</title>
<para>
In some cases it is desirable to set the power mode of an individual
controller separately from the mode for the system as a whole. For
example if a device is not currently being used then the associated
power controller could be set to <literal>PowerMode_Off</literal>,
even while the system as a whole is still active. This can be achieved
by calling the function
<function>power_set_controller_mode</function>. It takes two
arguments: the first identifies a particular controller; the second
specifies the desired new power mode for that controller. The function
operates in much the same way as <function>power_set_mode</function>,
for example if a separate power management thread is being used then
<function>power_set_controller_mode</function> operates by
manipulating some internal state and waking up that thread. The
limitations are also much the same as for
<function>power_set_mode</function>, so for example
<function>power_set_controller_mode</function> should not be invoked
from inside ISRs.
</para>
<para>
Manipulating individual controllers is often used in conjunction with
the function <link
linkend="power-attached"><function>power_set_controller_attached</function></link>,
allowing the policy module to specify which controllers are affected
by global mode changes.
</para>
</refsect1>
 
<refsect1 id="power-change-controller-now">
<title>Direct Manipulation of a Power Controller</title>
<para>
In exceptional circumstances it may be necessary to invoke a power
controller directly, bypassing the power management thread and
higher-level functionality such as <link
linkend="power-policy-callback">callback functions</link>. The
function <function>power_set_controller_mode_now</function> allows
this. It takes two arguments, a controller and a mode, just like
<function>power_set_controller_mode</function>.
</para>
<para>
Use of <function>power_set_controller_mode_now</function> is
dangerous. For example no attempt is made to synchronise with any
other power mode changes that might be happening concurrently. A
possible use is when the system gets woken up out of
<type>sleep</type> mode: depending on the hardware, on which power
controllers are present, and on the application code it may be
necessary to wake up some power controllers immediately before the
system as a whole is ready to run again.
</para>
</refsect1>
 
</refentry>
 
<!-- }}} -->
<!-- {{{ Policy support -->
 
<refentry id="power-policy">
<refmeta>
<refentrytitle>Support for Policy Modules</refentrytitle>
</refmeta>
<refnamediv>
<refname>Support for Policy Modules</refname>
<refpurpose>closer integration with higher-level code</refpurpose>
</refnamediv>
 
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>
#include &lt;cyg/power/power.h&gt;
</funcsynopsisinfo>
 
<funcprototype>
<funcdef>
void <function>power_set_policy_callback</function>
</funcdef>
<paramdef>
void (*)(PowerController*, PowerMode, PowerMode, PowerMode, PowerMode) <parameter>callback</parameter>
</paramdef>
</funcprototype>
<funcprototype>
<funcdef>
void (*)(PowerController*, PowerMode, PowerMode, PowerMode, PowerMode) <function>power_get_policy_callback</function>
</funcdef>
<void>
</funcprototype>
<funcprototype>
<funcdef>
CYG_ADDRWORD <function>power_get_controller_policy_data</function>
</funcdef>
<paramdef>
PowerController* <parameter>controller</parameter>
</paramdef>
</funcprototype>
<funcprototype>
<funcdef>
void <function>power_set_controller_policy_data</function>
</funcdef>
<paramdef>
PowerController* <parameter>controller</parameter>
</paramdef>
<paramdef>
CYG_ADDRWORD <parameter>data</parameter>
</paramdef>
</funcprototype>
 
</funcsynopsis>
</refsynopsisdiv>
 
<refsect1 id="power-policy-callback">
<title>Policy Callbacks</title>
<para>
The use of a separate thread to perform power mode changes in typical
configurations can cause problems for some policy modules.
Specifically, the policy module can request a mode change for the
system as a whole or for an individual controller, but it does not
know when the power management thread actually gets scheduled to run
again and carry out the request. Although it would be possible for the
policy module to perform some sort of polling, in general that is
undesirable.
</para>
<para>
To avoid such problems the policy module can install a callback
function using <function>power_set_policy_callback</function>. The
current callback function can be retrieved using
<function>power_get_policy_callback</function>. If a callback function
has been installed then it will be called by the power management
package whenever a power controller has been invoked to perform a mode
change. The callback will be called in the context of the power
management thread, so usually it will have to make use of thread
synchronisation primitives to interact with the main policy module. It
is passed five arguments:
</para>
<orderedlist>
<listitem>
<para>
The power controller that has just been invoked to perform a mode
change.
</para>
</listitem>
<listitem>
<para>
The mode this controller was running at before the invocation.
</para>
</listitem>
<listitem>
<para>
The current mode this controller is now running at.
</para>
</listitem>
<listitem>
<para>
The desired mode before the power controller was invoked. Usually this
will be the same as the current mode, unless the controller has
decided for some reason that this was inappropriate.
</para>
</listitem>
<listitem>
<para>
The current desired mode. This will differ from the previous argument
only if there has was another call to
<function>power_set_mode</function> or
<function>power_set_controller_mode</function> while the power
controller was being invoked, probably by the power controller itself.
</para>
</listitem>
</orderedlist>
<para>
A simple example of a policy callback function would be:
</para>
<programlisting>
static void
power_callback(
PowerController* controller,
PowerMode old_mode,
PowerMode new_mode,
PowerMode old_desired_mode,
powerMode new_desired_mode)
{
printf("Power mode change: %s, %s -> %d\n",
power_get_controller_id(controller),
mode_to_string(old_mode),
mode_to_string(new_mode));
 
CYG_UNUSED_PARAM(PowerMode, old_desired_mode);
CYG_UNUSED_PARAM(PowerMode, new_desired_mode);
}
 
int
main(int argc, char** argv)
{
&hellip;
power_set_policy_callback(&amp;power_callback);
&hellip;
}
</programlisting>
<para>
If <function>power_set_controller_mode_now</function> is used to
manipulate an individual controller the policy callback will not be
invoked. This function may get called from any context including DSRs,
and even if there is already a call to the policy callback happening
in some other context, so invoking the callback would usually be
unsafe.
</para>
<para>
If the power management package has not been configured to use a
separate thread then <function>power_set_mode</function> and
<function>power_set_controller_mode</function> will manipulate the
power controllers immediately and invoke the policy callback
afterwards. Therefore the policy callback will typically run in the
same context as the main policy module.
</para>
</refsect1>
 
<refsect1 id="power-policy-data">
<title>Policy-specific Controller Data</title>
<para>
Some policy modules may want to associate some additional data with
each power controller. This could be achieved by for example
maintaining a hash table or similar data structure, but for
convenience the power management package allows higher-level code,
typically the policy module, to store and retrieve one word of data in
each power controller. The function
<function>power_set_controller_policy_data</function> takes two
arguments, a pointer to a power controller and a
<type>CYG_ADDRWORD</type> of data: by appropriate use of casts this
word could be an integer or a pointer to some data structure. The
matching function
<function>power_get_controller_policy_data</function> retrieves the
word previously installed, and can be cast back to an integer or
pointer. The default value for the policy data is 0.
</para>
<para>
For example the following code fragment stores a simple index value in
each power controller. This could then be retrieved by the policy
callback.
</para>
<programlisting>
unsigned int i = 0;
PowerController* controller;
 
for (controller = &amp;(__POWER__[0]);
controller != &amp;(__POWER_END__);
controller++) {
power_set_controller_policy_data(controller, (CYG_ADDRWORD) i++);
}
</programlisting>
<para>
Not all policy modules will require per-controller data. The
configuration option
<varname>CYGIMP_POWER_PROVIDE_POLICY_DATA</varname> can be used to
control this functionality, thus avoiding wasting a small amount of
memory inside each power controller structure.
</para>
 
</refsect1>
</refentry>
 
<!-- }}} -->
<!-- {{{ Attached/detached controllers -->
 
<refentry id="power-attached">
<refmeta>
<refentrytitle>Attached and Detached Controllers</refentrytitle>
</refmeta>
<refnamediv>
<refname>Attached and Detached Controllers</refname>
<refpurpose>control which power controllers are affected by global changes</refpurpose>
</refnamediv>
 
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>
#include &lt;cyg/power/power.h&gt;
</funcsynopsisinfo>
<funcprototype>
<funcdef>
cyg_bool <function>power_get_controller_attached</function>
</funcdef>
<paramdef>
PowerController* <parameter>controller</parameter>
</paramdef>
</funcprototype>
<funcprototype>
<funcdef>
void <function>power_set_controller_attached</function>
</funcdef>
<paramdef>
PowerController* <parameter>controller</parameter>
</paramdef>
<paramdef>
cyg_bool <parameter>new_state</parameter>
</paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
 
<refsect1>
<title>Detaching Power Controllers</title>
<para>
By default the global operation <function>power_set_mode</function>
affects all power controllers. There may be circumstances when this is
not desirable. For example if a particular device is not currently
being used then it can be left switched off: the rest of the system
could be moving between <type>active</type>, <type>idle</type> and
<type>sleep</type> modes, but there is no point in invoking the power
controller for the unused device. To support this the power management
package supports the concept of attached and detached controllers. By
default all controllers are attached, and hence will be affected by
global mode changes. A specific controller can be detached using the
function <function>power_set_controller_attached</function>. This
function takes two arguments, one to specify a particular controller
and another to specify the desired new state.
<function>power_get_controller_attached</function> can be used to
determine whether or not a specific controller is currently attached.
</para>
<para>
The attached or detached state of a controller only affects what
happens during a global mode change, in other words following a call
to <function>power_set_mode</function>. It is still possible to
manipulate a detached controller using
<function>power_set_controller_mode</function> or
<function>power_set_controller_mode_now</function>.
</para>
 
</refsect1>
</refentry>
 
<!-- }}} -->
<!-- {{{ Implementing -->
 
<refentry id="power-controller">
<refmeta>
<refentrytitle>Implementing a Power Controller</refentrytitle>
</refmeta>
<refnamediv>
<refname>Implementing a Power Controller</refname>
<refpurpose>adding power management support to device drivers and
other packages</refpurpose>
</refnamediv>
 
<refsect1>
<title>Implementing a Power Controller</title>
<para>
A system will have some number of power controllers. Usually there
will be one power controller for the cpu,
<varname>power_controller_cpu</varname>, typically provided by one of
the HAL packages and responsible for managing the processor itself and
associated critical components such as memory. Some or all of the
device drivers will provide power controllers, allowing the power
consumption of the associated devices to be controlled. There may be
some arbitrary number of other controllers present in the system. The
power management package does not impose any restrictions on the
number or nature of the power controllers in the system, other than
insisting that at most one <varname>power_controller_cpu</varname> be
provided.
</para>
<para>
Each power controller involves a single data structure of type
<structname>PowerController</structname>, defined in the header file
<filename class="headerfile">cyg/power/power.h</filename>. These data
structures should all be placed in the table
<literal>__POWER__</literal>, so that the power management package and
other code can easily locate all the controllers in the system. This
table is constructed at link-time, avoiding code-size or run-time
overheads. To facilitate this the package provides two macros which
should be used to define a power controller,
<literal>POWER_CONTROLLER()</literal> and
<literal>POWER_CONTROLLER_CPU()</literal>.
</para>
<para>
The macro <literal>POWER_CONTROLLER</literal> takes four arguments:
</para>
<orderedlist>
<listitem>
<para>
A variable name. This can be used to access the power controller
directly, as well as via the table.
</para>
</listitem>
<listitem>
<para>
A priority. The table of power controllers is sorted, such that power
controllers with a numerically lower priority come earlier in the
table. The special controller <varname>power_controller_cpu</varname>
always comes at the end of the table. When moving from a high-power
mode to a lower-powered mode, the power management package iterates
through the table from front to back. When moving to a higher-powered
mode the reverse direction is used. The intention is that the power
controller for a software-only package such as a TCP/IP stack should
appear near the start of the table, whereas the controllers for the
ethernet and similar devices would be near the end of the table. Hence
when the policy module initiates a mode change to a lower-powered mode
the TCP/IP stack gets a chance to cancel this mode change, before the
devices it depends on are powered down. Similarly when moving to a
higher-powered mode the devices will be re-activated before any
software that depends on those devices.
</para>
<para>
The header file <filename
class="headerfile">cyg/power/power.h</filename> defines three
priorities <literal>PowerPri_Early</literal>,
<literal>PowerPri_Typical</literal> and
<literal>PowerPri_Late</literal>. For most controllers one of these
priorities, possibly with a small number added or subtracted, will
give sufficient control. If an application developer is uncertain
about the relative priorities of the various controllers, a simple
<link linkend="power-info-ids">test program</link> that iterates over
the table will quickly eliminate any confusion.
</para>
</listitem>
<listitem>
<para>
A constant string identifier. If the system has been configured
without support for such identifiers
(<varname>CYGIMP_POWER_PROVIDE_STRINGS</varname>) then this identifer
will be discarded at compile-time. Otherwise it will be made available
to higher-level code using the function
<function>power_get_controller_id</function>.
</para>
</listitem>
<listitem>
<para>
A function pointer. This will be invoked to perform actual mode
changes, as described below.
</para>
</listitem>
</orderedlist>
<para>
A typical example of the use of the
<literal>POWER_CONTROLLER</literal> macro would be as follows:
</para>
<programlisting>
#include &lt;pkgconf/system.h&gt;
 
#ifdef CYGPKG_POWER
# include &lt;cyg/power/power.h&gt;
 
static void
xyzzy_device_power_mode_change(
PowerController* controller,
PowerMode desired_mode,
PowerModeChange change)
{
// Do the work
}
 
static POWER_CONTROLLER(xyzzy_power_controller, \
PowerPri_Late, \
"xyzzy device", \
&amp;xyzzy_device_power_mode_change);
#endif
</programlisting>
<para>
This creates a variable <varname>xyzzy_power_controller</varname>,
which is a power controller data structure that will end up near the
end of the table of power controllers. Higher-level code can
iterate through this table and report the string <literal>"xyzzy
device"</literal> to the user. Whenever there is a mode change
operation that affects this controller, the function
<function>xyzzy_device_power_mode_change</function> will be invoked.
The variable is declared static so this controller cannot be
manipulated by name in any other code. Alternatively, if the variable
had not been declared static other code could manipulate this
controller by name as well as through the table, especially if the
package for the xyzzy device driver explicitly declared this
variable in an exported header file. Obviously exporting the variable
involves a slight risk of a name clash at link time.
</para>
<para>
The above code explicitly checks for the presence of the power
management package before including that package's header file or
providing any related functionality. Since power management
functionality is optional, such checks are recommended.
</para>
<para>
The macro <literal>POWER_CONTROLLER_CPU</literal> only takes two
arguments, a string identifier and a mode change function pointer.
This macro always instantiates a variable
<varname>power_controller_cpu</varname> so there is no need to provide
a variable name. The resulting power controller structure always
appears at the end of the table, so there is no need to specify a
priority. Typical usage of the <literal>POWER_CONTROLLER_CPU</literal>
macro would be:
</para>
<programlisting>
static void
wumpus_processor_power_mode_change(
PowerController* controller,
PowerMode desired_mode,
PowerModeChange change)
{
// Do the work
}
 
POWER_CONTROLLER_CPU("wumpus processor", \
&amp;wumpus_processor_power_mode_change);
</programlisting>
<para>
This defines a power controller structure
<varname>power_controller_cpu</varname>. It should not be declared
static since higher-level code may well want to manipulate the cpu's
power mode directly, and the variable is declared by the power
management package's header file.
</para>
<para>
Some care has to be taken to ensure that the power controllers
actually end up in the final executable. If a power controller
variable ends up in an ordinary library and is never referenced
directly then typically the linker will believe that the variable is
not needed and it will not end up in the executable. For eCos packages
this can be achieved in the CDL, by specifying that the containing
source file should end up in <filename>libextras.a</filename> rather
than the default <filename>libtarget.a</filename>:
</para>
<programlisting>
cdl_package CYGPKG_HAL_WUMPUS_ARCH {
&hellip;
compile -library=libextras.a data.c
}
</programlisting>
<para>
If the file <filename>data.c</filename> instantiates a power
controller this is now guaranteed to end up in the final executable,
as intended. Typically HAL and device driver packages will already
have some data that must not be eliminated by the linker, so they will
already contain a file that gets built into
<filename>libextras.a</filename>. For power controllers defined inside
application code it is important that the power controllers end up in
<filename>.o</filename> object files rather than in
<filename>.a</filename> library archive files.
</para>
<para>
All the real work of a power controller is done by the mode change
function. If the power management package has been configured to use a
separate thread then this mode change function will be invoked by that
thread (except for the special case of <link
linkend="power-change-controller-now"><function>power_set_controller_mode_now</function></link>).
If no separate thread is used then the mode change function will be
invoked directly by <function>power_set_mode</function> or
<function>power_set_controller_mode</function>.
</para>
<para>
The mode change function will be invoked with three arguments. The
first argument identifies the power controller. Usually this argument
is not actually required since a given mode change function will only
ever be invoked for a single power controller. For example,
<function>xyzzy_device_power_mode_change</function> will only ever be
used in conjunction with <varname>xyzzy_power_controller</varname>.
However there may be some packages which contain multiple controllers,
all of which can share a single mode change function, and in that case
it is essential to identify the specific controller. The second
argument specifies the mode the controller should switch to, if
possible: it will be one of <literal>PowerMode_Active</literal>,
<literal>PowerMode_Idle</literal>, <literal>PowerMode_Sleep</literal>
or <literal>PowerMode_Off</literal>. The final argument will be one of
<literal>PowerModeChange_Controller</literal>,
PowerModeChange_ControllerNow, or
<literal>PowerModeChange_Global</literal>, and identifies the call
that caused this invocation. For example, if the mode change function
was invoked because of a call to <function>power_set_mode</function>
then this argument will be <literal>PowerModeChange_Global</literal>.
It is up to each controller to decide how to interpret this final
argument. A typical controller might reject a global request to switch
to <type>off</type> mode if the associated device is still busy, but
if the request was aimed specifically at this controller then it could
instead abort any current I/O operations and switch off the device.
</para>
<para>
The <structname>PowerController</structname> data structure contains
one field, <structfield>mode</structfield>, that needs to be updated
by the power mode change function. At all times it should indicate the
current mode for this controller. When a mode change is requested the
desired mode is passed as the second argument. The exact operation of
the power mode change function depends very much on what is being
controlled and the current circumstances, but some guidelines are
possible:
</para>
<orderedlist>
<listitem>
<para>
If the request can be satisfied without obvious detriment, do so and
update the <structfield>mode</structfield> field. Reducing the power
consumption of a device that is not currently being used is generally
harmless.
</para>
</listitem>
<listitem>
<para>
If a request is a no-op, for example if the system is switching
from <type>idle</type> to <type>sleep</type> mode and the controller
does not distinguish between these modes, simply act as if the request
was satisfied.
</para>
</listitem>
<listitem>
<para>
If a request is felt to be unsafe, for example shutting down a
device that is still in use, then the controller may decide
to reject this request. This is especially true if the request was a
global mode change as opposed to one intended specifically for this
controller: in the latter case the policy module should be given due
deference. There are a number of ways in which a request can be
rejected:
</para>
<orderedlist>
<listitem>
<para>
If the request cannot be satisfied immediately but may be feasible in
a short while, leave the <structfield>mode</structfield> field
unchanged. Higher-level code in the policy module can interpret this
as a hint to retry the operation a little bit later. This approach is
also useful if the mode change can be started but will take some time
to complete, for example shutting down a socket connection, and
additional processing will be needed later on.
</para>
</listitem>
<listitem>
<para>
If the request is felt to be inappropriate, for example switching off
a device that is still in use, the mode change function can
call <function>power_set_controller_mode</function> to reset the
desired mode for this controller back to the current mode.
Higher-level code can then interpret this as a hint that there is more
activity in the system than had been apparent.
</para>
</listitem>
<listitem>
<para>
For a global mode change, if the new mode is felt to be inappropriate
then the power controller can call <function>power_set_mode</function>
to indicate this. An example of this would be the policy module
deciding to switch off the whole unit while there is still I/O
activity.
</para>
</listitem>
</orderedlist>
</listitem>
</orderedlist>
<para>
Mode change functions should not directly manipulate any other fields
in the <structname>PowerController</structname> data structure. If it
is necessary to keep track of additional data then static variables
can be used.
</para>
<para>
It should be noted that the above are only guidelines. Their
application in any given situation may be unclear. In addition the
detailed requirements of specific systems will vary, so even if the
power controller for a given device driver follows the above
guidelines exactly it may turn out that slightly different behaviour
would be more appropriate for the actual system that is being
developed. Fortunately the open source nature of
<productname>eCos</productname> allows system developers to fine-tune
power controllers to meet their exact requirements.
</para>
 
</refsect1>
</refentry>
 
<!-- }}} -->
 
<!-- /reference -->
</part>
/common/v2_0/src/power_data.cxx
0,0 → 1,77
//==========================================================================
//
// power_data.cxx
//
// Initialization and table support for power management.
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): bartv
// Contributors: bartv
// Date: 2001-06-12
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <pkgconf/power.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/hal/hal_tables.h>
 
// Run-time package initialization. This is only required when the
// power management package runs its own thread. It involves a dummy
// class plus a single instance of that class. Initialization is
// scheduled for after low-level device driver init, kernel init, and
// I/O subsystem init. That way all device drivers should be up and
// running already.
 
#ifdef CYGPKG_POWER_THREAD
externC void power_init(void);
 
class power_init_class {
public:
power_init_class(void) {
power_init();
}
};
 
static power_init_class _power_init CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO + 1);
#endif
 
// Define the table for power controllers.
CYG_HAL_TABLE_BEGIN( __POWER__, power );
CYG_HAL_TABLE_END( __POWER_END__, power );
/common/v2_0/src/power.cxx
0,0 → 1,371
//==========================================================================
//
// power.cxx
//
// Main implementation of power management support.
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): bartv
// Contributors: bartv
// Date: 2001-06-18
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
// Provide the external (non-inline) definitions of the inline functions
// in power.h so there's something available in C code when the compiler
// chooses not to inline
#define POWER_INLINE extern "C"
 
#include <pkgconf/power.h>
#include <cyg/power/power.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_ass.h>
#include <cyg/hal/hal_tables.h>
 
// ----------------------------------------------------------------------------
// Statics. Most of these are only relevant when a separate power
// management thread is being used. Some of these are exported, e.g.
// to allow the use of inline functions.
 
// The current power mode for the system as a whole.
PowerMode __power_mode = PowerMode_Active;
 
// The mode that the system should be running at.
PowerMode __power_desired_mode = PowerMode_Active;
 
// The policy callback function, if any.
__power_policy_callback_t __power_policy_callback = 0;
 
// This flag is used to abort a mode change. It allows a controller to
// call power_set_mode() while the mode is already being changed.
static volatile cyg_bool abort_mode_change = false;
 
#ifdef CYGPKG_POWER_THREAD
static unsigned char power_thread_stack[CYGNUM_POWER_THREAD_STACKSIZE];
static cyg_thread power_thread;
// The power management thread's handle is exported to support
// operations like changing the thread's priority.
cyg_handle_t power_thread_handle;
 
// This semaphore is used to wake up the power management thread when there
// is work to be done.
static cyg_sem_t power_thread_action;
 
#else
static cyg_bool power_doing_it = false;
static cyg_uint power_todo_count = 0;
#endif
 
// ----------------------------------------------------------------------------
// Synchronisation.
//
// There are two exported functions to worry about: power_set_mode()
// and power_set_controller_mode(). There are also two main scenarios:
// CYGPKG_POWER_THREAD enabled and CYGPKG_POWER_THREAD_DISABLED.
//
// If CYGPKG_POWER_THREAD is enabled then any external code may at any
// time invoke the exported functions. These are asynchronous calls.
// In addition when the power management thread invokes a power
// controller that controller may also call the exported functions,
// synchronously. In either scenario the calls can return before the
// operation has completed, hence the policy callback functionality.
//
// If CYGPKG_POWER_THREAD is disabled then there may be only one
// external call to the exported functions, and the operation must
// complete before that call returns. If there are multiple concurrent
// external calls then the behaviour of the system is undefined.
// Really. It is still possible for power controllers to call the
// exported functions synchronously, which complicates things
// somewhat.
//
// The CYGPKG_POWER_THREAD case is the easier to handle. The power
// management thread simply loops forever, waiting on a semaphore
// until there is some work to be done and then checking internal
// state to figure out what that work should be. Some care has to be
// taken that the internal state gets updated and read atomically,
// which can be achieved by cyg_scheduler_lock() and unlock() calls in
// strategic places. Obviously it is undesirable to keep these locks
// longer than is absolutely necessary since that would impact
// dispatch latency, and in particular power controllers must not be
// invoked with the scheduler locked because there are no specific
// restrictions on what a controller may or may not do.
//
// The call graph is something like:
// power_thread_fn() - the thread entry point, loops waiting on the semaphore
// power_doit() - do the real work. This can be either a global mode
// change or one or more individual controller mode changes.
// Either operation involves iterating through the controllers.
// power_change_controller_mode() - manipulate an individual controller.
//
// There is one little complication. If during a power_doit()
// set_mode() loop there is a call to power_set_mode() then the
// current loop should be aborted. This is especially important when
// switching to off mode and a controller has decided to cancel this
// via another call to set_mode().
//
// If no separate thread is used then there will only ever be one
// external call. That will result in an invocation of
// power_nothread_doit(), which in turn calls power_doit() and
// power_change_controller_mode() as in the threaded case. A flag is
// used so that it is possible to distinguish between external and
// synchronous calls, and a counter ensures that synchronous calls are
// processed correctly. Recursion is avoided so that stack usage
// remains deterministic.
// power_set_mode()/power_set_controller_mode()
// power_nothread_doit()
// power_doit()
// power_change_controller_mode();
//
// The main fields in the power controller data structures to worry
// about are "mode", "desired_mode", and "change_this". "mode" is only
// manipulated by the power controller itself, and since all power
// controller accesses are serialized no problems arise.
// "desired_mode" and "change_this" are updated by power_set_mode()
// and power_set_controller_mode(), and read by power_doit(). If a separate
// thread is in use then the scheduler lock protects access to thse fields.
// Without a separate thread concurrency is not an issue. Obviously there
// are other fields and variables, but most of these will only be set during
// system start-up and the rest do not require any special attention.
 
// ----------------------------------------------------------------------------
// Do the real work.
//
// power_change_controller_mode() acts on a single controller. It is invoked only
// from power_doit(), either for a global mode change or for an individual mode change.
// It should be invoked with the scheduler unlocked - power_doit() is responsible for
// synchronizing with the external calls.
static inline void
power_change_controller_mode(PowerController* controller, PowerMode desired_mode, cyg_bool change_this)
{
// The policy callback will want to know the previous power mode.
PowerMode old_mode = controller->mode;
 
// Invoke the mode change operation. Note that
// controller->change_this and controller->desired_mode may have
// been updated by now, but at some point they did have values
// which required a mode change.
(*controller->change_mode)(controller, desired_mode, change_this ? PowerModeChange_Controller : PowerModeChange_Global);
 
// Report the results to higher-level code. It is unlikely that
// the policy callback will be changed while the system is running,
// but just in case somebody installs a null pointer between the
// check and the call...
void (*callback)(PowerController*, PowerMode, PowerMode, PowerMode, PowerMode) = __power_policy_callback;
if (0 != callback) {
(*callback)(controller, old_mode, controller->mode, desired_mode, controller->desired_mode);
}
}
 
// power_doit() is responsible for a single iteration over the various controllers,
// aborting if there is a global mode change during the current iteration. The
// calling code, either power_thread_fn() or power_nothread_doit(), will take
// care of the higher-level iterating while there is work to be done.
//
// If a global mode change has been requested then the order in which the controllers
// are invoked is significant: front->back for lowering power modes, back->front for
// a higher power mode. If there are individual changes to be processed then
// arbitrarily front->back is used as well.
static inline void
power_doit()
{
PowerController* controller;
 
abort_mode_change = false;
 
if (__power_desired_mode < __power_mode) {
// The new mode is more active than the old one, so start with
// the power controllers at the back of the table.
for (controller = &(__POWER_END__) - 1; !abort_mode_change && (controller >= &(__POWER__[0])); controller--) {
PowerMode desired_mode;
cyg_bool change_this;
#ifdef CYGPKG_POWER_THREAD
// Read the desired_mode and change_this flags atomically.
cyg_scheduler_lock();
desired_mode = controller->desired_mode;
change_this = controller->change_this;
cyg_scheduler_unlock();
#else
desired_mode = controller->desired_mode;
change_this = controller->change_this;
#endif
// If this controller is not running at the desired mode, change it.
if (desired_mode != controller->mode) {
power_change_controller_mode(controller, desired_mode, change_this);
}
}
} else { // __power_desired_mode >= __power_mode.
// Either a global mode change to a less active mode, or
// one or more individual controller changes. Other than
// iterating in a different direction, the code is the same
// as above.
for (controller = &(__POWER__[0]); !abort_mode_change && (controller != &(__POWER_END__)); controller++) {
PowerMode desired_mode;
cyg_bool change_this;
#ifdef CYGPKG_POWER_THREAD
cyg_scheduler_lock();
desired_mode = controller->desired_mode;
change_this = controller->change_this;
cyg_scheduler_unlock();
#else
desired_mode = controller->desired_mode;
change_this = controller->change_this;
#endif
if (desired_mode != controller->mode) {
power_change_controller_mode(controller, desired_mode, change_this);
}
}
}
 
// All of the controllers have been invoked. If there have been no
// intervening calls to power_set_mode() (which would have updated
// abort_mode_change) then we must now be running at the desired
// global mode.
if (!abort_mode_change) {
__power_mode = __power_desired_mode;
}
}
 
#ifdef CYGPKG_POWER_THREAD
static void
power_thread_fn(cyg_addrword_t param)
{
for (;;) {
// Currently idle. Wait for a request to change power modes.
cyg_semaphore_wait(&power_thread_action);
power_doit();
}
}
#else
static inline void
power_nothread_doit()
{
power_todo_count++;
if (!power_doing_it) {
power_doing_it = true;
do {
power_doit();
} while (--power_todo_count > 0);
power_doing_it = false;
}
}
#endif
 
// ----------------------------------------------------------------------------
// The exported calls.
 
extern "C" void
power_set_controller_mode(PowerController* controller, PowerMode new_mode)
{
#ifdef CYGPKG_POWER_THREAD
cyg_scheduler_lock(); // Protect against concurrent calls
#endif
controller->desired_mode = new_mode;
controller->change_this = true;
 
#ifdef CYGPKG_POWER_THREAD
cyg_scheduler_unlock();
cyg_semaphore_post(&power_thread_action);
#else
power_nothread_doit();
#endif
}
 
extern "C" void
power_set_mode(PowerMode new_mode)
{
PowerController* controller;
 
#ifdef CYGPKG_POWER_THREAD
cyg_scheduler_lock();
#endif
__power_desired_mode = new_mode;
abort_mode_change = true;
// Update each controller. Most importantly, clear the
// "change_this" flag in every power controller. The net result is
// that power_set_mode() overrides any power_set_controller_mode()
// operations that have not yet been processed, but future
// power_set_controller_mode() calls will have the desired effect.
for (controller = &(__POWER__[0]); controller != &(__POWER_END__); controller++) {
if (controller->attached) {
controller->change_this = 0;
controller->desired_mode = new_mode;
}
}
 
#ifdef CYGPKG_POWER_THREAD
cyg_scheduler_unlock();
cyg_semaphore_post(&power_thread_action);
#else
power_nothread_doit();
#endif
}
 
// ----------------------------------------------------------------------------
// Power management initialization. This gets called from
// power_data.cxx using a prioritized constructors. Doing this way
// minimizes the amount of data that is going to end up in libextras.a
// and hence in the final executable, allowing linker garbage collection
// to clean up as much as possible. The main operation here is to start
// up a separate power management thread when configured to do so.
//
// If no separate thread is being used then no run-time initialization
// is needed.
#ifdef CYGPKG_POWER_THREAD
extern "C" void
power_init(void)
{
cyg_semaphore_init(&power_thread_action, 0);
cyg_thread_create(CYGNUM_POWER_THREAD_PRIORITY,
&power_thread_fn,
(cyg_addrword_t) 0,
"Power management thread",
power_thread_stack,
CYGNUM_POWER_THREAD_STACKSIZE,
&power_thread_handle,
&power_thread
);
cyg_thread_resume(power_thread_handle);
}
#endif
 
/common/v2_0/ChangeLog
0,0 → 1,79
2003-02-25 Jonathan Larmour <jifl@eCosCentric.com>
 
* doc/power.sgml: Declare as <part> not <reference> to get
correct TOC numbering.
Fix build on some jade versions by using &amp; instead of
plain '&'.
 
2003-02-24 Jonathan Larmour <jifl@eCosCentric.com>
 
* cdl/power.cdl: Fix doc links for config tool's doc system.
 
* doc/power.sgml: Comment out DOCTYPE for now to allow building
with standard doc build.
 
2001-11-21 Jonathan Larmour <jlarmour@redhat.com>
 
* include/power.h: Use a POWER_INLINE macro for "inline" to allow
non-inline versions to be defined when the C compiler chooses not to
inline.
* src/power.cxx: Using POWER_INLINE, define the non-inline versions
here.
 
2001-08-01 Bart Veer <bartv@redhat.com>
 
* doc/power.sgml, doc/*.html:
Major update to reflect the changes below and clarify
the expected behaviour.
 
* include/power.h:
* src/power.cxx:
Merge from development version. Various issues such as
synchronization should now be resolved.
 
* cdl/power.cdl:
Remove constraints requiring HAL support.
Add build-related options.
 
* tests/powertest.cxx:
Start of a testcase for power management
 
2001-07-13 Bart Veer <bartv@redhat.com>
 
* Initial check-in
 
//===========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//===========================================================================

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.