Adaptation/GUID-FA026EBD-7867-4A2C-9FA4-EC70A5243526.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 task
       
    11   PUBLIC "-//OASIS//DTD DITA Task//EN" "task.dtd">
       
    12 <task id="GUID-FA026EBD-7867-4A2C-9FA4-EC70A5243526" xml:lang="en"><title>Transferring Data with DMA</title><shortdesc>Explains how to transfer data using DMA.</shortdesc><prolog><metadata><keywords/></metadata></prolog><taskbody>
       
    13 <prereq id="GUID-FCC97364-77B5-4AB9-AEBD-0F63500A522D"><p>The client
       
    14 will typically have a DMA class containing pointers to:</p><ul>
       
    15 <li><p>a <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> object, </p> </li>
       
    16 <li><p>one or more <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita"><apiname>DDmaRequest</apiname></xref> objects, </p></li>
       
    17 <li><p>a <xref href="GUID-E675237D-0D05-30A3-9B82-DDD3D0F41E79.dita"><apiname>TDfcQueue</apiname></xref> object, and</p></li>
       
    18 <li><p>a callback which returns when the data transfer completes (successfully
       
    19 or not).</p></li>
       
    20 </ul><p>These classes are discussed in <xref href="GUID-D5ED62EB-744D-42EB-B8CF-D5623BDA5B38.dita">DMA OS Interface</xref>.</p></prereq>
       
    21 <context id="GUID-EAC78622-0692-4FBE-81FE-553F838A77DD"><p>To allow
       
    22 a client application to receive or transmit a block of data by DMA
       
    23 you set up a transfer between a source or a destination buffer and
       
    24 a source or a destination peripheral. Data is copied between the client
       
    25 process and kernel memory by IPC form data transfer between two buffers.
       
    26 When a shared chunk or a shared data buffer is used, copying of data
       
    27 to kernel memory is required. At the level of implementation there
       
    28 is no difference between receiving and transmitting. Client drivers
       
    29 using DMA sometimes have separate receive and transmit functions defined
       
    30 from the driver point of view.</p><p>You transfer data in this sequence:</p><ul>
       
    31 <li><p>Open a DMA channel.</p></li>
       
    32 <li><p>Fragment the data if necessary.</p></li>
       
    33 <li><p>Queue the transfer.</p></li>
       
    34 <li><p>Close the channel.</p></li>
       
    35 </ul><p>Example code in this tutorial is taken from the <xref href="GUID-8CC3B265-C29E-3FDB-ACE8-ACC49B9E69D5.dita"><apiname>DMemoryCardDma</apiname></xref> class which transfers data to and from MMC cards by DMA.</p></context>
       
    36 <steps id="GUID-4DD07DEC-6017-4237-BE46-1D69E5FBD744-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-7-1-3-3">
       
    37 <step id="GUID-9A69E5AD-E938-4092-A8C2-CB65C37C8962-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-7-1-3-3-1"><cmd>Initialize
       
    38 the client object by allocating a request and setting buffers.</cmd>
       
    39 <info><codeblock xml:space="preserve">     //pre-allocate space for DDmaRequest
       
    40      iDMARequest = (DDmaRequest*)Kern::AllocZ(sizeof(DDmaRequest));       
       
    41  
       
    42      // Check Buffer Length
       
    43      if (aBuffLen)
       
    44          {
       
    45          // Set Buffer Start
       
    46          iBufferStart = (TUint32)aBuffer;
       
    47          // Set Buffer End
       
    48          iBufferEnd   = iBufferStart + aBuffLen;
       
    49          // Set DFC Queue
       
    50          iDfcQue      = aDfcQue;
       
    51  
       
    52          return KErrNone;
       
    53          }
       
    54 </codeblock></info>
       
    55 <stepresult>The client object is now initialized.</stepresult>
       
    56 </step>
       
    57 <step id="GUID-9A69E5AD-E938-4092-A8C2-CB65C37C8962-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-7-1-3-3-2"><cmd>Open the
       
    58 channel by creating an <xref href="GUID-4057074E-2543-3F01-B24A-7FF8A19F79AF.dita"><apiname>SCreateInfo</apiname></xref> object and initializing
       
    59 it as follows:</cmd>
       
    60 <substeps id="GUID-53B21565-D779-4B76-A8BA-8C9059CB15B4">
       
    61 <substep id="GUID-3620E00A-FDE2-4EA3-9FB2-9D67AD0370AC"><cmd>Set the <xref href="GUID-B05C7976-F917-3CFC-9979-86FAC864CB4E.dita"><apiname>iCookie</apiname></xref> member to a platform specific channel identifier.</cmd>
       
    62 </substep>
       
    63 <substep id="GUID-1890DE64-D53B-4003-9419-ECC778D663FB"><cmd>Set the <xref href="GUID-84246C3A-C8C9-3839-B8C1-8BF05C826338.dita"><apiname>iDesCount</apiname></xref> member to the number of descriptors the channel
       
    64 can use.</cmd>
       
    65 <info><p>The value should be set to a value based on number of simultaneous
       
    66 transfers, transfer length and type of memory used for transfer. If
       
    67 you select too high a value, no descriptors will be left for other
       
    68 clients, and if you select too low a value the transfer may fail. </p></info>
       
    69 </substep>
       
    70 <substep id="GUID-FF5BB11D-C922-47A1-ADB8-1A7321C0931F"><cmd>Set the <xref href="GUID-D9C831A3-4841-3E4F-BFEC-8D3997BEEFFF.dita"><apiname>iDfcPriority</apiname></xref> member to the DFC priority. </cmd>
       
    71 </substep>
       
    72 <substep id="GUID-F1D4A3C1-6E81-4FA4-99D0-E127FCD2C004"><cmd>Set the <xref href="GUID-EC191BDB-5C89-3359-9C45-748C96EF08C1.dita"><apiname>iDfcQueue</apiname></xref> member to the client class queue: it will be
       
    73 used to service transfer completion events.</cmd>
       
    74 </substep>
       
    75 </substeps>
       
    76 <stepxmp><codeblock xml:space="preserve">     // Open and configure the channel
       
    77      if (!iDMAChannelOpen)
       
    78          {
       
    79          if (!iDfcQue)
       
    80              return KErrGeneral;
       
    81  
       
    82          TDmaChannel::SCreateInfo info;
       
    83  
       
    84          info.iCookie = (TUint32)iChannelId;
       
    85          info.iDesCount = 3;
       
    86          info.iDfcPriority = 3;
       
    87          info.iDfcQ = iDfcQue;
       
    88  
       
    89 </codeblock></stepxmp>
       
    90 <stepresult>The channel is now initialized.</stepresult>
       
    91 </step>
       
    92 <step id="GUID-9A69E5AD-E938-4092-A8C2-CB65C37C8962-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-7-1-3-3-3"><cmd>Pass the <xref href="GUID-4057074E-2543-3F01-B24A-7FF8A19F79AF.dita"><apiname>SCreateInfo</apiname></xref> object and a channel ID to the <xref href="GUID-20D0D10F-3401-3F72-8AF6-DC35F6025DC2.dita"><apiname>Open()</apiname></xref> function of <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> to open a DMA channel.</cmd>
       
    93 <info><p> This is not necessary if the channel is already open due
       
    94 to a previous transfer request by the same application on the same
       
    95 channel.</p></info>
       
    96 <stepxmp><codeblock xml:space="preserve">         // Open DMA Channel
       
    97          r = TDmaChannel::Open(info, iDMAChannel);
       
    98  
       
    99          if (r)
       
   100              return r;
       
   101  
       
   102          // Set DMA Channel Open
       
   103          iDMAChannelOpen = ETrue;
       
   104 </codeblock></stepxmp>
       
   105 <info>At what point you open the channel depends on platform configuration.
       
   106 If a channel is dedicated to a particular function such as USB, it
       
   107 is typically opened by the channel constructor method and closed by
       
   108 the destructor as there is never any contention for it. In other cases,
       
   109 you must open the channel at the start of a transfer and close it
       
   110 at the end.</info>
       
   111 <stepresult>The channel is now open.</stepresult>
       
   112 </step>
       
   113 <step id="GUID-9A69E5AD-E938-4092-A8C2-CB65C37C8962-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-7-1-3-3-4"><cmd>Call the <xref href="GUID-27816E89-D612-30BE-BC4B-50B892223918.dita"><apiname>Fragment()</apiname></xref> function of <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita"><apiname>DDmaRequest</apiname></xref> to
       
   114 fragment the data.</cmd>
       
   115 <info>:If your buffers are cacheable you must flush them before a
       
   116 write transfer and both before and after a read transfer, using these
       
   117 functions of the <xref href="GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F.dita"><apiname>Cache</apiname></xref> class:<ul>
       
   118 <li><p><codeph>Cache::SyncMemoryBeforeDmaWrite()</codeph> (takes source
       
   119 buffer as argument)</p></li>
       
   120 <li><p><codeph>Cache::SyncMemoryBeforeDmaRead()</codeph> (takes destination
       
   121 buffer as argument)</p></li>
       
   122 <li><p><codeph>Cache::SyncMemoryAfterDmaRead()</codeph> (takes destination
       
   123 buffer as argument)</p></li>
       
   124 </ul></info>
       
   125 <stepresult>The data is now fragmented.</stepresult>
       
   126 </step>
       
   127 <step id="GUID-99DC4339-5C3E-42AC-BE71-5FED662A6C3A"><cmd>Call the <xref href="GUID-78F37FB6-1286-39CD-80A5-24DA9F27A9AF.dita"><apiname>Queue()</apiname></xref> function of <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> to queue
       
   128 the data on the channel.</cmd>
       
   129 <stepxmp><codeblock xml:space="preserve">     TInt retval = KErrNone;
       
   130  
       
   131      if (iDMABusy)
       
   132          {
       
   133          if (iDMAChannel)
       
   134              {
       
   135              iDMAChannel-&gt;CancelAll();
       
   136              }
       
   137          }
       
   138  
       
   139      iDMABusy = ETrue;
       
   140  
       
   141      iDMAReadStarted = EFalse;
       
   142  
       
   143      if (!iDMAChannelOpen)
       
   144          {
       
   145           retval = Open();
       
   146          }
       
   147  
       
   148      if (iDMAChannelOpen)
       
   149          {
       
   150          iDMADestination = aDest;
       
   151          iDMACount       = aCount;
       
   152  
       
   153          // aDest cached, ivalidate RAM
       
   154          Cache::SyncMemoryBeforeDmaRead(aDest, aCount);
       
   155          retval = iDMARequest ? iDMARequest-&gt;Fragment(EDmaSDMMC, aDest, aCount, KDmaMemDest | KDmaIncDest, 0 /* no HW Flags*/) : KErrGeneral;
       
   156  
       
   157          if (retval)
       
   158              {
       
   159             return retval;
       
   160              }
       
   161  
       
   162          iDMAReadStarted = ETrue;
       
   163          if (iDMARequest)
       
   164              {
       
   165              iDMARequest-&gt;Queue();
       
   166              }
       
   167          }
       
   168 </codeblock></stepxmp>
       
   169 <stepresult><p>The data is now queued on the channel.</p></stepresult>
       
   170 </step>
       
   171 <step id="GUID-DA024D3E-F088-4BEC-BC20-DD467D11928F"><cmd>Close the
       
   172 channel. First check whether the channel is busy and take appropriate
       
   173 action if it is (in the following example code you cancel all pending
       
   174 transfers). Then call the <xref href="GUID-01D2AF56-21E1-3FF3-BF86-0C356A1658EF.dita"><apiname>Close()</apiname></xref> function of <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref>.</cmd>
       
   175 <stepxmp><codeblock xml:space="preserve">    if (iDMAChannelOpen &amp;&amp; iDMAChannel &amp;&amp; !iDMABusy)
       
   176          {
       
   177          iDMAChannel-&gt;CancelAll();
       
   178          iDMARequestsCount = 0;      // All DMA requests have been now canceled!
       
   179  
       
   180          if (iDMARequest)
       
   181              {
       
   182              //just call destructor explicitly and the object can reused
       
   183              iDMARequest-&gt;~DDmaRequest();
       
   184              }
       
   185 			...
       
   186          iDMAChannel-&gt;Close();
       
   187 </codeblock></stepxmp>
       
   188 <stepresult><p>The channel is now closed.</p></stepresult>
       
   189 </step>
       
   190 </steps>
       
   191 <result id="GUID-7BF6DAFD-2B40-4F3F-889D-F8FDDEFF091C"><p>You have
       
   192 now conducted a data transfer by DMA.</p></result>
       
   193 </taskbody></task>