Adaptation/GUID-F20D5802-7B83-5B78-8753-A88E74E28398.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-F20D5802-7B83-5B78-8753-A88E74E28398" xml:lang="en"><title>PSL Implementation</title><shortdesc>This topic describes how to implement the <codeph>DUsbClientController</codeph> interface to provide a platform-specific layer implementation for
       
    13 the USB client controller.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <p>The platform-specific layer only contains functionality that cannot
       
    15 be abstracted and made generic because different USB device controller
       
    16 designs operate differently. For example, the internal (and therefore
       
    17 external) management of the endpoint FIFOs can be different. In some
       
    18 USB device controller designs, the endpoints have hardwired FIFOs
       
    19 of specific sizes, which may possibly be configured, whereas other
       
    20 designs have a defined maximum amount of FIFO RAM available that has
       
    21 to be shared by all endpoints in use in a given configuration. The
       
    22 way that the chip is programmed can also differ. Some designs have
       
    23 a single register into which all commands and their parameters are
       
    24 written, whereas others are programmed via a number of special purpose
       
    25 control registers. </p>
       
    26 <p>Everything else that has to be common because it is defined in
       
    27 the USB specification, is contained in the <i>platform-independent
       
    28 layer</i>. </p>
       
    29 <p>The operation of the USB device controller is hardware specific
       
    30 and the implementers of the platform-specific layer is free to do
       
    31 whatever is necessary to use the hardware. All of this is transparent
       
    32 to the platform-independent layer, which uses only the fixed set of
       
    33 pure virtual functions defined in <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita"><apiname>DUsbClientController</apiname></xref> to communicate with the platform-specific layer, and therefore with
       
    34 the hardware. </p>
       
    35 <p>The platform-specific layer is also responsible for managing the
       
    36 transfer of data over the endpoints, and it is important that it can
       
    37 provide the services expected by the platform-independent layer. Data
       
    38 transfers are normally set up by the platform-independent layer by
       
    39 calling one of the following member functions of <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita"><apiname>DUsbClientController</apiname></xref>: </p>
       
    40 <codeblock id="GUID-34B3EEE2-F83F-5063-9885-5CC0092FB518" xml:space="preserve">TInt SetupEndpointRead(TInt aRealEndpoint, TUsbcRequestCallback&amp; aCallback) = 0;
       
    41 TInt SetupEndpointWrite(TInt aRealEndpoint, TUsbcRequestCallback&amp; aCallback) = 0;
       
    42 TInt SetupEndpointZeroRead() = 0;
       
    43 TInt SetupEndpointZeroWrite(const TUint8* aBuffer, TInt aLength, TBool aZlpReqd=EFalse) = 0;
       
    44 TInt SendEp0ZeroByteStatusPacket() = 0;</codeblock>
       
    45 <p>which the platform-specific layer implements. </p>
       
    46 <p>These data transfer functions fall into two groups: one for handling
       
    47 endpoint-0 and another for handling general endpoints. Endpoint-0
       
    48 is handled differently from general endpoints throughout the USB stack.
       
    49 The functions for handling general endpoints are used to transfer
       
    50 user data. In addition to taking an endpoint number, these functions
       
    51 also take a reference to a <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita"><apiname>TUsbcRequestCallback</apiname></xref> object. This is a request callback, it is key to the data transfer
       
    52 mechanism. </p>
       
    53 <section id="GUID-B9C7FD99-E5D9-5E08-A219-AD1FE89ED139"><title>Reading
       
    54 data</title> <ul>
       
    55 <li id="GUID-96C81B48-9C6A-5EDB-86B3-8F8EC9F94DF0"><p> <xref href="GUID-F20D5802-7B83-5B78-8753-A88E74E28398.dita#GUID-F20D5802-7B83-5B78-8753-A88E74E28398/GUID-4076097E-5FC3-594B-BA00-4A45B78E84CD">General endpoints</xref>  </p> </li>
       
    56 <li id="GUID-260D22D3-5BA7-50A3-B382-D2E5F74CA5D5"><p> <xref href="GUID-F20D5802-7B83-5B78-8753-A88E74E28398.dita#GUID-F20D5802-7B83-5B78-8753-A88E74E28398/GUID-DD28FFFD-9433-57C9-A517-81BA8E001129">Endpoint-0</xref>  </p> </li>
       
    57 </ul> <p id="GUID-4076097E-5FC3-594B-BA00-4A45B78E84CD"><b>General endpoints</b> </p> <p>The platform-independent layer issues a request to read
       
    58 data by calling <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-907F6988-4336-3160-BD41-7FBECE9C6E88"><apiname>DUsbClientController::SetupEndpointRead()</apiname></xref>, which is implemented by the platform-specific layer, passing it
       
    59 the endpoint and a <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita"><apiname>TUsbcRequestCallback</apiname></xref> object. </p> <p>Data is read into a large buffer, whose address and length are
       
    60 passed as data members of the <codeph>TUsbcRequestCallback</codeph> object: <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-B8507E01-B472-3FE6-82E7-281094A491C5"><apiname>TUsbcRequestCallback::iBufferStart</apiname></xref> and <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-565F9CC5-15CE-3AF3-87DD-539737E0E628"><apiname>TUsbcRequestCallback::iLength</apiname></xref> respectively. For Bulk reads,
       
    61 this buffer is intended to catch a burst of data transmitted from
       
    62 the host rather than just a single packet. </p> <p>For all other transfer
       
    63 types (Control, Interrupt, Isochronous) it is usual to return only
       
    64 single packets to the LDD. The amount of data returned is controlled
       
    65 – and limited - by the USB client driver (the LDD) through the <codeph>iLength</codeph> value. </p> <p>The <codeph>TUsbcRequestCallback</codeph> object also supplies a pair of arrays: </p> <ul>
       
    66 <li id="GUID-D1993F45-0E58-5ECA-A845-3B300558759B"><p> <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-843E57D1-4703-3127-B1BE-4C93F1AD54FC"><apiname>TUsbcRequestCallback::iPacketIndex</apiname></xref> containing the offset(s) into the data buffer of the single packet
       
    67 or burst data. </p> </li>
       
    68 <li id="GUID-6A2DDA06-DCB4-5675-AF62-6A9A5226AA2B"><p> <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-2C7B48F0-5A57-3D72-91ED-9FABC99D25EE"><apiname>TUsbcRequestCallback::iPacketSize</apiname></xref> containing the size(s) of the packet or burst data. </p> </li>
       
    69 </ul> <p>These arrays are logically linked; both are the same size
       
    70 and can hold information for two entries each. </p> <p>Therefore,
       
    71 received single packets have to be merged into one 'superpacket' in
       
    72 the read buffer. It is assumed that these merged packets consist of
       
    73 maximum packet sized packets, possibly terminated by a short packet.
       
    74 A zero length packet or ZLP must appear separately; this would be
       
    75 the optional second packet in the respective array. </p> <p>For example,
       
    76 for a Bulk endpoint with a maximum packet size of 64 bytes: </p> <ul>
       
    77 <li id="GUID-65A91C14-FD6C-5FDD-9DDF-9E9A5F11271A"><p>If 10 x 64 byte
       
    78 packets and one 10 byte packet arrive, then these are marked as a
       
    79 single large 650 byte packet. </p> </li>
       
    80 <li id="GUID-AEA01430-333D-5A6E-B32D-017FEF9B93F7"><p>If 10 x 64 byte
       
    81 packets and one ZLP arrive, then these should be entered as two packets
       
    82 in the arrays; one of size 640 bytes and one of size zero. </p> </li>
       
    83 </ul> <p>The general aim when servicing a Bulk read request from the
       
    84 platform-independent layer is to capture as much data as possible
       
    85 whilst not holding onto data too long before returning the data to
       
    86 the LDD and receiving another buffer. There is considerable flexibility
       
    87 in how this is achieved and the design does not mandate any particular
       
    88 method; it also depends to a certain extent on the USB device controller
       
    89 hardware used. </p> <p>The platform implementation can use a re-startable
       
    90 timer to see whether data has been received in the time (usually milliseconds)
       
    91 since the last data was received. If data has been received, then
       
    92 the timer is restarted. If data has not been received, then the timer
       
    93 is not restarted, and the buffer is marked as complete for the platform-independent
       
    94 layer by calling <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-30D6B783-B27B-3ECD-AF34-D22ADF34A12D"><apiname>DUsbClientController::EndpointRequestComplete()</apiname></xref>. </p> <p>Note the following: </p> <ul>
       
    95 <li id="GUID-60992745-5A02-5177-9707-B9DD6F087AE0"><p>In the interrupt
       
    96 service routine (ISR), the flag <codeph>iRxMoreDataRcvd</codeph> is
       
    97 used to indicate that data has been received. </p> </li>
       
    98 <li id="GUID-2B15F54F-66A6-5788-89E9-68D12D3EB8AF"><p>The timer is
       
    99 not restarted in the ISR - the timer is allowed to expire and then
       
   100 a test is made for received data. </p> </li>
       
   101 <li id="GUID-F5FEF7D6-8DD1-5B12-9AF3-2EBBB18F75A4"><p>Typical values
       
   102 for the timer range from 1—5 ms. </p> </li>
       
   103 <li id="GUID-D46B9ABA-5719-5FC3-89F0-3745779F5900"><p>Each OUT endpoint
       
   104 requires a separate timer. </p> </li>
       
   105 <li id="GUID-585E00C0-FE41-5176-8DEF-54C0AD8F55E2"><p>The read is
       
   106 not flagged as complete to the platform-independent layer if no data
       
   107 has been received. The timer is only started once the first packet/transfer
       
   108 has been received. </p> </li>
       
   109 <li id="GUID-62CCCC78-AD45-5570-BC15-050BD4509BC7"><p>The bare minimum
       
   110 of work is done in the ISR. After draining the FIFO, update the <codeph>iPacketSize</codeph> and <codeph>iPacketIndex</codeph> arrays and
       
   111 recalculate the buffer address ready for the next packet, taking into
       
   112 account any alignment restrictions. </p> </li>
       
   113 </ul> <p>The platform-specific layer completes a non endpoint-0 read
       
   114 request by calling the platform-independent layer function <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-30D6B783-B27B-3ECD-AF34-D22ADF34A12D"><apiname>DUsbClientController::EndpointRequestComplete()</apiname></xref>. This function
       
   115 takes as its sole argument a pointer to the updated request callback
       
   116 structure that was initially passed to the platform-specific layer
       
   117 for that read. Members that need to be updated, in addition to the
       
   118 packet arrays <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-843E57D1-4703-3127-B1BE-4C93F1AD54FC"><apiname>TUsbcRequestCallback::iPacketIndex</apiname></xref> and <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-2C7B48F0-5A57-3D72-91ED-9FABC99D25EE"><apiname>TUsbcRequestCallback::iPacketSize</apiname></xref>, are: </p> <ul>
       
   119 <li id="GUID-7EF9E9C2-DE14-5290-B3FE-B91918669AE2"><p> <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-8B2D125B-9943-386F-9A27-11CC1A25A0C2"><apiname>TUsbcRequestCallback::iRxPackets</apiname></xref>, with possible values: 1 or 2. </p> </li>
       
   120 <li id="GUID-9E1800A9-8D39-5D5D-92D0-13AF9CD3EF2A"><p> <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-A00F6B27-655A-3182-96E2-8B3D2404CB7C"><apiname>TUsbcRequestCallback::iError</apiname></xref>  </p> </li>
       
   121 </ul> <p><b>Summary of Completion Criteria for general Endpoints</b> </p> <p>The platform-specific layer completes a read request by calling <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-30D6B783-B27B-3ECD-AF34-D22ADF34A12D"><apiname>DUsbClientController::EndpointRequestComplete()</apiname></xref> when any
       
   122 of the following conditions are met: </p> <ul>
       
   123 <li id="GUID-F66AF5EC-56D4-5133-A930-2BB793478B31"><p>The requested
       
   124 number of bytes has been received. </p> </li>
       
   125 <li id="GUID-91D9D4E4-2196-55C9-9595-1BA6AE2C2848"><p>A short packet,
       
   126 including a ZLP, is received. In the case of a ZLP being received,
       
   127 it must be represented separately in the <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-E5FD5F91-B22B-31A9-8482-635B2F1EB0B4"><apiname>DUsbClientController::iPacketIndex</apiname></xref> and <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-BFB565F1-C8F9-3E44-88FB-E81E88D2DF3A"><apiname>DUsbClientController::iPacketSize</apiname></xref> arrays. </p> </li>
       
   128 <li id="GUID-42124450-1AC8-59F3-9C30-8C74EC425CAE"><p>If the number
       
   129 of bytes in the current packet (still in the FIFO) were to cause the
       
   130 total number of bytes to exceed the buffer length <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-A0A7399A-A51E-3544-A181-5C45B69AB121"><apiname>DUsbClientController::iLength</apiname></xref>. </p> </li>
       
   131 <li id="GUID-09281AB5-7240-5B29-B0C1-C5A4A8289B7F"><p>The timer has
       
   132 expired, data is available, but no further packets have been received. </p> </li>
       
   133 </ul> <p id="GUID-DD28FFFD-9433-57C9-A517-81BA8E001129"><b>Endpoint-0</b> </p> <p>The handling of endpoint-0 read requests is similar to general
       
   134 endpoints except for the following: </p> <ul>
       
   135 <li id="GUID-D9361990-1591-522E-9F9E-7E38A6EB0B08"><p>The platform-independent
       
   136 layer issues the request by calling <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-B3B4793E-7B75-3C40-A6FA-CD17B460CC73"><apiname>DUsbClientController::SetupEndpointZeroRead()</apiname></xref>. This function does not take any parameters because: </p> <ul>
       
   137 <li id="GUID-4AED5324-65B5-5BD3-AACA-5EA9FB7CB90A"><p>The endpoint
       
   138 number is known, this is zero. </p> </li>
       
   139 <li id="GUID-9CEAFC92-DF2D-5B07-B623-5BA562EC61BE"><p>The request
       
   140 is completed after every received packet, and a <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita"><apiname>TUsbcRequestCallback</apiname></xref> object is not needed. </p> </li>
       
   141 </ul> </li>
       
   142 </ul> <p>All the platform-specific layer needs to know is where to
       
   143 place the received data, and its size. Both are fixed values: <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-BC2DF410-292B-354A-BCEF-2C9E520024B8"><apiname>DUsbClientController::iEp0_RxBuf</apiname></xref> and <xref href="GUID-D0DFABCF-15B4-347E-BAE5-0F050E137949.dita"><apiname>KUsbcBufSzControl</apiname></xref> respectively. </p> <p>An endpoint-0 read request is completed by
       
   144 calling <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-71E33976-C185-34FA-A8BF-7DB3404DDA78"><apiname>DUsbClientController::Ep0RequestComplete()</apiname></xref>, passing the endpoint number (0, or symbolically, <codeph>KEp0_Out</codeph>), the number of bytes received, and the resulting error code for
       
   145 this request. </p> </section>
       
   146 <section id="GUID-2617EDBD-6792-53B9-9CE0-6B0CC729728C"><title>Writing
       
   147 data</title> <ul>
       
   148 <li id="GUID-97BDD391-F5BE-509C-AF67-51AD4822FD11"><p> <xref href="GUID-F20D5802-7B83-5B78-8753-A88E74E28398.dita#GUID-F20D5802-7B83-5B78-8753-A88E74E28398/GUID-69839EA3-9DC0-5A3C-BE62-AC91708477BA">General endpoints</xref>  </p> </li>
       
   149 <li id="GUID-8E0F6F8F-D3DA-5E67-8E8C-E4BE983DBF1A"><p> <xref href="GUID-F20D5802-7B83-5B78-8753-A88E74E28398.dita#GUID-F20D5802-7B83-5B78-8753-A88E74E28398/GUID-C674608C-393B-5397-A1E4-3C8368E2144C">Endpoint-0</xref>  </p> </li>
       
   150 </ul> <p id="GUID-69839EA3-9DC0-5A3C-BE62-AC91708477BA"><b>General endpoints</b> </p> <p>The platform-independent layer issues a request to write
       
   151 data by calling <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-F7880D1C-7E7D-3214-BF84-8811DA935B0C"><apiname>DUsbClientController::SetupEndpointWrite()</apiname></xref>, which is implemented by the platform-specific layer, passing the
       
   152 function an endpoint and a <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita"><apiname>TUsbcRequestCallback</apiname></xref> object. </p> <p>The address of the buffer, containing the data to
       
   153 be written, is passed into the data member <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-B8507E01-B472-3FE6-82E7-281094A491C5"><apiname>TUsbcRequestCallback::iBufferStart</apiname></xref>. The length of this buffer is passed into <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-565F9CC5-15CE-3AF3-87DD-539737E0E628"><apiname>TUsbcRequestCallback::iLength</apiname></xref>. The buffer is a single contiguous piece of memory. </p> <p>The
       
   154 platform-specific layer's implementation needs to set up the transfer,
       
   155 either using DMA or a conventional interrupt driven mechanism, and
       
   156 then wait for the host to collect, by sending an IN token, the data
       
   157 from the respective endpoint’s primed FIFO. This continues until all
       
   158 data from the buffer has been transmitted to the host. </p> <p>If
       
   159 the ZLP request flag <codeph>iZlpReqd</codeph> in the <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita"><apiname>TUsbcRequestCallback</apiname></xref> structure is set (=<xref href="GUID-781E8158-805B-3784-8FED-D7A191822FC3.dita"><apiname>ETrue</apiname></xref>), then the platform
       
   160 specific layer must determine, after all data has been sent, whether
       
   161 to send a ZLP or not. The decision is based on the size of the last
       
   162 packet sent and the current maximum packet size of the endpoint. </p> <p>To summarize, a ZLP should be sent at the end of a write request
       
   163 if: </p> <ul>
       
   164 <li id="GUID-B3AFEC6D-EB74-57FE-9618-E44C6AE10460"><p>The ZLP flag
       
   165 is set. </p> </li>
       
   166 <li id="GUID-970EE707-24D1-53B8-A830-3824562F2AA8"><p>The last packet
       
   167 of the write request was not a short packet (i.e. it was a max-packet-sized
       
   168 packet). </p> </li>
       
   169 </ul> <p>The platform-specific layer completes a non endpoint-0 write
       
   170 request by calling the platform-independent layer function <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-30D6B783-B27B-3ECD-AF34-D22ADF34A12D"><apiname>DUsbClientController::EndpointRequestComplete()</apiname></xref>. This function
       
   171 takes only one argument, a pointer to the updated request callback
       
   172 structure passed to the platform-specific layer for this write. Members
       
   173 that need to be updated are: </p> <ul>
       
   174 <li id="GUID-F02F662E-ABAE-5519-A80C-DA4D66F7A51A"><p> <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-31AF87D2-C1F3-3367-93AA-52924612A7D0"><apiname>TUsbcRequestCallback::iTxBytes</apiname></xref>  </p> </li>
       
   175 <li id="GUID-D8416C51-7A46-560F-9F6F-2565DA445004"><p> <xref href="GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F.dita#GUID-D395BF82-65B3-3A98-800B-E6EF43150E8F/GUID-A00F6B27-655A-3182-96E2-8B3D2404CB7C"><apiname>TUsbcRequestCallback::iError</apiname></xref>  </p> </li>
       
   176 </ul> <p id="GUID-C674608C-393B-5397-A1E4-3C8368E2144C"><b>Endpoint-0</b> </p> <p>The handling of endpoint-0 write requests is similar to general
       
   177 endpoints except for the following: </p> <p>The platform-independent
       
   178 layer issues the request by calling <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-DBE7AC29-8B85-3D98-BAF9-8EF059B33331"><apiname>DUsbClientController::SetupEndpointZeroWrite()</apiname></xref>. Unlike the equivalent read function, this function takes a number
       
   179 of parameters: </p> <ul>
       
   180 <li id="GUID-9831D5A3-2032-5C6C-B2AF-C78D9E00D09C"><p>the address
       
   181 of the location containing the data to be written </p> </li>
       
   182 <li id="GUID-C7F55C63-4AD4-5A37-B25B-1249850C5A92"><p>the length of
       
   183 the data to be written </p> </li>
       
   184 <li id="GUID-C2D21E5A-6FB9-5170-80F2-6B6351E5B11A"><p>a <xref href="GUID-4B942C06-1BAC-3A21-B3B1-89FB5C51ADA0.dita"><apiname>TBool</apiname></xref> parameter that indicates whether a zero length packet (ZLP) is to
       
   185 be sent immediately after the data has been sent. </p> </li>
       
   186 </ul> <p>An endpoint-0 write request is completed by calling <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-71E33976-C185-34FA-A8BF-7DB3404DDA78"><apiname>DUsbClientController::Ep0RequestComplete()</apiname></xref>, in the platform-independent
       
   187 layer, passing the function the endpoint number (0, or symbolically <codeph>KEp0_In</codeph>), the number of bytes written, and the error code
       
   188 for this write request. </p> <p>There is another endpoint-0 write
       
   189 function, <xref href="GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941.dita#GUID-82FA9C04-0B7E-3FAD-9AAD-3A68E1E6A941/GUID-95CCCE69-C8AA-39B1-8152-37AA0A7B9CEB"><apiname>DUsbClientController::SendEp0ZeroByteStatusPacket()</apiname></xref>, which is used for sending a zero length packet (ZLP) on its own.
       
   190 This separate function is provided because the USB device controller
       
   191 mechanism for transmitting a ZLP on its own can be different to the
       
   192 mechanism for transmitting the ZLP at the end of a data transmission. </p> </section>
       
   193 <section id="GUID-0805DDC6-2C17-50A2-97B6-F51C77DF3E4F"><title>Using
       
   194 DMA</title> <p>When planning to use DMA for transferring data from
       
   195 and to the endpoints’ FIFOs, there are two things that must be considered: </p> <ul>
       
   196 <li id="GUID-0E6B3A5B-CA84-5BB1-9447-70C7E493D8D2"><p> <xref href="GUID-F20D5802-7B83-5B78-8753-A88E74E28398.dita#GUID-F20D5802-7B83-5B78-8753-A88E74E28398/GUID-838483AC-BDDD-5A6A-AB8A-F26587851D9E">Flushing cached information for the data buffers</xref>  </p> </li>
       
   197 <li id="GUID-B9545262-93E4-5AA9-837F-D909B278B19F"><p> <xref href="GUID-F20D5802-7B83-5B78-8753-A88E74E28398.dita#GUID-F20D5802-7B83-5B78-8753-A88E74E28398/GUID-840EB8C0-8C29-5FDE-9505-D6D7131E61A4">Implementing DMA mode for OUT transfers (DMA reads)</xref>  </p> </li>
       
   198 </ul> <p id="GUID-838483AC-BDDD-5A6A-AB8A-F26587851D9E"><b>Flushing cached
       
   199 information for the data buffers</b> </p> <p>The cached information
       
   200 for the data buffers must be flushed before a DMA write operation,
       
   201 (i.e. transfer memory to a FIFO), and both before and after a DMA
       
   202 read operation, (i.e. transfer a FIFO to memory). </p> <p>The kernel
       
   203 provides three functions for that purpose. These are static functions
       
   204 in the class <xref href="GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F.dita"><apiname>Cache</apiname></xref>, declared in <filepath>...\e32\include\kernel\cache.h</filepath>: </p> <ul>
       
   205 <li id="GUID-4402C336-1638-5830-90A8-0A9746BC3CC7"><p> <xref href="GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F.dita#GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F/GUID-5F08DEAA-1237-32DE-AE41-CE7B18230972"><apiname>Cache::SyncMemoryBeforeDmaWrite()</apiname></xref>  </p> </li>
       
   206 <li id="GUID-BD880077-FF37-5604-BECF-EB4D86803EB4"><p> <xref href="GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F.dita#GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F/GUID-3FF3C567-C1BD-3D4E-97E1-B036456A374E"><apiname>Cache::SyncMemoryBeforeDmaRead()</apiname></xref>  </p> </li>
       
   207 <li id="GUID-49E1143C-2B5C-5E92-8ED8-66F75EB41D69"><p> <xref href="GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F.dita#GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F/GUID-78E6DE46-61F0-3840-B555-6926D21141BF"><apiname>Cache::SyncMemoryAfterDmaRead()</apiname></xref>  </p> </li>
       
   208 </ul> <p id="GUID-840EB8C0-8C29-5FDE-9505-D6D7131E61A4"><b>Implementing DMA
       
   209 mode for OUT transfers (DMA reads)</b> </p> <p>The implementation
       
   210 of DMA mode for IN transfers is normally relatively straightforward,
       
   211 however complications can occur with OUT transfers (DMA reads), depending
       
   212 on the DMA controller, the USB device controller and the way the two
       
   213 are connected. </p> <p>There are two issues: </p> <ol id="GUID-324F21A0-F3EB-5994-B23C-B0AD18973C2B">
       
   214 <li id="GUID-7513B814-D305-50A0-B18D-779D8F5B741E"><p>If we set up
       
   215 a DMA read for 4kB, for example, and this request returns after a
       
   216 short packet, we must be able to tell how much data has been received
       
   217 and is now in our buffer. In other words, the DMA controller must
       
   218 provide a way of finding out how many bytes have been received, otherwise
       
   219 we cannot complete the read request to the LDD. </p> <p>Here is a
       
   220 theoretical solution for a Scatter/Gather controller that doesn’t
       
   221 provide information about the number of bytes transferred directly. <b>Note: </b> This proposal has not been tested in practice! </p> <p>Instead of using one large DMA descriptor for 4kB, we could set up
       
   222 a chain of descriptors for max-packet-size bytes each. When the DMA
       
   223 completes, it will be: </p> <ul>
       
   224 <li id="GUID-B088943E-BEC6-568B-8E0E-7AA177566599"><p>for the whole
       
   225 transfer, in which case we know the number of bytes received. </p> </li>
       
   226 <li id="GUID-33974049-2069-57A3-A784-4A312BA846D8"><p>because it is
       
   227 a short packet. In this case we can try and find out which descriptor
       
   228 was being served at the time. The number of bytes received is then </p> <codeblock id="GUID-56C3A794-4077-5A83-BA17-E6BE58A675D4" xml:space="preserve">number of completed descriptors * max-packet-size + number of bytes in short packet.</codeblock> </li>
       
   229 </ul> </li>
       
   230 <li id="GUID-E7406164-A6C4-5508-AD5D-A8DA4F2E4AAC"><p>Another potential
       
   231 problem is posed by the restartable OUT endpoint timer described in
       
   232 the section <xref href="GUID-F20D5802-7B83-5B78-8753-A88E74E28398.dita#GUID-F20D5802-7B83-5B78-8753-A88E74E28398/GUID-B9C7FD99-E5D9-5E08-A219-AD1FE89ED139">Reading data</xref>. The situation in the timer callback DFC, when
       
   233 the LDD read request is about to complete, has to be handled with
       
   234 care in order to avoid data loss. If at this point the pending DMA
       
   235 request has already started transferring data from the endpoint FIFO
       
   236 into our data buffer, then we cannot complete the LDD request anymore
       
   237 (this data would be lost because the LDD would not know about it as
       
   238 the variables in the request structure do not take account of it).
       
   239 The buffer cannot be removed while it is receiving data from a DMA
       
   240 transfer. A possible solution would be as follows: (again, this is
       
   241 just an idea and therefore untested). In the timer DFC, before we
       
   242 complete to the LDD, we cancel the pending DMA request. If a DMA transfer
       
   243 was already happening, then this will somehow complete and the DMA
       
   244 complete DFC will be queued. What we need to find out in that situation
       
   245 is whether or not that DFC is pending: </p> <ul>
       
   246 <li id="GUID-EA31A9E0-5783-5E3C-BFAF-AE041FBC61F1"><p>if not, then
       
   247 there was no DMA transfer ongoing, and we can just complete our read
       
   248 request to the LDD. </p> </li>
       
   249 <li id="GUID-E971CEC8-B0EA-5924-83A6-6FF4E4EB8C9E"><p>otherwise we
       
   250 have to abandon, at this point, the plan to complete and return from
       
   251 the timer callback (without doing any damage). In this case, the DMA
       
   252 complete DFC will run next, the LDD read request structure will be
       
   253 updated, the RX timer will be set again, and we can proceed as normal. </p> </li>
       
   254 </ul> </li>
       
   255 </ol> </section>
       
   256 </conbody></concept>