|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-3B6544CD-FA6E-5AB2-AA63-61186F52167D" xml:lang="en"><title>Controllable |
|
13 Power Resources</title><shortdesc>This topic explains how power resources were controlled in older |
|
14 releases of Symbian platform. For later releases see the Power Resource Manager |
|
15 documentation.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
16 <p>This documentation is retained for reference for those working with hardware |
|
17 or software that is based on older versions of Symbian platform version (in |
|
18 particular old release 9.5). For later releases see the <xref href="GUID-2ECF13A1-9D56-5740-A09F-8267E6A45DD9.dita">Porting |
|
19 the Power Resource Manager</xref> documentation.</p> |
|
20 <p>Controllable power resources are defined as being any device resource, |
|
21 such as voltages on power-lines or clocks, which can be independently enabled, |
|
22 disabled or modified under software control. </p> |
|
23 <p>The following hardware block diagram is an example of the way power resources |
|
24 might be arranged: </p> |
|
25 <fig id="GUID-41113C18-2C87-5DEA-9D05-31083F51269A"> |
|
26 <title>Example power resource arrangement</title> |
|
27 <image href="GUID-622D6337-E60A-5252-8B2B-BA8232927453_d0e29152_href.png" placement="inline"/> |
|
28 </fig> |
|
29 <p>There is no default support or default implementation for controllable |
|
30 power resources in the generic layers of Symbian platform. They must be managed |
|
31 by the base port. </p> |
|
32 <p>We suggest that the management of controllable power resources (the resource |
|
33 manager) be implemented in the Variant DLL or the ASSP DLL. This allows the |
|
34 resource manager to be up and running by the time peripheral drivers, which |
|
35 might also be kernel extensions, are loaded. See the <xref href="GUID-984C2A0D-36BE-5A99-9D65-3F8791C669FF.dita#GUID-984C2A0D-36BE-5A99-9D65-3F8791C669FF/GUID-95C34114-F986-5428-9D40-5CF64429CDBD">ASSP/Variant Architecture</xref> and the <xref href="GUID-ECAC3FF3-CDB2-5153-AD76-90732BA83726.dita#GUID-ECAC3FF3-CDB2-5153-AD76-90732BA83726/GUID-F55D88DB-7DE1-5069-BAE7-A7FE3750D065">ASSP/Variant |
|
36 Tutorials</xref>. </p> |
|
37 <p>A suggested implementation has the instance of the <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref> derived |
|
38 class owning a pointer to the resource manager object. The interface class |
|
39 for the ASSP or Variant could then have an exported or an inline member function |
|
40 to return a pointer to this resource manager object. Peripheral drivers are |
|
41 expected to link against either the ASSP DLL, or the Variant DLL, or both. </p> |
|
42 <p>For example, for a device that has a Variant and an ASSP: </p> |
|
43 <codeblock id="GUID-049CEE21-944A-589A-9F1B-8F031D681198" xml:space="preserve">class MyVariant : public MyASSP |
|
44 { |
|
45 public: |
|
46 Init1(); |
|
47 Init3(); |
|
48 // Other mandatory Asic-derived member functions |
|
49 ... |
|
50 public: |
|
51 ResourceManager* myResMgrPtr; |
|
52 ... |
|
53 }; |
|
54 </codeblock> |
|
55 <p>where class <codeph>MyASSP</codeph> is derived from class <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref>. </p> |
|
56 <codeblock id="GUID-E8346FFB-1B0F-5482-9DF7-207B1B1948F8" xml:space="preserve">GLREF_D MyVariant TheVariant;</codeblock> |
|
57 <codeblock id="GUID-CEF1F0C7-62E4-52B1-9830-DBD32B2BE8CE" xml:space="preserve">class TMyVariant |
|
58 { |
|
59 public: |
|
60 inline static ResourceManager* ResourceManager() |
|
61 {return(TheVariant.myResMgrPtr);} |
|
62 // other exported methods |
|
63 ... |
|
64 }; |
|
65 </codeblock> |
|
66 <p>where <codeph>TMyvariant</codeph> is the Variant interface class, and <codeph>ResourceManager</codeph> is |
|
67 the resource manager class. </p> |
|
68 <p>The resource manager can be declared as a global object at the Variant |
|
69 (or ASSP) scope and can therefore be created when this component is first |
|
70 loaded. In this case, the <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita#GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D/GUID-FE55E398-7F08-384F-9E74-2CC2E45002B6"><apiname>Asic::Init3()</apiname></xref> function would |
|
71 initialise the <codeph>ResourceManager</codeph> object, and set up <codeph>myResMgrPtr</codeph>. |
|
72 Alternatively, if the Variant (or ASSP) were to need the resource manager |
|
73 up and running, then you would initialise <codeph>ResourceManager</codeph> in <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita#GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D/GUID-63F2135B-4264-3B3B-9B68-656A89BF7EE9"><apiname>Asic::Init1()</apiname></xref>. </p> |
|
74 <p>In this implementation, the Variant would export a header file(s) publishing |
|
75 a list of controllable power resources. </p> |
|
76 <section id="GUID-CC741BCC-D96E-4FB7-AA8C-7635D4131DE0"><title>Shared controllable |
|
77 power resources</title> <p>Some controllable power resources can be shared |
|
78 between groups of peripherals and therefore may require usage tracking. </p> <p>We |
|
79 recommend that shared power resources be represented by a class derived from <xref href="GUID-10105403-AF16-3908-AE9E-96CF2A03AD3A.dita"><apiname>MPowerInput</apiname></xref>. |
|
80 This class offers the <codeph>Use()</codeph> and <codeph>Release()</codeph> interface |
|
81 that encapsulates resource counting behaviour. This mechanism should turn |
|
82 the resource on when the count becomes non-zero, and turn the resource off |
|
83 when the count becomes zero. </p> <p>We suggest that your <xref href="GUID-10105403-AF16-3908-AE9E-96CF2A03AD3A.dita"><apiname>MPowerInput</apiname></xref> derived |
|
84 class defines and implements a <codeph>GetCount()</codeph> function that returns |
|
85 the usage count on the shared resource. </p> </section> |
|
86 <section id="GUID-37A4098A-5E44-5744-BCE1-CDC8B876E654"><title>A suggested |
|
87 implementation of a resource manager</title> <p>While we have implied that |
|
88 a resource manager is a single class, which we have called <codeph>ResourceManager</codeph>, |
|
89 the resource manager is a notional concept for controlling power resources. <i>Symbian |
|
90 neither mandates a format for a ResourceManager class, nor even its existence</i>. |
|
91 In practice, it may be more useful to embed resource manager functions and |
|
92 data in the Variant interface class (or the ASSP interface class, if appropriate). </p> <p>However, |
|
93 for the purpose of explaining what a resource manager can do, it is easier |
|
94 to assume that this behaviour is handled by a resource manager class. This |
|
95 is the outline definition of such a class. </p> <codeblock id="GUID-BB326270-B8C6-5398-AB36-FA50011004CA" xml:space="preserve">class ResourceManager |
|
96 { |
|
97 public: |
|
98 void InitResources(); // called by your Asic::Init3()/Asic::Init1() |
|
99 void Modify(TUint aSetMask, TUint aClrMask); // only 32 simple Resources can be managed |
|
100 TBool GetResourceState(TUint aResBitMask); // only 1 bit set on this mask, returns On/Off |
|
101 public: |
|
102 (MPowerInput-derived) iSharedResource1; // 1 per shared resource |
|
103 (MPowerInput-derived) iSharedResource2; |
|
104 ... |
|
105 }; |
|
106 </codeblock> <p>The <codeph>InitResources()</codeph> function would |
|
107 do at least two things: </p> <ul> |
|
108 <li id="GUID-29FA1D5C-0691-5EB2-A45A-5925D5C58A56"><p>enable an appropriate |
|
109 set of simple resources at boot time </p> </li> |
|
110 <li id="GUID-6F0D4084-48E9-585B-857B-F67B7B453DC7"><p>initialise the shared |
|
111 power resource tracking objects, i.e. the instances of your <xref href="GUID-10105403-AF16-3908-AE9E-96CF2A03AD3A.dita"><apiname>MPowerInput</apiname></xref> derived |
|
112 class(es). </p> </li> |
|
113 </ul> <p>The function would be called by the Variant or ASSP implementation |
|
114 of <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita#GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D/GUID-FE55E398-7F08-384F-9E74-2CC2E45002B6"><apiname>Asic::Init3()</apiname></xref> or <xref href="GUID-21641835-7103-374B-9FBB-FAB1875D59A5.dita"><apiname>Asic:Init1()</apiname></xref>. </p> <p>The <codeph>Modify()</codeph> function |
|
115 is an example of how to deal with power resources that are either on or off. |
|
116 The function would take bit masks, where a bit represents a separate controllable |
|
117 power resource. The first bit mask would represent the set of power resources |
|
118 to be turned on, while the second would represent the set of power resources |
|
119 to be turned off. This assumes that the function could behave synchronously. |
|
120 Drivers for peripherals that use a set of these controllable power resources, |
|
121 would call <codeph>Modify()</codeph> to turn the relevant controllable power |
|
122 resources on or off. </p> <p>As an example, the most common method of switching |
|
123 clock resources on or off is by setting and clearing bits in a hardware register. |
|
124 A base port could choose to implement common code for setting bits in registers. </p> <p>A |
|
125 shared power resource is further represented by a <xref href="GUID-10105403-AF16-3908-AE9E-96CF2A03AD3A.dita"><apiname>MPowerInput</apiname></xref> derived |
|
126 class. The implementations of <xref href="GUID-10105403-AF16-3908-AE9E-96CF2A03AD3A.dita#GUID-10105403-AF16-3908-AE9E-96CF2A03AD3A/GUID-2BCA5312-43D9-3763-9636-3B2EB046D2C1"><apiname>MPowerInput::Use()</apiname></xref> and <xref href="GUID-10105403-AF16-3908-AE9E-96CF2A03AD3A.dita#GUID-10105403-AF16-3908-AE9E-96CF2A03AD3A/GUID-606ECD77-A5F7-3408-9B63-C68C0A7B73C6"><apiname>MPowerInput::Release()</apiname></xref> would |
|
127 call <codeph>Modify()</codeph> to turn on the shared resource when the usage |
|
128 count becomes non zero, or turn it off when the usage count reaches zero. |
|
129 Peripheral drivers would have access to shared resources, and also to the |
|
130 member functions of the <codeph>ResourceManager</codeph> class, through the |
|
131 ASSP or Variant Interface class function that returns a pointer to it. </p> <p>The |
|
132 resource manager, or its functions and members, could be offered as part of |
|
133 a power controller interface class, the <codeph>TPowerController</codeph> class |
|
134 suggested when we discussed the implementation of the <xref href="GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita">Power |
|
135 Controller</xref>'s <xref href="GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita#GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703/GUID-5A0CAD08-AA12-56EE-B0A3-75548D1896C9">EnableWakeupEvents()</xref> function. |
|
136 The class would provide an exported function that would give access to the |
|
137 resource manager. The resource manager class would be made part of the power |
|
138 controller kernel extension. Peripheral drivers needing access to shared power |
|
139 resources would then link to the power controller DLL. If the Variant or ASSP |
|
140 were also to need access to the resource manager, then the resource manager |
|
141 would have to be initialised much earlier in the kernel start-up sequence. |
|
142 In this case, we would suggest that the standard power controller kernel extension |
|
143 entry point defined by <xref href="GUID-7964FC46-4641-3BDD-92C9-50FA22C3321A.dita"><apiname>DECLARE_STANDARD_EXTENSION()</apiname></xref> be |
|
144 replaced with a custom entry point that might look like this: </p> <codeblock id="GUID-B5262624-C7B8-51E4-AE14-1D905DFC0A99" xml:space="preserve">GLDEF_C TInt KernelModuleEntry(TInt aReason) |
|
145 { |
|
146 if(aReason==KModuleEntryReasonVariantInit0) |
|
147 { |
|
148 ResourceManager* c = new ResourceManager (); // create Resource Manager |
|
149 return c ? KErrNone : KErrNoMemory; |
|
150 } |
|
151 else if(aReason==KModuleEntryReasonExtensionInit0) |
|
152 { |
|
153 (create DPowerController and Battery Monitor and Power HAL handler) |
|
154 } |
|
155 return KErrNone; // gets here from calling with KModuleEntryReasonExtensionInit1 |
|
156 } |
|
157 </codeblock> <p>The Variant or ASSP would also need to link to the |
|
158 power controller DLL. </p> <p>The following base port software architecture |
|
159 could be applied to the power supply arrangement as illustrated in the hardware |
|
160 block diagram above (see the beginning of this section at <xref href="GUID-3B6544CD-FA6E-5AB2-AA63-61186F52167D.dita">Controllable |
|
161 Power Resources</xref>): </p> <fig id="GUID-309A6C5E-A347-5E04-B2C8-426A81755226"> |
|
162 <title>Base port software architecture</title> |
|
163 <image href="GUID-EE2F64B2-A2E3-524F-8E04-68BE9AA9EA36_d0e29378_href.png" placement="inline"/> |
|
164 </fig> </section> |
|
165 <section id="GUID-C4C67612-C5CD-5D64-B257-259FD12443C9"><title>Multi-level, |
|
166 composite and asynchronous power resources</title> <p>Some power resources |
|
167 may have more than one operational level. For example, it is possible that |
|
168 an input clock to a peripheral can be operated at a nominal value corresponding |
|
169 to the fully active state, and may be lowered to another level corresponding |
|
170 to the power saving state. </p> <p>The same could apply to the input voltages |
|
171 that the peripheral can operate on. The control model suggested above for |
|
172 simple resources may not be appropriate. A suggested alternative would have |
|
173 these multi-Level resources implementing an interface that offers a public |
|
174 enumeration to cover all possible usage levels at which the resource can be |
|
175 used, and APIs such as: </p> <codeblock id="GUID-44492A89-C7DC-5C97-928C-549BEAD38161" xml:space="preserve">class MultiLevelResource |
|
176 { |
|
177 enum TResourceLevel |
|
178 { |
|
179 EOperationalLevel1, |
|
180 EOperationalLevel2, |
|
181 . . . |
|
182 ELowPowerLevel1, |
|
183 ELowPowerLevel2, |
|
184 . . . |
|
185 }; |
|
186 void UseToLevel(); |
|
187 void ReleaseToLevel(); |
|
188 TResourceLevel GetCurrentLevel(); |
|
189 . . . |
|
190 };</codeblock> <p>More importantly, it is possible that resources may |
|
191 have to be operated in combination with other resources. For example, some |
|
192 peripherals may have more than one input clock, and on transition between |
|
193 power states, these clocks may have to be changed simultaneously. </p> <p>If |
|
194 the resources to be actuated simultaneously are simple resources, then the |
|
195 model above with a <codeph>Modify()</codeph> call that takes a bit mask and |
|
196 allows more than one resource to be changed at a time may be appropriate. |
|
197 If the resources to be actuated are shared or multi-level, or have to be represented |
|
198 individually, then another interface will have to be defined to allow modifying |
|
199 more than one of them simultaneously. </p> <p>Modifying some resources may |
|
200 not be an instantaneous operation. For example, it may take a non-negligible |
|
201 amount of time to stabilise an input clock that has just been modified. </p> <p>The |
|
202 nature of EKA2 strongly discourages actively waiting (or “spinning”) inside |
|
203 drivers; instead it is suggested that the multithreading capabilities of EKA2 |
|
204 kernel side code and the synchronisation mechanisms available be used to solve |
|
205 the problem of having the driver code having to wait for a resource to stabilise |
|
206 before proceeding with its use. </p> <p>As an example, let us assume that |
|
207 the multi-level resource mentioned above has a non-negligible delay associated |
|
208 with any level changes: </p> <ul> |
|
209 <li id="GUID-0549E815-BB6E-55C7-84DB-FB6A2ACA11AC"><p>If the length of time |
|
210 to wait for a power resource to stabilise is known, and is the order of a |
|
211 few milliseconds or less, or the driver executes on its unique kernel thread |
|
212 (not used by any other kernel-side code), then the best solution would be |
|
213 to sleep the driver thread, by calling <codeph>NKern::Sleep(aTime)</codeph> for |
|
214 the specified length of time after issuing a call to <codeph>UseToLevel()</codeph> (or <codeph>ReleaseToLevel()</codeph>). </p> </li> |
|
215 <li id="GUID-9F0FCB9F-2827-528A-B3D0-FEE6CF8470CD"><p>When the length of time |
|
216 to wait for a power resource to stabilise increases, then sleeping the driver |
|
217 thread may become a problem if the driver executes in a DFC queue used by |
|
218 other drivers, which is often the case. This is because blocking that thread |
|
219 means that no other drivers can run. Here, the best solution is for the driver |
|
220 to create another thread and DFC queue, by calling <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-B9D637A1-4EB9-39F7-8C5C-2C546994C4B8"><apiname>Kern::DfcQInit()</apiname></xref>, |
|
221 and whenever it needs to change the resource, queue a DFC on that queue, which |
|
222 will issue the calls to <codeph>UseToLevel()</codeph> (or <codeph>ReleaseToLevel()</codeph>) |
|
223 and then sleep the thread. </p> </li> |
|
224 <li id="GUID-C8472B27-FC27-5C72-B6C2-A0DA681EA3C6"><p>If the length of time |
|
225 to change a power resource cannot be known in advance, but the hardware provides |
|
226 an indication of completion of the change, for example, in the form of an |
|
227 interrupt, then the solution may involve the driver code waiting on a Fast |
|
228 Mutex, which is signalled by the completion event (in code belonging to the <codeph>MultiLevelResource</codeph> derived |
|
229 object). </p> </li> |
|
230 </ul> </section> |
|
231 </conbody></concept> |