📄 power.sgml
字号:
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>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -