Adaptation/GUID-E0DCBDCF-C056-53E5-A375-778327F848E4.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-E0DCBDCF-C056-53E5-A375-778327F848E4" xml:lang="en"><title>Asic Class Tutorial</title><shortdesc>Provides a work through tutorial that allows you to port
       
    13 an Asic implementation to the template variant. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <p id="GUID-39010DA3-632A-5C27-92BF-9AA8B5966EAB">  This tutorial
       
    15 describes how to implement the Asic class. This is a pure virtual
       
    16 interface that is defined and called by the Kernel, but which must
       
    17 be implemented by the ASSP/Variant. The tutorial assumes that the
       
    18 ASSP/Variant is split into an ASSP layer and a Variant layer. </p>
       
    19 <p>For a minimal port, it isn't necessary to provide implementations
       
    20 for the entire <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref> class to be able to test that
       
    21 the kernel boots, provided that those functions that are not fully
       
    22 implemented have a dummy function so that the code will build. </p>
       
    23 <p>The <codeph>Asic</codeph> class is defined in<filepath>..\e32\include\kernel\arm\assp.h</filepath>. For reference, the definition is: </p>
       
    24 <codeblock id="GUID-B33CCD29-C6D2-5DC9-9302-A265E248E8DF" xml:space="preserve">class Asic
       
    25     {
       
    26 public:
       
    27        // initialisation
       
    28     virtual TMachineStartupType StartupReason()=0;
       
    29     virtual void Init1()=0;
       
    30     virtual void Init3()=0;
       
    31 
       
    32     // debug
       
    33     virtual void DebugOutput(TUint aChar)=0;
       
    34 
       
    35     // power management
       
    36     virtual void Idle()=0;
       
    37 
       
    38     // timing
       
    39     virtual TInt MsTickPeriod()=0;
       
    40     virtual TInt SystemTimeInSecondsFrom2000(TInt&amp; aTime)=0;
       
    41     virtual TInt SetSystemTimeInSecondsFrom2000(TInt aTime)=0;
       
    42     virtual TUint32 NanoWaitCalibration()=0;
       
    43 
       
    44     // HAL
       
    45     virtual TInt VariantHal(TInt aFunction, TAny* a1, TAny* a2)=0;
       
    46 
       
    47     // Machine configuration
       
    48     virtual TPtr8 MachineConfiguration()=0;
       
    49     };</codeblock>
       
    50 <p>Taking the template port as a concrete example, the ASSP layer
       
    51 implementation of the <xref href="GUID-A83A7C3C-7DC0-3B9C-842F-70FCC751365D.dita"><apiname>Asic</apiname></xref> class is defined and
       
    52 implemented by the <codeph>TemplateAssp</codeph> class, and the Variant
       
    53 implemention is defined and implemented by the <codeph>Template</codeph> class. </p>
       
    54 <section id="GUID-7F5D4AD6-0881-5942-9A86-A95C02125A28"><title>Asic::Init1()
       
    55 implementation</title> <p><b>Entry conditions</b> </p> <ul>
       
    56 <li id="GUID-6B761E80-7B63-5F96-9852-65F7321D365B"><p>called in the
       
    57 context of the initial (null) thread </p> </li>
       
    58 <li id="GUID-B8211B76-1308-5372-8034-4B1B9CFE58F3"><p>interrupts are
       
    59 disabled </p> </li>
       
    60 <li id="GUID-482B5E00-A25F-5966-90FB-B622F9C1AF99"><p>there is no
       
    61 kernel heap </p> </li>
       
    62 <li id="GUID-6D985E4B-1A69-58B6-975D-7F696BB062C3"><p>memory management
       
    63 functions are not available. </p> </li>
       
    64 </ul> <p><b>What the function should do</b> </p> <p>This is called during
       
    65 stage 1 of kernel initialisation. </p> <p>In this function, you need
       
    66 to: </p> <ul>
       
    67 <li id="GUID-D156866C-0BA0-58AE-9438-C4D1D2628D67"><p>initialise the
       
    68 real time clock </p> </li>
       
    69 <li id="GUID-7FB60E9E-938C-515E-803D-27DA1315040C"><p>initialise the
       
    70 interrupt dispatcher before CPU interrupts are enabled. </p> </li>
       
    71 <li id="GUID-D55DD2D9-3E45-5256-B1F4-E583706AED66"><p>set the threshold
       
    72 values for cache maintenance. You can set separate values for: </p> <ul>
       
    73 <li id="GUID-B3CEB2A4-4849-517F-A0E9-76A6018537B8"><p>purging (invalidating)
       
    74 a cache </p> </li>
       
    75 <li id="GUID-9DE85DFB-D789-565C-A944-EFBF987D457C"><p>cleaning a cache </p> </li>
       
    76 <li id="GUID-0C638F72-1D6B-512D-88EB-7369240C776A"><p>flushing (i.e.
       
    77 cleaning and invalidating) a cache. </p> </li>
       
    78 </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
       
    79 to set these values. </p> <p>As an example of what the threshold values
       
    80 mean, if you purge a memory region from cache, and the size of that
       
    81 region is greater than the threshold value, then the entire cache
       
    82 is purged. If the size of that region is less than or equal to to
       
    83 the threshold value, then only the region is purged. </p> <p>The threshold
       
    84 values are platform specific, and you need to choose your values based
       
    85 on your own performance measurements. Symbian cannot make recommendations.
       
    86 If you choose not to set your own values, Symbian platform supplies
       
    87 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>
       
    88 <li id="GUID-DA94E963-6AA5-5084-8C19-77B7AD484A44"><p>set up the RAM
       
    89 zones. For details, see the <xref href="GUID-C376486D-B9BF-5D00-8B1A-1527FC1F83AD.dita">RAM Zone Tutorial</xref>. </p> </li>
       
    90 </ul> <p>Typically, you would also initialise any memory devices not
       
    91 initialised by the bootstrap. Any other initialisation that must happen
       
    92 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
       
    93 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()
       
    94     {
       
    95      __KTRACE_OPT(KBOOT,Kern::Printf("Template::Init1()"));
       
    96 
       
    97      //
       
    98      // TO DO: (mandatory)
       
    99      //
       
   100      // Configure Memory controller and Memrory Bus parameters (in addition to what was done in the Bootstrap)
       
   101      //
       
   102      __KTRACE_OPT(KBOOT,Kern::Printf("Memory Configuration done"));
       
   103 
       
   104      //
       
   105      // TO DO: (optional)
       
   106      //
       
   107      // Inform the kernel of the RAM zone configuration via Epoc::SetRamZoneConfig().
       
   108      // For devices that wish to reduce power consumption of the RAM IC(s) the callback functions
       
   109      // RamZoneCallback() and DoRamZoneCallback() will need to be implemented and passed 
       
   110      // to Epoc::SetRamZoneConfig() as the parameter aCallback.
       
   111      // The kernel will assume that all RAM ICs are fully intialised and ready for use from boot.
       
   112      //
       
   113 
       
   114      //
       
   115      // TO DO: (optional)
       
   116      //
       
   117      // Initialise other critical hardware functions such as I/O interfaces, etc, not done by Bootstrap
       
   118      //
       
   119      // if CPU is Sleep-capable, and requires some preparation to be put in that state (code provided in Bootstrap),
       
   120      // the address of the idle code is writen at this location by the Bootstrap
       
   121      // e.g.
       
   122      // iIdleFunction=*(TLinAddr*)((TUint8*)&amp;Kern::SuperPage()+0x1000);
       
   123      //
       
   124      TemplateAssp::Init1();
       
   125      }</codeblock> <p>The last line is a call into the ASSP layer,
       
   126 which is implemented as shown below. On the template port, it is the
       
   127 ASSP layer that initialises the interrupt dispatcher and the real
       
   128 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()
       
   129     {
       
   130      __KTRACE_OPT(KBOOT,Kern::Printf("TemplateAssp::Init1()"));
       
   131      //
       
   132      // TO DO: (optional)
       
   133      //
       
   134      TemplateInterrupt::Init1();            // initialise the ASSP interrupt controller
       
   135 
       
   136      //
       
   137      // TO DO: (optional)
       
   138      //
       
   139      // Initialises any hardware blocks which require early initialisation, e.g. enable and power the LCD, set up
       
   140      // RTC clocks, disable DMA controllers. etc.
       
   141      //
       
   142     }
       
   143 
       
   144    </codeblock> <p> <codeph>TemplateInterrupt::Init1();</codeph> is
       
   145 static function that initialises the interrupt dispatcher. See <xref href="GUID-423537D5-2C8A-5C26-8D7B-60446E95F681.dita">Interrupt Layer Initialisation</xref>. </p> </section>
       
   146 <section id="GUID-F5275882-BBD0-561F-B617-683AA2004BB9"><title>Asic::Init3()
       
   147 implementation</title> <p><b>Entry conditions</b> </p> <ul>
       
   148 <li id="GUID-9450694C-ADF3-52DE-AA58-4AFF53A1EEC6"><p>called in the
       
   149 context of the supervisor thread </p> </li>
       
   150 <li id="GUID-335F8A2E-0223-598E-AA23-F72E3BE84D76"><p>the kernel is
       
   151 ready to handle interrupts </p> </li>
       
   152 <li id="GUID-B198D669-9E88-5279-81A8-6A11F8EE3BFD"><p>the kernel heap
       
   153 and memory management system is fully functional. </p> </li>
       
   154 </ul> <p><b>What the function should do</b> </p> <p>This is called during
       
   155 stage 3 of kernel initialisation. </p> <p>In this function, you need
       
   156 to: </p> <ul>
       
   157 <li id="GUID-38C35732-E79A-595C-9852-12D1FE30A081"><p>enable interrupt
       
   158 sources </p> </li>
       
   159 <li id="GUID-D4F750D9-96B1-5AD1-AA66-2485D37B6323"><p>start the millisecond
       
   160 tick timer. </p> </li>
       
   161 <li id="GUID-390278B7-EF0F-59ED-A57D-54490655C97B"><p>Optionally,
       
   162 replace the implementation used by <codeph>Kern::NanoWait()</codeph>. </p> </li>
       
   163 </ul> <p>Any other general initialisation can also be done here. </p> <p>As an example, on the template port, the function is implemented
       
   164 in the Variant layer, by <codeph>Template::Init3()</codeph>. </p> <p><b>Millisecond tick timer</b> </p> <p>The kernel expects that the
       
   165 kernel's tick handler routine will be called at a fixed microsecond
       
   166 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
       
   167 is as follows: </p> <codeblock id="GUID-AF60AC52-5188-5911-9A03-A090D048ADA3" xml:space="preserve">EXPORT_C void TemplateAssp::Init3()
       
   168     {
       
   169     __KTRACE_OPT(KBOOT,Kern::Printf("TemplateAssp::Init3()"));
       
   170 
       
   171     TTemplate::Init3();
       
   172 
       
   173     NTimerQ&amp; m=*(NTimerQ*)NTimerQ::TimerAddress();
       
   174     iTimerQ=&amp;m;
       
   175     //
       
   176     // TO DO: (mandatory)
       
   177     //
       
   178     // If Hardware Timer used for System Ticks cannot give exactly the period required store the initial rounding value
       
   179     // here which is updated every time a match occurs. Note this leads to "wobbly" timers whose exact period change
       
   180     // but averages exactly the required value
       
   181     // e.g.
       
   182     // m.iRounding=-5;
       
   183     //
       
   184     
       
   185     TInt r=Interrupt::Bind(KIntIdOstMatchMsTimer,MsTimerTick,&amp;m);    // bind the System Tick interrupt
       
   186     if (r!=KErrNone)
       
   187         Kern::Fault("BindMsTick",r);
       
   188 
       
   189     // 
       
   190     // TO DO: (mandatory)
       
   191     //
       
   192     // Clear any pending OST interrupts and enable any OST match registers.
       
   193     // If possible may reset the OST here (to start counting from a full period). Set the harwdare to produce an 
       
   194     // interrupt on full count
       
   195     //
       
   196 
       
   197     r=Interrupt::Enable(KIntIdOstMatchMsTimer);    // enable the System Tick interrupt
       
   198     if (r!=KErrNone)
       
   199         Kern::Fault("EnbMsTick",r);
       
   200 
       
   201     // 
       
   202     // TO DO: (optional)
       
   203     //
       
   204     // Allocate physical RAM for video buffer, as per example below. However with some hardware, the Video Buffer
       
   205     // may not reside in main System memory, it may be dedicated memory.
       
   206     //
       
   207     // EXAMPLE ONLY
       
   208     TInt vSize=VideoRamSize();
       
   209     r=Epoc::AllocPhysicalRam(2*vSize,TemplateAssp::VideoRamPhys);
       
   210     if (r!=KErrNone)
       
   211         Kern::Fault("AllocVRam",r);
       
   212     }</codeblock> <p><b>Servicing the timer interrupt</b> </p> <p>The timer interrupt
       
   213 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
       
   214 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,
       
   215 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)
       
   216     {
       
   217     // Service 1ms tick interrupt
       
   218     asm("ldr ip, [r0, #%a0]" : : "i" _FOFF(NTimerQ,iRounding));
       
   219     asm("ldr r2, __KHwBaseOst ");
       
   220     asm("adds ip, ip, #2 ");
       
   221     asm("ldr r3, __KOst1000HzTickMatchIncrement ");
       
   222     asm("subcs ip, ip, #5 ");
       
   223     asm("str ip, [r0, #%a0]" : : "i" _FOFF(NTimerQ,iRounding));
       
   224     asm("addcs r3, r3, #1 ");
       
   225     asm("mov r1, #%a0" : : "i" ((TInt)(1&lt;&lt;KHwOstMatchMsTimer)));
       
   226     asm("str r1, [r2, #0x14] ");            // clear interrupt
       
   227     asm("ldr r1, [r2, #%a0]" : : "i" ((TInt)KHwOstMatchMsTimer*4));    // r1=old match value
       
   228     asm("add r1, r1, r3 ");            // step match value on
       
   229     asm("ldr ip, [r2, #0x10] ");            // r3=system timer value
       
   230     asm("str r1, [r2, #%a0]" : : "i" ((TInt)KHwOstMatchMsTimer*4));
       
   231     asm("cmp ip, r1 ");            // compare to next match value
       
   232 
       
   233 #ifdef _DEBUG
       
   234     asm("addpl r1, ip, #10 ");    // in DEBUG if timer&gt;match value, set match value to timer + a bit
       
   235     asm("strpl r1, [r2, #%a0]" : : "i" ((TInt)KHwOstMatchMsTimer*4));
       
   236     asm("b Tick__7NTimerQ ");    // call interrupt handler anyway
       
   237 #else
       
   238     asm("bmi Tick__7NTimerQ ");    // if timer&lt;match value, OK - call interrupt handler
       
   239 #endif
       
   240 
       
   241     // otherwise we are late for the next tick so force a data abort exception...
       
   242     asm("mvn r2, #0x10000002 ");    // r2=0xeffffffd
       
   243     asm("str r2, [r2] ");            // die
       
   244 
       
   245     // Constant data embedded in code. 
       
   246     asm("__KOst1000HzTickMatchIncrement: ");
       
   247     asm(".word %a0" : : "i" ((TInt)KOst1000HzTickMatchIncrement));
       
   248     asm("__KHwBaseOst: ");
       
   249     asm(".word %a0" : : "i" ((TInt)KHwBaseOst));
       
   250     }</codeblock> <p>Note that it is a requirement that the timer
       
   251 period should be an integral number of microseconds, even if the exact
       
   252 period is not 1000us. It is always possible to add code to the interrupt
       
   253 handler to achieve this average so that over a large number of ticks,
       
   254 the deviation from this average will tend to 0, by adjusting the exact
       
   255 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
       
   256 periods of time within the kernel. You call this function and specify
       
   257 the number of nanoseconds. The function is, in effect, a shell that
       
   258 uses default implementation code provided by the generic platform.
       
   259 You can provide your own implementation in your port, and register
       
   260 this with the platform. This allows the wait functionality to be implemented
       
   261 in the best possible way for your platform, possibly by using a hardware
       
   262 timer whose frequency is independent of the CPU frequency. </p> <p>To replace the default implementation, you need to: </p> <ul>
       
   263 <li id="GUID-733329E1-99C5-56A4-B80F-FFCFD74F1320"><p>code your own
       
   264 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)
       
   265     {
       
   266     // Wait for aInterval nanoseconds
       
   267     }</codeblock> <p>where <codeph>AsicImpl</codeph> is the class that is ultimately derived from <codeph>Asic</codeph>. </p> </li>
       
   268 <li id="GUID-BDE8C5D6-6E6C-5B2E-9219-A8D5DC114EA2"><p>register this
       
   269 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>
       
   270 </ul> <p>You can see where this goes by looking at the template port
       
   271 at: <filepath>...\base\cedar\template\template_assp\template_assp.cpp</filepath>  </p> </section>
       
   272 <section id="GUID-1028F2D0-BA8B-4880-9565-50C89EBD1685"><title>Asic::DebugOutput()
       
   273 implementation</title> <p>It is worth implementing this early so that
       
   274 it is possible to get trace output to see what the kernel is doing.
       
   275 This function is passed one character at a time. Normally this is
       
   276 sent to a UART, though it can be output through any convenient communications
       
   277 channel. </p> <p>On the template port, this is implemented in the
       
   278 Variant layer, by <codeph>Template::DebugOutput()</codeph> in <filepath>...\template_variant\specific\variant.cpp</filepath>. </p> </section>
       
   279 <section id="GUID-EEC48040-B7D7-406B-8138-4A1F646ED990"><title>Asic::Idle()
       
   280 implementation</title> <p>If no power management has been implemented,
       
   281 then this function is called when the system is to idle to allow power
       
   282 saving. This function can just return, until power management is implemented.
       
   283 Once power management has been implemented, then idling behaviour
       
   284 will be handled by the power controller, i.e. the Variant's implementation
       
   285 of the <xref href="GUID-B3D1C422-6A82-3C6E-9123-1E4F598F0366.dita"><apiname>DPowerController</apiname></xref> class </p> </section>
       
   286 <section id="GUID-917B420D-5F10-5190-97D2-9D2DAFD4FB76"><title>Asic::MsTickPeriod()
       
   287 implementation</title> <p>This function is used to return the number
       
   288 of microseconds per tick. To avoid timing drift, a tick frequency
       
   289 should be chosen that gives a round number of microseconds per tick.
       
   290 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
       
   291 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()
       
   292     {
       
   293      // 
       
   294      // TO DO: (mandatory)
       
   295      //
       
   296      // Return the OST tick period (System Tick) in microseconds ( 10E-06 s ).
       
   297      //
       
   298      return 1000;   // EXAMPLE ONLY
       
   299     }
       
   300 </codeblock> <p>See also <xref href="GUID-F84E18B8-5883-5A3A-A9DB-EC25BB86149F.dita">Timers</xref>. </p> </section>
       
   301 <section id="GUID-1C8A7F79-8CD5-442E-A9A5-925C94E80773"><title>Asic::SystemTimeInSecondsFrom2000()
       
   302           implementation</title> <p>This is a function that the kernel
       
   303 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
       
   304 to the number of seconds that have elapsed since the start of the
       
   305 year 2000. This is a positive number; a negative number is interpreted
       
   306 as time before 2000. </p> <p>For the template reference board, the
       
   307 implementation is as follows: </p> <codeblock id="GUID-C4812A82-C069-564B-972A-0922EAC00AAB" xml:space="preserve">EXPORT_C TInt TemplateAssp::SystemTimeInSecondsFrom2000(TInt&amp; aTime)
       
   308      {
       
   309       aTime=(TInt)TTemplate::RtcData();
       
   310       __KTRACE_OPT(KHARDWARE,Kern::Printf("RTC READ: %d",aTime));
       
   311       return KErrNone;
       
   312      }
       
   313 </codeblock> <p>Until a real time clock is implemented, this function
       
   314 can just return <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref>. </p> <p>This function
       
   315 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
       
   316 provided when the KHARDWARE bit in the kerneltrace flags is set for
       
   317 the debug build. </p> </section>
       
   318 <section id="GUID-F0AC3E98-345F-4491-9957-51B127437181"><title>Asic::SetSystemTimeInSecondsFrom2000()
       
   319 implementation</title> <p>This is a function that the kernel uses
       
   320 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
       
   321 elapsed since the start of the year 2000. This is a positive number;
       
   322 a negative number is interpreted as time before 2000. </p> <p>For
       
   323 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)
       
   324     {
       
   325      //
       
   326      // TO DO: (optional)
       
   327      //
       
   328      // Check if the RTC is running and is stable
       
   329      //
       
   330      __KTRACE_OPT(KHARDWARE,Kern::Printf("Set RTC: %d",aTime));
       
   331      TTemplate::SetRtcData(aTime);
       
   332      __KTRACE_OPT(KHARDWARE,Kern::Printf("RTC: %d",TTemplate::RtcData()));
       
   333      return KErrNone;
       
   334     }
       
   335 </codeblock> <p>Note that tracing output is provided when the KHARDWARE
       
   336 bit in the kerneltrace flags is set for the debug build. In this function,
       
   337 the trace output shows the value passed in from the kernel and then
       
   338 shows the value read back from the real time clock for verification. </p> </section>
       
   339 <section id="GUID-50BB6924-899F-4385-879E-19A2FC68657C"><title>Asic::NanoWaitCalibration()
       
   340  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
       
   341 within the kernel. You call this function and specify the number of
       
   342 nanoseconds. You can either use the default implementation of this
       
   343 function, or you can provide your own. </p> <p>The default implementation
       
   344 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
       
   345 of nanoseconds taken to execute 2 machine cycles. This is obviously
       
   346 dependent on the CPU clock speed, so if variants are likely to run
       
   347 at different speeds, then this should be implemented in the Variant
       
   348 layer. </p> <p>This approach cannot always take into account factors
       
   349 such as processor frequency scaling. An alternative approach is for
       
   350 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
       
   351 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,
       
   352 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()
       
   353     {
       
   354      // 
       
   355      // TO DO: (mandatory)
       
   356      //
       
   357      // Return the minimum time in nano-seconds that it takes to execute the following code:
       
   358      //     nanowait_loop:
       
   359      //               subs r0, r0, r1
       
   360   //               bhi nanowait_loop
       
   361      //
       
   362      // If accurate timings are required by the Base Port, then it should provide it's own implementation 
       
   363      // of NanoWait which uses a hardware counter. (See Kern::SetNanoWaitHandler)
       
   364      //
       
   365     
       
   366      return 0;   // EXAMPLE ONLY
       
   367     }
       
   368 </codeblock> </section>
       
   369 <section id="GUID-15F344C5-A1CC-45FC-AC94-27022A1DF448"><title>Asic::VariantHal()
       
   370 implementation</title> <p>You might find it useful to review <xref href="GUID-9AE254D4-AA60-579E-8D9D-F2797106A413.dita">User-Side Hardware
       
   371 Abstraction Technology</xref> first. </p> <p>This is the HAL handler
       
   372 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>
       
   373 <section id="GUID-2EEA143D-612C-47C5-B16C-22DAD1BC179E"><title>Asic::MachineConfiguration()
       
   374           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
       
   375 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
       
   376 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
       
   377 layer: </p> <codeblock id="GUID-B75F631E-03DB-5C98-911F-1161842AA17F" xml:space="preserve">TPtr8 Template::MachineConfiguration()
       
   378     {
       
   379      return TPtr8((TUint8*)&amp;Kern::MachineConfig(),sizeof(TActualMachineConfig),sizeof(TActualMachineConfig));
       
   380     }
       
   381 </codeblock> <p>Here, the machine configuration information is represented
       
   382 by an object of type <codeph>TTemplateMachineConfig</codeph>, which
       
   383 derives from <codeph>TMachineConfig</codeph>. In effect, <codeph>TMachineConfig</codeph> represents information that is common to all, while the Variant
       
   384 can extend this to contain whatever information is appropriate. </p> <p>Note that <codeph>TActualMachineConfig</codeph> is a typedef
       
   385 for <codeph>TTemplateMachineConfig</codeph>. </p> </section>
       
   386 <section id="GUID-B1E39D8C-1562-4464-A316-144ED89935C9"><title>Asic::StartupReason()
       
   387 implementation</title> <p>If a startup reason is available from hardware
       
   388 or a preserved RAM location, it should be returned by the function.
       
   389 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()
       
   390     {
       
   391      __KTRACE_OPT(KBOOT,Kern::Printf("TemplateAssp::StartupReason"));
       
   392   #ifdef _DEBUG                                                            // REMOVE THIS
       
   393      TUint s = Kern::SuperPage().iHwStartupReason;
       
   394      __KTRACE_OPT(KBOOT,Kern::Printf("CPU page value %08x", s));
       
   395   #endif                                                                    // REMOVE THIS
       
   396      //
       
   397      // TO DO: (mandatory)
       
   398      //
       
   399      // Map the startup reason read from the Super Page to one of TMachineStartupType enumerated values
       
   400      // and return this
       
   401      //
       
   402      return EStartupCold;   // EXAMPLE ONLY
       
   403     }
       
   404 </codeblock> </section>
       
   405 </conbody><related-links>
       
   406 <link href="GUID-984C2A0D-36BE-5A99-9D65-3F8791C669FF.dita#GUID-984C2A0D-36BE-5A99-9D65-3F8791C669FF/GUID-95C34114-F986-5428-9D40-5CF64429CDBD">
       
   407 <linktext>ASSP/Variant Architecture</linktext></link>
       
   408 </related-links></concept>