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" |
> </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 -- 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 <pkgconf/system.h> |
|
#ifdef CYGPKG_POWER |
# include <cyg/power/power.h> |
|
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", \ |
&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", \ |
&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 { |
… |
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" |
> </TD |
></TR |
><TR |
><TD |
WIDTH="33%" |
ALIGN="left" |
VALIGN="top" |
>Attached and Detached Controllers</TD |
><TD |
WIDTH="34%" |
ALIGN="center" |
VALIGN="top" |
> </TD |
><TD |
WIDTH="33%" |
ALIGN="right" |
VALIGN="top" |
> </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" |
> </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 |
> — eCos support for Power Management</DT |
><DT |
><A |
HREF="power-info.html" |
>Power Management Information</A |
> — finding out about the various power controllers in the system</DT |
><DT |
><A |
HREF="power-change.html" |
>Changing Power Modes</A |
> — reducing or increasing power consumption as needed</DT |
><DT |
><A |
HREF="power-policy.html" |
>Support for Policy Modules</A |
> — closer integration with higher-level code</DT |
><DT |
><A |
HREF="power-attached.html" |
>Attached and Detached Controllers</A |
> — control which power controllers are affected by global changes</DT |
><DT |
><A |
HREF="power-controller.html" |
>Implementing a Power Controller</A |
> — 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" |
> </TD |
><TD |
WIDTH="34%" |
ALIGN="center" |
VALIGN="top" |
> </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" |
> </TD |
><TD |
WIDTH="34%" |
ALIGN="center" |
VALIGN="top" |
> </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 -- 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 <cyg/power/power.h></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" |
> </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 -- 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 <cyg/power/power.h> |
|
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 = &(__POWER__[0]); |
controller != &(__POWER_END__); |
controller++) { |
|
… |
}</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 <stdio.h> |
#include <pkgconf/system.h> |
#ifndef CYGPKG_POWER |
# error The power management package is not present. |
#endif |
#include <pkgconf/power.h> |
#ifndef CYGIMP_POWER_PROVIDE_STRINGS |
# error Power controller identifiers are not available. |
#endif |
#include <cyg/power/power.h> |
|
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 = "<unknown>"; break; |
} |
return result; |
} |
|
int |
main(int argc, char** argv) |
{ |
PowerController* controller; |
|
for (controller = &(__POWER__[0]); |
controller != &(__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" |
> </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 -- 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" |
> </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 -- 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 <cyg/power/power.h></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" |
> </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 -- 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 <cyg/power/power.h></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 -> %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) |
{ |
… |
power_set_policy_callback(&power_callback); |
… |
}</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 = &(__POWER__[0]); |
controller != &(__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" |
> </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 <cyg/power/power.h> |
|
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 = &(__POWER__[0]); |
controller != &(__POWER_END__); |
controller++) { |
|
… |
} |
</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 <stdio.h> |
#include <pkgconf/system.h> |
#ifndef CYGPKG_POWER |
# error The power management package is not present. |
#endif |
#include <pkgconf/power.h> |
#ifndef CYGIMP_POWER_PROVIDE_STRINGS |
# error Power controller identifiers are not available. |
#endif |
#include <cyg/power/power.h> |
|
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 = "<unknown>"; break; |
} |
return result; |
} |
|
int |
main(int argc, char** argv) |
{ |
PowerController* controller; |
|
for (controller = &(__POWER__[0]); |
controller != &(__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 <cyg/power/power.h> |
</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 <cyg/power/power.h> |
</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) |
{ |
… |
power_set_policy_callback(&power_callback); |
… |
} |
</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 = &(__POWER__[0]); |
controller != &(__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 <cyg/power/power.h> |
</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 <pkgconf/system.h> |
|
#ifdef CYGPKG_POWER |
# include <cyg/power/power.h> |
|
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", \ |
&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", \ |
&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 { |
… |
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 & 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#### |
//=========================================================================== |