Symbian3/PDK/Source/GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita
changeset 9 59758314f811
parent 5 f345bda72bc4
child 12 80ef3a206772
--- a/Symbian3/PDK/Source/GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita	Fri Jun 11 12:39:03 2010 +0100
+++ b/Symbian3/PDK/Source/GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita	Fri Jun 11 15:24:34 2010 +0100
@@ -1,371 +1,371 @@
-<?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-34D1D0BF-20DE-5677-A067-8FF9DD72E703" xml:lang="en"><title>Power
-Controller DPowerController Implementation Tutorial</title><shortdesc>This topic describes how to implement the <codeph>DPowerController</codeph> class
-to provide the main power controller functionality in a base port.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
-<p><xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita"><apiname>DPowerController</apiname></xref> is defined as: </p>
-<codeblock id="GUID-95318C39-B205-557C-B1F3-75C1441E464A" xml:space="preserve">class DPowerController : public DBase
-    {
-public:
-    IMPORT_C DPowerController();
-    IMPORT_C void Register();
-    IMPORT_C void WakeupEvent();
-
-#ifndef __X86__
-    IMPORT_C TInt RegisterResourceController(DBase* aController, TInt aClientId);
-private:
-    struct SResourceControllerData
-        {
-        DBase* iResourceController;
-        TInt   iClientId;
-        } iResourceControllerData;
-#endif
-
-public:
-    volatile TPowerState    iTargetState;
-public:
-    virtual void CpuIdle() = 0;
-    virtual void EnableWakeupEvents() = 0;
-    virtual void DisableWakeupEvents() = 0;
-    virtual void AbsoluteTimerExpired() = 0;
-    virtual void PowerDown(TTimeK aWakeupTime) = 0;
-    };
-      </codeblock>
-<p>The first three functions are exported from the kernel, <filepath>EKERN.EXE</filepath>,
-while the other five pure virtual functions are implemented by your base port.
-You do not need to export any other functions. </p>
-<ul>
-<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>
-<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>
-<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>
-<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>
-<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>
-<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>
-</ul>
-<section id="GUID-BCCDBA09-415D-5779-BCE5-CDEB2E1EF7D8"><title>Initialising
-the power controller</title> <p>Typically, you implement your derived class
-in a power management kernel extension, which has the opportunity to perform
-initialisation before the system itself is fully initialised. This is done
-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
-as a wrapper around your initialisation code. There are at least three things
-to do here: </p> <ul>
-<li id="GUID-25C66F1B-6B2F-5B3B-A827-410263EE22A4"><p>create an instance of
-your power controller object </p> </li>
-<li id="GUID-369A09EC-74D3-529A-AC05-0EFE0C4ABBF7"><p>register your power
-controller object with the Symbian platform 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>.
-Your power controller cannot be used by the Symbian platform power manager
-until it has been registered. </p> </li>
-<li id="GUID-E4C7D934-AAB9-511B-93A4-125D5A5B248D"><p>if you intend to use
-a battery monitor, then you would create it and register it as the HAL handler
-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
-Tutorialc</xref> and <xref href="GUID-54042C84-6216-5930-9CBF-BAF635CECD4D.dita">Power
-HAL Handler Tutorial</xref> for more detail. </p> </li>
-</ul> <p>For example: </p> <codeblock id="GUID-1A909C4C-DCAF-54E3-B482-16918E33BF4F" xml:space="preserve">DECLARE_STANDARD_EXTENSION()
-    {
-    TInt r=KErrNoMemory;
-
-    // Create the power controller object, and register it.
-    DPowerController* pC = new DYourPowerController;
-    if !(pC)
-        {
-        return (r);
-        }
-        pC-&gt;Register();
-
-    // Create the battery monitor.
-    DBatteryMonitor* pM = new DYourBatteryMonitor;
-    if !(pM)
-        {
-        return(r);
-        }
-
-    r = KErrNone;
-    return(r);
-    }</codeblock> </section>
-<section id="GUID-DCD91EBA-CB0E-5EA9-84E0-8F8FED6FC91E"><title>DPowerController::RegisterResourceController()</title> <p>The
-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
-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
-with the resource controller</xref> in the PSL implementation document. </p> <p>To
-support idle power management the Power Controller's PSL must override <codeph>RegisterResourceController()</codeph> to
-include the registration of a list of resources whose states are of interest
-to idle power management. </p> <p><b>Idle
-power management</b> </p> <p>The Power Controller can assemble a list of resources
-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.
-Each entry in the list contains the resource ID that the power controller
-must enter before registering with the PRM. The resource list should be created
-in the kernel heap or data section. </p> <p>The example below creates a buffer
-to capture the state of all static resources. The PRM captures the information
-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">    ...
-//Allocate buffer for Idle resource management
-    NKern::ThreadEnterCS();
-    pBuf = HBuf::New(numResources * sizeof(SIdleResourceInfo)); 
-    NKern::ThreadLeaveCS();
-    if(!pBuf)
-        {
-           return KErrNoMemory;
-        }
-    SIdleResourceInfo* pI = (SIdleResourceInfo*)pBuf-&gt;Ptr();
-
-//Update resource ID
-    for(TUint c = 0; c &lt; numResources; c++)
-        {
-        pI[c].iResourceId = c+1; 
-        }
-    r = (iResourceControllerData.iResourceController)-&gt;RegisterResourcesForIdle(iResourceControllerData.iClientId, numResources, (TPtr*)pI);
-    ...</codeblock> <p>The first parameter passed to <codeph>RegisterResourcesForIdle()</codeph> is
-the client Id generated for the power controller this is the client ID passed
-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
-not exported and is only available for use by the Power Controller to register
-resources for idle power management. <b>Note</b>: <codeph>RegisterResourcesForIdle()</codeph> can
-only be called by the Power Controller once. </p> </section>
-<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
-Symbian Power Model defines 3 generic system-wide <xref href="GUID-113B3755-1797-5D1B-8E07-8A18F5FE1504.dita">power
-states</xref>: <i>Active</i>, <i>Standby</i> and <i>Off</i>, as defined in
-the <xref href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita">Symbian platform
-power model</xref>. </p> <p>Each of the system-wide low power states: <i>Standby</i> and <i>Off</i>,
-has a defined set of wake-up events. If a wake-up event occurs while the system
-is preparing to transition into one of these low power states, or when the
-system is in the <i>Standby</i> state, then this can result in the system
-moving back to the <i>Active</i> power state. Wake-up events may be different
-for different target power states. Wake-up events are platform-specific hardware
-events, and it is your base port that decides which events count as wake-up
-events. </p> <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-0642129D-05F2-3AB0-B562-37A7BB7A275F"><apiname>DPowerController::EnableWakeupEvents()</apiname></xref> is
-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
-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>.
-The class <xref href="GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87.dita"><apiname>Power</apiname></xref> is the user side interface to the power
-manager, and is used by the user side entity that is responsible for moving
-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
-state, it sends a notification to all of the user side power domains registered
-with it, giving their applications a chance to save their data and state.
-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>.
-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
-that it can be informed of a wake-up event. If it is notified of a wake-up
-event, it can halt, and reverse the user side response to the power transition. </p> <fig id="GUID-ACC6E7E3-71E3-5553-B433-9017CB04513D">
-<image href="GUID-65F3E8BD-22C9-5CF2-A3CC-270C24ADECC0_d0e399684_href.png" placement="inline"/>
-</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>,
-the power manager sets the <codeph>iTargetState</codeph> member of <codeph>DPowerController</codeph> to
-the applicable <xref href="GUID-87AB8B20-04EE-31D2-8F3D-EA904D05B8D0.dita"><apiname>TPowerState</apiname></xref>. This means that you can enable
-the appropriate set of wake-up events. </p> <p>Once the user side transition
-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
-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
-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
-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
-means that the power controller needs the ability to detect wake-up events
-so that it can halt, and reverse the power transition. </p> <p><b>Implementation issues</b> </p> <p>There are three possibilities in dealing
-with wake-up events: </p> <ul>
-<li id="GUID-4243E6DD-C903-58DE-B125-38CEDB8B5269"><p>if wake-up events are
-not handled by specific peripheral drivers, you could set up the hardware
-so that wake-up events are recorded in a location accessible by the software.
-Prior to completing the system power transition, the Power controller would
-check the relevant hardware to see whether a wakeup event had occurred. On
-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>
-<li id="GUID-289B86C4-A578-5A42-A0DF-70A7BF3F440E"><p>if wake-up events are
-not handled by specific peripheral drivers, you could arrange for wake-up
-events to interrupt the CPU. The code that services those interrupts would
-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>
-<li id="GUID-E51BAE55-0A81-5D1F-B509-096A7F2141EF"><p>if wakeup events are
-intercepted, serviced and cleared by peripheral drivers, then the following
-outline solution could be adopted: </p> <ul>
-<li id="GUID-5C942237-BBB2-5919-8578-B55BDAFAFC9F"><p>The power controller
-would need to publish a list of wake-up events, preferably as a bit mask,
-and export an API which peripheral drivers could use to notify the power controller
-that a wake-up event has occurred. The following interface class could be
-used for this purpose: </p> <codeblock id="GUID-084F7F46-66B6-5661-85AF-57D499250886" xml:space="preserve">class TPowerController
-    {
-public:
-    inline static void SetPowerControllerPointer(DPowerController* apPowerController)
-    { iPowerControllerPointer = apPowerController; }
-    IMPORT_C static void WakeupEventOccurred(TUint aWakeupEvent);
-    …        // other methods if required
-private:
-    DPowerController* iPowerControllerPointer;
-    };
-                      </codeblock> <p>The class would be implemented as part
-of the power management kernel extension and <codeph>SetPowerControllerPointer()</codeph> would
-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
-the power controller</xref>, but after creation of the power controller object. </p> <p>Those
-peripheral drivers that intercept wake-up events would need to link to the
-power controller DLL (i.e. the power management kernel extension). </p> <p>On
-the occurrence of a wake-up event, the peripheral driver software servicing
-that event would notify the power controller by calling <codeph>WakeupEventOccurred()</codeph>,
-specifying the appropriate wake-up event bit(s). </p> <p>You might implement <codeph>WakeupEventOccurred()</codeph> as
-follows: </p> <codeblock id="GUID-501ABA28-81B9-52C1-9842-003E1E389045" xml:space="preserve">EXPORT_C void TPowerController::WakeupEventOccurred(TUint aWakeupEvent)
-    {
-    if(iPowerControllerPointer-&gt;iWakeupEvents &amp; aWakeupEvent)
-        {
-        iPowerControllerPointer-&gt;WakeupEvent();
-        }
-    }</codeblock> <p>where <codeph>iWakeupEvents</codeph> is a data member
-defined in your <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita"><apiname>DPowerController</apiname></xref> -derived class that contains
-the bitmask representing the wake-up events. The bitmask groups wakeup events
-according to the target power state. </p> </li>
-</ul> </li>
-</ul> <p>When the peripheral driver powers down, it should leave the hardware
-that generates the wake-up event powered and enabled for detection. Thus,
-if a wake-up event of the type handled by this peripheral driver occurs, it
-will not be serviced in the normal way, but will be left pending until the
-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
-is called, the power controller must check the peripheral hardware directly
-to see whether the wakeup event has happened, or is happening right now, prior
-to transitioning the device to the target system-wide low power state. If
-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
-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
-handlers</xref> power down of the peripheral drivers. </p> </section>
-<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
-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
-manager</xref> whenever an absolute timer expires. An absolute timer is one
-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
-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
-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
-manager that a wake-up event has happened. </p> <p>It is recommended that
-you track absolute timers. </p> </section>
-<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
-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
-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,
-this is a result of the user side entity that is responsible for moving the
-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
-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
-manager</xref>. </p> <p>If <xref href="GUID-26621CA5-B686-53FB-AF3E-96CDD38C8520.dita">physical
-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
-this function to enable defragmentation of RAM zones that can then be powered
-down. </p> <p><b>Context</b> </p> <p>The
-target state is defined by the value of the <codeph>iTargetState</codeph> member
-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
-state: </p> <ul>
-<li id="GUID-0473B5C1-BEC0-5276-88C5-A4A8379A4621"><p>if the target state
-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>,
-then the power controller should put the hardware into a state corresponding
-to the <i>Standby</i> state. </p> <p>If at least one wake-up event has been
-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>,
-then <codeph>PowerDown()</codeph> should return immediately; otherwise, it
-should continue with the process of putting the device into <i>Standby</i>;
-execution of the function will halt, and can only continue, and return, when
-a wake-up event occurs. </p> </li>
-<li id="GUID-E38B9334-CFE4-5E91-9DD4-D7A0678AF344"><p>if the target state
-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>,
-then <codeph>PowerDown()</codeph> must <i>never</i> return. Typically, the
-power controller turns the device off, but can choose to perform other device-specific
-action such as a system reboot. </p> </li>
-</ul> <p>The <xref href="GUID-8C6E2996-24DE-3E59-927A-46D32290225E.dita"><apiname>TTimeK</apiname></xref> parameter passed to the function is
-a system time value. If non-zero, it specifies the time when the system should
-wakeup. The kernel calculates it as the time that the next absolute timer
-expires. Typically, your implementation will use the Real Time Clock module
-to generate an event at the specified time, and this will cause a return to
-the <i>Active</i> state. This implies that the base port should enable Real
-Time Clock event detection during <i>Standby</i>. </p> <p>The Symbian definition
-of the <i>Standby</i> state usually translates into the hardware manufacturer’s
-CPU “Standby” or “Sleep” modes of operation. Typically, the internal clocks
-associated with the core and some of the core peripherals, or their power
-supply, are suppressed, and their internal state is not preserved. In this
-case, the state of the core and core peripherals should be saved before going
-into <i>Standby</i> so that they can be restored when the system wakes-up.
-Note the following: </p> <ul>
-<li id="GUID-824D88FD-33FB-50DC-A904-F5F44BFBF90A"><p>for the core state,
-save the current mode, the banked registers for each mode, and the stack pointer
-for both the current mode and user mode </p> </li>
-<li id="GUID-E8CDFA98-E6F2-5D48-987F-E2591DAB242B"><p>for the core peripherals,
-save the state of the interrupt controller, the pin function controller, the
-bus state controller, and the clock controller </p> </li>
-<li id="GUID-90BEA663-F58C-5AD7-8578-353E5EFFBCCC"><p>for the MMU state, save
-the control register, the translation table base address, and the domain access
-control, if this is supported </p> </li>
-<li id="GUID-68AB9558-5CC7-573F-8A33-A38F16EAF304"><p>flush the data cache
-and drain the write buffer. </p> </li>
-</ul> <p>If all of this data is saved to a DRAM device, then this should be
-put into self refresh mode. </p> <p>Peripherals modules involved in the detection
-of wake-up events should be left powered. </p> <p>Tick timer events should
-be disabled, and the current count of this and any other system timers should
-be saved; relevant wake-up events should be left unmasked, and any others
-should be disabled. </p> </section>
-<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
-called whenever the Null thread is scheduled to run. This can happen as soon
-as the power model has been installed. It is the mechanism through which your
-base port can increase power savings when the system becomes inactive by moving
-the CPU or the system into a low power mode. </p> <p>If <xref href="GUID-26621CA5-B686-53FB-AF3E-96CDD38C8520.dita">physical
-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
-this function to enable defragmentation while the device is idle. </p> <p><b>Implementation issues</b> </p> <p>The implementation can call the Variant
-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
-state is usually implemented via a Wait-For-Interrupt type instruction that
-will usually suspend execution of the CPU, possibly triggering other ASIC
-power saving actions, and will resume execution when any unmasked interrupt
-occurs. </p> <p><b>Suppressing
-the system tick interrupt</b> </p> <p>To further increase power savings during
-CPU Idle, a base port can choose to suppress the system tick interrupt until
-the next nanokernel Timer (as implemented by <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref>) is
-due to expire. Nanokernel timers are the basic timing service and all Symbian
-platform tick-based timers and time-of-day functions are derived from nanokernel
-timers. </p> <p>In EKA2, timing services rely on a hardware timer, which is
-programmed by the base port Variant code, to generate the system tick. We
-refer to this as the <i>system timer</i>. </p> <p>Typically, the platform-specific
-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.
-The number of ticks before the next <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> is due to expire
-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
-going into Idle mode, <codeph>CpuIdle()</codeph> disables the hardware timer
-used to generate the system tick (i.e. the system timer) for the number of
-ticks to be suppressed; i.e. the system timer is reset to go off and generate
-an interrupt only when the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expires. Note that the
-clock supply to the hardware timer must be left enabled. </p> <p>On returning
-from Idle mode, the software must examine the system timer and decide whether
-the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration was responsible for waking up the
-processor, or whether it was due to some other interrupt. </p> <p>If waking
-up was due to the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref>, the system timer must be reset
-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>,
-must be adjusted with the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration time. As the
-expiration time is always an integer multiple of the number of ticks, then
-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
-waking up was due to another interrupt, then the software must read the system
-timer and calculate the time elapsed since going into Idle mode, and adjust
-the system tick count with the elapsed time (which could be a fractional number
-of ticks) and reprogram the system timer to continue generating the tick after
-the correct interval, as above. </p> <p>If the hardware timer that is used
-to generate the system ticks does not use a Compare-Match function, then some
-care has to be taken not to introduce skewing when manipulating the timer
-value directly. If the timer needs to be reloaded with the new value to give
-the next tick, then the software usually “spins”, waiting for the hardware
-timer to change, and then reloads it. This way the timer will always be reloaded
-on an edge of its internal clock. </p> <p><b>Waking
-up from “Sleep” modes with long wakeup latencies</b> </p> <p>Often, to further
-enhance power savings, the CPU and some peripherals are moved into a hardware
-“sleep” mode when <codeph>CpuIdle()</codeph> is called. This could be of long
-latency, and waking up could take longer than the system Tick period. There
-are two situations: </p> <ul>
-<li id="GUID-7484F7CB-C824-5752-9043-736E95D4405D"><p>if the wakeup time can
-be determined precisely, then <codeph>CpuIdle()</codeph> programs the system
-timer to bring the CPU back from the “Sleep“ mode at a time corresponding
-to the next <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration (as a number of Ticks to
-suppress) <i>minus</i> the number of ticks it takes to wake up from that mode.
-On waking up on the timer, the System tick count should be adjusted with the
-total number of ticks suppressed, i.e. the count corresponding to the time
-of the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration. </p> </li>
-<li id="GUID-C0A9B2A2-D98D-50C0-B58A-4E84FCEC12E4"><p>If the wakeup time cannot
-be known deterministically, then the above scheme must be combined with another
-system to allow adjusting the system timer from the hardware Real Time Clock
-(RTC). </p> <p>Typically, the hardware RTC is clocked with a 1Hz clock, and
-can be programmed to interrupt the CPU on multiples of one second intervals.
-The clock supply to the RTC must be left enabled on going into "sleep" mode. </p> </li>
-</ul> <p>To guarantee that timed events occur when they are due, the CPU should
-only be allowed to go to into the long latency hardware “sleep” mode if the
-RTC can be guaranteed to complete a second tick before the CPU is due to wakeup. </p> <p>Note
-that if waking up from hardware “Sleep” mode takes a non-negligible amount
-of time, extreme care should be taken when deciding to move the platform into
-that mode. For example, if a receive request is pending on a data input device <i>and</i> the
-CPU reaches the Idle mode <i>and</i> the platform is transitioned into a “sleep”
-state <i>and</i> data arrives while it is still in that state, <i>then</i> there
-is a possibility that the system will not wake up on time to service the incoming
-data. </p> </section>
-<section id="GUID-4B613C67-3A12-4AD5-8842-6ED510A68746"><title>Validation</title> <p>The <filepath>e32test</filepath> programs <filepath>t_power</filepath>, and <filepath>t_timer</filepath> will put the system into standby and resume
-off a timer. </p> </section>
-</conbody><related-links>
-<link href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita"><linktext>Power Management</linktext>
-</link>
+<?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-34D1D0BF-20DE-5677-A067-8FF9DD72E703" xml:lang="en"><title>Power
+Controller DPowerController Implementation Tutorial</title><shortdesc>This topic describes how to implement the <codeph>DPowerController</codeph> class
+to provide the main power controller functionality in a base port.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
+<p><xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita"><apiname>DPowerController</apiname></xref> is defined as: </p>
+<codeblock id="GUID-95318C39-B205-557C-B1F3-75C1441E464A" xml:space="preserve">class DPowerController : public DBase
+    {
+public:
+    IMPORT_C DPowerController();
+    IMPORT_C void Register();
+    IMPORT_C void WakeupEvent();
+
+#ifndef __X86__
+    IMPORT_C TInt RegisterResourceController(DBase* aController, TInt aClientId);
+private:
+    struct SResourceControllerData
+        {
+        DBase* iResourceController;
+        TInt   iClientId;
+        } iResourceControllerData;
+#endif
+
+public:
+    volatile TPowerState    iTargetState;
+public:
+    virtual void CpuIdle() = 0;
+    virtual void EnableWakeupEvents() = 0;
+    virtual void DisableWakeupEvents() = 0;
+    virtual void AbsoluteTimerExpired() = 0;
+    virtual void PowerDown(TTimeK aWakeupTime) = 0;
+    };
+      </codeblock>
+<p>The first three functions are exported from the kernel, <filepath>EKERN.EXE</filepath>,
+while the other five pure virtual functions are implemented by your base port.
+You do not need to export any other functions. </p>
+<ul>
+<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>
+<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>
+<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>
+<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>
+<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>
+<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>
+</ul>
+<section id="GUID-BCCDBA09-415D-5779-BCE5-CDEB2E1EF7D8"><title>Initialising
+the power controller</title> <p>Typically, you implement your derived class
+in a power management kernel extension, which has the opportunity to perform
+initialisation before the system itself is fully initialised. This is done
+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
+as a wrapper around your initialisation code. There are at least three things
+to do here: </p> <ul>
+<li id="GUID-25C66F1B-6B2F-5B3B-A827-410263EE22A4"><p>create an instance of
+your power controller object </p> </li>
+<li id="GUID-369A09EC-74D3-529A-AC05-0EFE0C4ABBF7"><p>register your power
+controller object with the Symbian platform 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>.
+Your power controller cannot be used by the Symbian platform power manager
+until it has been registered. </p> </li>
+<li id="GUID-E4C7D934-AAB9-511B-93A4-125D5A5B248D"><p>if you intend to use
+a battery monitor, then you would create it and register it as the HAL handler
+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
+Tutorialc</xref> and <xref href="GUID-54042C84-6216-5930-9CBF-BAF635CECD4D.dita">Power
+HAL Handler Tutorial</xref> for more detail. </p> </li>
+</ul> <p>For example: </p> <codeblock id="GUID-1A909C4C-DCAF-54E3-B482-16918E33BF4F" xml:space="preserve">DECLARE_STANDARD_EXTENSION()
+    {
+    TInt r=KErrNoMemory;
+
+    // Create the power controller object, and register it.
+    DPowerController* pC = new DYourPowerController;
+    if !(pC)
+        {
+        return (r);
+        }
+        pC-&gt;Register();
+
+    // Create the battery monitor.
+    DBatteryMonitor* pM = new DYourBatteryMonitor;
+    if !(pM)
+        {
+        return(r);
+        }
+
+    r = KErrNone;
+    return(r);
+    }</codeblock> </section>
+<section id="GUID-DCD91EBA-CB0E-5EA9-84E0-8F8FED6FC91E"><title>DPowerController::RegisterResourceController()</title> <p>The
+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
+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
+with the resource controller</xref> in the PSL implementation document. </p> <p>To
+support idle power management the Power Controller's PSL must override <codeph>RegisterResourceController()</codeph> to
+include the registration of a list of resources whose states are of interest
+to idle power management. </p> <p><b>Idle
+power management</b> </p> <p>The Power Controller can assemble a list of resources
+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.
+Each entry in the list contains the resource ID that the power controller
+must enter before registering with the PRM. The resource list should be created
+in the kernel heap or data section. </p> <p>The example below creates a buffer
+to capture the state of all static resources. The PRM captures the information
+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">    ...
+//Allocate buffer for Idle resource management
+    NKern::ThreadEnterCS();
+    pBuf = HBuf::New(numResources * sizeof(SIdleResourceInfo)); 
+    NKern::ThreadLeaveCS();
+    if(!pBuf)
+        {
+           return KErrNoMemory;
+        }
+    SIdleResourceInfo* pI = (SIdleResourceInfo*)pBuf-&gt;Ptr();
+
+//Update resource ID
+    for(TUint c = 0; c &lt; numResources; c++)
+        {
+        pI[c].iResourceId = c+1; 
+        }
+    r = (iResourceControllerData.iResourceController)-&gt;RegisterResourcesForIdle(iResourceControllerData.iClientId, numResources, (TPtr*)pI);
+    ...</codeblock> <p>The first parameter passed to <codeph>RegisterResourcesForIdle()</codeph> is
+the client Id generated for the power controller this is the client ID passed
+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
+not exported and is only available for use by the Power Controller to register
+resources for idle power management. <b>Note</b>: <codeph>RegisterResourcesForIdle()</codeph> can
+only be called by the Power Controller once. </p> </section>
+<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
+Symbian Power Model defines 3 generic system-wide <xref href="GUID-113B3755-1797-5D1B-8E07-8A18F5FE1504.dita">power
+states</xref>: <i>Active</i>, <i>Standby</i> and <i>Off</i>, as defined in
+the <xref href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita">Symbian platform
+power model</xref>. </p> <p>Each of the system-wide low power states: <i>Standby</i> and <i>Off</i>,
+has a defined set of wake-up events. If a wake-up event occurs while the system
+is preparing to transition into one of these low power states, or when the
+system is in the <i>Standby</i> state, then this can result in the system
+moving back to the <i>Active</i> power state. Wake-up events may be different
+for different target power states. Wake-up events are platform-specific hardware
+events, and it is your base port that decides which events count as wake-up
+events. </p> <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-0642129D-05F2-3AB0-B562-37A7BB7A275F"><apiname>DPowerController::EnableWakeupEvents()</apiname></xref> is
+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
+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>.
+The class <xref href="GUID-15D25C07-CFD2-32CE-AD22-E17D512D8E87.dita"><apiname>Power</apiname></xref> is the user side interface to the power
+manager, and is used by the user side entity that is responsible for moving
+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
+state, it sends a notification to all of the user side power domains registered
+with it, giving their applications a chance to save their data and state.
+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>.
+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
+that it can be informed of a wake-up event. If it is notified of a wake-up
+event, it can halt, and reverse the user side response to the power transition. </p> <fig id="GUID-ACC6E7E3-71E3-5553-B433-9017CB04513D">
+<image href="GUID-65F3E8BD-22C9-5CF2-A3CC-270C24ADECC0_d0e388259_href.png" placement="inline"/>
+</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>,
+the power manager sets the <codeph>iTargetState</codeph> member of <codeph>DPowerController</codeph> to
+the applicable <xref href="GUID-87AB8B20-04EE-31D2-8F3D-EA904D05B8D0.dita"><apiname>TPowerState</apiname></xref>. This means that you can enable
+the appropriate set of wake-up events. </p> <p>Once the user side transition
+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
+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
+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
+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
+means that the power controller needs the ability to detect wake-up events
+so that it can halt, and reverse the power transition. </p> <p><b>Implementation issues</b> </p> <p>There are three possibilities in dealing
+with wake-up events: </p> <ul>
+<li id="GUID-4243E6DD-C903-58DE-B125-38CEDB8B5269"><p>if wake-up events are
+not handled by specific peripheral drivers, you could set up the hardware
+so that wake-up events are recorded in a location accessible by the software.
+Prior to completing the system power transition, the Power controller would
+check the relevant hardware to see whether a wakeup event had occurred. On
+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>
+<li id="GUID-289B86C4-A578-5A42-A0DF-70A7BF3F440E"><p>if wake-up events are
+not handled by specific peripheral drivers, you could arrange for wake-up
+events to interrupt the CPU. The code that services those interrupts would
+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>
+<li id="GUID-E51BAE55-0A81-5D1F-B509-096A7F2141EF"><p>if wakeup events are
+intercepted, serviced and cleared by peripheral drivers, then the following
+outline solution could be adopted: </p> <ul>
+<li id="GUID-5C942237-BBB2-5919-8578-B55BDAFAFC9F"><p>The power controller
+would need to publish a list of wake-up events, preferably as a bit mask,
+and export an API which peripheral drivers could use to notify the power controller
+that a wake-up event has occurred. The following interface class could be
+used for this purpose: </p> <codeblock id="GUID-084F7F46-66B6-5661-85AF-57D499250886" xml:space="preserve">class TPowerController
+    {
+public:
+    inline static void SetPowerControllerPointer(DPowerController* apPowerController)
+    { iPowerControllerPointer = apPowerController; }
+    IMPORT_C static void WakeupEventOccurred(TUint aWakeupEvent);
+    …        // other methods if required
+private:
+    DPowerController* iPowerControllerPointer;
+    };
+                      </codeblock> <p>The class would be implemented as part
+of the power management kernel extension and <codeph>SetPowerControllerPointer()</codeph> would
+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
+the power controller</xref>, but after creation of the power controller object. </p> <p>Those
+peripheral drivers that intercept wake-up events would need to link to the
+power controller DLL (i.e. the power management kernel extension). </p> <p>On
+the occurrence of a wake-up event, the peripheral driver software servicing
+that event would notify the power controller by calling <codeph>WakeupEventOccurred()</codeph>,
+specifying the appropriate wake-up event bit(s). </p> <p>You might implement <codeph>WakeupEventOccurred()</codeph> as
+follows: </p> <codeblock id="GUID-501ABA28-81B9-52C1-9842-003E1E389045" xml:space="preserve">EXPORT_C void TPowerController::WakeupEventOccurred(TUint aWakeupEvent)
+    {
+    if(iPowerControllerPointer-&gt;iWakeupEvents &amp; aWakeupEvent)
+        {
+        iPowerControllerPointer-&gt;WakeupEvent();
+        }
+    }</codeblock> <p>where <codeph>iWakeupEvents</codeph> is a data member
+defined in your <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita"><apiname>DPowerController</apiname></xref> -derived class that contains
+the bitmask representing the wake-up events. The bitmask groups wakeup events
+according to the target power state. </p> </li>
+</ul> </li>
+</ul> <p>When the peripheral driver powers down, it should leave the hardware
+that generates the wake-up event powered and enabled for detection. Thus,
+if a wake-up event of the type handled by this peripheral driver occurs, it
+will not be serviced in the normal way, but will be left pending until the
+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
+is called, the power controller must check the peripheral hardware directly
+to see whether the wakeup event has happened, or is happening right now, prior
+to transitioning the device to the target system-wide low power state. If
+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
+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
+handlers</xref> power down of the peripheral drivers. </p> </section>
+<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
+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
+manager</xref> whenever an absolute timer expires. An absolute timer is one
+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
+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
+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
+manager that a wake-up event has happened. </p> <p>It is recommended that
+you track absolute timers. </p> </section>
+<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
+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
+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,
+this is a result of the user side entity that is responsible for moving the
+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
+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
+manager</xref>. </p> <p>If <xref href="GUID-26621CA5-B686-53FB-AF3E-96CDD38C8520.dita">physical
+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
+this function to enable defragmentation of RAM zones that can then be powered
+down. </p> <p><b>Context</b> </p> <p>The
+target state is defined by the value of the <codeph>iTargetState</codeph> member
+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
+state: </p> <ul>
+<li id="GUID-0473B5C1-BEC0-5276-88C5-A4A8379A4621"><p>if the target state
+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>,
+then the power controller should put the hardware into a state corresponding
+to the <i>Standby</i> state. </p> <p>If at least one wake-up event has been
+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>,
+then <codeph>PowerDown()</codeph> should return immediately; otherwise, it
+should continue with the process of putting the device into <i>Standby</i>;
+execution of the function will halt, and can only continue, and return, when
+a wake-up event occurs. </p> </li>
+<li id="GUID-E38B9334-CFE4-5E91-9DD4-D7A0678AF344"><p>if the target state
+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>,
+then <codeph>PowerDown()</codeph> must <i>never</i> return. Typically, the
+power controller turns the device off, but can choose to perform other device-specific
+action such as a system reboot. </p> </li>
+</ul> <p>The <xref href="GUID-8C6E2996-24DE-3E59-927A-46D32290225E.dita"><apiname>TTimeK</apiname></xref> parameter passed to the function is
+a system time value. If non-zero, it specifies the time when the system should
+wakeup. The kernel calculates it as the time that the next absolute timer
+expires. Typically, your implementation will use the Real Time Clock module
+to generate an event at the specified time, and this will cause a return to
+the <i>Active</i> state. This implies that the base port should enable Real
+Time Clock event detection during <i>Standby</i>. </p> <p>The Symbian definition
+of the <i>Standby</i> state usually translates into the hardware manufacturer’s
+CPU “Standby” or “Sleep” modes of operation. Typically, the internal clocks
+associated with the core and some of the core peripherals, or their power
+supply, are suppressed, and their internal state is not preserved. In this
+case, the state of the core and core peripherals should be saved before going
+into <i>Standby</i> so that they can be restored when the system wakes-up.
+Note the following: </p> <ul>
+<li id="GUID-824D88FD-33FB-50DC-A904-F5F44BFBF90A"><p>for the core state,
+save the current mode, the banked registers for each mode, and the stack pointer
+for both the current mode and user mode </p> </li>
+<li id="GUID-E8CDFA98-E6F2-5D48-987F-E2591DAB242B"><p>for the core peripherals,
+save the state of the interrupt controller, the pin function controller, the
+bus state controller, and the clock controller </p> </li>
+<li id="GUID-90BEA663-F58C-5AD7-8578-353E5EFFBCCC"><p>for the MMU state, save
+the control register, the translation table base address, and the domain access
+control, if this is supported </p> </li>
+<li id="GUID-68AB9558-5CC7-573F-8A33-A38F16EAF304"><p>flush the data cache
+and drain the write buffer. </p> </li>
+</ul> <p>If all of this data is saved to a DRAM device, then this should be
+put into self refresh mode. </p> <p>Peripherals modules involved in the detection
+of wake-up events should be left powered. </p> <p>Tick timer events should
+be disabled, and the current count of this and any other system timers should
+be saved; relevant wake-up events should be left unmasked, and any others
+should be disabled. </p> </section>
+<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
+called whenever the Null thread is scheduled to run. This can happen as soon
+as the power model has been installed. It is the mechanism through which your
+base port can increase power savings when the system becomes inactive by moving
+the CPU or the system into a low power mode. </p> <p>If <xref href="GUID-26621CA5-B686-53FB-AF3E-96CDD38C8520.dita">physical
+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
+this function to enable defragmentation while the device is idle. </p> <p><b>Implementation issues</b> </p> <p>The implementation can call the Variant
+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
+state is usually implemented via a Wait-For-Interrupt type instruction that
+will usually suspend execution of the CPU, possibly triggering other ASIC
+power saving actions, and will resume execution when any unmasked interrupt
+occurs. </p> <p><b>Suppressing
+the system tick interrupt</b> </p> <p>To further increase power savings during
+CPU Idle, a base port can choose to suppress the system tick interrupt until
+the next nanokernel Timer (as implemented by <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref>) is
+due to expire. Nanokernel timers are the basic timing service and all Symbian
+platform tick-based timers and time-of-day functions are derived from nanokernel
+timers. </p> <p>In EKA2, timing services rely on a hardware timer, which is
+programmed by the base port Variant code, to generate the system tick. We
+refer to this as the <i>system timer</i>. </p> <p>Typically, the platform-specific
+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.
+The number of ticks before the next <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> is due to expire
+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
+going into Idle mode, <codeph>CpuIdle()</codeph> disables the hardware timer
+used to generate the system tick (i.e. the system timer) for the number of
+ticks to be suppressed; i.e. the system timer is reset to go off and generate
+an interrupt only when the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expires. Note that the
+clock supply to the hardware timer must be left enabled. </p> <p>On returning
+from Idle mode, the software must examine the system timer and decide whether
+the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration was responsible for waking up the
+processor, or whether it was due to some other interrupt. </p> <p>If waking
+up was due to the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref>, the system timer must be reset
+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>,
+must be adjusted with the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration time. As the
+expiration time is always an integer multiple of the number of ticks, then
+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
+waking up was due to another interrupt, then the software must read the system
+timer and calculate the time elapsed since going into Idle mode, and adjust
+the system tick count with the elapsed time (which could be a fractional number
+of ticks) and reprogram the system timer to continue generating the tick after
+the correct interval, as above. </p> <p>If the hardware timer that is used
+to generate the system ticks does not use a Compare-Match function, then some
+care has to be taken not to introduce skewing when manipulating the timer
+value directly. If the timer needs to be reloaded with the new value to give
+the next tick, then the software usually “spins”, waiting for the hardware
+timer to change, and then reloads it. This way the timer will always be reloaded
+on an edge of its internal clock. </p> <p><b>Waking
+up from “Sleep” modes with long wakeup latencies</b> </p> <p>Often, to further
+enhance power savings, the CPU and some peripherals are moved into a hardware
+“sleep” mode when <codeph>CpuIdle()</codeph> is called. This could be of long
+latency, and waking up could take longer than the system Tick period. There
+are two situations: </p> <ul>
+<li id="GUID-7484F7CB-C824-5752-9043-736E95D4405D"><p>if the wakeup time can
+be determined precisely, then <codeph>CpuIdle()</codeph> programs the system
+timer to bring the CPU back from the “Sleep“ mode at a time corresponding
+to the next <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration (as a number of Ticks to
+suppress) <i>minus</i> the number of ticks it takes to wake up from that mode.
+On waking up on the timer, the System tick count should be adjusted with the
+total number of ticks suppressed, i.e. the count corresponding to the time
+of the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> expiration. </p> </li>
+<li id="GUID-C0A9B2A2-D98D-50C0-B58A-4E84FCEC12E4"><p>If the wakeup time cannot
+be known deterministically, then the above scheme must be combined with another
+system to allow adjusting the system timer from the hardware Real Time Clock
+(RTC). </p> <p>Typically, the hardware RTC is clocked with a 1Hz clock, and
+can be programmed to interrupt the CPU on multiples of one second intervals.
+The clock supply to the RTC must be left enabled on going into "sleep" mode. </p> </li>
+</ul> <p>To guarantee that timed events occur when they are due, the CPU should
+only be allowed to go to into the long latency hardware “sleep” mode if the
+RTC can be guaranteed to complete a second tick before the CPU is due to wakeup. </p> <p>Note
+that if waking up from hardware “Sleep” mode takes a non-negligible amount
+of time, extreme care should be taken when deciding to move the platform into
+that mode. For example, if a receive request is pending on a data input device <i>and</i> the
+CPU reaches the Idle mode <i>and</i> the platform is transitioned into a “sleep”
+state <i>and</i> data arrives while it is still in that state, <i>then</i> there
+is a possibility that the system will not wake up on time to service the incoming
+data. </p> </section>
+<section id="GUID-4B613C67-3A12-4AD5-8842-6ED510A68746"><title>Validation</title> <p>The <filepath>e32test</filepath> programs <filepath>t_power</filepath>, and <filepath>t_timer</filepath> will put the system into standby and resume
+off a timer. </p> </section>
+</conbody><related-links>
+<link href="GUID-0C435514-EEC6-5660-BB5F-535790349632.dita"><linktext>Power Management</linktext>
+</link>
 </related-links></concept>
\ No newline at end of file