Adaptation/GUID-3B6544CD-FA6E-5AB2-AA63-61186F52167D.dita
author Graeme Price <GRAEME.PRICE@NOKIA.COM>
Fri, 15 Oct 2010 14:32:18 +0100
changeset 15 307f4279f433
permissions -rw-r--r--
Initial contribution of the Adaptation Documentation.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-3B6544CD-FA6E-5AB2-AA63-61186F52167D" xml:lang="en"><title>Controllable
Power Resources</title><shortdesc>This topic explains how power resources were controlled in older
releases of Symbian platform. For later releases see the Power Resource Manager
documentation.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>This documentation is retained for reference for those working with hardware
or software that is based on older versions of Symbian platform version (in
particular old release 9.5). For later releases see the <xref href="GUID-2ECF13A1-9D56-5740-A09F-8267E6A45DD9.dita">Porting
the Power Resource Manager</xref> documentation.</p>
<p>Controllable power resources are defined as being any device resource,
such as voltages on power-lines or clocks, which can be independently enabled,
disabled or modified under software control. </p>
<p>The following hardware block diagram is an example of the way power resources
might be arranged: </p>
<fig id="GUID-41113C18-2C87-5DEA-9D05-31083F51269A">
<title>Example power resource arrangement</title>
<image href="GUID-622D6337-E60A-5252-8B2B-BA8232927453_d0e29152_href.png" placement="inline"/>
</fig>
<p>There is no default support or default implementation for controllable
power resources in the generic layers of Symbian platform. They must be managed
by the base port. </p>
<p>We suggest that the management of controllable power resources (the resource
manager) be implemented in the Variant DLL or the ASSP DLL. This allows the
resource manager to be up and running by the time peripheral drivers, which
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
Tutorials</xref>. </p>
<p>A suggested implementation has the instance of the <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref> derived
class owning a pointer to the resource manager object. The interface class
for the ASSP or Variant could then have an exported or an inline member function
to return a pointer to this resource manager object. Peripheral drivers are
expected to link against either the ASSP DLL, or the Variant DLL, or both. </p>
<p>For example, for a device that has a Variant and an ASSP: </p>
<codeblock id="GUID-049CEE21-944A-589A-9F1B-8F031D681198" xml:space="preserve">class MyVariant : public MyASSP
    {
public:
    Init1();
    Init3();
    // Other mandatory Asic-derived member functions
    ...
public:
    ResourceManager* myResMgrPtr;
    ...
    };
      </codeblock>
<p>where class <codeph>MyASSP</codeph> is derived from class <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref>. </p>
<codeblock id="GUID-E8346FFB-1B0F-5482-9DF7-207B1B1948F8" xml:space="preserve">GLREF_D MyVariant TheVariant;</codeblock>
<codeblock id="GUID-CEF1F0C7-62E4-52B1-9830-DBD32B2BE8CE" xml:space="preserve">class TMyVariant
    {
public:
    inline static ResourceManager* ResourceManager()
        {return(TheVariant.myResMgrPtr);}
    // other exported methods
    ...
    };
      </codeblock>
<p>where <codeph>TMyvariant</codeph> is the Variant interface class, and <codeph>ResourceManager</codeph> is
the resource manager class. </p>
<p>The resource manager can be declared as a global object at the Variant
(or ASSP) scope and can therefore be created when this component is first
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
initialise the <codeph>ResourceManager</codeph> object, and set up <codeph>myResMgrPtr</codeph>.
Alternatively, if the Variant (or ASSP) were to need the resource manager
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>
<p>In this implementation, the Variant would export a header file(s) publishing
a list of controllable power resources. </p>
<section id="GUID-CC741BCC-D96E-4FB7-AA8C-7635D4131DE0"><title>Shared controllable
power resources</title> <p>Some controllable power resources can be shared
between groups of peripherals and therefore may require usage tracking. </p> <p>We
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>.
This class offers the <codeph>Use()</codeph> and <codeph>Release()</codeph> interface
that encapsulates resource counting behaviour. This mechanism should turn
the resource on when the count becomes non-zero, and turn the resource off
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
class defines and implements a <codeph>GetCount()</codeph> function that returns
the usage count on the shared resource. </p> </section>
<section id="GUID-37A4098A-5E44-5744-BCE1-CDC8B876E654"><title>A suggested
implementation of a resource manager</title> <p>While we have implied that
a resource manager is a single class, which we have called <codeph>ResourceManager</codeph>,
the resource manager is a notional concept for controlling power resources. <i>Symbian
neither mandates a format for a ResourceManager class, nor even its existence</i>.
In practice, it may be more useful to embed resource manager functions and
data in the Variant interface class (or the ASSP interface class, if appropriate). </p> <p>However,
for the purpose of explaining what a resource manager can do, it is easier
to assume that this behaviour is handled by a resource manager class. This
is the outline definition of such a class. </p> <codeblock id="GUID-BB326270-B8C6-5398-AB36-FA50011004CA" xml:space="preserve">class ResourceManager
    {
public:    
    void InitResources();                            // called by your Asic::Init3()/Asic::Init1()
    void Modify(TUint aSetMask, TUint aClrMask);    // only 32 simple Resources can be managed
    TBool GetResourceState(TUint aResBitMask);    // only 1 bit set on this mask, returns On/Off
public:
    (MPowerInput-derived) iSharedResource1;        // 1 per shared resource
    (MPowerInput-derived) iSharedResource2;
    ...
    };
      </codeblock> <p>The <codeph>InitResources()</codeph> function would
