Symbian3/PDK/Source/GUID-E0DCBDCF-C056-53E5-A375-778327F848E4.dita
changeset 14 578be2adaf3e
parent 5 f345bda72bc4
--- a/Symbian3/PDK/Source/GUID-E0DCBDCF-C056-53E5-A375-778327F848E4.dita	Tue Jul 20 12:00:49 2010 +0100
+++ b/Symbian3/PDK/Source/GUID-E0DCBDCF-C056-53E5-A375-778327F848E4.dita	Fri Aug 13 16:47:46 2010 +0100
@@ -1,433 +1,433 @@
-<?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-E0DCBDCF-C056-53E5-A375-778327F848E4" xml:lang="en"><title>Asic
-Class Tutorial</title><shortdesc>Provides a work through tutorial that allows you to port an Asic
-implementation to the template variant. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
-<p id="GUID-39010DA3-632A-5C27-92BF-9AA8B5966EAB">  This tutorial describes
-how to implement the Asic class. This is a pure virtual interface that is
-defined and called by the Kernel, but which must be implemented by the ASSP/Variant.
-The tutorial assumes that the ASSP/Variant is split into an ASSP layer and
-a Variant layer. </p>
-<p>For a minimal port, it isn't necessary to provide implementations for the
-entire <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref> class to be able to test that the kernel boots,
-provided that those functions that are not fully implemented have a dummy
-function so that the code will build. </p>
-<p>The <codeph>Asic</codeph> class is defined in<filepath>..\e32\include\kernel\arm\assp.h</filepath>.
-For reference, the definition is: </p>
-<codeblock id="GUID-B33CCD29-C6D2-5DC9-9302-A265E248E8DF" xml:space="preserve">class Asic
-    {
-public:
-       // initialisation
-    virtual TMachineStartupType StartupReason()=0;
-    virtual void Init1()=0;
-    virtual void Init3()=0;
-
-    // debug
-    virtual void DebugOutput(TUint aChar)=0;
-
-    // power management
-    virtual void Idle()=0;
-
-    // timing
-    virtual TInt MsTickPeriod()=0;
-    virtual TInt SystemTimeInSecondsFrom2000(TInt&amp; aTime)=0;
-    virtual TInt SetSystemTimeInSecondsFrom2000(TInt aTime)=0;
-    virtual TUint32 NanoWaitCalibration()=0;
-
-    // HAL
-    virtual TInt VariantHal(TInt aFunction, TAny* a1, TAny* a2)=0;
-
-    // Machine configuration
-    virtual TPtr8 MachineConfiguration()=0;
-    };</codeblock>
-<p>Taking the template port as a concrete example, the ASSP layer implementation
-of the <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref> class is defined and implemented by the <codeph>TemplateAssp</codeph> class,
-and the Variant implemention is defined and implemented by the <codeph>Template</codeph> class. </p>
-<section id="GUID-7F5D4AD6-0881-5942-9A86-A95C02125A28"><title>Asic::Init1()
-implementation</title> <p><b>Entry
-conditions</b> </p> <ul>
-<li id="GUID-6B761E80-7B63-5F96-9852-65F7321D365B"><p>called in the context
-of the initial (null) thread </p> </li>
-<li id="GUID-B8211B76-1308-5372-8034-4B1B9CFE58F3"><p>interrupts are disabled </p> </li>
-<li id="GUID-482B5E00-A25F-5966-90FB-B622F9C1AF99"><p>there is no kernel heap </p> </li>
-<li id="GUID-6D985E4B-1A69-58B6-975D-7F696BB062C3"><p>memory management functions
-are not available. </p> </li>
-</ul> <p><b>What
-the function should do</b> </p> <p>This is called during stage 1 of kernel
-initialisation. </p> <p>In this function, you need to: </p> <ul>
-<li id="GUID-D156866C-0BA0-58AE-9438-C4D1D2628D67"><p>initialise the real
-time clock </p> </li>
-<li id="GUID-7FB60E9E-938C-515E-803D-27DA1315040C"><p>initialise the interrupt
-dispatcher before CPU interrupts are enabled. </p> </li>
-<li id="GUID-D55DD2D9-3E45-5256-B1F4-E583706AED66"><p>set the threshold values
-for cache maintenance. You can set separate values for: </p> <ul>
-<li id="GUID-B3CEB2A4-4849-517F-A0E9-76A6018537B8"><p>purging (invalidating)
-a cache </p> </li>
-<li id="GUID-9DE85DFB-D789-565C-A944-EFBF987D457C"><p>cleaning a cache </p> </li>
-<li id="GUID-0C638F72-1D6B-512D-88EB-7369240C776A"><p>flushing (i.e. cleaning
-and invalidating) a cache. </p> </li>
-</ul> <p>You use the <xref href="GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F.dita#GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F/GUID-81AA7412-9754-3020-9D77-14DEDD3196CA"><apiname>Cache::SetThresholds()</apiname></xref> interface to
-set these values. </p> <p>As an example of what the threshold values mean,
-if you purge a memory region from cache, and the size of that region is greater
-than the threshold value, then the entire cache is purged. If the size of
-that region is less than or equal to to the threshold value, then only the
-region is purged. </p> <p>The threshold values are platform specific, and
-you need to choose your values based on your own performance measurements.
-Symbian cannot make recommendations. If you choose not to set your own values,
-Symbian platform supplies a set of default values, which are set by <codeph>Cache::Init1()</codeph>. </p> <p>Note
-that there is also a <xref href="GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F.dita#GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F/GUID-2DBD79A7-2061-3B89-89FA-B0DFC7AFFCF9"><apiname>Cache::GetThresholds()</apiname></xref> interface that
-you may find useful. </p> </li>
-<li id="GUID-DA94E963-6AA5-5084-8C19-77B7AD484A44"><p>set up the RAM zones.
-For details, see the <xref href="GUID-C376486D-B9BF-5D00-8B1A-1527FC1F83AD.dita">RAM
-Zone Tutorial</xref>. </p> </li>
-</ul> <p>Typically, you would also initialise any memory devices not initialised
-by the bootstrap. Any other initialisation that must happen early on should
-also be done here. </p> <p>The kernel calls the Variant's <codeph>Init1()</codeph> function.
-On the template port, this is the Variant layer's <codeph>Init1()</codeph>,
-i.e. the functions <codeph>Template::Init1()</codeph>. The source for this
-is in <filepath>...\template_variant\specific\variant.cpp</filepath>. </p> <codeblock id="GUID-E1247A9A-B7F7-5C0F-BD3B-A0E471FA4654" xml:space="preserve">void Template::Init1()
-    {
-     __KTRACE_OPT(KBOOT,Kern::Printf("Template::Init1()"));
-
-     //
-     // TO DO: (mandatory)
-     //
-     // Configure Memory controller and Memrory Bus parameters (in addition to what was done in the Bootstrap)
-     //
-     __KTRACE_OPT(KBOOT,Kern::Printf("Memory Configuration done"));
-
-     //
-     // TO DO: (optional)
-     //
-     // Inform the kernel of the RAM zone configuration via Epoc::SetRamZoneConfig().
-     // For devices that wish to reduce power consumption of the RAM IC(s) the callback functions
-     // RamZoneCallback() and DoRamZoneCallback() will need to be implemented and passed 
-     // to Epoc::SetRamZoneConfig() as the parameter aCallback.
-     // The kernel will assume that all RAM ICs are fully intialised and ready for use from boot.
-     //
-
-     //
-     // TO DO: (optional)
-     //
-     // Initialise other critical hardware functions such as I/O interfaces, etc, not done by Bootstrap
-     //
-     // if CPU is Sleep-capable, and requires some preparation to be put in that state (code provided in Bootstrap),
-     // the address of the idle code is writen at this location by the Bootstrap
-     // e.g.
-     // iIdleFunction=*(TLinAddr*)((TUint8*)&amp;Kern::SuperPage()+0x1000);
-     //
-     TemplateAssp::Init1();
-     }</codeblock> <p>The last line is a call into the ASSP layer, which is
-implemented as shown below. On the template port, it is the ASSP layer that
-initialises the interrupt dispatcher and the real time clock. The source for
-this is in <filepath>...\template_assp\assp.cpp</filepath>: </p> <codeblock id="GUID-1E90071E-6CB0-5B01-984C-AFCFD095CA64" xml:space="preserve">EXPORT_C void TemplateAssp::Init1()
-    {
-     __KTRACE_OPT(KBOOT,Kern::Printf("TemplateAssp::Init1()"));
-     //
-     // TO DO: (optional)
-     //
-     TemplateInterrupt::Init1();            // initialise the ASSP interrupt controller
-
-     //
-     // TO DO: (optional)
-     //
-     // Initialises any hardware blocks which require early initialisation, e.g. enable and power the LCD, set up
-     // RTC clocks, disable DMA controllers. etc.
-     //
-    }
-
-   </codeblock> <p> <codeph>TemplateInterrupt::Init1();</codeph> is static
-function that initialises the interrupt dispatcher. See <xref href="GUID-423537D5-2C8A-5C26-8D7B-60446E95F681.dita">Interrupt
-Layer Initialisation</xref>. </p> </section>
-<section id="GUID-F5275882-BBD0-561F-B617-683AA2004BB9"><title>Asic::Init3()
-implementation</title> <p><b>Entry
-conditions</b> </p> <ul>
-<li id="GUID-9450694C-ADF3-52DE-AA58-4AFF53A1EEC6"><p>called in the context
-of the supervisor thread </p> </li>
-<li id="GUID-335F8A2E-0223-598E-AA23-F72E3BE84D76"><p>the kernel is ready
-to handle interrupts </p> </li>
-<li id="GUID-B198D669-9E88-5279-81A8-6A11F8EE3BFD"><p>the kernel heap and
-memory management system is fully functional. </p> </li>
-</ul> <p><b>What
-the function should do</b> </p> <p>This is called during stage 3 of kernel
-initialisation. </p> <p>In this function, you need to: </p> <ul>
-<li id="GUID-38C35732-E79A-595C-9852-12D1FE30A081"><p>enable interrupt sources </p> </li>
-<li id="GUID-D4F750D9-96B1-5AD1-AA66-2485D37B6323"><p>start the millisecond
-tick timer. </p> </li>
-<li id="GUID-390278B7-EF0F-59ED-A57D-54490655C97B"><p>Optionally, replace
-the implementation used by <codeph>Kern::NanoWait()</codeph>. </p> </li>
-</ul> <p>Any other general initialisation can also be done here. </p> <p>As
-an example, on the template port, the function is implemented in the Variant
-layer, by <codeph>Template::Init3()</codeph>. </p> <p><b>Millisecond
-tick timer</b> </p> <p>The kernel expects that the kernel's tick handler routine
-will be called at a fixed microsecond period, the value of which is returned
-by the implementation of <xref href="GUID-E0DCBDCF-C056-53E5-A375-778327F848E4.dita#GUID-E0DCBDCF-C056-53E5-A375-778327F848E4/GUID-917B420D-5F10-5190-97D2-9D2DAFD4FB76">Asic::MsTickPeriod()</xref> function. The <codeph>Init3()</codeph> function must be implemented to start
-this. See <xref href="GUID-F84E18B8-5883-5A3A-A9DB-EC25BB86149F.dita">Kernel Timers</xref> for
-background information. </p> <p>The template implementation is as follows: </p> <codeblock id="GUID-AF60AC52-5188-5911-9A03-A090D048ADA3" xml:space="preserve">EXPORT_C void TemplateAssp::Init3()
-    {
-    __KTRACE_OPT(KBOOT,Kern::Printf("TemplateAssp::Init3()"));
-
-    TTemplate::Init3();
-
-    NTimerQ&amp; m=*(NTimerQ*)NTimerQ::TimerAddress();
-    iTimerQ=&amp;m;
-    //
-    // TO DO: (mandatory)
-    //
-    // If Hardware Timer used for System Ticks cannot give exactly the period required store the initial rounding value
-    // here which is updated every time a match occurs. Note this leads to "wobbly" timers whose exact period change
-    // but averages exactly the required value
-    // e.g.
-    // m.iRounding=-5;
-    //
-    
-    TInt r=Interrupt::Bind(KIntIdOstMatchMsTimer,MsTimerTick,&amp;m);    // bind the System Tick interrupt
-    if (r!=KErrNone)
-        Kern::Fault("BindMsTick",r);
-
-    // 
-    // TO DO: (mandatory)
-    //
-    // Clear any pending OST interrupts and enable any OST match registers.
-    // If possible may reset the OST here (to start counting from a full period). Set the harwdare to produce an 
-    // interrupt on full count
-    //
-
-    r=Interrupt::Enable(KIntIdOstMatchMsTimer);    // enable the System Tick interrupt
-    if (r!=KErrNone)
-        Kern::Fault("EnbMsTick",r);
-
-    // 
-    // TO DO: (optional)
-    //
-    // Allocate physical RAM for video buffer, as per example below. However with some hardware, the Video Buffer
-    // may not reside in main System memory, it may be dedicated memory.
-    //
-    // EXAMPLE ONLY
-    TInt vSize=VideoRamSize();
-    r=Epoc::AllocPhysicalRam(2*vSize,TemplateAssp::VideoRamPhys);
-    if (r!=KErrNone)
-        Kern::Fault("AllocVRam",r);
-    }</codeblock> <p><b>Servicing
-the timer interrupt</b> </p> <p>The timer interrupt service routine is required
-only to call the <xref href="GUID-DFEAC0DA-E384-3249-BF6A-529A76C3AC34.dita#GUID-DFEAC0DA-E384-3249-BF6A-529A76C3AC34/GUID-DA340CB0-C334-3C17-B903-14B135ABDCF1"><apiname>Ntimer::TickQ()</apiname></xref> function and perform any
-housekeeping necessary to ensure that the handler itself is called again after
-the time reported by the <xref href="GUID-BCFC62D6-B87A-3319-8DA7-4BA64A9D0311.dita"><apiname>MsTickPeriod()</apiname></xref> routine. Since
-the handler is called frequently, it is written in assembler for the fastest
-execution. </p> <codeblock id="GUID-0770E505-10F8-582C-BCAA-BC99074FD906" xml:space="preserve">__NAKED__ void MsTimerTick(TAny* aPtr)
-    {
-    // Service 1ms tick interrupt
-    asm("ldr ip, [r0, #%a0]" : : "i" _FOFF(NTimerQ,iRounding));
-    asm("ldr r2, __KHwBaseOst ");
-    asm("adds ip, ip, #2 ");
-    asm("ldr r3, __KOst1000HzTickMatchIncrement ");
-    asm("subcs ip, ip, #5 ");
-    asm("str ip, [r0, #%a0]" : : "i" _FOFF(NTimerQ,iRounding));
-    asm("addcs r3, r3, #1 ");
-    asm("mov r1, #%a0" : : "i" ((TInt)(1&lt;&lt;KHwOstMatchMsTimer)));
-    asm("str r1, [r2, #0x14] ");            // clear interrupt
-    asm("ldr r1, [r2, #%a0]" : : "i" ((TInt)KHwOstMatchMsTimer*4));    // r1=old match value
-    asm("add r1, r1, r3 ");            // step match value on
-    asm("ldr ip, [r2, #0x10] ");            // r3=system timer value
-    asm("str r1, [r2, #%a0]" : : "i" ((TInt)KHwOstMatchMsTimer*4));
-    asm("cmp ip, r1 ");            // compare to next match value
-
-#ifdef _DEBUG
-    asm("addpl r1, ip, #10 ");    // in DEBUG if timer&gt;match value, set match value to timer + a bit
-    asm("strpl r1, [r2, #%a0]" : : "i" ((TInt)KHwOstMatchMsTimer*4));
-    asm("b Tick__7NTimerQ ");    // call interrupt handler anyway
-#else
-    asm("bmi Tick__7NTimerQ ");    // if timer&lt;match value, OK - call interrupt handler
-#endif
-
-    // otherwise we are late for the next tick so force a data abort exception...
-    asm("mvn r2, #0x10000002 ");    // r2=0xeffffffd
-    asm("str r2, [r2] ");            // die
-
-    // Constant data embedded in code. 
-    asm("__KOst1000HzTickMatchIncrement: ");
-    asm(".word %a0" : : "i" ((TInt)KOst1000HzTickMatchIncrement));
-    asm("__KHwBaseOst: ");
-    asm(".word %a0" : : "i" ((TInt)KHwBaseOst));
-    }</codeblock> <p>Note that it is a requirement that the timer period should
-be an integral number of microseconds, even if the exact period is not 1000us.
-It is always possible to add code to the interrupt handler to achieve this
-average so that over a large number of ticks, the deviation from this average
-will tend to 0, by adjusting the exact number of ticks from tick to tick.
-See also <xref href="GUID-F84E18B8-5883-5A3A-A9DB-EC25BB86149F.dita">Timers</xref></p> <p><b>NanoWait() implementation</b> </p> <p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-0EEAFE45-5C0D-32A9-AD64-CE3AB0AEE6B3"><apiname>Kern::NanoWait()</apiname></xref> is
-a function that can be called if you want to wait for very short periods of
-time within the kernel. You call this function and specify the number of nanoseconds.
-The function is, in effect, a shell that uses default implementation code
-provided by the generic platform. You can provide your own implementation
-in your port, and register this with the platform. This allows the wait functionality
-to be implemented in the best possible way for your platform, possibly by
-using a hardware timer whose frequency is independent of the CPU frequency. </p> <p>To
-replace the default implementation, you need to: </p> <ul>
-<li id="GUID-733329E1-99C5-56A4-B80F-FFCFD74F1320"><p>code your own function.
-This has the same signature as <codeph>Kern::NanoWait()</codeph>: </p> <codeblock id="GUID-0AC0DC75-38C7-58A8-8A4F-4C5AA8F23A80" xml:space="preserve">void AsicImpl::DoNanoWait(TUint32 aInterval)
-    {
-    // Wait for aInterval nanoseconds
-    }</codeblock> <p>where <codeph>AsicImpl</codeph> is the
-class that is ultimately derived from <codeph>Asic</codeph>. </p> </li>
-<li id="GUID-BDE8C5D6-6E6C-5B2E-9219-A8D5DC114EA2"><p>register this implementation
-by adding the following call into your <codeph>Asic::Init3()</codeph> function: </p> <codeblock id="GUID-1A99C7D2-A550-5B39-9AE7-559AE7B13C3E" xml:space="preserve">Kern::SetNanoWaitHandler(AsicImpl::DoNanoWait);</codeblock> </li>
-</ul> <p>You can see where this goes by looking at the template port at: <filepath>...\base\cedar\template\template_assp\template_assp.cpp</filepath>  </p> </section>
-<section id="GUID-1028F2D0-BA8B-4880-9565-50C89EBD1685"><title>Asic::DebugOutput()
-implementation</title> <p>It is worth implementing this early so that it is
-possible to get trace output to see what the kernel is doing. This function
-is passed one character at a time. Normally this is sent to a UART, though
-it can be output through any convenient communications channel. </p> <p>On
-the template port, this is implemented in the Variant layer, by <codeph>Template::DebugOutput()</codeph> in <filepath>...\template_variant\specific\variant.cpp</filepath>. </p> </section>
-<section id="GUID-EEC48040-B7D7-406B-8138-4A1F646ED990"><title>Asic::Idle()
-implementation</title> <p>If no power management has been implemented, then
-this function is called when the system is to idle to allow power saving.
-This function can just return, until power management is implemented. Once
-power management has been implemented, then idling behaviour will be handled
-by the power controller, i.e. the Variant's implementation of the <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita"><apiname>DPowerController</apiname></xref> class </p> </section>
-<section id="GUID-917B420D-5F10-5190-97D2-9D2DAFD4FB76"><title>Asic::MsTickPeriod()
-implementation</title> <p>This function is used to return the number of microseconds
-per tick. To avoid timing drift, a tick frequency should be chosen that gives
-a round number of microseconds per tick. The function can return zero until
-the tick timer has been implemented. </p> <p>On the template port, this function
-is implemented in the ASSP layer, and can be found in the source file <filepath>...\template_assp\assp.cpp</filepath>.
-It is a simple function that just returns the value. </p> <codeblock id="GUID-C0D88A32-974C-5824-8D9D-A9B6D7C45802" xml:space="preserve">EXPORT_C TInt TemplateAssp::MsTickPeriod()
-    {
-     // 
-     // TO DO: (mandatory)
-     //
-     // Return the OST tick period (System Tick) in microseconds ( 10E-06 s ).
-     //
-     return 1000;   // EXAMPLE ONLY
-    }
-</codeblock> <p>See also <xref href="GUID-F84E18B8-5883-5A3A-A9DB-EC25BB86149F.dita">Timers</xref>. </p> </section>
-<section id="GUID-1C8A7F79-8CD5-442E-A9A5-925C94E80773"><title>Asic::SystemTimeInSecondsFrom2000()
-          implementation</title> <p>This is a function that the kernel uses
-to get the system time. Its signature is </p> <codeblock id="GUID-A1FF9777-D627-5409-B6CD-02F20F7A1889" xml:space="preserve">Tint SystemTimeInSecondsFrom2000(Tint&amp; aTime);</codeblock> <p>An implementation must set the <codeph>aTime</codeph> reference to the
-number of seconds that have elapsed since the start of the year 2000. This
-is a positive number; a negative number is interpreted as time before 2000. </p> <p>For
-the template reference board, the implementation is as follows: </p> <codeblock id="GUID-C4812A82-C069-564B-972A-0922EAC00AAB" xml:space="preserve">EXPORT_C TInt TemplateAssp::SystemTimeInSecondsFrom2000(TInt&amp; aTime)
-     {
-      aTime=(TInt)TTemplate::RtcData();
-      __KTRACE_OPT(KHARDWARE,Kern::Printf("RTC READ: %d",aTime));
-      return KErrNone;
-     }
-</codeblock> <p>Until a real time clock is implemented, this function can
-just return <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref>. </p> <p>This function calls the register
-access functions in the <codeph>TTemplate</codeph> class. See <filepath>...\template_assp\template_assp.cpp</filepath> for
-implementation details. </p> <p>Note that tracing output is provided when
-the KHARDWARE bit in the kerneltrace flags is set for the debug build. </p> </section>
-<section id="GUID-F0AC3E98-345F-4491-9957-51B127437181"><title>Asic::SetSystemTimeInSecondsFrom2000()
-implementation</title> <p>This is a function that the kernel uses to set the
-system time. Its signature is </p> <codeblock id="GUID-B965C38C-A65E-5E54-BE09-C81300B59EDC" xml:space="preserve">Tint SetSystemTimeInSecondsFrom2000(Tint aTime);</codeblock> <p>This sets the real time clock to the number of seconds that have elapsed
-since the start of the year 2000. This is a positive number; a negative number
-is interpreted as time before 2000. </p> <p>For the template reference board,
-the implementation is as follows: </p> <codeblock id="GUID-89BFC844-B053-51B7-9ACA-81B19E63414B" xml:space="preserve">EXPORT_C TInt TemplateAssp::SetSystemTimeInSecondsFrom2000(TInt aTime)
-    {
-     //
-     // TO DO: (optional)
-     //
-     // Check if the RTC is running and is stable
-     //
-     __KTRACE_OPT(KHARDWARE,Kern::Printf("Set RTC: %d",aTime));
-     TTemplate::SetRtcData(aTime);
-     __KTRACE_OPT(KHARDWARE,Kern::Printf("RTC: %d",TTemplate::RtcData()));
-     return KErrNone;
-    }
-</codeblock> <p>Note that tracing output is provided when the KHARDWARE bit
-in the kerneltrace flags is set for the debug build. In this function, the
-trace output shows the value passed in from the kernel and then shows the
-value read back from the real time clock for verification. </p> </section>
-<section id="GUID-50BB6924-899F-4385-879E-19A2FC68657C"><title>Asic::NanoWaitCalibration()
- implementation</title> <p>The function <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-0EEAFE45-5C0D-32A9-AD64-CE3AB0AEE6B3"><apiname>Kern::NanoWait()</apiname></xref> can
-be called if you want to wait for very short periods of time within the kernel.
-You call this function and specify the number of nanoseconds. You can either
-use the default implementation of this function, or you can provide your own. </p> <p>The
-default implementation provided by Symbian platform that <codeph>Kern::NanoWait()</codeph> uses
-is a busy loop that is calibrated by calling <codeph>Asic::NanoWaitCalibration()</codeph>. <codeph>NanoWaitCalibration()</codeph> should
-return the number of nanoseconds taken to execute 2 machine cycles. This is
-obviously dependent on the CPU clock speed, so if variants are likely to run
-at different speeds, then this should be implemented in the Variant layer. </p> <p>This
-approach cannot always take into account factors such as processor frequency
-scaling. An alternative approach is for the Variant to supply its own implementation
-to be used by <codeph>Kern::NanoWait()</codeph>. Note that you do not replace <codeph>Kern::NanoWait()</codeph> itself
-as this is a shell function that results in a call to the the implementation.
-See <xref href="GUID-E0DCBDCF-C056-53E5-A375-778327F848E4.dita#GUID-E0DCBDCF-C056-53E5-A375-778327F848E4/GUID-F5275882-BBD0-561F-B617-683AA2004BB9">Asic::Init3()</xref> for
-detail on how to replace the implementation. </p> <p>On the template port, <codeph>Asic::NanoWaitCalibration()</codeph> is
-implemented in the ASSP layer, and not in the Variant layer, and can be found
-in the source file <filepath>...\template_assp\assp.cpp</filepath>. It is
-a simple function that just returns the value. </p> <codeblock id="GUID-68298BF1-EAE7-507D-9B5B-DDACE6C19799" xml:space="preserve">EXPORT_C TUint32 TemplateAssp::NanoWaitCalibration()
-    {
-     // 
-     // TO DO: (mandatory)
-     //
-     // Return the minimum time in nano-seconds that it takes to execute the following code:
-     //     nanowait_loop:
-     //               subs r0, r0, r1
-  //               bhi nanowait_loop
-     //
-     // If accurate timings are required by the Base Port, then it should provide it's own implementation 
-     // of NanoWait which uses a hardware counter. (See Kern::SetNanoWaitHandler)
-     //
-    
-     return 0;   // EXAMPLE ONLY
-    }
-</codeblock> </section>
-<section id="GUID-15F344C5-A1CC-45FC-AC94-27022A1DF448"><title>Asic::VariantHal()
-implementation</title> <p>You might find it useful to review <xref href="GUID-9AE254D4-AA60-579E-8D9D-F2797106A413.dita">User-Side
-Hardware Abstraction Technology</xref> first. </p> <p>This is the HAL handler
-for the HAL group <xref href="GUID-66A851A0-2A0C-3624-AEC1-22F6629FABF7.dita#GUID-66A851A0-2A0C-3624-AEC1-22F6629FABF7/GUID-3FA061DE-68F8-3948-96B3-5AFC989DBDE1"><apiname>THalFunctionGroup::EHalGroupVariant</apiname></xref>. </p> </section>
-<section id="GUID-2EEA143D-612C-47C5-B16C-22DAD1BC179E"><title>Asic::MachineConfiguration()
-          implementation</title> <p>This returns a <xref href="GUID-C0D29B11-1535-3D11-B318-B18D30A6120B.dita"><apiname>TPtr8</apiname></xref> descriptor
-representing an area containing machine configuration information. </p> <p>The
-address of this object is obtained by calling <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-4DAE5199-1EB0-31D1-BA06-8F47E96EEADE"><apiname>Kern::MachineConfig()</apiname></xref>.
-However, the Variant (either the ASSP layer or the Variant layer or both)
-is responsible for the content. </p> <p>In the template port, the function
-is implemented in the Variant layer: </p> <codeblock id="GUID-B75F631E-03DB-5C98-911F-1161842AA17F" xml:space="preserve">TPtr8 Template::MachineConfiguration()
-    {
-     return TPtr8((TUint8*)&amp;Kern::MachineConfig(),sizeof(TActualMachineConfig),sizeof(TActualMachineConfig));
-    }
-</codeblock> <p>Here, the machine configuration information is represented
-by an object of type <codeph>TTemplateMachineConfig</codeph>, which derives
-from <codeph>TMachineConfig</codeph>. In effect, <codeph>TMachineConfig</codeph> represents
-information that is common to all, while the Variant can extend this to contain
-whatever information is appropriate. </p> <p>Note that <codeph>TActualMachineConfig</codeph> is
-a typedef for <codeph>TTemplateMachineConfig</codeph>. </p> </section>
-<section id="GUID-B1E39D8C-1562-4464-A316-144ED89935C9"><title>Asic::StartupReason()
-implementation</title> <p>If a startup reason is available from hardware or
-a preserved RAM location, it should be returned by the function. The default
-is to return <codeph>EStartupColdReset</codeph>. </p> <p>On the template port,
-this is implemented in the ASSP layer: </p> <codeblock id="GUID-FC4FFA46-804D-5A7F-B7CA-DDDC72C60041" xml:space="preserve">EXPORT_C TMachineStartupType TemplateAssp::StartupReason()
-    {
-     __KTRACE_OPT(KBOOT,Kern::Printf("TemplateAssp::StartupReason"));
-  #ifdef _DEBUG                                                            // REMOVE THIS
-     TUint s = Kern::SuperPage().iHwStartupReason;
-     __KTRACE_OPT(KBOOT,Kern::Printf("CPU page value %08x", s));
-  #endif                                                                    // REMOVE THIS
-     //
-     // TO DO: (mandatory)
-     //
-     // Map the startup reason read from the Super Page to one of TMachineStartupType enumerated values
-     // and return this
-     //
-     return EStartupCold;   // EXAMPLE ONLY
-    }
-</codeblock> </section>
-</conbody><related-links>
-<link href="GUID-984C2A0D-36BE-5A99-9D65-3F8791C669FF.dita#GUID-984C2A0D-36BE-5A99-9D65-3F8791C669FF/GUID-95C34114-F986-5428-9D40-5CF64429CDBD">
-<linktext>ASSP/Variant Architecture</linktext></link>
-<link href="GUID-B498EDA0-677E-5521-9E4F-24D7C2048F2E.dita"><linktext>Implementing
-the ASSP                 Register</linktext></link>
-<link href="GUID-5194A7B6-471B-5BCF-8569-16A3BA59000A.dita"><linktext>Using the
-ASSP Register</linktext></link>
-<link href="GUID-77DF7A6B-F01D-5B9F-9C7A-662A04ED8BE7.dita"><linktext>ASSP Kernel
-Extension                 Overview</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-E0DCBDCF-C056-53E5-A375-778327F848E4" xml:lang="en"><title>Asic
+Class Tutorial</title><shortdesc>Provides a work through tutorial that allows you to port an Asic
+implementation to the template variant. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
+<p id="GUID-39010DA3-632A-5C27-92BF-9AA8B5966EAB">  This tutorial describes
+how to implement the Asic class. This is a pure virtual interface that is
+defined and called by the Kernel, but which must be implemented by the ASSP/Variant.
+The tutorial assumes that the ASSP/Variant is split into an ASSP layer and
+a Variant layer. </p>
+<p>For a minimal port, it isn't necessary to provide implementations for the
+entire <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref> class to be able to test that the kernel boots,
+provided that those functions that are not fully implemented have a dummy
+function so that the code will build. </p>
+<p>The <codeph>Asic</codeph> class is defined in<filepath>..\e32\include\kernel\arm\assp.h</filepath>.
+For reference, the definition is: </p>
+<codeblock id="GUID-B33CCD29-C6D2-5DC9-9302-A265E248E8DF" xml:space="preserve">class Asic
+    {
+public:
+       // initialisation
+    virtual TMachineStartupType StartupReason()=0;
+    virtual void Init1()=0;
+    virtual void Init3()=0;
+
+    // debug
+    virtual void DebugOutput(TUint aChar)=0;
+
+    // power management
+    virtual void Idle()=0;
+
+    // timing
+    virtual TInt MsTickPeriod()=0;
+    virtual TInt SystemTimeInSecondsFrom2000(TInt&amp; aTime)=0;
+    virtual TInt SetSystemTimeInSecondsFrom2000(TInt aTime)=0;
+    virtual TUint32 NanoWaitCalibration()=0;
+
+    // HAL
+    virtual TInt VariantHal(TInt aFunction, TAny* a1, TAny* a2)=0;
+
+    // Machine configuration
+    virtual TPtr8 MachineConfiguration()=0;
+    };</codeblock>
+<p>Taking the template port as a concrete example, the ASSP layer implementation
+of the <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref> class is defined and implemented by the <codeph>TemplateAssp</codeph> class,
+and the Variant implemention is defined and implemented by the <codeph>Template</codeph> class. </p>
+<section id="GUID-7F5D4AD6-0881-5942-9A86-A95C02125A28"><title>Asic::Init1()
+implementation</title> <p><b>Entry
+conditions</b> </p> <ul>
+<li id="GUID-6B761E80-7B63-5F96-9852-65F7321D365B"><p>called in the context
+of the initial (null) thread </p> </li>
+<li id="GUID-B8211B76-1308-5372-8034-4B1B9CFE58F3"><p>interrupts are disabled </p> </li>
+<li id="GUID-482B5E00-A25F-5966-90FB-B622F9C1AF99"><p>there is no kernel heap </p> </li>
+<li id="GUID-6D985E4B-1A69-58B6-975D-7F696BB062C3"><p>memory management functions
+are not available. </p> </li>
+</ul> <p><b>What
+the function should do</b> </p> <p>This is called during stage 1 of kernel
+initialisation. </p> <p>In this function, you need to: </p> <ul>
+<li id="GUID-D156866C-0BA0-58AE-9438-C4D1D2628D67"><p>initialise the real
+time clock </p> </li>
+<li id="GUID-7FB60E9E-938C-515E-803D-27DA1315040C"><p>initialise the interrupt
+dispatcher before CPU interrupts are enabled. </p> </li>
+<li id="GUID-D55DD2D9-3E45-5256-B1F4-E583706AED66"><p>set the threshold values
+for cache maintenance. You can set separate values for: </p> <ul>
+<li id="GUID-B3CEB2A4-4849-517F-A0E9-76A6018537B8"><p>purging (invalidating)
+a cache </p> </li>
+<li id="GUID-9DE85DFB-D789-565C-A944-EFBF987D457C"><p>cleaning a cache </p> </li>
+<li id="GUID-0C638F72-1D6B-512D-88EB-7369240C776A"><p>flushing (i.e. cleaning
+and invalidating) a cache. </p> </li>
+</ul> <p>You use the <xref href="GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F.dita#GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F/GUID-81AA7412-9754-3020-9D77-14DEDD3196CA"><apiname>Cache::SetThresholds()</apiname></xref> interface to
+set these values. </p> <p>As an example of what the threshold values mean,
+if you purge a memory region from cache, and the size of that region is greater
+than the threshold value, then the entire cache is purged. If the size of
+that region is less than or equal to to the threshold value, then only the
+region is purged. </p> <p>The threshold values are platform specific, and
+you need to choose your values based on your own performance measurements.
+Symbian cannot make recommendations. If you choose not to set your own values,
+Symbian platform supplies a set of default values, which are set by <codeph>Cache::Init1()</codeph>. </p> <p>Note
+that there is also a <xref href="GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F.dita#GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F/GUID-2DBD79A7-2061-3B89-89FA-B0DFC7AFFCF9"><apiname>Cache::GetThresholds()</apiname></xref> interface that
+you may find useful. </p> </li>
+<li id="GUID-DA94E963-6AA5-5084-8C19-77B7AD484A44"><p>set up the RAM zones.
+For details, see the <xref href="GUID-C376486D-B9BF-5D00-8B1A-1527FC1F83AD.dita">RAM
+Zone Tutorial</xref>. </p> </li>
+</ul> <p>Typically, you would also initialise any memory devices not initialised
+by the bootstrap. Any other initialisation that must happen early on should
+also be done here. </p> <p>The kernel calls the Variant's <codeph>Init1()</codeph> function.
+On the template port, this is the Variant layer's <codeph>Init1()</codeph>,
+i.e. the functions <codeph>Template::Init1()</codeph>. The source for this
+is in <filepath>...\template_variant\specific\variant.cpp</filepath>. </p> <codeblock id="GUID-E1247A9A-B7F7-5C0F-BD3B-A0E471FA4654" xml:space="preserve">void Template::Init1()
+    {
+     __KTRACE_OPT(KBOOT,Kern::Printf("Template::Init1()"));
+
+     //
+     // TO DO: (mandatory)
+     //
+     // Configure Memory controller and Memrory Bus parameters (in addition to what was done in the Bootstrap)
+     //
+     __KTRACE_OPT(KBOOT,Kern::Printf("Memory Configuration done"));
+
+     //
+     // TO DO: (optional)
+     //
+     // Inform the kernel of the RAM zone configuration via Epoc::SetRamZoneConfig().
+     // For devices that wish to reduce power consumption of the RAM IC(s) the callback functions
+     // RamZoneCallback() and DoRamZoneCallback() will need to be implemented and passed 
+     // to Epoc::SetRamZoneConfig() as the parameter aCallback.
+     // The kernel will assume that all RAM ICs are fully intialised and ready for use from boot.
+     //
+
+     //
+     // TO DO: (optional)
+     //
+     // Initialise other critical hardware functions such as I/O interfaces, etc, not done by Bootstrap
+     //
+     // if CPU is Sleep-capable, and requires some preparation to be put in that state (code provided in Bootstrap),
+     // the address of the idle code is writen at this location by the Bootstrap
+     // e.g.
+     // iIdleFunction=*(TLinAddr*)((TUint8*)&amp;Kern::SuperPage()+0x1000);
+     //
+     TemplateAssp::Init1();
+     }</codeblock> <p>The last line is a call into the ASSP layer, which is
+implemented as shown below. On the template port, it is the ASSP layer that
+initialises the interrupt dispatcher and the real time clock. The source for
+this is in <filepath>...\template_assp\assp.cpp</filepath>: </p> <codeblock id="GUID-1E90071E-6CB0-5B01-984C-AFCFD095CA64" xml:space="preserve">EXPORT_C void TemplateAssp::Init1()
+    {
+     __KTRACE_OPT(KBOOT,Kern::Printf("TemplateAssp::Init1()"));
+     //
+     // TO DO: (optional)
+     //
+     TemplateInterrupt::Init1();            // initialise the ASSP interrupt controller
+
+     //
+     // TO DO: (optional)
+     //
+     // Initialises any hardware blocks which require early initialisation, e.g. enable and power the LCD, set up
+     // RTC clocks, disable DMA controllers. etc.
+     //
+    }
+
+   </codeblock> <p> <codeph>TemplateInterrupt::Init1();</codeph> is static
+function that initialises the interrupt dispatcher. See <xref href="GUID-423537D5-2C8A-5C26-8D7B-60446E95F681.dita">Interrupt
+Layer Initialisation</xref>. </p> </section>
+<section id="GUID-F5275882-BBD0-561F-B617-683AA2004BB9"><title>Asic::Init3()
+implementation</title> <p><b>Entry
+conditions</b> </p> <ul>
+<li id="GUID-9450694C-ADF3-52DE-AA58-4AFF53A1EEC6"><p>called in the context
+of the supervisor thread </p> </li>
+<li id="GUID-335F8A2E-0223-598E-AA23-F72E3BE84D76"><p>the kernel is ready
+to handle interrupts </p> </li>
+<li id="GUID-B198D669-9E88-5279-81A8-6A11F8EE3BFD"><p>the kernel heap and
+memory management system is fully functional. </p> </li>
+</ul> <p><b>What
+the function should do</b> </p> <p>This is called during stage 3 of kernel
+initialisation. </p> <p>In this function, you need to: </p> <ul>
+<li id="GUID-38C35732-E79A-595C-9852-12D1FE30A081"><p>enable interrupt sources </p> </li>
+<li id="GUID-D4F750D9-96B1-5AD1-AA66-2485D37B6323"><p>start the millisecond
+tick timer. </p> </li>
+<li id="GUID-390278B7-EF0F-59ED-A57D-54490655C97B"><p>Optionally, replace
+the implementation used by <codeph>Kern::NanoWait()</codeph>. </p> </li>
+</ul> <p>Any other general initialisation can also be done here. </p> <p>As
+an example, on the template port, the function is implemented in the Variant
+layer, by <codeph>Template::Init3()</codeph>. </p> <p><b>Millisecond
+tick timer</b> </p> <p>The kernel expects that the kernel's tick handler routine
+will be called at a fixed microsecond period, the value of which is returned
+by the implementation of <xref href="GUID-E0DCBDCF-C056-53E5-A375-778327F848E4.dita#GUID-E0DCBDCF-C056-53E5-A375-778327F848E4/GUID-917B420D-5F10-5190-97D2-9D2DAFD4FB76">Asic::MsTickPeriod()</xref> function. The <codeph>Init3()</codeph> function must be implemented to start
+this. See <xref href="GUID-F84E18B8-5883-5A3A-A9DB-EC25BB86149F.dita">Kernel Timers</xref> for
+background information. </p> <p>The template implementation is as follows: </p> <codeblock id="GUID-AF60AC52-5188-5911-9A03-A090D048ADA3" xml:space="preserve">EXPORT_C void TemplateAssp::Init3()
+    {
+    __KTRACE_OPT(KBOOT,Kern::Printf("TemplateAssp::Init3()"));
+
+    TTemplate::Init3();
+
+    NTimerQ&amp; m=*(NTimerQ*)NTimerQ::TimerAddress();
+    iTimerQ=&amp;m;
+    //
+    // TO DO: (mandatory)
+    //
+    // If Hardware Timer used for System Ticks cannot give exactly the period required store the initial rounding value
+    // here which is updated every time a match occurs. Note this leads to "wobbly" timers whose exact period change
+    // but averages exactly the required value
+    // e.g.
+    // m.iRounding=-5;
+    //
+    
+    TInt r=Interrupt::Bind(KIntIdOstMatchMsTimer,MsTimerTick,&amp;m);    // bind the System Tick interrupt
+    if (r!=KErrNone)
+        Kern::Fault("BindMsTick",r);
+
+    // 
+    // TO DO: (mandatory)
+    //
+    // Clear any pending OST interrupts and enable any OST match registers.
+    // If possible may reset the OST here (to start counting from a full period). Set the harwdare to produce an 
+    // interrupt on full count
+    //
+
+    r=Interrupt::Enable(KIntIdOstMatchMsTimer);    // enable the System Tick interrupt
+    if (r!=KErrNone)
+        Kern::Fault("EnbMsTick",r);
+
+    // 
+    // TO DO: (optional)
+    //
+    // Allocate physical RAM for video buffer, as per example below. However with some hardware, the Video Buffer
+    // may not reside in main System memory, it may be dedicated memory.
+    //
+    // EXAMPLE ONLY
+    TInt vSize=VideoRamSize();
+    r=Epoc::AllocPhysicalRam(2*vSize,TemplateAssp::VideoRamPhys);
+    if (r!=KErrNone)
+        Kern::Fault("AllocVRam",r);
+    }</codeblock> <p><b>Servicing
+the timer interrupt</b> </p> <p>The timer interrupt service routine is required
+only to call the <xref href="GUID-DFEAC0DA-E384-3249-BF6A-529A76C3AC34.dita#GUID-DFEAC0DA-E384-3249-BF6A-529A76C3AC34/GUID-DA340CB0-C334-3C17-B903-14B135ABDCF1"><apiname>Ntimer::TickQ()</apiname></xref> function and perform any
+housekeeping necessary to ensure that the handler itself is called again after
+the time reported by the <xref href="GUID-BCFC62D6-B87A-3319-8DA7-4BA64A9D0311.dita"><apiname>MsTickPeriod()</apiname></xref> routine. Since
+the handler is called frequently, it is written in assembler for the fastest
+execution. </p> <codeblock id="GUID-0770E505-10F8-582C-BCAA-BC99074FD906" xml:space="preserve">__NAKED__ void MsTimerTick(TAny* aPtr)
+    {
+    // Service 1ms tick interrupt
+    asm("ldr ip, [r0, #%a0]" : : "i" _FOFF(NTimerQ,iRounding));
+    asm("ldr r2, __KHwBaseOst ");
+    asm("adds ip, ip, #2 ");
+    asm("ldr r3, __KOst1000HzTickMatchIncrement ");
+    asm("subcs ip, ip, #5 ");
+    asm("str ip, [r0, #%a0]" : : "i" _FOFF(NTimerQ,iRounding));
+    asm("addcs r3, r3, #1 ");
+    asm("mov r1, #%a0" : : "i" ((TInt)(1&lt;&lt;KHwOstMatchMsTimer)));
+    asm("str r1, [r2, #0x14] ");            // clear interrupt
+    asm("ldr r1, [r2, #%a0]" : : "i" ((TInt)KHwOstMatchMsTimer*4));    // r1=old match value
+    asm("add r1, r1, r3 ");            // step match value on
+    asm("ldr ip, [r2, #0x10] ");            // r3=system timer value
+    asm("str r1, [r2, #%a0]" : : "i" ((TInt)KHwOstMatchMsTimer*4));
+    asm("cmp ip, r1 ");            // compare to next match value
+
+#ifdef _DEBUG
+    asm("addpl r1, ip, #10 ");    // in DEBUG if timer&gt;match value, set match value to timer + a bit
+    asm("strpl r1, [r2, #%a0]" : : "i" ((TInt)KHwOstMatchMsTimer*4));
+    asm("b Tick__7NTimerQ ");    // call interrupt handler anyway
+#else
+    asm("bmi Tick__7NTimerQ ");    // if timer&lt;match value, OK - call interrupt handler
+#endif
+
+    // otherwise we are late for the next tick so force a data abort exception...
+    asm("mvn r2, #0x10000002 ");    // r2=0xeffffffd
+    asm("str r2, [r2] ");            // die
+
+    // Constant data embedded in code. 
+    asm("__KOst1000HzTickMatchIncrement: ");
+    asm(".word %a0" : : "i" ((TInt)KOst1000HzTickMatchIncrement));
+    asm("__KHwBaseOst: ");
+    asm(".word %a0" : : "i" ((TInt)KHwBaseOst));
+    }</codeblock> <p>Note that it is a requirement that the timer period should
+be an integral number of microseconds, even if the exact period is not 1000us.
+It is always possible to add code to the interrupt handler to achieve this
+average so that over a large number of ticks, the deviation from this average
+will tend to 0, by adjusting the exact number of ticks from tick to tick.
+See also <xref href="GUID-F84E18B8-5883-5A3A-A9DB-EC25BB86149F.dita">Timers</xref></p> <p><b>NanoWait() implementation</b> </p> <p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-0EEAFE45-5C0D-32A9-AD64-CE3AB0AEE6B3"><apiname>Kern::NanoWait()</apiname></xref> is
+a function that can be called if you want to wait for very short periods of
+time within the kernel. You call this function and specify the number of nanoseconds.
+The function is, in effect, a shell that uses default implementation code
+provided by the generic platform. You can provide your own implementation
+in your port, and register this with the platform. This allows the wait functionality
+to be implemented in the best possible way for your platform, possibly by
+using a hardware timer whose frequency is independent of the CPU frequency. </p> <p>To
+replace the default implementation, you need to: </p> <ul>
+<li id="GUID-733329E1-99C5-56A4-B80F-FFCFD74F1320"><p>code your own function.
+This has the same signature as <codeph>Kern::NanoWait()</codeph>: </p> <codeblock id="GUID-0AC0DC75-38C7-58A8-8A4F-4C5AA8F23A80" xml:space="preserve">void AsicImpl::DoNanoWait(TUint32 aInterval)
+    {
+    // Wait for aInterval nanoseconds
+    }</codeblock> <p>where <codeph>AsicImpl</codeph> is the
+class that is ultimately derived from <codeph>Asic</codeph>. </p> </li>
+<li id="GUID-BDE8C5D6-6E6C-5B2E-9219-A8D5DC114EA2"><p>register this implementation
+by adding the following call into your <codeph>Asic::Init3()</codeph> function: </p> <codeblock id="GUID-1A99C7D2-A550-5B39-9AE7-559AE7B13C3E" xml:space="preserve">Kern::SetNanoWaitHandler(AsicImpl::DoNanoWait);</codeblock> </li>
+</ul> <p>You can see where this goes by looking at the template port at: <filepath>...\base\cedar\template\template_assp\template_assp.cpp</filepath>  </p> </section>
+<section id="GUID-1028F2D0-BA8B-4880-9565-50C89EBD1685"><title>Asic::DebugOutput()
+implementation</title> <p>It is worth implementing this early so that it is
+possible to get trace output to see what the kernel is doing. This function
+is passed one character at a time. Normally this is sent to a UART, though
+it can be output through any convenient communications channel. </p> <p>On
+the template port, this is implemented in the Variant layer, by <codeph>Template::DebugOutput()</codeph> in <filepath>...\template_variant\specific\variant.cpp</filepath>. </p> </section>
+<section id="GUID-EEC48040-B7D7-406B-8138-4A1F646ED990"><title>Asic::Idle()
+implementation</title> <p>If no power management has been implemented, then
+this function is called when the system is to idle to allow power saving.
+This function can just return, until power management is implemented. Once
+power management has been implemented, then idling behaviour will be handled
+by the power controller, i.e. the Variant's implementation of the <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita"><apiname>DPowerController</apiname></xref> class </p> </section>
+<section id="GUID-917B420D-5F10-5190-97D2-9D2DAFD4FB76"><title>Asic::MsTickPeriod()
+implementation</title> <p>This function is used to return the number of microseconds
+per tick. To avoid timing drift, a tick frequency should be chosen that gives
+a round number of microseconds per tick. The function can return zero until
+the tick timer has been implemented. </p> <p>On the template port, this function
+is implemented in the ASSP layer, and can be found in the source file <filepath>...\template_assp\assp.cpp</filepath>.
+It is a simple function that just returns the value. </p> <codeblock id="GUID-C0D88A32-974C-5824-8D9D-A9B6D7C45802" xml:space="preserve">EXPORT_C TInt TemplateAssp::MsTickPeriod()
+    {
+     // 
+     // TO DO: (mandatory)
+     //
+     // Return the OST tick period (System Tick) in microseconds ( 10E-06 s ).
+     //
+     return 1000;   // EXAMPLE ONLY
+    }
+</codeblock> <p>See also <xref href="GUID-F84E18B8-5883-5A3A-A9DB-EC25BB86149F.dita">Timers</xref>. </p> </section>
+<section id="GUID-1C8A7F79-8CD5-442E-A9A5-925C94E80773"><title>Asic::SystemTimeInSecondsFrom2000()
+          implementation</title> <p>This is a function that the kernel uses
+to get the system time. Its signature is </p> <codeblock id="GUID-A1FF9777-D627-5409-B6CD-02F20F7A1889" xml:space="preserve">Tint SystemTimeInSecondsFrom2000(Tint&amp; aTime);</codeblock> <p>An implementation must set the <codeph>aTime</codeph> reference to the
+number of seconds that have elapsed since the start of the year 2000. This
+is a positive number; a negative number is interpreted as time before 2000. </p> <p>For
+the template reference board, the implementation is as follows: </p> <codeblock id="GUID-C4812A82-C069-564B-972A-0922EAC00AAB" xml:space="preserve">EXPORT_C TInt TemplateAssp::SystemTimeInSecondsFrom2000(TInt&amp; aTime)
+     {
+      aTime=(TInt)TTemplate::RtcData();
+      __KTRACE_OPT(KHARDWARE,Kern::Printf("RTC READ: %d",aTime));
+      return KErrNone;
+     }
+</codeblock> <p>Until a real time clock is implemented, this function can
+just return <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref>. </p> <p>This function calls the register
+access functions in the <codeph>TTemplate</codeph> class. See <filepath>...\template_assp\template_assp.cpp</filepath> for
+implementation details. </p> <p>Note that tracing output is provided when
+the KHARDWARE bit in the kerneltrace flags is set for the debug build. </p> </section>
+<section id="GUID-F0AC3E98-345F-4491-9957-51B127437181"><title>Asic::SetSystemTimeInSecondsFrom2000()
+implementation</title> <p>This is a function that the kernel uses to set the
+system time. Its signature is </p> <codeblock id="GUID-B965C38C-A65E-5E54-BE09-C81300B59EDC" xml:space="preserve">Tint SetSystemTimeInSecondsFrom2000(Tint aTime);</codeblock> <p>This sets the real time clock to the number of seconds that have elapsed
+since the start of the year 2000. This is a positive number; a negative number
+is interpreted as time before 2000. </p> <p>For the template reference board,
+the implementation is as follows: </p> <codeblock id="GUID-89BFC844-B053-51B7-9ACA-81B19E63414B" xml:space="preserve">EXPORT_C TInt TemplateAssp::SetSystemTimeInSecondsFrom2000(TInt aTime)
+    {
+     //
+     // TO DO: (optional)
+     //
+     // Check if the RTC is running and is stable
+     //
+     __KTRACE_OPT(KHARDWARE,Kern::Printf("Set RTC: %d",aTime));
+     TTemplate::SetRtcData(aTime);
+     __KTRACE_OPT(KHARDWARE,Kern::Printf("RTC: %d",TTemplate::RtcData()));
+     return KErrNone;
+    }
+</codeblock> <p>Note that tracing output is provided when the KHARDWARE bit
+in the kerneltrace flags is set for the debug build. In this function, the
+trace output shows the value passed in from the kernel and then shows the
+value read back from the real time clock for verification. </p> </section>
+<section id="GUID-50BB6924-899F-4385-879E-19A2FC68657C"><title>Asic::NanoWaitCalibration()
+ implementation</title> <p>The function <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-0EEAFE45-5C0D-32A9-AD64-CE3AB0AEE6B3"><apiname>Kern::NanoWait()</apiname></xref> can
+be called if you want to wait for very short periods of time within the kernel.
+You call this function and specify the number of nanoseconds. You can either
+use the default implementation of this function, or you can provide your own. </p> <p>The
+default implementation provided by Symbian platform that <codeph>Kern::NanoWait()</codeph> uses
+is a busy loop that is calibrated by calling <codeph>Asic::NanoWaitCalibration()</codeph>. <codeph>NanoWaitCalibration()</codeph> should
+return the number of nanoseconds taken to execute 2 machine cycles. This is
+obviously dependent on the CPU clock speed, so if variants are likely to run
+at different speeds, then this should be implemented in the Variant layer. </p> <p>This
+approach cannot always take into account factors such as processor frequency
+scaling. An alternative approach is for the Variant to supply its own implementation
+to be used by <codeph>Kern::NanoWait()</codeph>. Note that you do not replace <codeph>Kern::NanoWait()</codeph> itself
+as this is a shell function that results in a call to the the implementation.
+See <xref href="GUID-E0DCBDCF-C056-53E5-A375-778327F848E4.dita#GUID-E0DCBDCF-C056-53E5-A375-778327F848E4/GUID-F5275882-BBD0-561F-B617-683AA2004BB9">Asic::Init3()</xref> for
+detail on how to replace the implementation. </p> <p>On the template port, <codeph>Asic::NanoWaitCalibration()</codeph> is
+implemented in the ASSP layer, and not in the Variant layer, and can be found
+in the source file <filepath>...\template_assp\assp.cpp</filepath>. It is
+a simple function that just returns the value. </p> <codeblock id="GUID-68298BF1-EAE7-507D-9B5B-DDACE6C19799" xml:space="preserve">EXPORT_C TUint32 TemplateAssp::NanoWaitCalibration()
+    {
+     // 
+     // TO DO: (mandatory)
+     //
+     // Return the minimum time in nano-seconds that it takes to execute the following code:
+     //     nanowait_loop:
+     //               subs r0, r0, r1
+  //               bhi nanowait_loop
+     //
+     // If accurate timings are required by the Base Port, then it should provide it's own implementation 
+     // of NanoWait which uses a hardware counter. (See Kern::SetNanoWaitHandler)
+     //
+    
+     return 0;   // EXAMPLE ONLY
+    }
+</codeblock> </section>
+<section id="GUID-15F344C5-A1CC-45FC-AC94-27022A1DF448"><title>Asic::VariantHal()
+implementation</title> <p>You might find it useful to review <xref href="GUID-9AE254D4-AA60-579E-8D9D-F2797106A413.dita">User-Side
+Hardware Abstraction Technology</xref> first. </p> <p>This is the HAL handler
+for the HAL group <xref href="GUID-66A851A0-2A0C-3624-AEC1-22F6629FABF7.dita#GUID-66A851A0-2A0C-3624-AEC1-22F6629FABF7/GUID-3FA061DE-68F8-3948-96B3-5AFC989DBDE1"><apiname>THalFunctionGroup::EHalGroupVariant</apiname></xref>. </p> </section>
+<section id="GUID-2EEA143D-612C-47C5-B16C-22DAD1BC179E"><title>Asic::MachineConfiguration()
+          implementation</title> <p>This returns a <xref href="GUID-C0D29B11-1535-3D11-B318-B18D30A6120B.dita"><apiname>TPtr8</apiname></xref> descriptor
+representing an area containing machine configuration information. </p> <p>The
+address of this object is obtained by calling <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-4DAE5199-1EB0-31D1-BA06-8F47E96EEADE"><apiname>Kern::MachineConfig()</apiname></xref>.
+However, the Variant (either the ASSP layer or the Variant layer or both)
+is responsible for the content. </p> <p>In the template port, the function
+is implemented in the Variant layer: </p> <codeblock id="GUID-B75F631E-03DB-5C98-911F-1161842AA17F" xml:space="preserve">TPtr8 Template::MachineConfiguration()
+    {
+     return TPtr8((TUint8*)&amp;Kern::MachineConfig(),sizeof(TActualMachineConfig),sizeof(TActualMachineConfig));
+    }
+</codeblock> <p>Here, the machine configuration information is represented
+by an object of type <codeph>TTemplateMachineConfig</codeph>, which derives
+from <codeph>TMachineConfig</codeph>. In effect, <codeph>TMachineConfig</codeph> represents
+information that is common to all, while the Variant can extend this to contain
+whatever information is appropriate. </p> <p>Note that <codeph>TActualMachineConfig</codeph> is
+a typedef for <codeph>TTemplateMachineConfig</codeph>. </p> </section>
+<section id="GUID-B1E39D8C-1562-4464-A316-144ED89935C9"><title>Asic::StartupReason()
+implementation</title> <p>If a startup reason is available from hardware or
+a preserved RAM location, it should be returned by the function. The default
+is to return <codeph>EStartupColdReset</codeph>. </p> <p>On the template port,
+this is implemented in the ASSP layer: </p> <codeblock id="GUID-FC4FFA46-804D-5A7F-B7CA-DDDC72C60041" xml:space="preserve">EXPORT_C TMachineStartupType TemplateAssp::StartupReason()
+    {
+     __KTRACE_OPT(KBOOT,Kern::Printf("TemplateAssp::StartupReason"));
+  #ifdef _DEBUG                                                            // REMOVE THIS
+     TUint s = Kern::SuperPage().iHwStartupReason;
+     __KTRACE_OPT(KBOOT,Kern::Printf("CPU page value %08x", s));
+  #endif                                                                    // REMOVE THIS
+     //
+     // TO DO: (mandatory)
+     //
+     // Map the startup reason read from the Super Page to one of TMachineStartupType enumerated values
+     // and return this
+     //
+     return EStartupCold;   // EXAMPLE ONLY
+    }
+</codeblock> </section>
+</conbody><related-links>
+<link href="GUID-984C2A0D-36BE-5A99-9D65-3F8791C669FF.dita#GUID-984C2A0D-36BE-5A99-9D65-3F8791C669FF/GUID-95C34114-F986-5428-9D40-5CF64429CDBD">
+<linktext>ASSP/Variant Architecture</linktext></link>
+<link href="GUID-B498EDA0-677E-5521-9E4F-24D7C2048F2E.dita"><linktext>Implementing
+the ASSP                 Register</linktext></link>
+<link href="GUID-5194A7B6-471B-5BCF-8569-16A3BA59000A.dita"><linktext>Using the
+ASSP Register</linktext></link>
+<link href="GUID-77DF7A6B-F01D-5B9F-9C7A-662A04ED8BE7.dita"><linktext>ASSP Kernel
+Extension                 Overview</linktext></link>
 </related-links></concept>
\ No newline at end of file