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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [power/] [common/] [v2_0/] [doc/] [power-controller.html] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
<!-- 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
>

powered by: WebSVN 2.1.0

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