do at least two things: </p> <ul>
<li id="GUID-29FA1D5C-0691-5EB2-A45A-5925D5C58A56"><p>enable an appropriate
set of simple resources at boot time </p> </li>
<li id="GUID-6F0D4084-48E9-585B-857B-F67B7B453DC7"><p>initialise the shared
power resource tracking objects, i.e. the instances of your <xref href="GUID-10105403-AF16-3908-AE9E-96CF2A03AD3A.dita"><apiname>MPowerInput</apiname></xref> derived
class(es). </p> </li>
</ul> <p>The function would be called by the Variant or ASSP implementation
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
is an example of how to deal with power resources that are either on or off.
The function would take bit masks, where a bit represents a separate controllable
power resource. The first bit mask would represent the set of power resources
to be turned on, while the second would represent the set of power resources
to be turned off. This assumes that the function could behave synchronously.
Drivers for peripherals that use a set of these controllable power resources,
would call <codeph>Modify()</codeph> to turn the relevant controllable power
resources on or off. </p> <p>As an example, the most common method of switching
clock resources on or off is by setting and clearing bits in a hardware register.
A base port could choose to implement common code for setting bits in registers. </p> <p>A
shared power resource is further represented by a <xref href="GUID-10105403-AF16-3908-AE9E-96CF2A03AD3A.dita"><apiname>MPowerInput</apiname></xref> derived
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
call <codeph>Modify()</codeph> to turn on the shared resource when the usage
count becomes non zero, or turn it off when the usage count reaches zero.
Peripheral drivers would have access to shared resources, and also to the
member functions of the <codeph>ResourceManager</codeph> class, through the
ASSP or Variant Interface class function that returns a pointer to it. </p> <p>The
resource manager, or its functions and members, could be offered as part of
a power controller interface class, the <codeph>TPowerController</codeph> class
suggested when we discussed the implementation of the <xref href="GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita">Power
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.
The class would provide an exported function that would give access to the
resource manager. The resource manager class would be made part of the power
controller kernel extension. Peripheral drivers needing access to shared power
resources would then link to the power controller DLL. If the Variant or ASSP
were also to need access to the resource manager, then the resource manager
would have to be initialised much earlier in the kernel start-up sequence.
In this case, we would suggest that the standard power controller kernel extension
entry point defined by <xref href="GUID-7964FC46-4641-3BDD-92C9-50FA22C3321A.dita"><apiname>DECLARE_STANDARD_EXTENSION()</apiname></xref> be
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)
    {
    if(aReason==KModuleEntryReasonVariantInit0)
        {
        ResourceManager* c = new ResourceManager ();    // create Resource Manager
        return c ? KErrNone : KErrNoMemory;    
        }
    else if(aReason==KModuleEntryReasonExtensionInit0)
        {
        (create DPowerController and Battery Monitor and Power HAL handler)
        }
    return KErrNone;         // gets here from calling with KModuleEntryReasonExtensionInit1
    }
        </codeblock> <p>The Variant or ASSP would also need to link to the
