Symbian3/PDK/Source/GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita
changeset 1 25a17d01db0c
child 5 f345bda72bc4
equal deleted inserted replaced
0:89d6a7a84779 1:25a17d01db0c
       
     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-34D1D0BF-20DE-5677-A067-8FF9DD72E703" xml:lang="en"><title>Power
       
    13 Controller DPowerController Implementation Tutorial</title><shortdesc>This topic describes how to implement the <apiname>DPowerController</apiname> class
       
    14 to provide the main power controller functionality in a base port.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <p><xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita"><apiname>DPowerController</apiname></xref> is defined as: </p>
       
    16 <codeblock id="GUID-95318C39-B205-557C-B1F3-75C1441E464A" xml:space="preserve">class DPowerController : public DBase
       
    17     {
       
    18 public:
       
    19     IMPORT_C DPowerController();
       
    20     IMPORT_C void Register();
       
    21     IMPORT_C void WakeupEvent();
       
    22 
       
    23 #ifndef __X86__
       
    24     IMPORT_C TInt RegisterResourceController(DBase* aController, TInt aClientId);
       
    25 private:
       
    26     struct SResourceControllerData
       
    27         {
       
    28         DBase* iResourceController;
       
    29         TInt   iClientId;
       
    30         } iResourceControllerData;
       
    31 #endif
       
    32 
       
    33 public:
       
    34     volatile TPowerState    iTargetState;
       
    35 public:
       
    36     virtual void CpuIdle() = 0;
       
    37     virtual void EnableWakeupEvents() = 0;
       
    38     virtual void DisableWakeupEvents() = 0;
       
    39     virtual void AbsoluteTimerExpired() = 0;
       
    40     virtual void PowerDown(TTimeK aWakeupTime) = 0;
       
    41     };
       
    42       </codeblock>
       
    43 <p>The first three functions are exported from the kernel, <filepath>EKERN.EXE</filepath>,
       
    44 while the other five pure virtual functions are implemented by your base port.
       
    45 You do not need to export any other functions. </p>
       
    46 <ul>
       
    47 <li id="GUID-2EEFEFF3-FCAF-526C-A11B-790A2A47AA9C"><p> <xref href="GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita#GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703/GUID-BCCDBA09-415D-5779-BCE5-CDEB2E1EF7D8">Initialising the power controller</xref>, </p> </li>
       
    48 <li id="GUID-CBB1EE9C-CD27-5417-973C-3BBED74715D6"><p> <xref href="GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita#GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703/GUID-DCD91EBA-CB0E-5EA9-84E0-8F8FED6FC91E">DPowerController::RegisterResourceController()</xref>, </p> </li>
       
    49 <li id="GUID-4E2D396D-E6FA-5658-830F-9F82D4A63AD1"><p> <xref href="GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita#GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703/GUID-5A0CAD08-AA12-56EE-B0A3-75548D1896C9">DPowerController::EnableWakeupEvents()</xref>, </p> </li>
       
    50 <li id="GUID-DB82BCE3-702A-51EB-ADE0-9434D59CD553"><p> <xref href="GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita#GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703/GUID-51D37A0C-AD46-52D5-A31C-CB3A8046CE84">DPowerController::AbsoluteTimerExpired()</xref>, </p> </li>
       
    51 <li id="GUID-77CCBFFE-037D-5B86-BF14-1BE87D38B47A"><p> <xref href="GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita#GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703/GUID-1F77C71C-D226-58BB-ABAE-43F958CC0C61">DPowerController::PowerDown()</xref>, </p> </li>
       
    52 <li id="GUID-8657D772-2338-588D-B074-832B06144D8B"><p> <xref href="GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita#GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703/GUID-E2A072D0-A67F-5E6D-81ED-CFD77B6ED4F1">CpuIdle()</xref>. </p> </li>
       
    53 </ul>
       
    54 <section id="GUID-BCCDBA09-415D-5779-BCE5-CDEB2E1EF7D8"><title>Initialising
       
    55 the power controller</title> <p>Typically, you implement your derived class
       
    56 in a power management kernel extension, which has the opportunity to perform
       
    57 initialisation before the system itself is fully initialised. This is done
       
    58 via the extension's DLL entry point. You use the <xref href="GUID-7964FC46-4641-3BDD-92C9-50FA22C3321A.dita"><apiname>DECLARE_STANDARD_EXTENSION()</apiname></xref> macro
       
    59 as a wrapper around your initialisation code. There are at least three things
       
    60 to do here: </p> <ul>
       
    61 <li id="GUID-25C66F1B-6B2F-5B3B-A827-410263EE22A4"><p>create an instance of
       
    62 your power controller object </p> </li>
       
    63 <li id="GUID-369A09EC-74D3-529A-AC05-0EFE0C4ABBF7"><p>register your power
       
    64 controller object with the Symbian OS power manager, by calling <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-F66D72D0-AA27-3BAF-8915-C6E8CC4E7CCF"><apiname>DPowerController::Register()</apiname></xref>.
       
    65 Your power controller cannot be used by the Symbian OS power manager until
       
    66 it has been registered. </p> </li>
       
    67 <li id="GUID-E4C7D934-AAB9-511B-93A4-125D5A5B248D"><p>if you intend to use
       
    68 a battery monitor, then you would create it and register it as the HAL handler
       
    69 to deal with <xref href="GUID-66A851A0-2A0C-3624-AEC1-22F6629FABF7.dita#GUID-66A851A0-2A0C-3624-AEC1-22F6629FABF7/GUID-227B4DCD-5D74-3AB7-8E09-64A04D88F094"><apiname>THalFunctionGroup::EHALGroupPower</apiname></xref> calls. See <xref href="GUID-65CDCA83-C726-5173-8E46-B8981D1D7B02.dita">Battery Monitor Implementation
       
    70 Tutorialc</xref> and <xref href="GUID-54042C84-6216-5930-9CBF-BAF635CECD4D.dita">Power
       
    71 HAL Handler Tutorial</xref> for more detail. </p> </li>
       
    72 </ul> <p>For example: </p> <codeblock id="GUID-1A909C4C-DCAF-54E3-B482-16918E33BF4F" xml:space="preserve">DECLARE_STANDARD_EXTENSION()
       
    73     {
       
    74     TInt r=KErrNoMemory;
       
    75 
       
    76     // Create the power controller object, and register it.
       
    77     DPowerController* pC = new DYourPowerController;
       
    78     if !(pC)
       
    79         {
       
    80         return (r);
       
    81         }
       
    82         pC-&gt;Register();
       
    83 
       
    84     // Create the battery monitor.
       
    85     DBatteryMonitor* pM = new DYourBatteryMonitor;
       
    86     if !(pM)
       
    87         {
       
    88         return(r);
       
    89         }
       
    90 
       
    91     r = KErrNone;
       
    92     return(r);
       
    93     }</codeblock> </section>
       
    94 <section id="GUID-DCD91EBA-CB0E-5EA9-84E0-8F8FED6FC91E"><title>DPowerController::RegisterResourceController()</title> <p>The
       
    95 function <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-42896B4D-9F77-3D91-82BD-50102A8F3DA4"><apiname>DPowerController::RegisterResourceController()</apiname></xref> allows
       
    96 the Resource Controller to register itself with the Power Controller. See <xref href="GUID-66FD040B-133E-57CF-80DD-9369F62709C6.dita#GUID-66FD040B-133E-57CF-80DD-9369F62709C6/GUID-08BFCAF4-9AF0-5999-A1C4-7BBD107C9354">registering
       
    97 with the resource controller</xref> in the PSL implementation document. </p> <p>To
       
    98 support idle power management the Power Controller's PSL must override <codeph>RegisterResourceController()</codeph> to
       
    99 include the registration of a list of resources whose states are of interest
       
   100 to idle power management. </p> <p><b>Idle
       
   101 power management</b> </p> <p>The Power Controller can assemble a list of resources
       
   102 whose state it is interested in from a NULL thread in an array of <xref href="GUID-586AF75A-8350-345D-ABF4-6542C8E75DED.dita"><apiname>SIdleResourceInfo</apiname></xref> structures.
       
   103 Each entry in the list contains the resource ID that the power controller
       
   104 must enter before registering with the PRM. The resource list should be created
       
   105 in the kernel heap or data section. </p> <p>The example below creates a buffer
       
   106 to capture the state of all static resources. The PRM captures the information
       
   107 using <xref href="GUID-46F2174F-0206-345B-8C5D-F8B5763652E0.dita#GUID-46F2174F-0206-345B-8C5D-F8B5763652E0/GUID-52DC308A-9DF1-3BDE-A905-A4DD3B692638"><apiname>DPowerResourceController::RegisterResourcesForIdle()</apiname></xref>. </p> <codeblock id="GUID-C6E907FD-094D-5412-8F81-FC02CDE8B411" xml:space="preserve">    ...
       
   108 //Allocate buffer for Idle resource management
       
   109     NKern::ThreadEnterCS();
       
   110     pBuf = HBuf::New(numResources * sizeof(SIdleResourceInfo)); 
       
   111     NKern::ThreadLeaveCS();
       
   112     if(!pBuf)
       
   113         {
       
   114            return KErrNoMemory;
       
   115         }
       
   116     SIdleResourceInfo* pI = (SIdleResourceInfo*)pBuf-&gt;Ptr();
       
   117 
       
   118 //Update resource ID
       
   119     for(TUint c = 0; c &lt; numResources; c++)
       
   120         {
       
   121         pI[c].iResourceId = c+1; 
       
   122         }
       
   123     r = (iResourceControllerData.iResourceController)-&gt;RegisterResourcesForIdle(iResourceControllerData.iClientId, numResources, (TPtr*)pI);
       
   124     ...</codeblock> <p>The first parameter passed to <codeph>RegisterResourcesForIdle()</codeph> is
       
   125 the client Id generated for the power controller this is the client ID passed
       
   126 by the PRM when calling <xref href="GUID-B2C466D1-0B65-3BB7-81B1-7297400E60C4.dita"><apiname>RegisterResourceController</apiname></xref>. </p> <p> <b>Note</b>: <codeph>RegisterResourcesForIdle()</codeph> is
       
   127 not exported and is only available for use by the Power Controller to register
       
   128 resources for idle power management. <b>Note</b>: <codeph>RegisterResourcesForIdle()</codeph> can
       
   129 only be called by the Power Controller once. </p> </section>
       
   130 <section id="GUID-5A0CAD08-AA12-56EE-B0A3-75548D1896C9"><title>DPowerController::EnableWakeupEvents()</title> <codeblock id="GUID-38714507-C38C-5787-997F-5D45F3A90357" xml:space="preserve">virtual void EnableWakeupEvents() = 0;</codeblock> <p>The
       
   131 Symbian Power Model defines 3 generic system-wide <xref href="GUID-113B3755-1797-5D1B-8E07-8A18F5FE1504.dita">power
       
   132 states</xref>: <i>Active</i>, <i>Standby</i> and <i>Off</i>, as defined in
       
   133 the <xref href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita">Symbian OS power
       
   134 model</xref>. </p> <p>Each of the system-wide low power states: <i>Standby</i> and <i>Off</i>,
       
   135 has a defined set of wake-up events. If a wake-up event occurs while the system
       
   136 is preparing to transition into one of these low power states, or when the
       
   137 system is in the <i>Standby</i> state, then this can result in the system
       
   138 moving back to the <i>Active</i> power state. Wake-up events may be different
       
   139 for different target power states. Wake-up events are platform-specific hardware
       
   140 events, and it is your base port that decides which events count as wake-up
       
   141 events. </p> <p><b>When
       
   142 is it called?</b> </p> <p> <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-0642129D-05F2-3AB0-B562-37A7BB7A275F"><apiname>DPowerController::EnableWakeupEvents()</apiname></xref> is
       
   143 called called by the <xref href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita#GUID-0C435514-EEC6-5660-BB5F-535790349632/GUID-330F07B2-BBDF-5675-B7D5-FF6B25DD03F4">power
       
   144 manager</xref> as a result of a user side call to <xref href="GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87.dita#GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87/GUID-C49C0A07-EAC7-32CB-956F-1FFEFF2FD326"><apiname>Power::EnableWakeupEvents()</apiname></xref>.
       
   145 The class <xref href="GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87.dita"><apiname>Power</apiname></xref> is the user side interface to the power
       
   146 manager, and is used by the user side entity that is responsible for moving
       
   147 the device into a low power state. </p> <p><b>Context</b> </p> <p>When the user side entity decides to move the device to a low power
       
   148 state, it sends a notification to all of the user side power domains registered
       
   149 with it, giving their applications a chance to save their data and state.
       
   150 However, before doing this, it calls <xref href="GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87.dita#GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87/GUID-C49C0A07-EAC7-32CB-956F-1FFEFF2FD326"><apiname>Power::EnableWakeupEvents()</apiname></xref>.
       
   151 It also calls <xref href="GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87.dita#GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87/GUID-6CFE19D9-249A-3305-8224-823D2FDB1859"><apiname>Power::RequestWakeupEventNotification()</apiname></xref> so
       
   152 that it can be informed of a wake-up event. If it is notified of a wake-up
       
   153 event, it can halt, and reverse the user side response to the power transition. </p> <fig id="GUID-ACC6E7E3-71E3-5553-B433-9017CB04513D">
       
   154 <image href="GUID-65F3E8BD-22C9-5CF2-A3CC-270C24ADECC0_d0e378167_href.png" placement="inline"/>
       
   155 </fig> <p>Before calling <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-0642129D-05F2-3AB0-B562-37A7BB7A275F"><apiname>DPowerController::EnableWakeupEvents()</apiname></xref>,
       
   156 the power manager sets the <codeph>iTargetState</codeph> member of <codeph>DPowerController</codeph> to
       
   157 the applicable <xref href="GUID-87AB8B20-04EE-31D2-8F3D-EA904D05B8D0.dita"><apiname>TPowerState</apiname></xref>. This means that you can enable
       
   158 the appropriate set of wake-up events. </p> <p>Once the user side transition
       
   159 is complete, it calls <xref href="GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87.dita#GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87/GUID-7C6F3F0F-319B-3DEE-81BF-1EB5BB2EAB0A"><apiname>Power::PowerDown()</apiname></xref> in the user side
       
   160 interface to the <xref href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita#GUID-0C435514-EEC6-5660-BB5F-535790349632/GUID-330F07B2-BBDF-5675-B7D5-FF6B25DD03F4">power
       
   161 manager</xref>, which results in a call to <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-8AE99718-6B82-3920-9029-28C2041A3B10"><apiname>DPowerController::PowerDown()</apiname></xref> in
       
   162 the power controller. This starts the transition of all <xref href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita#GUID-0C435514-EEC6-5660-BB5F-535790349632/GUID-DC5F1ECD-CCA3-59FF-A2F1-A3DBD76CD458">power handlers</xref> to a low power state, a potentially long process. This
       
   163 means that the power controller needs the ability to detect wake-up events
       
   164 so that it can halt, and reverse the power transition. </p> <p><b>Implementation issues</b> </p> <p>There are three possibilities in dealing
       
   165 with wake-up events: </p> <ul>
       
   166 <li id="GUID-4243E6DD-C903-58DE-B125-38CEDB8B5269"><p>if wake-up events are
       
   167 not handled by specific peripheral drivers, you could set up the hardware
       
   168 so that wake-up events are recorded in a location accessible by the software.
       
   169 Prior to completing the system power transition, the Power controller would
       
   170 check the relevant hardware to see whether a wakeup event had occurred. On
       
   171 detecting a wake-up event it would tell the power manager by calling <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-C193F898-2C15-3C42-8353-14F00789BCDA"><apiname>DPowerController::WakeupEvent()</apiname></xref>. </p> </li>
       
   172 <li id="GUID-289B86C4-A578-5A42-A0DF-70A7BF3F440E"><p>if wake-up events are
       
   173 not handled by specific peripheral drivers, you could arrange for wake-up
       
   174 events to interrupt the CPU. The code that services those interrupts would
       
   175 tell the power manager by calling <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-FABDB7E2-DEC5-3EA9-8106-66C971C04AB7"><apiname>DPowerController::WakepEvent()</apiname></xref>. </p> </li>
       
   176 <li id="GUID-E51BAE55-0A81-5D1F-B509-096A7F2141EF"><p>if wakeup events are
       
   177 intercepted, serviced and cleared by peripheral drivers, then the following
       
   178 outline solution could be adopted: </p> <ul>
       
   179 <li id="GUID-5C942237-BBB2-5919-8578-B55BDAFAFC9F"><p>The power controller
       
   180 would need to publish a list of wake-up events, preferably as a bit mask,
       
   181 and export an API which peripheral drivers could use to notify the power controller
       
   182 that a wake-up event has occurred. The following interface class could be
       
   183 used for this purpose: </p> <codeblock id="GUID-084F7F46-66B6-5661-85AF-57D499250886" xml:space="preserve">class TPowerController
       
   184     {
       
   185 public:
       
   186     inline static void SetPowerControllerPointer(DPowerController* apPowerController)
       
   187     { iPowerControllerPointer = apPowerController; }
       
   188     IMPORT_C static void WakeupEventOccurred(TUint aWakeupEvent);
       
   189     …        // other methods if required
       
   190 private:
       
   191     DPowerController* iPowerControllerPointer;
       
   192     };
       
   193                       </codeblock> <p>The class would be implemented as part
       
   194 of the power management kernel extension and <codeph>SetPowerControllerPointer()</codeph> would
       
   195 be called when <xref href="GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita#GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703/GUID-BCCDBA09-415D-5779-BCE5-CDEB2E1EF7D8">initialising
       
   196 the power controller</xref>, but after creation of the power controller object. </p> <p>Those
       
   197 peripheral drivers that intercept wake-up events would need to link to the
       
   198 power controller DLL (i.e. the power management kernel extension). </p> <p>On
       
   199 the occurrence of a wake-up event, the peripheral driver software servicing
       
   200 that event would notify the power controller by calling <codeph>WakeupEventOccurred()</codeph>,
       
   201 specifying the appropriate wake-up event bit(s). </p> <p>You might implement <codeph>WakeupEventOccurred()</codeph> as
       
   202 follows: </p> <codeblock id="GUID-501ABA28-81B9-52C1-9842-003E1E389045" xml:space="preserve">EXPORT_C void TPowerController::WakeupEventOccurred(TUint aWakeupEvent)
       
   203     {
       
   204     if(iPowerControllerPointer-&gt;iWakeupEvents &amp; aWakeupEvent)
       
   205         {
       
   206         iPowerControllerPointer-&gt;WakeupEvent();
       
   207         }
       
   208     }</codeblock> <p>where <codeph>iWakeupEvents</codeph> is a data member
       
   209 defined in your <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita"><apiname>DPowerController</apiname></xref> -derived class that contains
       
   210 the bitmask representing the wake-up events. The bitmask groups wakeup events
       
   211 according to the target power state. </p> </li>
       
   212 </ul> </li>
       
   213 </ul> <p>When the peripheral driver powers down, it should leave the hardware
       
   214 that generates the wake-up event powered and enabled for detection. Thus,
       
   215 if a wake-up event of the type handled by this peripheral driver occurs, it
       
   216 will not be serviced in the normal way, but will be left pending until the
       
   217 power controller services it. </p> <p>When the power controller’s <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-8AE99718-6B82-3920-9029-28C2041A3B10"><apiname>DPowerController::PowerDown()</apiname></xref> function
       
   218 is called, the power controller must check the peripheral hardware directly
       
   219 to see whether the wakeup event has happened, or is happening right now, prior
       
   220 to transitioning the device to the target system-wide low power state. If
       
   221 the wake-up event is found to have happened then <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-8AE99718-6B82-3920-9029-28C2041A3B10"><apiname>DPowerController::PowerDown()</apiname></xref> would
       
   222 return immediately, instead of initiating the <xref href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita#GUID-0C435514-EEC6-5660-BB5F-535790349632/GUID-DC5F1ECD-CCA3-59FF-A2F1-A3DBD76CD458">power
       
   223 handlers</xref> power down of the peripheral drivers. </p> </section>
       
   224 <section id="GUID-51D37A0C-AD46-52D5-A31C-CB3A8046CE84"><title> DPowerController::AbsoluteTimerExpired()</title> <codeblock id="GUID-5EC61B73-DA37-51C8-963F-4E4169AC1BE7" xml:space="preserve">virtual void AbsoluteTimerExpired() = 0;</codeblock> <p><b>When is it called?</b> </p> <p> <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-C6F792DB-1EC0-33F4-8F82-AB3F7B44B061"><apiname>DPowerController::AbsoluteTimerExpired()</apiname></xref> is
       
   225 called by the <xref href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita#GUID-0C435514-EEC6-5660-BB5F-535790349632/GUID-330F07B2-BBDF-5675-B7D5-FF6B25DD03F4">power
       
   226 manager</xref> whenever an absolute timer expires. An absolute timer is one
       
   227 that is set to complete at a specific time, as queued by a call to <xref href="GUID-8A423EA2-4264-30C9-9579-0466994E6E88.dita#GUID-8A423EA2-4264-30C9-9579-0466994E6E88/GUID-3F302410-5CC2-3CCB-82F4-47E953E7A29B"><apiname>RTimer::At()</apiname></xref>. </p> <p><b>Implementation issues</b> </p> <p>If absolute timer expiration is one
       
   228 of your wake-up events, then your implementation of <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-C6F792DB-1EC0-33F4-8F82-AB3F7B44B061"><apiname>DPowerController::AbsoluteTimerExpired()</apiname></xref> should
       
   229 call <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-C193F898-2C15-3C42-8353-14F00789BCDA"><apiname>DPowerController::WakeupEvent()</apiname></xref> to notify the power
       
   230 manager that a wake-up event has happened. </p> <p>It is recommended that
       
   231 you track absolute timers. </p> </section>
       
   232 <section id="GUID-1F77C71C-D226-58BB-ABAE-43F958CC0C61"><title>DPowerController::PowerDown()</title> <codeblock id="GUID-AD394AD5-8E3E-5FE3-938E-639C4E5E9F79" xml:space="preserve">virtual void PowerDown(TTimeK aWakeupTime) = 0;</codeblock> <p><b>When is it called?</b> </p> <p> <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-8AE99718-6B82-3920-9029-28C2041A3B10"><apiname>DPowerController::PowerDown()</apiname></xref> is
       
   233 called by the <xref href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita#GUID-0C435514-EEC6-5660-BB5F-535790349632/GUID-330F07B2-BBDF-5675-B7D5-FF6B25DD03F4">power
       
   234 manager</xref> to move the device into one of the system-wide low power states: <i>Standby</i> or <i>Off</i>. </p> <p>Typically,
       
   235 this is a result of the user side entity that is responsible for moving the
       
   236 device into a low power state calling <xref href="GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87.dita#GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87/GUID-7C6F3F0F-319B-3DEE-81BF-1EB5BB2EAB0A"><apiname>Power::PowerDown()</apiname></xref> in
       
   237 the user side interface to the <xref href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita#GUID-0C435514-EEC6-5660-BB5F-535790349632/GUID-330F07B2-BBDF-5675-B7D5-FF6B25DD03F4">power
       
   238 manager</xref>. </p> <p>If <xref href="GUID-26621CA5-B686-53FB-AF3E-96CDD38C8520.dita">physical
       
   239 RAM defragmentation</xref> is implemented you may wish to include calls to <xref href="GUID-AE7E0A8E-1513-3F6B-A6D5-150084C4E262.dita#GUID-AE7E0A8E-1513-3F6B-A6D5-150084C4E262/GUID-B4825007-E3DB-3559-9D58-637150EF3DB9"><apiname> TRamDefragRequest::DefragRam()</apiname></xref> within
       
   240 this function to enable defragmentation of RAM zones that can then be powered
       
   241 down. </p> <p><b>Context</b> </p> <p>The
       
   242 target state is defined by the value of the <codeph>iTargetState</codeph> member
       
   243 of <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita"><apiname>DPowerController</apiname></xref>, as set by the power manager. </p> <p><b>Implementation issues</b> </p> <p>Implementation depends on the target
       
   244 state: </p> <ul>
       
   245 <li id="GUID-0473B5C1-BEC0-5276-88C5-A4A8379A4621"><p>if the target state
       
   246 is <i>Standby</i>, as implied by a value of <xref href="GUID-87AB8B20-04EE-31D2-8F3D-EA904D05B8D0.dita#GUID-87AB8B20-04EE-31D2-8F3D-EA904D05B8D0/GUID-5604F598-8CBC-3A94-865F-CA58DA4492B0"><apiname>TPowerState::EPwStandby</apiname></xref> in <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-86A0C14F-B219-3E0B-BD5E-A2C20EEDBF64"><apiname>DPowerController::iTargetState</apiname></xref>,
       
   247 then the power controller should put the hardware into a state corresponding
       
   248 to the <i>Standby</i> state. </p> <p>If at least one wake-up event has been
       
   249 detected and recorded since the last call to <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-0642129D-05F2-3AB0-B562-37A7BB7A275F"><apiname>DPowerController::EnableWakeupEvents()</apiname></xref>,
       
   250 then <codeph>PowerDown()</codeph> should return immediately; otherwise, it
       
   251 should continue with the process of putting the device into <i>Standby</i>;
       
   252 execution of the function will halt, and can only continue, and return, when
       
   253 a wake-up event occurs. </p> </li>
       
   254 <li id="GUID-E38B9334-CFE4-5E91-9DD4-D7A0678AF344"><p>if the target state
       
   255 is <i>Off</i>, as implied by a value of <xref href="GUID-87AB8B20-04EE-31D2-8F3D-EA904D05B8D0.dita#GUID-87AB8B20-04EE-31D2-8F3D-EA904D05B8D0/GUID-0DAD6E93-BD08-3C90-BCE8-ADBFC2681227"><apiname>TPowerState::EPwOff</apiname></xref> in <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-86A0C14F-B219-3E0B-BD5E-A2C20EEDBF64"><apiname>DPowerController::iTargetState</apiname></xref>,
       
   256 then <codeph>PowerDown()</codeph> must <i>never</i> return. Typically, the
       
   257 power controller turns the device off, but can choose to perform other device-specific
       
   258 action such as a system reboot. </p> </li>
       
   259 </ul> <p>The <xref href="GUID-8C6E2996-24DE-3E59-927A-46D32290225E.dita"><apiname>TTimeK</apiname></xref> parameter passed to the function is
       
   260 a system time value. If non-zero, it specifies the time when the system should
       
   261 wakeup. The kernel calculates it as the time that the next absolute timer
       
   262 expires. Typically, your implementation will use the Real Time Clock module
       
   263 to generate an event at the specified time, and this will cause a return to
       
   264 the <i>Active</i> state. This implies that the base port should enable Real
       
   265 Time Clock event detection during <i>Standby</i>. </p> <p>The Symbian definition
       
   266 of the <i>Standby</i> state usually translates into the hardware manufacturer’s
       
   267 CPU “Standby” or “Sleep” modes of operation. Typically, the internal clocks
       
   268 associated with the core and some of the core peripherals, or their power
       
   269 supply, are suppressed, and their internal state is not preserved. In this
       
   270 case, the state of the core and core peripherals should be saved before going
       
   271 into <i>Standby</i> so that they can be restored when the system wakes-up.
       
   272 Note the following: </p> <ul>
       
   273 <li id="GUID-824D88FD-33FB-50DC-A904-F5F44BFBF90A"><p>for the core state,
       
   274 save the current mode, the banked registers for each mode, and the stack pointer
       
   275 for both the current mode and user mode </p> </li>
       
   276 <li id="GUID-E8CDFA98-E6F2-5D48-987F-E2591DAB242B"><p>for the core peripherals,
       
   277 save the state of the interrupt controller, the pin function controller, the
       
   278 bus state controller, and the clock controller </p> </li>
       
   279 <li id="GUID-90BEA663-F58C-5AD7-8578-353E5EFFBCCC"><p>for the MMU state, save
       
   280 the control register, the translation table base address, and the domain access
       
   281 control, if this is supported </p> </li>
       
   282 <li id="GUID-68AB9558-5CC7-573F-8A33-A38F16EAF304"><p>flush the data cache
       
   283 and drain the write buffer. </p> </li>
       
   284 </ul> <p>If all of this data is saved to a DRAM device, then this should be
       
   285 put into self refresh mode. </p> <p>Peripherals modules involved in the detection
       
   286 of wake-up events should be left powered. </p> <p>Tick timer events should
       
   287 be disabled, and the current count of this and any other system timers should
       
   288 be saved; relevant wake-up events should be left unmasked, and any others
       
   289 should be disabled. </p> </section>
       
   290 <section id="GUID-E2A072D0-A67F-5E6D-81ED-CFD77B6ED4F1"><title>DPowerController::CpuIdle()</title> <codeblock id="GUID-0E6F1B1D-F979-575B-BA3C-096CE4C0CA15" xml:space="preserve">virtual void CpuIdle()=0;</codeblock> <p><b>When is it called?</b> </p> <p> <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita#GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366/GUID-473874CA-FC35-3EB2-BC23-A97D7176B833"><apiname>DPowerController::CpuIdle()</apiname></xref> is
       
   291 called whenever the Null thread is scheduled to run. This can happen as soon
       
   292 as the power model has been installed. It is the mechanism through which your
       
   293 base port can increase power savings when the system becomes inactive by moving
       
   294 the CPU or the system into a low power mode. </p> <p>If <xref href="GUID-26621CA5-B686-53FB-AF3E-96CDD38C8520.dita">physical
       
   295 RAM defragmentation</xref> is implemented you may wish to include calls to <xref href="GUID-AE7E0A8E-1513-3F6B-A6D5-150084C4E262.dita#GUID-AE7E0A8E-1513-3F6B-A6D5-150084C4E262/GUID-B4825007-E3DB-3559-9D58-637150EF3DB9"><apiname> TRamDefragRequest::DefragRam()</apiname></xref> within
       
   296 this function to enable defragmentation while the device is idle. </p> <p><b>Implementation issues</b> </p> <p>The implementation can call the Variant
       
   297 or ASSP implementation of <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita#GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D/GUID-6F242C0C-2EFC-30EC-9A5E-A34C8D15E0D7"><apiname>Asic::Idle()</apiname></xref>. </p> <p>The idle
       
   298 state is usually implemented via a Wait-For-Interrupt type instruction that
       
   299 will usually suspend execution of the CPU, possibly triggering other ASIC
       
   300 power saving actions, and will resume execution when any unmasked interrupt
       
   301 occurs. </p> <p><b>Suppressing
       
   302 the system tick interrupt</b> </p> <p>To further increase power savings during
       
   303 CPU Idle, a base port can choose to suppress the system tick interrupt until
       
   304 the next nanokernel Timer (as implemented by <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref>) is
       
   305 due to expire. Nanokernel timers are the basic timing service and all Symbian
       
   306 OS tick-based timers and time-of-day functions are derived from nanokernel
       
   307 timers. </p> <p>In EKA2, timing services rely on a hardware timer, which is
       
   308 programmed by the base port Variant code, to generate the system tick. We
       
   309 refer to this as the <i>system timer</i>. </p> <p>Typically, the platform-specific
       
   310 ASSP or Variant object has a pointer to the nanokernel timer queue, an <xref href="GUID-C54D99AA-FF6E-3023-8260-8F5A88FBFBE0.dita"><apiname>NTimerQ</apiname></xref> object.
       
   311 The number of ticks before the next <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> is due to expire
       
   312 can be found by calling <xref href="GUID-C54D99AA-FF6E-3023-8260-8F5A88FBFBE0.dita#GUID-C54D99AA-FF6E-3023-8260-8F5A88FBFBE0/GUID-69103F26-2C21-3ECA-9DB5-C31A41F6C238"><apiname>NTimerQ::IdleTime()</apiname></xref>. </p> <p>Before
       
   313 going into Idle mode, <codeph>CpuIdle()</codeph> disables the hardware timer
       
   314 used to generate the system tick (i.e. the system timer) for the number of
       
   315 ticks to be suppressed; i.e. the system timer is reset to go off and generate
       
   316 an interrupt only when the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expires. Note that the
       
   317 clock supply to the hardware timer must be left enabled. </p> <p>On returning
       
   318 from Idle mode, the software must examine the system timer and decide whether
       
   319 the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration was responsible for waking up the
       
   320 processor, or whether it was due to some other interrupt. </p> <p>If waking
       
   321 up was due to the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref>, the system timer must be reset
       
   322 to generate the system tick at the frequency desired, and the tick count, <xref href="GUID-C54D99AA-FF6E-3023-8260-8F5A88FBFBE0.dita#GUID-C54D99AA-FF6E-3023-8260-8F5A88FBFBE0/GUID-ACFDFE7C-19AE-3C81-9D38-3266A3A3EF1F"><apiname>NTimerQ::iMsCount</apiname></xref>,
       
   323 must be adjusted with the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration time. As the
       
   324 expiration time is always an integer multiple of the number of ticks, then
       
   325 the <xref href="GUID-C54D99AA-FF6E-3023-8260-8F5A88FBFBE0.dita#GUID-C54D99AA-FF6E-3023-8260-8F5A88FBFBE0/GUID-AA1EC86F-8A6E-340D-848F-A86554772A13"><apiname>NTimerQ::Advance()</apiname></xref> function can be used for this purpose. </p> <p>If
       
   326 waking up was due to another interrupt, then the software must read the system
       
   327 timer and calculate the time elapsed since going into Idle mode, and adjust
       
   328 the system tick count with the elapsed time (which could be a fractional number
       
   329 of ticks) and reprogram the system timer to continue generating the tick after
       
   330 the correct interval, as above. </p> <p>If the hardware timer that is used
       
   331 to generate the system ticks does not use a Compare-Match function, then some
       
   332 care has to be taken not to introduce skewing when manipulating the timer
       
   333 value directly. If the timer needs to be reloaded with the new value to give
       
   334 the next tick, then the software usually “spins”, waiting for the hardware
       
   335 timer to change, and then reloads it. This way the timer will always be reloaded
       
   336 on an edge of its internal clock. </p> <p><b>Waking
       
   337 up from “Sleep” modes with long wakeup latencies</b> </p> <p>Often, to further
       
   338 enhance power savings, the CPU and some peripherals are moved into a hardware
       
   339 “sleep” mode when <codeph>CpuIdle()</codeph> is called. This could be of long
       
   340 latency, and waking up could take longer than the system Tick period. There
       
   341 are two situations: </p> <ul>
       
   342 <li id="GUID-7484F7CB-C824-5752-9043-736E95D4405D"><p>if the wakeup time can
       
   343 be determined precisely, then <codeph>CpuIdle()</codeph> programs the system
       
   344 timer to bring the CPU back from the “Sleep“ mode at a time corresponding
       
   345 to the next <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration (as a number of Ticks to
       
   346 suppress) <i>minus</i> the number of ticks it takes to wake up from that mode.
       
   347 On waking up on the timer, the System tick count should be adjusted with the
       
   348 total number of ticks suppressed, i.e. the count corresponding to the time
       
   349 of the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration. </p> </li>
       
   350 <li id="GUID-C0A9B2A2-D98D-50C0-B58A-4E84FCEC12E4"><p>If the wakeup time cannot
       
   351 be known deterministically, then the above scheme must be combined with another
       
   352 system to allow adjusting the system timer from the hardware Real Time Clock
       
   353 (RTC). </p> <p>Typically, the hardware RTC is clocked with a 1Hz clock, and
       
   354 can be programmed to interrupt the CPU on multiples of one second intervals.
       
   355 The clock supply to the RTC must be left enabled on going into "sleep" mode. </p> </li>
       
   356 </ul> <p>To guarantee that timed events occur when they are due, the CPU should
       
   357 only be allowed to go to into the long latency hardware “sleep” mode if the
       
   358 RTC can be guaranteed to complete a second tick before the CPU is due to wakeup. </p> <p>Note
       
   359 that if waking up from hardware “Sleep” mode takes a non-negligible amount
       
   360 of time, extreme care should be taken when deciding to move the platform into
       
   361 that mode. For example, if a receive request is pending on a data input device <i>and</i> the
       
   362 CPU reaches the Idle mode <i>and</i> the platform is transitioned into a “sleep”
       
   363 state <i>and</i> data arrives while it is still in that state, <i>then</i> there
       
   364 is a possibility that the system will not wake up on time to service the incoming
       
   365 data. </p> </section>
       
   366 <section id="GUID-4B613C67-3A12-4AD5-8842-6ED510A68746"><title>Validation</title> <p>The <filepath>e32test</filepath> programs <filepath>t_power</filepath>,
       
   367 and <filepath>t_timer</filepath> will put the system into standby and resume
       
   368 off a timer. </p> </section>
       
   369 </conbody><related-links>
       
   370 <link href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita"><linktext>Power Management</linktext>
       
   371 </link>
       
   372 </related-links></concept>