Adaptation/GUID-E0DCBDCF-C056-53E5-A375-778327F848E4.dita
changeset 15 307f4279f433
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Adaptation/GUID-E0DCBDCF-C056-53E5-A375-778327F848E4.dita	Fri Oct 15 14:32:18 2010 +0100
@@ -0,0 +1,408 @@
+<?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>
+</related-links></concept>
\ No newline at end of file