Adaptation/GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita
changeset 15 307f4279f433
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Adaptation/GUID-34D1D0BF-20DE-5677-A067-8FF9DD72E703.dita	Fri Oct 15 14:32:18 2010 +0100
@@ -0,0 +1,331 @@
+<?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-AEDBF425-6077-4C84-A698-508291671F2B_d0e27993_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