comparison packages/services/power/common/current/doc/power-controller.html @ 208:e0c0827131d1 ecos

Merge from eCos master repository on 2002-05-20-20:11:54-BST
author jlarmour
date Mon, 20 May 2002 22:19:26 +0000
parents
children 74dbf4c3f2e1
comparison
equal deleted inserted replaced
207:74c807ddde34 208:e0c0827131d1
1 <!-- Copyright (C) 2001 Red Hat, Inc. -->
2 <!-- This material may be distributed only subject to the terms -->
3 <!-- and conditions set forth in the Open Publication License, v1.0 -->
4 <!-- or later (the latest version is presently available at -->
5 <!-- http://www.opencontent.org/openpub/). -->
6 <!-- Distribution of substantively modified versions of this -->
7 <!-- document is prohibited without the explicit permission of the -->
8 <!-- copyright holder. -->
9 <!-- Distribution of the work or derivative of the work in any -->
10 <!-- standard (paper) book form is prohibited unless prior -->
11 <!-- permission is obtained from the copyright holder. -->
12 <HTML
13 ><HEAD
14 ><TITLE
15 >Implementing a Power Controller</TITLE
16 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
17 <META
18 NAME="GENERATOR"
19 CONTENT="Modular DocBook HTML Stylesheet Version 1.64
20 "><LINK
21 REL="HOME"
22 TITLE="eCos Power Management Support"
23 HREF="services-power.html"><LINK
24 REL="PREVIOUS"
25 TITLE="Attached and Detached Controllers"
26 HREF="power-attached.html"></HEAD
27 ><BODY
28 CLASS="REFENTRY"
29 BGCOLOR="#FFFFFF"
30 TEXT="#000000"
31 LINK="#0000FF"
32 VLINK="#840084"
33 ALINK="#0000FF"
34 ><DIV
35 CLASS="NAVHEADER"
36 ><TABLE
37 WIDTH="100%"
38 BORDER="0"
39 CELLPADDING="0"
40 CELLSPACING="0"
41 ><TR
42 ><TH
43 COLSPAN="3"
44 ALIGN="center"
45 >eCos Power Management Support</TH
46 ></TR
47 ><TR
48 ><TD
49 WIDTH="10%"
50 ALIGN="left"
51 VALIGN="bottom"
52 ><A
53 HREF="power-attached.html"
54 >Prev</A
55 ></TD
56 ><TD
57 WIDTH="80%"
58 ALIGN="center"
59 VALIGN="bottom"
60 ></TD
61 ><TD
62 WIDTH="10%"
63 ALIGN="right"
64 VALIGN="bottom"
65 >&nbsp;</TD
66 ></TR
67 ></TABLE
68 ><HR
69 ALIGN="LEFT"
70 WIDTH="100%"></DIV
71 ><H1
72 ><A
73 NAME="POWER-CONTROLLER"
74 >Implementing a Power Controller</A
75 ></H1
76 ><DIV
77 CLASS="REFNAMEDIV"
78 ><A
79 NAME="AEN355"
80 ></A
81 ><H2
82 >Name</H2
83 >Implementing a Power Controller&nbsp;--&nbsp;adding power management support to device drivers and
84 other packages</DIV
85 ><DIV
86 CLASS="REFSECT1"
87 ><A
88 NAME="AEN358"
89 ></A
90 ><H2
91 >Implementing a Power Controller</H2
92 ><P
93 >A system will have some number of power controllers. Usually there
94 will be one power controller for the cpu,
95 <TT
96 CLASS="VARNAME"
97 >power_controller_cpu</TT
98 >, typically provided by one of
99 the HAL packages and responsible for managing the processor itself and
100 associated critical components such as memory. Some or all of the
101 device drivers will provide power controllers, allowing the power
102 consumption of the associated devices to be controlled. There may be
103 some arbitrary number of other controllers present in the system. The
104 power management package does not impose any restrictions on the
105 number or nature of the power controllers in the system, other than
106 insisting that at most one <TT
107 CLASS="VARNAME"
108 >power_controller_cpu</TT
109 > be
110 provided.</P
111 ><P
112 >Each power controller involves a single data structure of type
113 <SPAN
114 CLASS="STRUCTNAME"
115 >PowerController</SPAN
116 >, defined in the header file
117 <TT
118 CLASS="FILENAME"
119 >cyg/power/power.h</TT
120 >. These data
121 structures should all be placed in the table
122 <TT
123 CLASS="LITERAL"
124 >__POWER__</TT
125 >, so that the power management package and
126 other code can easily locate all the controllers in the system. This
127 table is constructed at link-time, avoiding code-size or run-time
128 overheads. To facilitate this the package provides two macros which
129 should be used to define a power controller,
130 <TT
131 CLASS="LITERAL"
132 >POWER_CONTROLLER()</TT
133 > and
134 <TT
135 CLASS="LITERAL"
136 >POWER_CONTROLLER_CPU()</TT
137 >.</P
138 ><P
139 >The macro <TT
140 CLASS="LITERAL"
141 >POWER_CONTROLLER</TT
142 > takes four arguments:</P
143 ><P
144 ></P
145 ><OL
146 TYPE="1"
147 ><LI
148 ><P
149 >A variable name. This can be used to access the power controller
150 directly, as well as via the table.</P
151 ></LI
152 ><LI
153 ><P
154 >A priority. The table of power controllers is sorted, such that power
155 controllers with a numerically lower priority come earlier in the
156 table. The special controller <TT
157 CLASS="VARNAME"
158 >power_controller_cpu</TT
159 >
160 always comes at the end of the table. When moving from a high-power
161 mode to a lower-powered mode, the power management package iterates
162 through the table from front to back. When moving to a higher-powered
163 mode the reverse direction is used. The intention is that the power
164 controller for a software-only package such as a TCP/IP stack should
165 appear near the start of the table, whereas the controllers for the
166 ethernet and similar devices would be near the end of the table. Hence
167 when the policy module initiates a mode change to a lower-powered mode
168 the TCP/IP stack gets a chance to cancel this mode change, before the
169 devices it depends on are powered down. Similarly when moving to a
170 higher-powered mode the devices will be re-activated before any
171 software that depends on those devices.</P
172 ><P
173 >The header file <TT
174 CLASS="FILENAME"
175 >cyg/power/power.h</TT
176 > defines three
177 priorities <TT
178 CLASS="LITERAL"
179 >PowerPri_Early</TT
180 >,
181 <TT
182 CLASS="LITERAL"
183 >PowerPri_Typical</TT
184 > and
185 <TT
186 CLASS="LITERAL"
187 >PowerPri_Late</TT
188 >. For most controllers one of these
189 priorities, possibly with a small number added or subtracted, will
190 give sufficient control. If an application developer is uncertain
191 about the relative priorities of the various controllers, a simple
192 <A
193 HREF="power-info.html#POWER-INFO-IDS"
194 >test program</A
195 > that iterates over
196 the table will quickly eliminate any confusion.</P
197 ></LI
198 ><LI
199 ><P
200 >A constant string identifier. If the system has been configured
201 without support for such identifiers
202 (<TT
203 CLASS="VARNAME"
204 >CYGIMP_POWER_PROVIDE_STRINGS</TT
205 >) then this identifer
206 will be discarded at compile-time. Otherwise it will be made available
207 to higher-level code using the function
208 <TT
209 CLASS="FUNCTION"
210 >power_get_controller_id</TT
211 >. </P
212 ></LI
213 ><LI
214 ><P
215 >A function pointer. This will be invoked to perform actual mode
216 changes, as described below.</P
217 ></LI
218 ></OL
219 ><P
220 >A typical example of the use of the
221 <TT
222 CLASS="LITERAL"
223 >POWER_CONTROLLER</TT
224 > macro would be as follows:</P
225 ><TABLE
226 BORDER="0"
227 BGCOLOR="#E0E0E0"
228 WIDTH="100%"
229 ><TR
230 ><TD
231 ><PRE
232 CLASS="PROGRAMLISTING"
233 >#include &lt;pkgconf/system.h&gt;
234
235 #ifdef CYGPKG_POWER
236 # include &lt;cyg/power/power.h&gt;
237
238 static void
239 xyzzy_device_power_mode_change(
240 PowerController* controller,
241 PowerMode desired_mode,
242 PowerModeChange change)
243 {
244 // Do the work
245 }
246
247 static POWER_CONTROLLER(xyzzy_power_controller, \
248 PowerPri_Late, \
249 "xyzzy device", \
250 &amp;xyzzy_device_power_mode_change);
251 #endif</PRE
252 ></TD
253 ></TR
254 ></TABLE
255 ><P
256 >This creates a variable <TT
257 CLASS="VARNAME"
258 >xyzzy_power_controller</TT
259 >,
260 which is a power controller data structure that will end up near the
261 end of the table of power controllers. Higher-level code can
262 iterate through this table and report the string <TT
263 CLASS="LITERAL"
264 >"xyzzy
265 device"</TT
266 > to the user. Whenever there is a mode change
267 operation that affects this controller, the function
268 <TT
269 CLASS="FUNCTION"
270 >xyzzy_device_power_mode_change</TT
271 > will be invoked.
272 The variable is declared static so this controller cannot be
273 manipulated by name in any other code. Alternatively, if the variable
274 had not been declared static other code could manipulate this
275 controller by name as well as through the table, especially if the
276 package for the xyzzy device driver explicitly declared this
277 variable in an exported header file. Obviously exporting the variable
278 involves a slight risk of a name clash at link time.</P
279 ><P
280 >The above code explicitly checks for the presence of the power
281 management package before including that package's header file or
282 providing any related functionality. Since power management
283 functionality is optional, such checks are recommended.</P
284 ><P
285 >The macro <TT
286 CLASS="LITERAL"
287 >POWER_CONTROLLER_CPU</TT
288 > only takes two
289 arguments, a string identifier and a mode change function pointer.
290 This macro always instantiates a variable
291 <TT
292 CLASS="VARNAME"
293 >power_controller_cpu</TT
294 > so there is no need to provide
295 a variable name. The resulting power controller structure always
296 appears at the end of the table, so there is no need to specify a
297 priority. Typical usage of the <TT
298 CLASS="LITERAL"
299 >POWER_CONTROLLER_CPU</TT
300 >
301 macro would be:</P
302 ><TABLE
303 BORDER="0"
304 BGCOLOR="#E0E0E0"
305 WIDTH="100%"
306 ><TR
307 ><TD
308 ><PRE
309 CLASS="PROGRAMLISTING"
310 >static void
311 wumpus_processor_power_mode_change(
312 PowerController* controller,
313 PowerMode desired_mode,
314 PowerModeChange change)
315 {
316 // Do the work
317 }
318
319 POWER_CONTROLLER_CPU("wumpus processor", \
320 &amp;wumpus_processor_power_mode_change);</PRE
321 ></TD
322 ></TR
323 ></TABLE
324 ><P
325 >This defines a power controller structure
326 <TT
327 CLASS="VARNAME"
328 >power_controller_cpu</TT
329 >. It should not be declared
330 static since higher-level code may well want to manipulate the cpu's
331 power mode directly, and the variable is declared by the power
332 management package's header file.</P
333 ><P
334 >Some care has to be taken to ensure that the power controllers
335 actually end up in the final executable. If a power controller
336 variable ends up in an ordinary library and is never referenced
337 directly then typically the linker will believe that the variable is
338 not needed and it will not end up in the executable. For eCos packages
339 this can be achieved in the CDL, by specifying that the containing
340 source file should end up in <TT
341 CLASS="FILENAME"
342 >libextras.a</TT
343 > rather
344 than the default <TT
345 CLASS="FILENAME"
346 >libtarget.a</TT
347 >:</P
348 ><TABLE
349 BORDER="0"
350 BGCOLOR="#E0E0E0"
351 WIDTH="100%"
352 ><TR
353 ><TD
354 ><PRE
355 CLASS="PROGRAMLISTING"
356 >cdl_package CYGPKG_HAL_WUMPUS_ARCH {
357 &#8230;
358 compile -library=libextras.a data.c
359 }</PRE
360 ></TD
361 ></TR
362 ></TABLE
363 ><P
364 >If the file <TT
365 CLASS="FILENAME"
366 >data.c</TT
367 > instantiates a power
368 controller this is now guaranteed to end up in the final executable,
369 as intended. Typically HAL and device driver packages will already
370 have some data that must not be eliminated by the linker, so they will
371 already contain a file that gets built into
372 <TT
373 CLASS="FILENAME"
374 >libextras.a</TT
375 >. For power controllers defined inside
376 application code it is important that the power controllers end up in
377 <TT
378 CLASS="FILENAME"
379 >.o</TT
380 > object files rather than in
381 <TT
382 CLASS="FILENAME"
383 >.a</TT
384 > library archive files.</P
385 ><P
386 >All the real work of a power controller is done by the mode change
387 function. If the power management package has been configured to use a
388 separate thread then this mode change function will be invoked by that
389 thread (except for the special case of <A
390 HREF="power-change.html#POWER-CHANGE-CONTROLLER-NOW"
391 ><TT
392 CLASS="FUNCTION"
393 >power_set_controller_mode_now</TT
394 ></A
395 >).
396 If no separate thread is used then the mode change function will be
397 invoked directly by <TT
398 CLASS="FUNCTION"
399 >power_set_mode</TT
400 > or
401 <TT
402 CLASS="FUNCTION"
403 >power_set_controller_mode</TT
404 >.</P
405 ><P
406 >The mode change function will be invoked with three arguments. The
407 first argument identifies the power controller. Usually this argument
408 is not actually required since a given mode change function will only
409 ever be invoked for a single power controller. For example,
410 <TT
411 CLASS="FUNCTION"
412 >xyzzy_device_power_mode_change</TT
413 > will only ever be
414 used in conjunction with <TT
415 CLASS="VARNAME"
416 >xyzzy_power_controller</TT
417 >.
418 However there may be some packages which contain multiple controllers,
419 all of which can share a single mode change function, and in that case
420 it is essential to identify the specific controller. The second
421 argument specifies the mode the controller should switch to, if
422 possible: it will be one of <TT
423 CLASS="LITERAL"
424 >PowerMode_Active</TT
425 >,
426 <TT
427 CLASS="LITERAL"
428 >PowerMode_Idle</TT
429 >, <TT
430 CLASS="LITERAL"
431 >PowerMode_Sleep</TT
432 >
433 or <TT
434 CLASS="LITERAL"
435 >PowerMode_Off</TT
436 >. The final argument will be one of
437 <TT
438 CLASS="LITERAL"
439 >PowerModeChange_Controller</TT
440 >,
441 PowerModeChange_ControllerNow, or
442 <TT
443 CLASS="LITERAL"
444 >PowerModeChange_Global</TT
445 >, and identifies the call
446 that caused this invocation. For example, if the mode change function
447 was invoked because of a call to <TT
448 CLASS="FUNCTION"
449 >power_set_mode</TT
450 >
451 then this argument will be <TT
452 CLASS="LITERAL"
453 >PowerModeChange_Global</TT
454 >.
455 It is up to each controller to decide how to interpret this final
456 argument. A typical controller might reject a global request to switch
457 to <SPAN
458 CLASS="TYPE"
459 >off</SPAN
460 > mode if the associated device is still busy, but
461 if the request was aimed specifically at this controller then it could
462 instead abort any current I/O operations and switch off the device.</P
463 ><P
464 >The <SPAN
465 CLASS="STRUCTNAME"
466 >PowerController</SPAN
467 > data structure contains
468 one field, <TT
469 CLASS="STRUCTFIELD"
470 ><I
471 >mode</I
472 ></TT
473 >, that needs to be updated
474 by the power mode change function. At all times it should indicate the
475 current mode for this controller. When a mode change is requested the
476 desired mode is passed as the second argument. The exact operation of
477 the power mode change function depends very much on what is being
478 controlled and the current circumstances, but some guidelines are
479 possible:</P
480 ><P
481 ></P
482 ><OL
483 TYPE="1"
484 ><LI
485 ><P
486 >If the request can be satisfied without obvious detriment, do so and
487 update the <TT
488 CLASS="STRUCTFIELD"
489 ><I
490 >mode</I
491 ></TT
492 > field. Reducing the power
493 consumption of a device that is not currently being used is generally
494 harmless.</P
495 ></LI
496 ><LI
497 ><P
498 >If a request is a no-op, for example if the system is switching
499 from <SPAN
500 CLASS="TYPE"
501 >idle</SPAN
502 > to <SPAN
503 CLASS="TYPE"
504 >sleep</SPAN
505 > mode and the controller
506 does not distinguish between these modes, simply act as if the request
507 was satisfied.</P
508 ></LI
509 ><LI
510 ><P
511 >If a request is felt to be unsafe, for example shutting down a
512 device that is still in use, then the controller may decide
513 to reject this request. This is especially true if the request was a
514 global mode change as opposed to one intended specifically for this
515 controller: in the latter case the policy module should be given due
516 deference. There are a number of ways in which a request can be
517 rejected:</P
518 ><P
519 ></P
520 ><OL
521 TYPE="a"
522 ><LI
523 ><P
524 >If the request cannot be satisfied immediately but may be feasible in
525 a short while, leave the <TT
526 CLASS="STRUCTFIELD"
527 ><I
528 >mode</I
529 ></TT
530 > field
531 unchanged. Higher-level code in the policy module can interpret this
532 as a hint to retry the operation a little bit later. This approach is
533 also useful if the mode change can be started but will take some time
534 to complete, for example shutting down a socket connection, and
535 additional processing will be needed later on.</P
536 ></LI
537 ><LI
538 ><P
539 >If the request is felt to be inappropriate, for example switching off
540 a device that is still in use, the mode change function can
541 call <TT
542 CLASS="FUNCTION"
543 >power_set_controller_mode</TT
544 > to reset the
545 desired mode for this controller back to the current mode.
546 Higher-level code can then interpret this as a hint that there is more
547 activity in the system than had been apparent.</P
548 ></LI
549 ><LI
550 ><P
551 >For a global mode change, if the new mode is felt to be inappropriate
552 then the power controller can call <TT
553 CLASS="FUNCTION"
554 >power_set_mode</TT
555 >
556 to indicate this. An example of this would be the policy module
557 deciding to switch off the whole unit while there is still I/O
558 activity.</P
559 ></LI
560 ></OL
561 ></LI
562 ></OL
563 ><P
564 >Mode change functions should not directly manipulate any other fields
565 in the <SPAN
566 CLASS="STRUCTNAME"
567 >PowerController</SPAN
568 > data structure. If it
569 is necessary to keep track of additional data then static variables
570 can be used.</P
571 ><P
572 >It should be noted that the above are only guidelines. Their
573 application in any given situation may be unclear. In addition the
574 detailed requirements of specific systems will vary, so even if the
575 power controller for a given device driver follows the above
576 guidelines exactly it may turn out that slightly different behaviour
577 would be more appropriate for the actual system that is being
578 developed. Fortunately the open source nature of
579 <SPAN
580 CLASS="PRODUCTNAME"
581 >eCos</SPAN
582 > allows system developers to fine-tune
583 power controllers to meet their exact requirements.</P
584 ></DIV
585 ><DIV
586 CLASS="NAVFOOTER"
587 ><HR
588 ALIGN="LEFT"
589 WIDTH="100%"><TABLE
590 WIDTH="100%"
591 BORDER="0"
592 CELLPADDING="0"
593 CELLSPACING="0"
594 ><TR
595 ><TD
596 WIDTH="33%"
597 ALIGN="left"
598 VALIGN="top"
599 ><A
600 HREF="power-attached.html"
601 >Prev</A
602 ></TD
603 ><TD
604 WIDTH="34%"
605 ALIGN="center"
606 VALIGN="top"
607 ><A
608 HREF="services-power.html"
609 >Home</A
610 ></TD
611 ><TD
612 WIDTH="33%"
613 ALIGN="right"
614 VALIGN="top"
615 >&nbsp;</TD
616 ></TR
617 ><TR
618 ><TD
619 WIDTH="33%"
620 ALIGN="left"
621 VALIGN="top"
622 >Attached and Detached Controllers</TD
623 ><TD
624 WIDTH="34%"
625 ALIGN="center"
626 VALIGN="top"
627 >&nbsp;</TD
628 ><TD
629 WIDTH="33%"
630 ALIGN="right"
631 VALIGN="top"
632 >&nbsp;</TD
633 ></TR
634 ></TABLE
635 ></DIV
636 ></BODY
637 ></HTML
638 >