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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [doc/] [html/] [ref/] [power-controller.html] - Blame information for rev 638

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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