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