power controller DLL. </p> <p>The following base port software architecture
could be applied to the power supply arrangement as illustrated in the hardware
block diagram above (see the beginning of this section at <xref href="GUID-3B6544CD-FA6E-5AB2-AA63-61186F52167D.dita">Controllable
Power Resources</xref>): </p> <fig id="GUID-309A6C5E-A347-5E04-B2C8-426A81755226">
<title>Base port software architecture</title>
<image href="GUID-EE2F64B2-A2E3-524F-8E04-68BE9AA9EA36_d0e29378_href.png" placement="inline"/>
</fig> </section>
<section id="GUID-C4C67612-C5CD-5D64-B257-259FD12443C9"><title>Multi-level,
composite and asynchronous power resources</title> <p>Some power resources
may have more than one operational level. For example, it is possible that
an input clock to a peripheral can be operated at a nominal value corresponding
to the fully active state, and may be lowered to another level corresponding
to the power saving state. </p> <p>The same could apply to the input voltages
that the peripheral can operate on. The control model suggested above for
simple resources may not be appropriate. A suggested alternative would have
these multi-Level resources implementing an interface that offers a public
enumeration to cover all possible usage levels at which the resource can be
used, and APIs such as: </p> <codeblock id="GUID-44492A89-C7DC-5C97-928C-549BEAD38161" xml:space="preserve">class MultiLevelResource
    {
    enum TResourceLevel
        {
        EOperationalLevel1,
        EOperationalLevel2,
        . . .
        ELowPowerLevel1,
        ELowPowerLevel2,
        . . .
        };
    void UseToLevel();
    void ReleaseToLevel();
    TResourceLevel GetCurrentLevel();
    . . . 
    };</codeblock> <p>More importantly, it is possible that resources may
have to be operated in combination with other resources. For example, some
peripherals may have more than one input clock, and on transition between
power states, these clocks may have to be changed simultaneously. </p> <p>If
the resources to be actuated simultaneously are simple resources, then the
model above with a <codeph>Modify()</codeph> call that takes a bit mask and
allows more than one resource to be changed at a time may be appropriate.
If the resources to be actuated are shared or multi-level, or have to be represented
individually, then another interface will have to be defined to allow modifying
more than one of them simultaneously. </p> <p>Modifying some resources may
not be an instantaneous operation. For example, it may take a non-negligible
amount of time to stabilise an input clock that has just been modified. </p> <p>The
nature of EKA2 strongly discourages actively waiting (or “spinning”) inside
drivers; instead it is suggested that the multithreading capabilities of EKA2
kernel side code and the synchronisation mechanisms available be used to solve
the problem of having the driver code having to wait for a resource to stabilise
before proceeding with its use. </p> <p>As an example, let us assume that
the multi-level resource mentioned above has a non-negligible delay associated
with any level changes: </p> <ul>
<li id="GUID-0549E815-BB6E-55C7-84DB-FB6A2ACA11AC"><p>If the length of time
to wait for a power resource to stabilise is known, and is the order of a
few milliseconds or less, or the driver executes on its unique kernel thread
(not used by any other kernel-side code), then the best solution would be
to sleep the driver thread, by calling <codeph>NKern::Sleep(aTime)</codeph> for
the specified length of time after issuing a call to <codeph>UseToLevel()</codeph> (or <codeph>ReleaseToLevel()</codeph>). </p> </li>
<li id="GUID-9F0FCB9F-2827-528A-B3D0-FEE6CF8470CD"><p>When the length of time
to wait for a power resource to stabilise increases, then sleeping the driver
thread may become a problem if the driver executes in a DFC queue used by
other drivers, which is often the case. This is because blocking that thread
means that no other drivers can run. Here, the best solution is for the driver
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>,
and whenever it needs to change the resource, queue a DFC on that queue, which
will issue the calls to <codeph>UseToLevel()</codeph> (or <codeph>ReleaseToLevel()</codeph>)
and then sleep the thread. </p> </li>
<li id="GUID-C8472B27-FC27-5C72-B6C2-A0DA681EA3C6"><p>If the length of time
to change a power resource cannot be known in advance, but the hardware provides
an indication of completion of the change, for example, in the form of an
interrupt, then the solution may involve the driver code waiting on a Fast
Mutex, which is signalled by the completion event (in code belonging to the <codeph>MultiLevelResource</codeph> derived
object). </p> </li>
</ul> </section>
</conbody></concept>