Adaptation/GUID-F461CBB3-F8D1-5961-AD51-5741143A1CB1.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-F461CBB3-F8D1-5961-AD51-5741143A1CB1" xml:lang="en"><title>Client of Slave Channel Tutorial</title><shortdesc>This document describes a simple implementation of a client
       
    13 of an IIC slave channel. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <section id="GUID-803E9D3A-19F4-58EA-A3F8-1912C7223FE2"><title>Required
       
    15 background</title> <p>Before you start, you must: </p> <ul>
       
    16 <li id="GUID-E20D2D65-CB2C-52A0-B694-B26EC96B6F99"><p>Have installed
       
    17 the platform specific implementation of IIC channels that is required
       
    18 to support the IIC platform service API. </p> </li>
       
    19 <li id="GUID-F675A381-8125-5077-8D9E-70188B1ACA6C"><p>Ensure that
       
    20 the <filepath>iic.dll</filepath> has been included in the <filepath>kernel.iby</filepath> file. </p> </li>
       
    21 <li id="GUID-638684A5-4938-5F60-9BB1-97F5AFD199B4"><p>Include the <filepath>iic.h</filepath> and <filepath>iic_channel.h</filepath> header files. </p> </li>
       
    22 </ul> </section>
       
    23 <section id="GUID-D71B8CE6-AD6B-56A4-835F-44B80FB2E0A6"><title>Introduction</title> <p>An application communicates over an IIC channel by operating
       
    24 as a client of the channel. When the channel uses a slave node, a
       
    25 transmission must be conducted at the level of the transfer because
       
    26 slaves react to transfers between it and a master node. For this reason,
       
    27 a large part of the client functionality is implemented as a callback
       
    28 function which is passed to the channel object and placed on the client
       
    29 thread’s DFC queue for execution. The callback notifies the client
       
    30 of the individual transfers and is the entry point to the application
       
    31 functionality which uses the data being transmitted. The other client
       
    32 API functions control the transmission as a whole. </p> </section>
       
    33 <section id="GUID-F6E864D9-F951-4A2D-B933-166F5DE4F5C3"><title>Procedure
       
    34 for writing a client</title> <ol id="GUID-E1360AA1-59E2-53FE-9CED-967D731F17CA">
       
    35 <li id="GUID-D8ABA659-47A9-536E-9EC6-E8741909CAFF"><p>Capture the
       
    36 channel by calling <xref href="GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF.dita#GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF/GUID-0078D2B4-07B7-3936-8CB2-6A967C9B1FCD"><apiname>IicBus::CaptureChannel()</apiname></xref>. </p> <ol id="GUID-A0A19CF5-5A45-588A-8C15-A11C12800055">
       
    37 <li id="GUID-37BA179D-1D7F-560C-8C81-6C9EE7674459"><p>Pass the channel
       
    38 Id as its <codeph>TInt aBusId</codeph> parameter. </p> </li>
       
    39 <li id="GUID-BF8B3291-626A-59F1-897A-25A73D22FCCD"><p>Pass the channel
       
    40 configuration header as <codeph>TDes8* aConfigHdr</codeph>. </p> </li>
       
    41 <li id="GUID-E1BA9A5F-81CE-522E-8CC0-CF38D0BC474B"><p>Pass a pointer
       
    42 to the callback function as <codeph>TIicBusSlaveCallback* aCallback</codeph>. </p> </li>
       
    43 <li id="GUID-DB6262F2-51D4-5D2D-857B-7F54E6EF1521"><p>Pass the boolean <xref href="GUID-781E8158-805B-3784-8FED-D7A191822FC3.dita"><apiname>ETrue</apiname></xref> as <codeph>TBool aAsynch</codeph> to specify asynchronous
       
    44 channel capture and otherwise pass <xref href="GUID-A759CA2D-8327-348F-9337-4886E619D920.dita"><apiname>EFalse</apiname></xref>. </p> </li>
       
    45 </ol> <p><codeblock id="GUID-713BDFF9-83E2-5A63-BD3A-A36556E5A70C" xml:space="preserve">
       
    46     TInt channelId = 0;
       
    47     // capture channel..
       
    48     r = IicBus::CaptureChannel(TInt aBusId, &amp;header, iSlaveCallback, channelId, aAsynch);
       
    49     if (r != KErrNone)
       
    50         {
       
    51         __KTRACE(Kern::Printf("Error capturing the channel, r %d", r));
       
    52         }
       
    53 </codeblock> </p> <p>In synchronous transmission when the function
       
    54 returns the parameter <codeph>TInt&amp; aChannelId</codeph> is set
       
    55 to a token value, the channel Id, which is used by the other functions
       
    56 to acquire the exclusive use of the channel. In asynchronous transmission
       
    57 the channel Id is set immediately before calling the client callback. </p> </li>
       
    58 <li id="GUID-1D366FFE-DEE0-59E1-9FC7-507C06C58964"><p>Register receive
       
    59 and transmit buffers by calling <xref href="GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF.dita#GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF/GUID-E6D971CA-E09C-36B2-92B2-759CC81AF3F1"><apiname>IicBus::RegisterRxBuffer()</apiname></xref> and <xref href="GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF.dita#GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF/GUID-E885DF1D-2192-3BC7-8165-1E5A194ABA28"><apiname>IicBus::RegisterTxBuffer()</apiname></xref>. </p> <ol id="GUID-7722A592-4EB3-5701-9F7F-79EEB8E6221D">
       
    60 <li id="GUID-520C3DF1-91AE-5FAC-AFFC-806361672660"><p>Pass the channel
       
    61 Id as the <codeph>aChannelId</codeph> parameter. </p> </li>
       
    62 <li id="GUID-E4971790-1830-5CA3-90DB-89F3FA169758"><p>A buffer is
       
    63 represented by a descriptor containing a point to the start of the
       
    64 buffer, its total size in bytes and an indication of how much of it
       
    65 is in use. Initialise a descriptor with these values and pass it as <codeph>TPtr8 aRxBuffer</codeph>, and similarly for <codeph>TPtr8 aTxBuffer</codeph>  </p> </li>
       
    66 </ol> <p><codeblock id="GUID-6585AF43-450D-5A6A-A55E-39CEDACF0CA1" xml:space="preserve">
       
    67     TPtr8 rxBuf(0, 0);
       
    68     TPtr8 txBuf(0, 0);
       
    69 
       
    70     rxBuf.Set((TUint8*) iRxBuf.Ptr(), iSlaveBufSize, iRxBuf.MaxLength());
       
    71     txBuf.Set((TUint8*) iTxBuf.Ptr(), iSlaveBufSize, iTxBuf.MaxLength());
       
    72 
       
    73     r = IicBus::RegisterRxBuffer(iChannelId, rxBuf, 8, iSlaveBufSize, 0);
       
    74     if(r != KErrNone)
       
    75         {
       
    76         __KTRACE(Kern::Printf("Error Register Rx Buffer, r %d", r));
       
    77         }
       
    78     else
       
    79         {
       
    80         r = IicBus::RegisterTxBuffer(iChannelId, txBuf, 8, iSlaveBufSize, 0);
       
    81         }
       
    82 
       
    83     return r;
       
    84 </codeblock> </p> </li>
       
    85 <li id="GUID-BC801368-74D3-504D-95D6-A802C34062C9"><p>Call <xref href="GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF.dita#GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF/GUID-8FD1E53D-5C7C-38ED-8B2C-59B4BCF8940B"><apiname>IicBus::SetNotificationTrigger()</apiname></xref>. This function informs
       
    86 the channel of the conditions under which the callback is to be called. </p> <ol id="GUID-FB921A67-1B9D-5B7A-9B9E-1587F32328A6">
       
    87 <li id="GUID-4DB389EA-2BC7-5275-AF4C-D6EE411B2400"><p>Pass the channel
       
    88 Id as <codeph>TInt&amp; aChannelId</codeph>. </p> </li>
       
    89 <li id="GUID-0F57322E-3D82-5E67-932C-9C6145B4E7C6"><p>The callback
       
    90 is called when the state of the channel satisfies one of a number
       
    91 of conditions called triggers which are specified in the enumeration <xref href="GUID-5216FF3E-19BA-3862-B188-A3871D7D1BF5.dita"><apiname>TIicBusSlaveTrigger</apiname></xref>. Determine which triggers are appropriate,
       
    92 create a bitmask of them and pass it as <codeph>TInt aTrigger</codeph>. </p> </li>
       
    93 </ol> <p><codeblock id="GUID-03217DC6-FD76-5786-8103-55BB847533CB" xml:space="preserve">
       
    94 /*
       
    95     ERxAllBytes            = 0x01,    // Master has written the required number of bytes
       
    96     ERxUnderrun            = 0x02,    // Master has written less than the required number of bytes, and ceased transmitting
       
    97     ERxOverrun            = 0x04,    // Master has written the required number of bytes and is continuing to transmit
       
    98     ETxAllBytes            = 0x08,    // Master has read the required number of bytes
       
    99     ETxUnderrun            = 0x10,    // Master has read the required number of bytes and is continuing to read
       
   100     ETxOverrun            = 0x20,    // Master has read less than the required number of bytes, and ceased reading
       
   101     EGeneralBusError    = 0x40,    // An error has occurred during a transaction
       
   102     EAsyncCaptChan        = 0x80     // Completion of asynchronous CaptureChannelr = IicBus::SetNotificationTrigger(iChannelId, aTrigger);
       
   103 */
       
   104  r = SetNotificationTrigger(iChannelId, aTrigger);
       
   105     if (r != KErrNone)
       
   106         {
       
   107         __KTRACE(Kern::Printf("Error setting notification trigger, r %d", r));
       
   108         }
       
   109 
       
   110     return r;
       
   111 </codeblock> </p> <p>The transmission of data will now take place,
       
   112 controlled by the mechanism of callback and triggers. Different buses
       
   113 signal that a transmission has been completed in different ways: for
       
   114 instance I2C uses a stop bit and SPI changes the voltage on Chip Select. </p> </li>
       
   115 <li id="GUID-488F34BF-E6E8-5316-8484-14560A689CD8"><p>When you have
       
   116 finished using the channel, release it by calling <xref href="GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF.dita#GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF/GUID-C1B69722-1316-3C7D-BB8B-0E54B8F44C5D"><apiname>IicBus::ReleaseChannel()</apiname></xref> with the channel Id as its argument. </p> <p><codeblock id="GUID-06528860-5B5D-5909-BBD5-BABE2146F616" xml:space="preserve">
       
   117         r = IicBus::ReleaseChannel(iChannelId);
       
   118         if (r == KErrNone)
       
   119             {
       
   120    // resetting channel Id
       
   121             iChannelId = 0;
       
   122             if(iSlaveCallback)
       
   123                 {
       
   124     // callback object no longer needed, so delete
       
   125                 delete iSlaveCallback;
       
   126                 iSlaveCallback = NULL;
       
   127                 }
       
   128 
       
   129             }
       
   130 </codeblock> </p> </li>
       
   131 </ol> </section>
       
   132 <section id="GUID-C82AB1DF-2988-4E29-92D1-235662B0485C"><title>Next
       
   133 steps</title> <ul>
       
   134 <li id="GUID-FD946C48-CC78-5E04-A682-65DAC3CF31C2"><p>Implement the
       
   135 callback as a function containing a series of conditions on the triggers.
       
   136 Its prototype must match the typedef for (*<xref href="GUID-7EB83085-7D28-3914-802B-44D8260E9074.dita"><apiname>TIicBusSlaveCbFn</apiname></xref>). </p> <codeblock id="GUID-A0F3DD87-11B7-5AD1-B3F1-F5515B4A97BD" xml:space="preserve">typedef void (*TIicBusSlaveCbFn)(TInt   /*aChannelId*/,
       
   137                                  TInt   /*aReturn*/,
       
   138                                  TInt   /*aTrigger*/,
       
   139                                  TInt16 /*aRxWords*/,
       
   140                                  TInt16 /*aTxWords*/,
       
   141                                  TAny*  /*aParam*/);
       
   142 </codeblock> <p>These functions serve three purposes. </p> <ul>
       
   143 <li id="GUID-7E871B53-4DA7-5C38-9485-A7FAD2ACCC4B"><p>The callback
       
   144 must react to the completion of an asynchronous transmission between
       
   145 it and the bus master. </p> </li>
       
   146 <li id="GUID-068201FA-B27E-55F5-AF14-CBA53A8D1AAD"><p>It must implement
       
   147 the actual functionality of the application by doing something with
       
   148 the data which is written to or read from the buffers. </p> </li>
       
   149 <li id="GUID-7F9AFCB8-6C3F-51C4-B1B9-C5DA492ED039"><p>It must react
       
   150 to cases where the physical transfer of the data has not taken place
       
   151 exactly as expected. For example there may be more data to transfer
       
   152 than had been anticipated. </p> </li>
       
   153 </ul> <ul>
       
   154 <li id="GUID-74EA3A8B-8DEE-57E8-90F3-606FE671588A"><p>Implement the
       
   155 reaction to a completed asynchronous transmission as a conditional
       
   156 statement where <xref href="GUID-DAAA6E18-9E78-3ED2-A686-EC28E5C92A24.dita"><apiname>EAsyncaptChan</apiname></xref> is true. The callback
       
   157 should return and control should revert to the client. </p> <codeblock id="GUID-F6ECA83D-E4D8-5015-A88C-B76228DA74BB" xml:space="preserve">
       
   158   // aTrigger and aReturn are the arguments provided to the clients 
       
   159   // callback functions as defined by TIicBusSlaveCbFn
       
   160         if(aTrigger &amp; (EAsyncCaptChan))
       
   161             {
       
   162             if(aReturn == KErrCompletion)
       
   163                 {
       
   164     // a is a pointer to the client's object
       
   165     // which stores the channel Id, client Id etc
       
   166                 a-&gt;iChannelId = aChannelId;
       
   167                 __KTRACE(Kern::Printf("channelId %d", aChannelId));
       
   168                 }
       
   169 
       
   170             Kern::RequestComplete(a-&gt;iClient, a-&gt;iSlaveReqStatus, aReturn);
       
   171             return;
       
   172             }
       
   173 </codeblock> </li>
       
   174 <li id="GUID-16448D59-2A11-5D89-806F-763D96CEFEC6"><p>Implement the
       
   175 actual functionality of the application as a conditional statement
       
   176 where <xref href="GUID-CC0F0C9A-25B6-3A18-93D1-EC0710DFB6A7.dita"><apiname>EAllBytes</apiname></xref> is true. The callback should return
       
   177 at the end of this condition. </p> <codeblock id="GUID-905D54F9-A19E-51C9-98A5-A95471BAFB53" xml:space="preserve">
       
   178         if(aReturn &amp; (ETxAllBytes | ERxAllBytes))
       
   179             {
       
   180             Kern::RequestComplete(a-&gt;iClient, a-&gt;iSlaveReqStatus, KErrNone);
       
   181             }
       
   182 
       
   183         if(aTrigger &amp; (/*ERxAllBytes |*/ ETxAllBytes))
       
   184             {
       
   185             Kern::RequestComplete(a-&gt;iClient, a-&gt;iSlaveReqStatus, KErrNone);
       
   186             }
       
   187         }
       
   188 </codeblock> </li>
       
   189 <li id="GUID-9725BAF2-14B1-5CC7-8DE4-46FB3DDF609E"><p>Implement the
       
   190 other cases as conditional statements where the other triggers in <xref href="GUID-5216FF3E-19BA-3862-B188-A3871D7D1BF5.dita"><apiname>TIicBusSlaveTrigger</apiname></xref> are true. In the event of <xref href="GUID-1D10124D-F27E-33C3-B803-FEBDEB2B7964.dita"><apiname>EGeneralBusError</apiname></xref> the callback should simply complete. The
       
   191 other triggers involve buffer underruns and overruns which may require
       
   192 new buffers which the unexpected data can be read from and written
       
   193 to. </p> <ul>
       
   194 <li id="GUID-67BAE1C9-1A2B-524D-B3D0-7E28CC309BDA"><p>Register the
       
   195 new buffers by calling <xref href="GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF.dita#GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF/GUID-E6D971CA-E09C-36B2-92B2-759CC81AF3F1"><apiname>IicBus::RegisterRxBuffer()</apiname></xref> and <xref href="GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF.dita#GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF/GUID-E885DF1D-2192-3BC7-8165-1E5A194ABA28"><apiname>IicBus::RegisterTxBuffer()</apiname></xref> as explained before. </p> </li>
       
   196 <li id="GUID-C6711DE9-F3B1-53F2-B0F9-03B3550F1487"><p>Start data transfer
       
   197 to and from the new buffers by calling <xref href="GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF.dita#GUID-69949E47-8FDF-3651-BEEF-43726EBEB5FF/GUID-8FD1E53D-5C7C-38ED-8B2C-59B4BCF8940B"><apiname>IicBus::SetNotificationTrigger()</apiname></xref> as explained before. </p> <p>The channel is implemented as a state
       
   198 machine as illustrated. The channel starts and finishes in the <codeph>EInactive</codeph> state. During operation it alternates between
       
   199 the two states <codeph>EWaitForClient</codeph> and <codeph>EWaitForMaster</codeph> as the client notifies the channel of new triggers and the channel
       
   200 reacts to them. There is a timer on these two states and the state
       
   201 machine returns to <codeph>EInactive</codeph> either when there are
       
   202 no triggers remaining to be detected or the timers time out. When
       
   203 the client fails to respond on time it enters the state <xref href="GUID-68E03A23-AE1E-3412-B831-7770882B8C2B.dita"><apiname>EClientTimeout</apiname></xref>. </p> </li>
       
   204 </ul> <codeblock id="GUID-73A80A1E-4C07-55DB-AFCF-608B48B68460" xml:space="preserve">
       
   205         if(aTrigger &amp; ETxUnderrun)
       
   206             {
       
   207             TPtr8 txBuf(0, 0);
       
   208 
       
   209             txBuf.Set((TUint8*) a-&gt;iTxBuf.Ptr(), a-&gt;iTxBuf.MaxLength(), a-&gt;iTxBuf.MaxLength());
       
   210 
       
   211    // if there is more data to transmit
       
   212             // use aTxWords as an offset..
       
   213              if(aTxWords + 32 &lt;= KMaxSlaveTestBufferSize)
       
   214                 {
       
   215     // register the next buffer
       
   216                 r = IicBus::RegisterTxBuffer(a-&gt;iChannelId, txBuf, 8, 32, aTxWords);
       
   217     // check it was successful
       
   218                 if (r != KErrNone)
       
   219                     {
       
   220                      Kern::Printf("Error Register Tx Buffer, r %d", r);
       
   221                     }
       
   222                 else
       
   223                     {
       
   224      // set the trigger to transmit the required number of bytes
       
   225                     r = IicBus::SetNotificationTrigger(a-&gt;iChannelId, ETxAllBytes);
       
   226      // check the request was accepted
       
   227                     if (r != KErrNone)
       
   228                         {
       
   229                         Kern::Printf("Error setting notification trigger, r %d", r);
       
   230                         }
       
   231                     }
       
   232 
       
   233                 // updated the buffer - so return..
       
   234                 return;
       
   235                 }
       
   236             }
       
   237 </codeblock> </li>
       
   238 </ul> </li>
       
   239 </ul> <fig id="GUID-2A41FE33-8734-5A13-ACB0-B971E4429C85">
       
   240 <title>              Client state machine 1            </title>
       
   241 <image href="GUID-8A78D678-D1C8-4A4E-9BF1-81C7019815C3_d0e94711_href.png" placement="inline"/>
       
   242 </fig> <fig id="GUID-2178C529-1F08-5504-9C04-C46D59F4951F">
       
   243 <image href="GUID-4CB3C746-606F-4533-8BBB-4A1254A74772_d0e94716_href.png" placement="inline"/>
       
   244 </fig> <fig id="GUID-FB2C9F89-6148-5AE2-A07A-C0D643407044">
       
   245 <title>              Client state machine 3            </title>
       
   246 <image href="GUID-ACC010D4-B419-4CDD-8091-C85579575D46_d0e94724_href.png" placement="inline"/>
       
   247 </fig> </section>
       
   248 </conbody><related-links>
       
   249 <link href="GUID-9986DCC6-EE73-59FB-BDAC-9B09DC64FBCE.dita"><linktext>Client
       
   250 of Master Channel Tutorial</linktext></link>
       
   251 <link href="GUID-B2F86F54-EF50-56DB-ADF7-15325AC9324D.dita"><linktext>IIC
       
   252 Concepts</linktext></link>
       
   253 <link href="GUID-3A30DA16-ECA8-5639-A9DC-6BE2AD55420B.dita"><linktext>I2C
       
   254 Technology Guide</linktext></link>
       
   255 </related-links></concept>