SAMV71 Xplained Ultra Software Package 1.5

hal_udphs.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /**
00031 
00032  \file
00033 
00034  \section Purpose
00035 
00036     Implementation of USB device functions on a UDP controller.
00037 
00038     See \ref usbd_api_method USBD API Methods.
00039 */
00040 
00041 /** \addtogroup usbd_hal
00042  *@{*/
00043 
00044 /*---------------------------------------------------------------------------
00045  *      Headers
00046  *---------------------------------------------------------------------------*/
00047 
00048 #include "chip.h"
00049 #include "USBD_HAL.h"
00050 
00051 #include <stdbool.h>
00052 #include <stdint.h>
00053 #include <stdio.h>
00054 #include <string.h>
00055 
00056 /*---------------------------------------------------------------------------
00057  *      Definitions
00058  *---------------------------------------------------------------------------*/
00059 
00060 #define DMA
00061 
00062 /** Maximum number of endpoints interrupts. */
00063 #define NUM_IT_MAX       \
00064     (UDPHS->UDPHS_IPFEATURES & UDPHS_IPFEATURES_EPT_NBR_MAX_Msk)
00065 /** Maximum number of endpoint DMA interrupts */
00066 #define NUM_IT_MAX_DMA   \
00067     ((UDPHS->UDPHS_IPFEATURES \
00068         & UDPHS_IPFEATURES_DMA_CHANNEL_NBR_Msk) \
00069       >>UDPHS_IPFEATURES_DMA_CHANNEL_NBR_Pos)
00070 /** Bits that should be shifted to access DMA control bits. */
00071 #define SHIFT_DMA        24
00072 /** Bits that should be shifted to access interrupt bits. */
00073 #define SHIFT_INTERUPT    8
00074 
00075 /** Max size of the FMA FIFO */
00076 #define DMA_MAX_FIFO_SIZE     (65536/1)
00077 /** fifo space size in DW */
00078 #define EPT_VIRTUAL_SIZE      16384
00079 
00080 /**
00081  * \section endpoint_states_sec "UDP Endpoint states"
00082  *
00083  *  This page lists the endpoint states.
00084  *
00085  *  \subsection States
00086  *  - UDPHS_ENDPOINT_DISABLED
00087  *  - UDPHS_ENDPOINT_HALTED
00088  *  - UDPHS_ENDPOINT_IDLE
00089  *  - UDPHS_ENDPOINT_SENDING
00090  *  - UDPHS_ENDPOINT_RECEIVING
00091  *  - UDPHS_ENDPOINT_SENDINGM
00092  *  - UDPHS_ENDPOINT_RECEIVINGM
00093  */
00094 
00095 /**  Endpoint states: Endpoint is disabled */
00096 #define UDPHS_ENDPOINT_DISABLED       0
00097 /**  Endpoint states: Endpoint is halted (i.e. STALLs every request) */
00098 #define UDPHS_ENDPOINT_HALTED         1
00099 /**  Endpoint states: Endpoint is idle (i.e. ready for transmission) */
00100 #define UDPHS_ENDPOINT_IDLE           2
00101 /**  Endpoint states: Endpoint is sending data */
00102 #define UDPHS_ENDPOINT_SENDING        3
00103 /**  Endpoint states: Endpoint is receiving data */
00104 #define UDPHS_ENDPOINT_RECEIVING      4
00105 /**  Endpoint states: Endpoint is sending MBL */
00106 #define UDPHS_ENDPOINT_SENDINGM       5
00107 /**  Endpoint states: Endpoint is receiving MBL */
00108 #define UDPHS_ENDPOINT_RECEIVINGM     6
00109 
00110 /** Get Number of buffer in Multi-Buffer-List
00111  *  \param i    input index
00112  *  \param o    output index
00113  *  \param size list size
00114  */
00115 #define MBL_NbBuffer(i, o, size) (((i)>(o))?((i)-(o)):((i)+(size)-(o)))
00116 
00117 /** Buffer list is full */
00118 #define MBL_FULL        1
00119 /** Buffer list is null */
00120 #define MBL_NULL        2
00121 
00122 /*---------------------------------------------------------------------------
00123  *      Types
00124  *---------------------------------------------------------------------------*/
00125 
00126 /**  Describes header for UDP endpoint transfer. */
00127 typedef struct {
00128     /**  Optional callback to invoke when the transfer completes. */
00129     void*   fCallback;
00130     /**  Optional argument to the callback function. */
00131     void*   pArgument;
00132     /**  Transfer type */
00133     uint8_t transType;
00134     /* Reserved to 32-b aligned */
00135     uint8_t reserved[3];
00136 } TransferHeader;
00137 
00138 /**  Describes a transfer on a UDP endpoint. */
00139 typedef struct {
00140 
00141     /**  Optional callback to invoke when the transfer completes. */
00142     TransferCallback fCallback;
00143     /**  Optional argument to the callback function. */
00144     void             *pArgument;
00145     /**  Transfer type */
00146     uint8_t          transType;
00147     uint8_t          reserved[3];
00148     /**  Number of bytes which have been written into the UDP internal FIFO
00149      *   buffers. */
00150     int32_t          buffered;
00151     /**  Pointer to a data buffer used for emission/reception. */
00152     uint8_t          *pData;
00153     /**  Number of bytes which have been sent/received. */
00154     int32_t          transferred;
00155     /**  Number of bytes which have not been buffered/transferred yet. */
00156     int32_t          remaining;
00157 } Transfer;
00158 
00159 /**  Describes Multi Buffer List transfer on a UDP endpoint. */
00160 typedef struct {
00161     /**  Optional callback to invoke when the transfer completes. */
00162     MblTransferCallback fCallback;
00163     /**  Optional argument to the callback function. */
00164     void                *pArgument;
00165     /** Transfer type */
00166     uint8_t             transType;
00167     /** List state (OK, FULL, NULL) (run time) */
00168     uint8_t             listState;
00169     /**  Multi-Buffer List size */
00170     uint16_t            listSize;
00171     /**  Pointer to multi-buffer list */
00172     USBDTransferBuffer *pMbl;
00173     /**  Offset number of buffers to start transfer */
00174     uint16_t            offsetSize;
00175     /**  Current processing buffer index (run time) */
00176     uint16_t            outCurr;
00177     /**  Loast loaded buffer index (run time) */
00178     uint16_t            outLast;
00179     /**  Current buffer for input (run time) */
00180     uint16_t            inCurr;
00181 } MblTransfer;
00182 
00183 /**
00184  *  Describes the state of an endpoint of the UDP controller.
00185  */
00186 typedef struct {
00187 
00188     /* CSR */
00189     /**  Current endpoint state. */
00190     volatile uint8_t  state;
00191     /**  Current reception bank (0 or 1). */
00192     volatile uint8_t  bank;
00193     /**  Maximum packet size for the endpoint. */
00194     volatile uint16_t size;
00195     /**  Describes an ongoing transfer (if current state is either
00196      *   UDPHS_ENDPOINT_SENDING or UDPHS_ENDPOINT_RECEIVING) */
00197     union {
00198         TransferHeader transHdr;
00199         Transfer       singleTransfer;
00200         MblTransfer    mblTransfer;
00201     } transfer;
00202     /** Special case for send a ZLP */
00203     uint32_t sendZLP;
00204 } Endpoint;
00205 
00206 /**
00207  * DMA Descriptor.
00208  */
00209 typedef struct {
00210     void    *pNxtDesc;
00211     void    *pAddr;
00212     uint32_t dwCtrl;
00213     uint32_t dw;
00214 } UdphsDmaDescriptor;
00215 
00216 /*---------------------------------------------------------------------------
00217  *      Internal variables
00218  *---------------------------------------------------------------------------*/
00219 
00220 /** Holds the internal state for each endpoint of the UDP. */
00221 static Endpoint endpoints[CHIP_USB_NUMENDPOINTS];
00222 
00223 /** 7.1.20 Test Mode Support
00224  * Test codes for the USB HS test mode. */
00225 static const char test_packet_buffer[] = {
00226     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                // JKJKJKJK * 9
00227     0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,                     // JJKKJJKK * 8
00228     0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,                     // JJJJKKKK * 8
00229     0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8
00230     0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,                          // JJJJJJJK * 8
00231     0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E                 // {JKKKKKKK * 10}, JK
00232 };
00233 
00234 /** Force FS mode */
00235 static const uint8_t forceUsbFS = 0;
00236 
00237 /** DMA link list */
00238 static UdphsDmaDescriptor  dmaLL[5];
00239 static UdphsDmaDescriptor *pDmaLL;
00240 
00241 /*---------------------------------------------------------------------------
00242  *      Internal Functions
00243  *---------------------------------------------------------------------------*/
00244 
00245 /**
00246  * Enables the clock of the UDP peripheral.
00247  * \return 1 if peripheral status changed.
00248  */
00249 static uint8_t UDPHS_EnablePeripheralClock(void)
00250 {
00251     if (!PMC_IsPeriphEnabled(ID_UDPHS)) {
00252         PMC_EnablePeripheral(ID_UDPHS);
00253         return 1;
00254     }
00255     return 0;
00256 }
00257 
00258 /**
00259  * Disables the UDP peripheral clock.
00260  */
00261 static inline void UDPHS_DisablePeripheralClock(void)
00262 {
00263     PMC_DisablePeripheral(ID_UDPHS);
00264 }
00265 
00266 /**
00267  * Enables the 480MHz USB clock.
00268  */
00269 static inline void UDPHS_EnableUsbClock(void)
00270 {
00271     Pmc *pPmc = PMC;
00272     /* Enable 480Mhz UPLL */
00273     pPmc->CKGR_UCKR |= CKGR_UCKR_UPLLEN
00274                        | CKGR_UCKR_UPLLCOUNT(0x3)
00275                        | CKGR_UCKR_BIASCOUNT(0x1);
00276     /* Wait until UPLL is locked */
00277     while ((pPmc->PMC_SR & PMC_SR_LOCKU) == 0);
00278 }
00279 
00280 /**
00281  *  Disables the 480MHz USB clock.
00282  */
00283 static inline void UDPHS_DisableUsbClock(void)
00284 {
00285     Pmc *pPmc = PMC;
00286     pPmc->CKGR_UCKR &= ~(uint32_t)CKGR_UCKR_UPLLEN;
00287 }
00288 
00289 /**
00290  * Enables the BIAS.
00291  */
00292 static inline void UDPHS_EnableBIAS(void)
00293 {
00294     Pmc *pPmc = PMC;
00295     pPmc->CKGR_UCKR |= CKGR_UCKR_BIASEN;
00296 }
00297 
00298 /**
00299  * Disables the BIAS.
00300  */
00301 static inline void UDPHS_DisableBIAS(void)
00302 {
00303     Pmc *pPmc = PMC;
00304     pPmc->CKGR_UCKR &= ~(uint32_t)CKGR_UCKR_BIASEN;
00305 }
00306 
00307 /**
00308  * Handles a completed transfer on the given endpoint, invoking the
00309  * configured callback if any.
00310  * \param bEndpoint Number of the endpoint for which the transfer has completed.
00311  * \param bStatus   Status code returned by the transfer operation
00312  */
00313 static void UDPHS_EndOfTransfer(uint8_t bEndpoint, uint8_t bStatus)
00314 {
00315     Endpoint *pEp = &(endpoints[bEndpoint]);
00316 
00317     /* Check that endpoint was sending or receiving data */
00318     if ( (pEp->state == UDPHS_ENDPOINT_RECEIVING)
00319             || (pEp->state == UDPHS_ENDPOINT_SENDING) )
00320     {
00321         Transfer *pXfr = (Transfer*)&(pEp->transfer);
00322         uint32_t transferred = pXfr->transferred;
00323         uint32_t remaining   = pXfr->remaining + pXfr->buffered;
00324 
00325         TRACE_DEBUG_WP("EoT ");
00326 
00327         if (pEp->state == UDPHS_ENDPOINT_SENDING)
00328             pEp->sendZLP = 0;
00329         pEp->state = UDPHS_ENDPOINT_IDLE;
00330 
00331         pXfr->pData = 0;
00332         pXfr->transferred = -1;
00333         pXfr->buffered    = -1;
00334         pXfr->remaining   = -1;
00335 
00336         /* Invoke callback */
00337         if (pXfr->fCallback)
00338         {
00339             pXfr->fCallback(pXfr->pArgument, bStatus, transferred, remaining);
00340         }
00341         else
00342         {
00343             TRACE_DEBUG_WP("NoCB ");
00344         }
00345     }
00346     else if ( (pEp->state == UDPHS_ENDPOINT_RECEIVINGM)
00347                 || (pEp->state == UDPHS_ENDPOINT_SENDINGM) )
00348     {
00349         MblTransfer *pXfr = (MblTransfer*)&(pEp->transfer);
00350 
00351         TRACE_DEBUG_WP("EoMT ");
00352 
00353         pEp->state = UDPHS_ENDPOINT_IDLE;
00354         pXfr->listState = 0;
00355         pXfr->outCurr = pXfr->inCurr = pXfr->outLast = 0;
00356         /* Invoke callback */
00357         if (pXfr->fCallback)
00358         {
00359             pXfr->fCallback(pXfr->pArgument, bStatus);
00360         }
00361         else
00362         {
00363             TRACE_DEBUG_WP("NoCB ");
00364         }
00365     }
00366 }
00367 
00368 /**
00369  * Update multi-buffer-transfer descriptors.
00370  * \param pTransfer Pointer to instance MblTransfer.
00371  * \param size      Size of bytes that processed.
00372  * \param forceEnd  Force the buffer END.
00373  * \return 1 if current buffer ended.
00374  */
00375 static uint8_t UDPHS_MblUpdate(MblTransfer *pTransfer,
00376                           USBDTransferBuffer * pBi,
00377                           uint16_t size,
00378                           uint8_t forceEnd)
00379 {
00380     /* Update transfer descriptor */
00381     pBi->remaining -= size;
00382     /* Check if list NULL */
00383     if (pTransfer->listState == MBL_NULL) {
00384         return 1;
00385     }
00386     /* Check if current buffer ended */
00387     if (pBi->remaining == 0 || forceEnd || size == 0) {
00388 
00389         /* Process to next buffer */
00390         if ((++ pTransfer->outCurr) == pTransfer->listSize)
00391             pTransfer->outCurr = 0;
00392         /* Check buffer NULL case */
00393         if (pTransfer->outCurr == pTransfer->inCurr)
00394             pTransfer->listState = MBL_NULL;
00395         else {
00396             pTransfer->listState = 0;
00397             /* Continue transfer, prepare for next operation */
00398             pBi = &pTransfer->pMbl[pTransfer->outCurr];
00399             pBi->buffered    = 0;
00400             pBi->transferred = 0;
00401             pBi->remaining   = pBi->size;
00402         }
00403         return 1;
00404     }
00405     return 0;
00406 }
00407 
00408 /**
00409  * Transfers a data payload from the current tranfer buffer to the endpoint
00410  * FIFO
00411  * \param bEndpoint Number of the endpoint which is sending data.
00412  */
00413 static uint8_t UDPHS_MblWriteFifo(uint8_t bEndpoint)
00414 {
00415     Endpoint    *pEndpoint   = &(endpoints[bEndpoint]);
00416     MblTransfer *pTransfer   = (MblTransfer*)&(pEndpoint->transfer);
00417     USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->outCurr]);
00418     uint8_t *pFifo;
00419     int32_t size;
00420 
00421     volatile uint8_t * pBytes;
00422     volatile uint8_t bufferEnd = 1;
00423 
00424     /* Get the number of bytes to send */
00425     size = pEndpoint->size;
00426     if (size > pBi->remaining) size = pBi->remaining;
00427 
00428     TRACE_DEBUG_WP("w%d.%d ", pTransfer->outCurr, size);
00429 
00430     /* Record last accessed buffer */
00431     pTransfer->outLast = pTransfer->outCurr;
00432 
00433     pBytes = &(pBi->pBuffer[pBi->transferred + pBi->buffered]);
00434     pBi->buffered += size;
00435     bufferEnd = UDPHS_MblUpdate(pTransfer, pBi, size, 0);
00436 
00437     /* Write packet in the FIFO buffer */
00438     pFifo = (uint8_t*)((uint32_t*)UDPHS_RAM_ADDR
00439                                     + (EPT_VIRTUAL_SIZE * bEndpoint));
00440     if (size) {
00441         int32_t c8 = size >> 3;
00442         int32_t c1 = size & 0x7;
00443         for (; c8; c8 --) {
00444             *(pFifo++) = *(pBytes ++);
00445             *(pFifo++) = *(pBytes ++);
00446             *(pFifo++) = *(pBytes ++);
00447             *(pFifo++) = *(pBytes ++);
00448 
00449             *(pFifo++) = *(pBytes ++);
00450             *(pFifo++) = *(pBytes ++);
00451             *(pFifo++) = *(pBytes ++);
00452             *(pFifo++) = *(pBytes ++);
00453         }
00454         for (; c1; c1 --) {
00455             *(pFifo++) = *(pBytes ++);
00456         }
00457     }
00458     return bufferEnd;
00459 }
00460 
00461 #if 0
00462 /**
00463  *  Transfers a data payload from an endpoint FIFO to the current transfer
00464  *  buffer, if NULL packet received, the current buffer is ENDed.
00465  *  \param bEndpoint Endpoint number.
00466  *  \param wPacketSize Size of received data packet */
00467  *  \return 1 if the buffer ENDed. */
00468  */
00469 static uint8_t UDPHS_MblReadFifo(uint8_t bEndpoint, uint16_t wPacketSize)
00470 {
00471 
00472     return 0;
00473 }
00474 */
00475 #endif
00476 /**
00477  * Transfers a data payload from the current tranfer buffer to the endpoint
00478  * FIFO
00479  * \param bEndpoint Number of the endpoint which is sending data.
00480  */
00481 static void UDPHS_WritePayload(uint8_t bEndpoint, int32_t size)
00482 {
00483     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00484     Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
00485     uint8_t  *pFifo;
00486 
00487     /* Get the number of bytes to send */
00488     if (size > pTransfer->remaining)
00489     {
00490         size = pTransfer->remaining;
00491     }
00492 
00493     /* Update transfer descriptor information */
00494     pTransfer->buffered += size;
00495     pTransfer->remaining -= size;
00496 
00497     /* Write packet in the FIFO buffer */
00498     pFifo = (uint8_t*)((uint32_t*)UDPHS_RAM_ADDR
00499                                     + (EPT_VIRTUAL_SIZE * bEndpoint));
00500     for (; size; size --)
00501     {
00502         *(pFifo ++) = *(pTransfer->pData ++);
00503     }
00504 }
00505 
00506 /**
00507  * Transfers a data payload from an endpoint FIFO to the current transfer buffer
00508  * \param bEndpoint Endpoint number.
00509  * \param wPacketSize Size of received data packet
00510  */
00511 static void UDPHS_ReadPayload(uint8_t bEndpoint, int32_t wPacketSize)
00512 {
00513     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00514     Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
00515     uint8_t  *pFifo;
00516 
00517     /* Check that the requested size is not bigger than the remaining transfer */
00518     if (wPacketSize > pTransfer->remaining) {
00519 
00520         pTransfer->buffered += wPacketSize - pTransfer->remaining;
00521         wPacketSize = pTransfer->remaining;
00522     }
00523 
00524     /* Update transfer descriptor information */
00525     pTransfer->remaining -= wPacketSize;
00526     pTransfer->transferred += wPacketSize;
00527 
00528     /* Retrieve packet */
00529     pFifo = (uint8_t*)((uint32_t*)UDPHS_RAM_ADDR
00530                                     + (EPT_VIRTUAL_SIZE * bEndpoint));
00531     while (wPacketSize > 0)
00532     {
00533         *(pTransfer->pData ++) = *(pFifo ++);
00534         wPacketSize--;
00535     }
00536 }
00537 
00538 /**
00539  * Received SETUP packet from endpoint 0 FIFO
00540  * \param pRequest Generic USB SETUP request sent over Control endpoints
00541  */
00542 static void UDPHS_ReadRequest(USBGenericRequest *pRequest)
00543 {
00544     uint32_t *pData = (uint32_t *)pRequest;
00545     volatile uint32_t *pFifo;
00546     pFifo = (volatile uint32_t*)UDPHS_RAM_ADDR;
00547     *pData ++ = *pFifo;
00548     pFifo = (volatile uint32_t*)UDPHS_RAM_ADDR;
00549     *pData    = *pFifo;
00550     //printf("REQ: %08x %08x\n\r", pData[0], pData[1]);
00551 }
00552 
00553 /**
00554  * Endpoint interrupt handler.
00555  * Handle IN/OUT transfers, received SETUP packets and STALLing
00556  * \param bEndpoint Index of endpoint
00557  */
00558 static void UDPHS_EndpointHandler(uint8_t bEndpoint)
00559 {
00560     Udphs    *pUdp = UDPHS;
00561     UdphsEpt *pEpt = &pUdp->UDPHS_EPT[bEndpoint];
00562     //UdphsDma *pDma = &pUdp->UDPHS_DMA[bEndpoint];
00563 
00564     Endpoint *pEp      = &(endpoints[bEndpoint]);
00565     Transfer *pXfr     = (Transfer*)&(pEp->transfer);
00566     //MblTransfer *pMblt = (MblTransfer*)&(pEp->transfer);
00567     uint32_t status = pEpt->UDPHS_EPTSTA;
00568     uint32_t type   = pEpt->UDPHS_EPTCFG & UDPHS_EPTCFG_EPT_TYPE_Msk;
00569     uint32_t reqBuf[2];
00570     USBGenericRequest *pReq = (USBGenericRequest *)reqBuf;
00571     uint16_t wPktSize;
00572 
00573     TRACE_DEBUG_WP("Ep%d ", bEndpoint);
00574     //TRACE_DEBUG_WP("St:%x ", status);
00575 
00576     /* IN packet sent */
00577     if (   (pEpt->UDPHS_EPTCTL & UDPHS_EPTCTL_TX_PK_RDY)
00578         && (0 == (status & UDPHS_EPTSTA_TX_PK_RDY)) )
00579     {
00580         TRACE_DEBUG_WP("Wr ");
00581 
00582         /* Multi-buffer-list transfer state */
00583         if ( pEp->state == UDPHS_ENDPOINT_SENDINGM )
00584         {
00585         }
00586         /* Sending state */
00587         else if ( pEp->state == UDPHS_ENDPOINT_SENDING )
00588         {
00589             if (pXfr->buffered)
00590             {
00591                 pXfr->transferred += pXfr->buffered;
00592                 pXfr->buffered = 0;
00593             }
00594             if (   pXfr->buffered == 0
00595                 && pXfr->transferred == 0
00596                 && pXfr->remaining == 0
00597                 && pEp->sendZLP == 0 )
00598             {
00599                 pEp->sendZLP = 1;
00600             }
00601 
00602             /* End of Xfr ? */
00603             if (   pXfr->remaining
00604                 || pEp->sendZLP == 1)
00605             {
00606                 pEp->sendZLP = 2;
00607 
00608                 /* Transfer remaining */
00609                 TRACE_DEBUG_WP("%d ", pEp->size);
00610                 /* Send next packet */
00611                 UDPHS_WritePayload(bEndpoint, pEp->size);
00612                 pEpt->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_TX_PK_RDY;
00613             }
00614             else
00615             {
00616                 TRACE_DEBUG_WP("l%d ", pXfr->transferred);
00617                 /* Disable interrupt on none-control EP */
00618                 if (type != UDPHS_EPTCFG_EPT_TYPE_CTRL8)
00619                 {
00620                     pUdp->UDPHS_IEN &= ~(UDPHS_IEN_EPT_0 << bEndpoint);
00621                 }
00622                 pEpt->UDPHS_EPTCTLDIS = UDPHS_EPTCTLDIS_TX_PK_RDY;
00623 
00624                 UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00625                 pEp->sendZLP = 0;
00626             }
00627         }
00628         else
00629         {
00630             TRACE_DEBUG("Err Wr %d\n\r", pEp->sendZLP);
00631         }
00632     }
00633     /* OUT packet received */
00634     if ( UDPHS_EPTSTA_RX_BK_RDY & status )
00635     {
00636         TRACE_DEBUG_WP("Rd ");
00637 
00638         /* NOT in receiving state */
00639         if (pEp->state != UDPHS_ENDPOINT_RECEIVING)
00640         {
00641             /* Check if ACK received on a Control EP */
00642             if (   (UDPHS_EPTCFG_EPT_TYPE_CTRL8 == type)
00643                 && (0 == (status & UDPHS_EPTSTA_BYTE_COUNT_Msk)) )
00644             {
00645                 TRACE_DEBUG_WP("Ack ");
00646                 pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY;
00647                 UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00648             }
00649             /* data has been STALLed */
00650             else if (UDPHS_EPTSTA_FRCESTALL & status)
00651             {
00652                 TRACE_DEBUG_WP("Discard ");
00653                 pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY;
00654             }
00655             /* NAK the data */
00656             else
00657             {
00658                 TRACE_DEBUG_WP("Nak ");
00659                 pUdp->UDPHS_IEN &= ~(UDPHS_IEN_EPT_0 << bEndpoint);
00660             }
00661         }
00662         /* In read state */
00663         else
00664         {
00665             wPktSize = (uint16_t)((status & UDPHS_EPTSTA_BYTE_COUNT_Msk) >> UDPHS_EPTSTA_BYTE_COUNT_Pos);
00666 
00667             TRACE_DEBUG_WP("%d ", wPktSize);
00668             UDPHS_ReadPayload(bEndpoint, wPktSize);
00669             pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY;
00670             /* Check if transfer is finished */
00671             if (pXfr->remaining == 0 || wPktSize < pEp->size)
00672             {
00673                 pEpt->UDPHS_EPTCTLDIS = UDPHS_EPTCTLDIS_RX_BK_RDY;
00674 
00675                 /* Disable interrupt if not control EP */
00676                 if (UDPHS_EPTCFG_EPT_TYPE_CTRL8 != type)
00677                 {
00678                     pUdp->UDPHS_IEN &= ~(UDPHS_IEN_EPT_0 << bEndpoint);
00679                 }
00680                 UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00681             }
00682         }
00683     }
00684     /* STALL sent */
00685     if ( UDPHS_EPTSTA_STALL_SNT & status )
00686     {
00687         /* Acknowledge */
00688         pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_STALL_SNT;
00689 
00690         /* ISO error */
00691         if (type == UDPHS_EPTCFG_EPT_TYPE_ISO)
00692         {
00693             TRACE_WARNING("IsoE[%d]\n\r", bEndpoint);
00694 
00695             UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
00696         }
00697         /* If EP is not halted, clear STALL */
00698         else
00699         {
00700             TRACE_WARNING("Stall[%d]\n\r", bEndpoint);
00701 
00702             if (pEp->state != UDPHS_ENDPOINT_HALTED)
00703             {
00704                 pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_FRCESTALL;
00705             }
00706         }
00707     }
00708     /* SETUP packet received */
00709     if ( UDPHS_EPTSTA_RX_SETUP & status )
00710     {
00711         /* If a transfer was pending, complete it
00712            Handles the case where during the status phase of a control write
00713            transfer, the host receives the device ZLP and ack it, but the ack
00714            is not received by the device */
00715         if (pEp->state == UDPHS_ENDPOINT_RECEIVING
00716             || pEp->state == UDPHS_ENDPOINT_RECEIVINGM
00717             || pEp->state == UDPHS_ENDPOINT_SENDING
00718             || pEp->state == UDPHS_ENDPOINT_SENDINGM)
00719         {
00720             UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00721         }
00722 
00723         /* ISO Err Flow */
00724         if (type == UDPHS_EPTCFG_EPT_TYPE_ISO)
00725         {
00726             TRACE_WARNING("IsoFE[%d]\n\r", bEndpoint);
00727             /* Acknowledge setup packet */
00728             pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_SETUP;
00729         }
00730         else
00731         {
00732             TRACE_DEBUG_WP("Stup ");
00733 
00734             /* Copy setup */
00735             UDPHS_ReadRequest(pReq);
00736             /* Acknowledge setup packet */
00737             pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_SETUP;
00738             /* Handler */
00739             USBD_RequestHandler(bEndpoint, pReq);
00740         }
00741     }
00742 }
00743 #ifdef DMA
00744 /**
00745  * DMA Single transfer
00746  * \param bEndpoint EP number.
00747  * \pXfr  Pointer to transfer instance.
00748  * \dwCfg DMA Control configuration (excluding length).
00749  */
00750 static inline void UDPHS_DmaSingle(uint8_t bEndpoint, Transfer *pXfr, uint32_t dwCfg)
00751 {
00752     Udphs *pUdp = UDPHS;
00753 
00754     /* Single transfer */
00755     pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMAADDRESS =
00756                 (uint32_t)&pXfr->pData[pXfr->transferred];
00757     pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
00758     /* Interrupt enable */
00759     pUdp->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
00760 
00761     TRACE_DEBUG_WP("Dma[B%d:T%d] ", pXfr->buffered, pXfr->transferred);
00762     /* DMA Configure */
00763     pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0;
00764     pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0
00765                             | UDPHS_DMACONTROL_BUFF_LENGTH(pXfr->buffered)
00766                             | dwCfg;
00767 }
00768 /**
00769  * Endpoint DMA interrupt handler.
00770  * This function handles DMA interrupts.
00771  * \param bEndpoint Index of endpoint
00772  */
00773 static void UDPHS_DmaHandler(uint8_t bEndpoint)
00774 {
00775     Udphs    *pUdp  = UDPHS;
00776     //UdphsEpt *pHwEp = &pUdp->UDPHS_EPT[bEndpoint];
00777 
00778     Endpoint *pEp  = &(endpoints[bEndpoint]);
00779     Transfer *pXfr = (Transfer*)&(pEp->transfer);
00780 
00781     uint32_t dwDmaSr;
00782     int32_t iRemain, iXfred;
00783     uint8_t bRc = USBD_STATUS_SUCCESS;
00784 
00785     dwDmaSr = pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
00786     TRACE_DEBUG_WP("iDma%d,%x ", bEndpoint, dwDmaSr);
00787     /* Mbl transfer */
00788     if (pEp->state == UDPHS_ENDPOINT_SENDINGM)
00789     {
00790         /* Not implemented */
00791         return;
00792     }
00793     else if (pEp->state == UDPHS_ENDPOINT_RECEIVINGM)
00794     {
00795         /* Not implemented */
00796         return;
00797     }
00798 
00799     /* Disable DMA interrupt to avoid receiving 2 (B_EN and TR_EN) */
00800     pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL &= ~(UDPHS_DMACONTROL_END_TR_EN
00801                                                     |UDPHS_DMACONTROL_END_B_EN);
00802     if (UDPHS_DMASTATUS_END_BF_ST & dwDmaSr)
00803     {
00804         TRACE_DEBUG_WP("EoDmaB ");
00805         /* BUFF_COUNT holds the number of untransmitted bytes.
00806            BUFF_COUNT is equal to zero in case of good transfer */
00807         iRemain = (dwDmaSr & UDPHS_DMASTATUS_BUFF_COUNT_Msk)
00808                         >> UDPHS_DMASTATUS_BUFF_COUNT_Pos;
00809 
00810         TRACE_DEBUG_WP("C%d ", iRemain);
00811         iXfred  = pXfr->buffered - iRemain;
00812 
00813         pXfr->transferred += iXfred;
00814         pXfr->buffered     = iRemain;
00815         pXfr->remaining   -= iXfred;
00816 
00817         TRACE_DEBUG_WP("[B%d:T%d:R%d] ",
00818             pXfr->buffered, pXfr->transferred, pXfr->remaining);
00819 
00820         /* There is still data */
00821         if (pXfr->remaining + pXfr->buffered > 0)
00822         {
00823             if (pXfr->remaining > DMA_MAX_FIFO_SIZE)
00824             {
00825                 pXfr->buffered = DMA_MAX_FIFO_SIZE;
00826             }
00827             else
00828             {
00829                 pXfr->buffered = pXfr->remaining;
00830             }
00831             /* Single transfer again */
00832             UDPHS_DmaSingle(bEndpoint, pXfr, UDPHS_DMACONTROL_END_TR_EN
00833                                              | UDPHS_DMACONTROL_END_TR_IT
00834                                              | UDPHS_DMACONTROL_END_B_EN
00835                                              | UDPHS_DMACONTROL_END_BUFFIT
00836                                              | UDPHS_DMACONTROL_CHANN_ENB);
00837         }
00838     }
00839     else if (UDPHS_DMASTATUS_END_TR_ST & dwDmaSr)
00840     {
00841         TRACE_DEBUG_WP("EoDmaT ");
00842         pXfr->transferred = pXfr->buffered -
00843             ((dwDmaSr & UDPHS_DMASTATUS_BUFF_COUNT_Msk)
00844                     >> UDPHS_DMASTATUS_BUFF_COUNT_Pos);
00845         pXfr->remaining = 0;
00846 
00847         TRACE_DEBUG_WP("[B%d:T%d] ", pXfr->buffered, pXfr->transferred);
00848     }
00849     else
00850     {
00851         TRACE_ERROR("UDPHS_DmaHandler: ST 0x%X\n\r", dwDmaSr);
00852         bRc = USBD_STATUS_ABORTED;
00853     }
00854     /* Callback */
00855     if (pXfr->remaining == 0)
00856     {
00857         UDPHS_EndOfTransfer(bEndpoint, bRc);
00858     }
00859 
00860 }
00861 #endif
00862 /**
00863  * Sends data through a USB endpoint. Sets up the transfer descriptor,
00864  * writes one or two data payloads (depending on the number of FIFO bank
00865  * for the endpoint) and then starts the actual transfer. The operation is
00866  * complete when all the data has been sent.
00867  *
00868  * *If the size of the buffer is greater than the size of the endpoint
00869  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
00870  *  must be kept allocated until the transfer is finished*. This means that
00871  *  it is not possible to declare it on the stack (i.e. as a local variable
00872  *  of a function which returns after starting a transfer).
00873  *
00874  * \param pEndpoint Pointer to Endpoint struct.
00875  * \param pData Pointer to a buffer with the data to send.
00876  * \param dLength Size of the data buffer.
00877  * \return USBD_STATUS_SUCCESS if the transfer has been started;
00878  *         otherwise, the corresponding error status code.
00879  */
00880 static inline uint8_t UDPHS_Write(uint8_t    bEndpoint,
00881                                 const void *pData,
00882                                 uint32_t   dLength)
00883 {
00884     Udphs    *pUdp  = UDPHS;
00885     UdphsEpt *pHwEp = &pUdp->UDPHS_EPT[bEndpoint];
00886 
00887     Endpoint *pEp  = &(endpoints[bEndpoint]);
00888     Transfer *pXfr = (Transfer*)&(pEp->transfer);
00889     /* Return if busy */
00890     if (pEp->state != UDPHS_ENDPOINT_IDLE)
00891     {
00892         return USBD_STATUS_LOCKED;
00893     }
00894     /* Sending state */
00895     pEp->state = UDPHS_ENDPOINT_SENDING;
00896 
00897     TRACE_DEBUG_WP("Wr%d(%d) ", bEndpoint, dLength);
00898     pEp->sendZLP = 0;
00899     /* Setup transfer descriptor */
00900     pXfr->pData       = (void*) pData;
00901     pXfr->remaining   = dLength;
00902     pXfr->buffered    = 0;
00903     pXfr->transferred = 0;
00904 
00905   #ifdef DMA
00906     /* 1. DMA supported, 2. Not ZLP */
00907     if (CHIP_USB_ENDPOINTS_DMA(bEndpoint)
00908         && pXfr->remaining > 0)
00909     {
00910         if (pXfr->remaining > DMA_MAX_FIFO_SIZE)
00911         {
00912             /* Transfer the max */
00913             pXfr->buffered = DMA_MAX_FIFO_SIZE;
00914         }
00915         else
00916         {
00917             /* Good size */
00918             pXfr->buffered = pXfr->remaining;
00919         }
00920         /* Single transfer */
00921         UDPHS_DmaSingle(bEndpoint, pXfr, UDPHS_DMACONTROL_END_B_EN
00922                                          | UDPHS_DMACONTROL_END_BUFFIT
00923                                          | UDPHS_DMACONTROL_CHANN_ENB);
00924         return USBD_STATUS_SUCCESS;
00925     }
00926   #endif
00927 
00928     /* Enable IT */
00929     pUdp->UDPHS_IEN |= ( UDPHS_IEN_EPT_0 << bEndpoint );
00930     pHwEp->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_TX_PK_RDY;
00931     return USBD_STATUS_SUCCESS;
00932 }
00933 
00934 /**
00935  * Sends data through a USB endpoint. Sets up the transfer descriptor list,
00936  * writes one or two data payloads (depending on the number of FIFO bank
00937  * for the endpoint) and then starts the actual transfer. The operation is
00938  * complete when all the transfer buffer in the list has been sent.
00939  *
00940  * *If the size of the buffer is greater than the size of the endpoint
00941  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
00942  *  must be kept allocated until the transfer is finished*. This means that
00943  *  it is not possible to declare it on the stack (i.e. as a local variable
00944  *  of a function which returns after starting a transfer).
00945  *
00946  * \param pEndpoint Pointer to Endpoint struct.
00947  * \param pData Pointer to a buffer with the data to send.
00948  * \param dLength Size of the data buffer.
00949  * \return USBD_STATUS_SUCCESS if the transfer has been started;
00950  *         otherwise, the corresponding error status code.
00951  */
00952 static inline uint8_t UDPHS_AddWr(uint8_t   bEndpoint,
00953                                 const void *pData,
00954                                 uint32_t    dLength)
00955 {
00956     Udphs    *pUdp  = UDPHS;
00957     UdphsEpt *pHwEp = &pUdp->UDPHS_EPT[bEndpoint];
00958 
00959     Endpoint *pEp  = &(endpoints[bEndpoint]);
00960     MblTransfer *pMbl = (MblTransfer*)&(pEp->transfer);
00961     USBDTransferBuffer *pTx;
00962 
00963     /* Check parameter */
00964     if (dLength >= 0x10000)
00965     {
00966         return USBD_STATUS_INVALID_PARAMETER;
00967     }
00968     /* Data in process */
00969     if (pEp->state > UDPHS_ENDPOINT_IDLE)
00970     {   /* MBL transfer */
00971         if (pMbl->transType)
00972         {
00973             if (pMbl->listState == MBL_FULL)
00974             {
00975                 return USBD_STATUS_LOCKED;
00976             }
00977         }
00978         else
00979         {
00980             return USBD_STATUS_LOCKED;
00981         }
00982     }
00983 
00984     TRACE_DEBUG_WP("AddW%d(%d) ", bEndpoint, dLength);
00985     /* Add buffer to buffer list and update index */
00986     pTx = &(pMbl->pMbl[pMbl->inCurr]);
00987     pTx->pBuffer = (uint8_t*)pData;
00988     pTx->size = pTx->remaining = dLength;
00989     pTx->transferred = pTx->buffered = 0;
00990     /* Update input index */
00991     if (pMbl->inCurr >= (pMbl->listSize-1)) pMbl->inCurr = 0;
00992     else                                    pMbl->inCurr ++;
00993     if (pMbl->inCurr == pMbl->outCurr)      pMbl->listState = MBL_FULL;
00994     else                                    pMbl->listState = 0;
00995     /* Start sending when offset achieved */
00996     if (MBL_NbBuffer(pMbl->inCurr, pMbl->outCurr, pMbl->listSize)
00997             >= pMbl->offsetSize
00998         && pEp->state == UDPHS_ENDPOINT_IDLE)
00999     {
01000         uint8_t nbBanks = CHIP_USB_ENDPOINTS_BANKS(bEndpoint);
01001 
01002         /* Change state */
01003         pEp->state = UDPHS_ENDPOINT_SENDINGM;
01004 
01005         TRACE_DEBUG_WP("StartM ");
01006 
01007         /* Fill data into FIFO */
01008         for (;
01009              nbBanks && pMbl->pMbl[pMbl->inCurr].remaining;
01010              nbBanks --)
01011         {
01012             UDPHS_MblWriteFifo(bEndpoint);
01013             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_TX_PK_RDY;
01014         }
01015 
01016         /* Enable interrupt */
01017         pUdp->UDPHS_IEN |= (UDPHS_IEN_EPT_0 << bEndpoint);
01018         pHwEp->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_TX_PK_RDY;
01019 
01020     }
01021 
01022     return USBD_STATUS_SUCCESS;
01023 }
01024 
01025 /**
01026  * Reads incoming data on an USB endpoint This methods sets the transfer
01027  * descriptor and activate the endpoint interrupt. The actual transfer is
01028  * then carried out by the endpoint interrupt handler. The Read operation
01029  * finishes either when the buffer is full, or a short packet (inferior to
01030  * endpoint maximum  size) is received.
01031  *
01032  * *The buffer must be kept allocated until the transfer is finished*.
01033  * \param bEndpoint Endpoint number.
01034  * \param pData Pointer to a data buffer.
01035  * \param dLength Size of the data buffer in bytes.
01036  * \return USBD_STATUS_SUCCESS if the read operation has been started;
01037  *         otherwise, the corresponding error code.
01038  */
01039 static inline uint8_t UDPHS_Read(uint8_t  bEndpoint,
01040                                  void     *pData,
01041                                  uint32_t dLength)
01042 {
01043     Udphs    *pUdp  = UDPHS;
01044     UdphsEpt *pHwEp = &pUdp->UDPHS_EPT[bEndpoint];
01045 
01046     Endpoint *pEp  = &(endpoints[bEndpoint]);
01047     Transfer *pXfr = (Transfer*)&(pEp->transfer);
01048     /* Return if busy */
01049     if (pEp->state != UDPHS_ENDPOINT_IDLE)
01050     {
01051         return USBD_STATUS_LOCKED;
01052     }
01053     /* Receiving state */
01054     pEp->state = UDPHS_ENDPOINT_RECEIVING;
01055 
01056     TRACE_DEBUG_WP("Rd%d(%d) ", bEndpoint, dLength);
01057     /* Setup transfer descriptor */
01058     pXfr->pData       = (void*) pData;
01059     pXfr->remaining   = dLength;
01060     pXfr->buffered    = 0;
01061     pXfr->transferred = 0;
01062 
01063   #ifdef DMA
01064     /* If: 1. DMA supported, 2. Has data */
01065     if (CHIP_USB_ENDPOINTS_DMA(bEndpoint)
01066         && pXfr->remaining > 0)
01067     {
01068         /* DMA XFR size adjust */
01069         if (pXfr->remaining > DMA_MAX_FIFO_SIZE)
01070             pXfr->buffered = DMA_MAX_FIFO_SIZE;
01071         else
01072             pXfr->buffered = pXfr->remaining;
01073         /* Single transfer */
01074         UDPHS_DmaSingle(bEndpoint, pXfr, UDPHS_DMACONTROL_END_TR_EN
01075                                          | UDPHS_DMACONTROL_END_TR_IT
01076                                          | UDPHS_DMACONTROL_END_B_EN
01077                                          | UDPHS_DMACONTROL_END_BUFFIT
01078                                          | UDPHS_DMACONTROL_CHANN_ENB);
01079         return USBD_STATUS_SUCCESS;
01080     }
01081   #endif
01082 
01083     /* Enable IT */
01084     pUdp->UDPHS_IEN |= ( UDPHS_IEN_EPT_0 << bEndpoint );
01085     pHwEp->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_RX_BK_RDY;
01086 
01087     return USBD_STATUS_SUCCESS;
01088 }
01089 #if 0
01090 /**
01091  * Reads incoming data on an USB endpoint This methods sets the transfer
01092  * descriptor and activate the endpoint interrupt. The actual transfer is
01093  * then carried out by the endpoint interrupt handler. The Read operation
01094  * finishes either when the buffer is full, or a short packet (inferior to
01095  * endpoint maximum  size) is received.
01096  *
01097  * *The buffer must be kept allocated until the transfer is finished*.
01098  * \param bEndpoint Endpoint number.
01099  * \param pData Pointer to a data buffer.
01100  * \param dLength Size of the data buffer in bytes.
01101  * \return USBD_STATUS_SUCCESS if the read operation has been started;
01102  *         otherwise, the corresponding error code.
01103  */
01104 static inline uint8_t UDPHS_AddRd(uint8_t  bEndpoint,
01105                                 void     *pData,
01106                                 uint32_t dLength)
01107 {
01108     return USBD_STATUS_SW_NOT_SUPPORTED;
01109 }
01110 #endif
01111 /*---------------------------------------------------------------------------
01112  *      Exported functions
01113  *---------------------------------------------------------------------------*/
01114 extern void USBD_IrqHandler(void);
01115 /**
01116  * USBD (UDP) interrupt handler
01117  * Manages device resume, suspend, end of bus reset.
01118  * Forwards endpoint events to the appropriate handler.
01119  */
01120 void USBD_IrqHandler(void)
01121 {
01122     Udphs *pUdp = UDPHS;
01123 
01124     uint32_t status;
01125     uint8_t  numIt;
01126 
01127     status  = pUdp->UDPHS_INTSTA;
01128     status &= pUdp->UDPHS_IEN;
01129 
01130     /* Handle all UDPHS interrupts */
01131     TRACE_DEBUG_WP("\n\r%c ", USBD_HAL_IsHighSpeed() ? 'H' : 'F');
01132     while ( status )
01133     {
01134         /* SOF */
01135         if (status & UDPHS_INTSTA_INT_SOF)
01136         {
01137             TRACE_DEBUG_WP("SOF ");
01138             /* SOF handler */
01139             //USBD_SofHandler();
01140 
01141             /* Acknowledge interrupt */
01142             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_INT_SOF;
01143             status &= ~(uint32_t)UDPHS_INTSTA_INT_SOF;
01144         }
01145         /* Suspend, treated last */
01146         else if (status == UDPHS_INTSTA_DET_SUSPD)
01147         {
01148             TRACE_WARNING_WP("Susp ");
01149 
01150             /* Enable wakeup */
01151             pUdp->UDPHS_IEN |= (UDPHS_IEN_WAKE_UP | UDPHS_IEN_ENDOFRSM);
01152             pUdp->UDPHS_IEN &= ~(uint32_t)UDPHS_IEN_DET_SUSPD;
01153 
01154             /* Acknowledge interrupt */
01155             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_DET_SUSPD | UDPHS_CLRINT_WAKE_UP;
01156 
01157             USBD_SuspendHandler();
01158         }
01159         /* Resume */
01160         else if ( (status & UDPHS_INTSTA_WAKE_UP)
01161                || (status & UDPHS_INTSTA_ENDOFRSM) )
01162         {
01163             USBD_ResumeHandler();
01164 
01165             TRACE_INFO_WP("Rsm ");
01166 
01167             /* Acknowledge interrupt */
01168             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP
01169                                | UDPHS_CLRINT_ENDOFRSM
01170                                | UDPHS_CLRINT_DET_SUSPD;
01171 
01172             pUdp->UDPHS_IEN |= UDPHS_IEN_ENDOFRSM | UDPHS_IEN_DET_SUSPD;
01173             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP | UDPHS_CLRINT_ENDOFRSM;
01174             pUdp->UDPHS_IEN &= ~(uint32_t)UDPHS_IEN_WAKE_UP;
01175         }
01176         /* Bus reset */
01177         else if (status & UDPHS_INTSTA_ENDRESET)
01178         {
01179             TRACE_DEBUG_WP("EoB ");
01180 
01181             /* Flush and enable the suspend interrupt */
01182             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP | UDPHS_CLRINT_DET_SUSPD;
01183             pUdp->UDPHS_IEN |= UDPHS_IEN_DET_SUSPD;
01184 
01185             /* Reset handler */
01186             USBD_ResetHandler();
01187 
01188             /* Acknowledge interrupt */
01189             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_ENDRESET;
01190         }
01191         /* Upstream resume */
01192         else if (status & UDPHS_INTSTA_UPSTR_RES)
01193         {
01194             TRACE_DEBUG_WP("ExtRes ");
01195 
01196             /* Acknowledge interrupt */
01197             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_UPSTR_RES;
01198         }
01199         /* Endpoints */
01200         else
01201         {
01202           #ifdef DMA
01203             for (numIt = 0; numIt < NUM_IT_MAX; numIt ++)
01204             {
01205                 if (status & (1 << SHIFT_DMA << numIt))
01206                 {
01207                     UDPHS_DmaHandler(numIt);
01208                 }
01209                 else if (status & (UDPHS_INTSTA_EPT_0 << numIt))
01210                 {
01211                     UDPHS_EndpointHandler(numIt);
01212                 }
01213             }
01214           #else
01215             for (numIt = 0; numIt < NUM_IT_MAX; numIt ++)
01216             {
01217                 if (status & (UDPHS_INTSTA_EPT_0 << numIt))
01218                 {
01219                     UDPHS_EndpointHandler(numIt);
01220                 }
01221             }
01222           #endif
01223         }
01224 
01225         /* Update interrupt status */
01226         status  = pUdp->UDPHS_INTSTA;
01227         status &= pUdp->UDPHS_IEN;
01228 
01229         TRACE_DEBUG_WP("\n\r");
01230         if (status)
01231         {
01232             TRACE_DEBUG_WP(" - ");
01233         }
01234     }
01235 }
01236 
01237 /**
01238  * \brief Reset endpoints and disable them.
01239  * -# Terminate transfer if there is any, with given status;
01240  * -# Reset the endpoint & disable it.
01241  * \param bmEPs    Bitmap for endpoints to reset.
01242  * \param bStatus  Status passed to terminate transfer on endpoint.
01243  * \param bKeepCfg 1 to keep old endpoint configuration.
01244  * \note Use USBD_HAL_ConfigureEP() to configure and enable endpoint
01245          if not keeping old configuration.
01246  * \sa USBD_HAL_ConfigureEP().
01247  */
01248 void USBD_HAL_ResetEPs(uint32_t bmEPs, uint8_t bStatus, uint8_t bKeepCfg)
01249 {
01250     Udphs *pUdp = UDPHS;
01251     UdphsEpt *pHwEp;
01252 
01253     Endpoint *pEndpoint;
01254     uint32_t tmp = bmEPs & ((1<<CHIP_USB_NUMENDPOINTS)-1);
01255     uint8_t  ep;
01256     uint32_t epBit, epCfg;
01257 
01258     for (ep = 0, epBit = 1; ep < CHIP_USB_NUMENDPOINTS; ep ++)
01259     {
01260         if (tmp & epBit)
01261         {
01262             pHwEp = &pUdp->UDPHS_EPT[ep];
01263 
01264             /* Disable ISR */
01265             pUdp->UDPHS_IEN &= ~(epBit << SHIFT_INTERUPT);
01266             /* Kill pending Banks ?? */
01267             #if 0
01268             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;
01269             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;
01270             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;
01271             #endif
01272 
01273             /* Reset transfer information */
01274             pEndpoint = &(endpoints[ep]);
01275             /* Reset endpoint state */
01276             pEndpoint->bank = 0;
01277             /* Endpoint configure */
01278             epCfg = pHwEp->UDPHS_EPTCFG;
01279             /* Reset endpoint */
01280             pUdp->UDPHS_EPTRST = epBit;
01281             /* Restore configure */
01282             if (bKeepCfg)
01283             {
01284                 pHwEp->UDPHS_EPTCFG = epCfg;
01285             }
01286             else
01287             {
01288                 pEndpoint->state = UDPHS_ENDPOINT_DISABLED;
01289             }
01290 
01291             /* Terminate transfer on this EP */
01292             UDPHS_EndOfTransfer(ep, bStatus);
01293         }
01294         epBit <<= 1;
01295     }
01296 }
01297 
01298 /**
01299  * Cancel pending READ/WRITE
01300  * \param bmEPs    Bitmap for endpoints to reset.
01301  * \note EP callback is invoked with USBD_STATUS_CANCELED.
01302  */
01303 void USBD_HAL_CancelIo(uint32_t bmEPs)
01304 {
01305     Udphs *pUdp = UDPHS;
01306     //UdphsEpt *pHwEp = NULL;
01307 
01308     uint32_t tmp = bmEPs & ((1<<CHIP_USB_NUMENDPOINTS)-1);
01309     uint8_t  ep;
01310     uint32_t epBit;
01311     for (ep = 0, epBit = 1; ep < CHIP_USB_NUMENDPOINTS; ep ++)
01312     {
01313         if (tmp & epBit)
01314         {
01315             //pHwEp = &pUdp->UDPHS_EPT[ep];
01316 
01317             /* Disable ISR */
01318             pUdp->UDPHS_IEN &= ~(epBit << SHIFT_INTERUPT);
01319             /* Kill pending Banks ?? */
01320             #if 0
01321             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;
01322             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;
01323             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;
01324             #endif
01325 
01326             /* Terminate transfer on this EP */
01327             UDPHS_EndOfTransfer(ep, USBD_STATUS_CANCELED);
01328         }
01329         epBit <<= 1;
01330     }
01331 }
01332 
01333 /**
01334  * Configures an endpoint according to its endpoint Descriptor.
01335  * \param pDescriptor Pointer to an endpoint descriptor.
01336  * \return The endpoint address.
01337  */
01338 uint8_t USBD_HAL_ConfigureEP(const USBEndpointDescriptor *pDescriptor)
01339 {
01340     Udphs    *pUdp = UDPHS;
01341     UdphsEpt *pEpt;
01342     //UdphsDma *pDma;
01343 
01344     Endpoint *pEndpoint;
01345     uint8_t  bEndpoint;
01346     uint8_t  bType;
01347     uint8_t  bEndpointDir;
01348     //uint8_t bInterval = 0;
01349     uint8_t  bNbTrans  = 1;
01350     uint8_t  bSizeEpt  = 0;
01351     uint8_t  bHs = ((pUdp->UDPHS_INTSTA & UDPHS_INTSTA_SPEED) > 0);
01352 
01353     /* NULL descriptor -> Control endpoint 0 */
01354     if (pDescriptor == 0)
01355     {
01356 
01357         bEndpoint = 0;
01358         pEndpoint = &(endpoints[bEndpoint]);
01359         pEpt      = &(pUdp->UDPHS_EPT[0]);
01360         bType = USBEndpointDescriptor_CONTROL;
01361         bEndpointDir = 0;
01362         pEndpoint->size = CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0);
01363         pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(0);
01364     }
01365     /* Device descriptor -> Control endpoint 0 */
01366     else if (pDescriptor->bDescriptorType == USBGenericDescriptor_DEVICE)
01367     {
01368         USBDeviceDescriptor *pDevDesc = (USBDeviceDescriptor*)pDescriptor;
01369         bEndpoint = 0;
01370         pEndpoint = &(endpoints[bEndpoint]);
01371         pEpt      = &(pUdp->UDPHS_EPT[0]);
01372         bType = USBEndpointDescriptor_CONTROL;
01373         bEndpointDir = 0;
01374         pEndpoint->size =pDevDesc->bMaxPacketSize0;
01375         pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(0);
01376     }
01377     /* Endpoint descriptor */
01378     else
01379     {
01380         /* The endpoint number */
01381         bEndpoint = USBEndpointDescriptor_GetNumber(pDescriptor);
01382         pEndpoint = &(endpoints[bEndpoint]);
01383         pEpt      = &(pUdp->UDPHS_EPT[bEndpoint]);
01384         /* Transfer type: Control, Isochronous, Bulk, Interrupt */
01385         bType = USBEndpointDescriptor_GetType(pDescriptor);
01386         /* interval */
01387         //bInterval = USBEndpointDescriptor_GetInterval(pDescriptor);
01388         /* Direction, ignored for control endpoints */
01389         bEndpointDir = USBEndpointDescriptor_GetDirection(pDescriptor);
01390         pEndpoint->size = USBEndpointDescriptor_GetMaxPacketSize(pDescriptor);
01391         pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(bEndpoint);
01392 
01393         /* Convert descriptor value to EP configuration */
01394         if (bHs) {  /* HS Interval, *125us */
01395 
01396             /* MPS: Bit12,11 specify NB_TRANS, as USB 2.0 Spec. */
01397             bNbTrans = ((pEndpoint->size >> 11) & 0x3);
01398             if (bNbTrans == 3)
01399                 bNbTrans = 1;
01400             else
01401                 bNbTrans ++;
01402 
01403             /* Mask, bit 10..0 is the size */
01404             pEndpoint->size &= 0x7FF;
01405         }
01406     }
01407 
01408     //TRACE_DEBUG_WP("CfgE%d ", bEndpoint);
01409 
01410     /* Abort the current transfer is the endpoint was configured and in
01411        Write or Read state */
01412     if ( (pEndpoint->state == UDPHS_ENDPOINT_RECEIVING)
01413      || (pEndpoint->state == UDPHS_ENDPOINT_SENDING)
01414      || (pEndpoint->state == UDPHS_ENDPOINT_RECEIVINGM)
01415      || (pEndpoint->state == UDPHS_ENDPOINT_SENDINGM) ) {
01416 
01417         UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_RESET);
01418     }
01419     pEndpoint->state = UDPHS_ENDPOINT_IDLE;
01420 
01421     /* Disable endpoint */
01422     pEpt->UDPHS_EPTCTLDIS = UDPHS_EPTCTLDIS_SHRT_PCKT
01423                           | UDPHS_EPTCTLDIS_BUSY_BANK
01424                           | UDPHS_EPTCTLDIS_NAK_OUT
01425                           | UDPHS_EPTCTLDIS_NAK_IN
01426                           | UDPHS_EPTCTLDIS_STALL_SNT
01427                           | UDPHS_EPTCTLDIS_RX_SETUP
01428                           | UDPHS_EPTCTLDIS_TX_PK_RDY
01429                           | UDPHS_EPTCTLDIS_RX_BK_RDY
01430                           | UDPHS_EPTCTLDIS_ERR_OVFLW
01431                           | UDPHS_EPTCTLDIS_MDATA_RX
01432                           | UDPHS_EPTCTLDIS_DATAX_RX
01433                           | UDPHS_EPTCTLDIS_NYET_DIS
01434                           | UDPHS_EPTCTLDIS_INTDIS_DMA
01435                           | UDPHS_EPTCTLDIS_AUTO_VALID
01436                           | UDPHS_EPTCTLDIS_EPT_DISABL
01437                          ;
01438     /* Reset Endpoint Fifos */
01439     pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TOGGLESQ | UDPHS_EPTCLRSTA_FRCESTALL;
01440     pUdp->UDPHS_EPTRST = 1 << bEndpoint;
01441     /* Configure endpoint size */
01442     if ( pEndpoint->size <= 8 )
01443         bSizeEpt = 0;
01444     else if ( pEndpoint->size <= 16 )
01445         bSizeEpt = 1;
01446     else if ( pEndpoint->size <= 32 )
01447         bSizeEpt = 2;
01448     else if ( pEndpoint->size <= 64 )
01449         bSizeEpt = 3;
01450     else if ( pEndpoint->size <= 128 )
01451         bSizeEpt = 4;
01452     else if ( pEndpoint->size <= 256 )
01453         bSizeEpt = 5;
01454     else if ( pEndpoint->size <= 512 )
01455         bSizeEpt = 6;
01456     else if ( pEndpoint->size <= 1024 )
01457         bSizeEpt = 7;
01458 
01459     /* Configure endpoint */
01460     if (bType == USBEndpointDescriptor_CONTROL)
01461     {
01462         pUdp->UDPHS_IEN |= (UDPHS_IEN_EPT_0 << bEndpoint);
01463     }
01464 
01465     pEpt->UDPHS_EPTCFG =    bSizeEpt
01466                         | ( bEndpointDir << 3)
01467                         | ( bType << 4)
01468                         | ((pEndpoint->bank) << 6)
01469                         | ( bNbTrans << 8)
01470                        ;
01471 
01472     while ( (UDPHS_EPTCFG_EPT_MAPD & pEpt->UDPHS_EPTCFG) == 0 ) {
01473 
01474         /* resolved by clearing the reset IT in good place */
01475         TRACE_ERROR("PB bEndpoint: 0x%X\n\r", bEndpoint);
01476         TRACE_ERROR("PB bSizeEpt: 0x%X\n\r", bSizeEpt);
01477         TRACE_ERROR("PB bEndpointDir: 0x%X\n\r", bEndpointDir);
01478         TRACE_ERROR("PB bType: 0x%X\n\r", bType);
01479         TRACE_ERROR("PB pEndpoint->bank: 0x%X\n\r", pEndpoint->bank);
01480         TRACE_ERROR("PB UDPHS_EPTCFG: 0x%X\n\r", pEpt->UDPHS_EPTCFG);
01481         for(;;);
01482     }
01483 
01484     if (bType == USBEndpointDescriptor_CONTROL)
01485     {
01486         pEpt->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_RX_BK_RDY
01487                               | UDPHS_EPTCTLENB_RX_SETUP
01488                               | UDPHS_EPTCTLENB_EPT_ENABL;
01489     }
01490     else
01491     {
01492 #ifndef DMA
01493         pEpt->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_EPT_ENABL;
01494 #else
01495         pEpt->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_AUTO_VALID | UDPHS_EPTCTLENB_EPT_ENABL;
01496 #endif
01497     }
01498 
01499     //TRACE_DEBUG_WP("<%x,%x,%x> ", pEpt->UDPHS_EPTCFG, pEpt->UDPHS_EPTCTL, pEpt->UDPHS_EPTSTA);
01500     return bEndpoint;
01501 }
01502 
01503 /**
01504  * Set callback for a USB endpoint for transfer (read/write).
01505  *
01506  * \param bEP       Endpoint number.
01507  * \param fCallback Optional callback function to invoke when the transfer is
01508  *                  complete.
01509  * \param pCbData   Optional pointer to data to the callback function.
01510  * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED if endpoint is busy.
01511  */
01512 uint8_t USBD_HAL_SetTransferCallback(uint8_t          bEP,
01513                                   TransferCallback fCallback,
01514                                   void             *pCbData)
01515 {
01516     Endpoint *pEndpoint = &(endpoints[bEP]);
01517     TransferHeader *pTransfer = (TransferHeader*)&(pEndpoint->transfer);
01518     /* Check that the endpoint is not transferring */
01519     if (pEndpoint->state > UDPHS_ENDPOINT_IDLE) {
01520         return USBD_STATUS_LOCKED;
01521     }
01522     TRACE_DEBUG_WP("sXfrCb ");
01523     /* Setup the transfer callback and extension data */
01524     pTransfer->fCallback = (void*)fCallback;
01525     pTransfer->pArgument = pCbData;
01526     return USBD_STATUS_SUCCESS;
01527 }
01528 
01529 /**
01530  * Configure an endpoint to use multi-buffer-list transfer mode.
01531  * The buffers can be added by _Read/_Write function.
01532  * \param pMbList  Pointer to a multi-buffer list used, NULL to disable MBL.
01533  * \param mblSize  Multi-buffer list size (number of buffers can be queued)
01534  * \param startOffset When number of buffer achieve this offset transfer start
01535  */
01536 uint8_t USBD_HAL_SetupMblTransfer( uint8_t bEndpoint,
01537                                    USBDTransferBuffer* pMbList,
01538                                    uint16_t mblSize,
01539                                    uint16_t startOffset)
01540 {
01541     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
01542     MblTransfer *pXfr = (MblTransfer*)&(pEndpoint->transfer);
01543     uint16_t i;
01544     /* Check that the endpoint is not transferring */
01545     if (pEndpoint->state > UDPHS_ENDPOINT_IDLE) {
01546         return USBD_STATUS_LOCKED;
01547     }
01548     TRACE_DEBUG_WP("sMblXfr ");
01549     /* Enable Multi-Buffer Transfer List */
01550     if (pMbList) {
01551         /* Reset list items */
01552         for (i = 0; i < mblSize; i --) {
01553             pMbList[i].pBuffer     = NULL;
01554             pMbList[i].size        = 0;
01555             pMbList[i].transferred = 0;
01556             pMbList[i].buffered    = 0;
01557             pMbList[i].remaining   = 0;
01558         }
01559         /* Setup transfer */
01560         pXfr->transType  = 1;
01561         pXfr->listState  = 0; /* OK */
01562         pXfr->listSize   = mblSize;
01563         pXfr->pMbl       = pMbList;
01564         pXfr->outCurr = pXfr->outLast = 0;
01565         pXfr->inCurr  = 0;
01566         pXfr->offsetSize = startOffset;
01567     }
01568     /* Disable Multi-Buffer Transfer */
01569     else {
01570         pXfr->transType  = 0;
01571         pXfr->pMbl       = NULL;
01572         pXfr->listSize   = 0;
01573         pXfr->offsetSize = 1;
01574     }
01575     return USBD_STATUS_SUCCESS;
01576 }
01577 
01578 /**
01579  * Sends data through a USB endpoint. Sets up the transfer descriptor,
01580  * writes one or two data payloads (depending on the number of FIFO bank
01581  * for the endpoint) and then starts the actual transfer. The operation is
01582  * complete when all the data has been sent.
01583  *
01584  * *If the size of the buffer is greater than the size of the endpoint
01585  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
01586  *  must be kept allocated until the transfer is finished*. This means that
01587  *  it is not possible to declare it on the stack (i.e. as a local variable
01588  *  of a function which returns after starting a transfer).
01589  *
01590  * \param bEndpoint Endpoint number.
01591  * \param pData Pointer to a buffer with the data to send.
01592  * \param dLength Size of the data buffer.
01593  * \return USBD_STATUS_SUCCESS if the transfer has been started;
01594  *         otherwise, the corresponding error status code.
01595  */
01596 uint8_t USBD_HAL_Write( uint8_t          bEndpoint,
01597                         const void       *pData,
01598                         uint32_t         dLength)
01599 {
01600     if (endpoints[bEndpoint].transfer.transHdr.transType)
01601         return UDPHS_AddWr(bEndpoint, pData, dLength);
01602     else
01603         return UDPHS_Write(bEndpoint, pData, dLength);
01604 }
01605 
01606 /**
01607  * Special write function.
01608  * Sends data through a USB endpoint. Sets up the transfer descriptor,
01609  * writes header and one or two data payloads (depending on the number of
01610  * FIFO bank for the endpoint) and then starts the actual transfer. The
01611  * operation is complete when all the data has been sent.
01612  *
01613  * *If the size of the buffer is greater than the size of the endpoint
01614  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
01615  *  must be kept allocated until the transfer is finished*. This means that
01616  *  it is not possible to declare it on the stack (i.e. as a local variable
01617  *  of a function which returns after starting a transfer).
01618  *
01619  * \param bEndpoint Endpoint number.
01620  * \param pData Pointer to a buffer with the data to send.
01621  * \param dLength Size of the data buffer.
01622  * \return USBD_STATUS_SUCCESS if the transfer has been started;
01623  *         otherwise, the corresponding error status code.
01624  */
01625 uint8_t USBD_HAL_WrWithHdr(uint8_t bEndpoint,
01626                            const void * pHdr, uint8_t bHdrLen,
01627                            const void * pData,uint32_t dLength)
01628 {
01629     Udphs    *pUdp  = UDPHS;
01630     UdphsEpt *pHwEp = &pUdp->UDPHS_EPT[bEndpoint];
01631 
01632     Endpoint *pEp  = &(endpoints[bEndpoint]);
01633     Transfer *pXfr = (Transfer*)&(pEp->transfer);
01634 
01635     /* Return if DMA is not supported */
01636     if (!CHIP_USB_ENDPOINTS_DMA(bEndpoint))
01637     {
01638        return USBD_STATUS_HW_NOT_SUPPORTED;
01639     }
01640 
01641 #ifdef DMA
01642     /* Return if busy */
01643     if (pEp->state != UDPHS_ENDPOINT_IDLE)
01644     {
01645         return USBD_STATUS_LOCKED;
01646     }
01647     /* Sending state */
01648     pEp->state = UDPHS_ENDPOINT_SENDING;
01649     TRACE_DEBUG_WP("Wr%d(%d+%d) ", bEndpoint, bHdrLen, dLength);
01650     //printf("Wr%d(%d+%d) ", bEndpoint, bHdrLen, dLength);
01651 
01652     pEp->sendZLP = 0;
01653 
01654     /* Setup transfer descriptor */
01655     pXfr->pData       = (void*) pData;
01656     pXfr->remaining   = bHdrLen + dLength;
01657     pXfr->buffered    = 0;
01658     pXfr->transferred = 0;
01659 
01660     /* 1. DMA supported always, 2. Not ZLP */
01661     if (bHdrLen + dLength > 0)
01662     {
01663         uint8_t bNbTrans = (pHwEp->UDPHS_EPTCFG & UDPHS_EPTCFG_NB_TRANS_Msk)
01664                                                   >> UDPHS_EPTCFG_NB_TRANS_Pos;
01665         if (pXfr->remaining > DMA_MAX_FIFO_SIZE)
01666         {
01667             /* Transfer the max */
01668             pXfr->buffered = DMA_MAX_FIFO_SIZE;
01669         }
01670         else
01671         {
01672             /* Good size, total size */
01673             pXfr->buffered = pXfr->remaining;
01674         }
01675 
01676         /* LD1: header - load to fifo without interrupt */
01677         /* Header discarded if exceed the DMA FIFO length */
01678         //if (bHdrLen > DMA_MAX_FIFO_SIZE) bHdrLen = DMA_MAX_FIFO_SIZE;
01679         pDmaLL[0].pNxtDesc = (void*)&pDmaLL[1];
01680         pDmaLL[0].pAddr    = (void*)pHdr;
01681         pDmaLL[0].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB
01682                            | UDPHS_DMACONTROL_BUFF_LENGTH(bHdrLen)
01683                            | UDPHS_DMACONTROL_LDNXT_DSC;
01684         /* High bandwidth ISO EP, max size n*ep_size */
01685         if (bNbTrans > 1) {
01686             uint8_t* pU8 = (uint8_t*)pData;
01687             uint32_t maxSize = bNbTrans * pEp->size;
01688             dLength = pXfr->buffered - bHdrLen;
01689             if (dLength > maxSize) dLength = maxSize;
01690           #if 0 /* Prepare banks by 1 DMA descriptor -- NK if not standard EP size, works! */
01691             /* LD2: data   -  load to fifo with interrupt */
01692             pDmaLL[1].pNxtDesc = (void*)NULL;
01693             pDmaLL[1].pAddr    = (void*)pU8;
01694             pDmaLL[1].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB
01695                                | UDPHS_DMACONTROL_BUFF_LENGTH(dLength)
01696                                | UDPHS_DMACONTROL_END_B_EN
01697                                | UDPHS_DMACONTROL_END_BUFFIT;
01698           #else
01699             uint32_t pktLen, ndxData = 0;
01700             /* LD2: data   -  bank 0 */
01701             pktLen = pEp->size - bHdrLen;
01702             if (pktLen >= dLength) { /* It's the last DMA LLI */
01703                 pDmaLL[1].pNxtDesc = (void*)NULL;
01704                 pDmaLL[1].pAddr    = (void*)pU8;
01705                 pDmaLL[1].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB
01706                                    | UDPHS_DMACONTROL_BUFF_LENGTH(dLength)
01707                                    | UDPHS_DMACONTROL_END_B_EN
01708                                    | UDPHS_DMACONTROL_END_BUFFIT;
01709             }
01710             else {
01711                 pDmaLL[1].pNxtDesc = (void*)&pDmaLL[2];
01712                 pDmaLL[1].pAddr    = (void*)pU8;
01713                 pDmaLL[1].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB
01714                                    | UDPHS_DMACONTROL_BUFF_LENGTH(pktLen)
01715                                    | UDPHS_DMACONTROL_END_B_EN
01716                                    | UDPHS_DMACONTROL_LDNXT_DSC;
01717                 dLength -= pktLen; ndxData += pktLen;
01718                 /* LD3: data  - bank 1 */
01719                 pktLen = pEp->size;
01720                 if (pktLen >= dLength) { /* It's the last */
01721                     pDmaLL[1].pNxtDesc = (void*) NULL;
01722                     pDmaLL[1].pAddr    = (void*)&pU8[ndxData];
01723                     pDmaLL[1].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB
01724                                        | UDPHS_DMACONTROL_BUFF_LENGTH(dLength)
01725                                        | UDPHS_DMACONTROL_END_B_EN
01726                                        | UDPHS_DMACONTROL_END_BUFFIT;
01727                 }
01728                 else {
01729                     pDmaLL[2].pNxtDesc = (void*)&pDmaLL[3];
01730                     pDmaLL[2].pAddr    = (void*)&pU8[ndxData];
01731                     pDmaLL[2].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB
01732                                        | UDPHS_DMACONTROL_BUFF_LENGTH(pktLen)
01733                                        | UDPHS_DMACONTROL_END_B_EN
01734                                        | UDPHS_DMACONTROL_LDNXT_DSC;
01735                     dLength -= pktLen; ndxData += pktLen;
01736                     /* LD4: data  - bank 2 */
01737                     pDmaLL[3].pNxtDesc = (void*) NULL;
01738                     pDmaLL[3].pAddr    = (void*)&pU8[ndxData];
01739                     pDmaLL[3].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB
01740                                        | UDPHS_DMACONTROL_BUFF_LENGTH(dLength)
01741                                        | UDPHS_DMACONTROL_END_B_EN
01742                                        | UDPHS_DMACONTROL_END_BUFFIT;
01743                 }
01744             }
01745           #endif
01746         }
01747         else { /* Normal, fill all data */
01748             /* LD2: data   -  load to fifo with interrupt */
01749             dLength = pXfr->buffered - bHdrLen;
01750             pDmaLL[1].pNxtDesc = (void*)NULL;
01751             pDmaLL[1].pAddr    = (void*)pData;
01752             pDmaLL[1].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB
01753                                | UDPHS_DMACONTROL_BUFF_LENGTH(dLength)
01754                                | UDPHS_DMACONTROL_END_B_EN
01755                                | UDPHS_DMACONTROL_END_BUFFIT;
01756         }
01757 
01758         /* Interrupt enable */
01759         pUdp->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
01760         /* Start transfer with LLI */
01761         pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMANXTDSC  = (uint32_t)pDmaLL;
01762         pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0;
01763         pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = UDPHS_DMACONTROL_LDNXT_DSC;
01764         return USBD_STATUS_SUCCESS;
01765     }
01766 #endif
01767 
01768     /* Enable IT */
01769     pUdp->UDPHS_IEN |= ( UDPHS_IEN_EPT_0 << bEndpoint );
01770     pHwEp->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_TX_PK_RDY;
01771     return USBD_STATUS_SUCCESS;
01772 }
01773 
01774 /**
01775  * Reads incoming data on an USB endpoint This methods sets the transfer
01776  * descriptor and activate the endpoint interrupt. The actual transfer is
01777  * then carried out by the endpoint interrupt handler. The Read operation
01778  * finishes either when the buffer is full, or a short packet (inferior to
01779  * endpoint maximum  size) is received.
01780  *
01781  * *The buffer must be kept allocated until the transfer is finished*.
01782  * \param bEndpoint Endpoint number.
01783  * \param pData Pointer to a data buffer.
01784  * \param dLength Size of the data buffer in bytes.
01785  * \return USBD_STATUS_SUCCESS if the read operation has been started;
01786  *         otherwise, the corresponding error code.
01787  */
01788 uint8_t USBD_HAL_Read(uint8_t    bEndpoint,
01789                       void       *pData,
01790                       uint32_t   dLength)
01791 {
01792     if (endpoints[bEndpoint].transfer.transHdr.transType)
01793         return USBD_STATUS_SW_NOT_SUPPORTED;
01794     else
01795         return UDPHS_Read(bEndpoint, pData, dLength);
01796 }
01797 
01798 /**
01799  *  \brief Enable Pull-up, connect.
01800  *
01801  *  -# Enable HW access if needed
01802  *  -# Enable Pull-Up
01803  *  -# Disable HW access if needed
01804  */
01805 void USBD_HAL_Connect(void)
01806 {
01807     Udphs *pUdp = UDPHS;
01808 
01809     uint8_t dis = UDPHS_EnablePeripheralClock();
01810     pUdp->UDPHS_CTRL |= UDPHS_CTRL_PULLD_DIS;
01811     pUdp->UDPHS_CTRL &= ~(uint32_t)UDPHS_CTRL_DETACH;
01812     if (dis) UDPHS_DisablePeripheralClock();
01813 }
01814 
01815 /**
01816  *  \brief Disable Pull-up, disconnect.
01817  *
01818  *  -# Enable HW access if needed
01819  *  -# Disable PULL-Up
01820  *  -# Disable HW access if needed
01821  */
01822 void USBD_HAL_Disconnect(void)
01823 {
01824     Udphs *pUdp = UDPHS;
01825 
01826     uint8_t dis = UDPHS_EnablePeripheralClock();
01827     pUdp->UDPHS_CTRL |= UDPHS_CTRL_DETACH;
01828     pUdp->UDPHS_CTRL &= ~(uint32_t)UDPHS_CTRL_PULLD_DIS;
01829     if (dis) UDPHS_DisablePeripheralClock();
01830 }
01831 
01832 /**
01833  * Starts a remote wake-up procedure.
01834  */
01835 void USBD_HAL_RemoteWakeUp(void)
01836 {
01837     Udphs *pUdp = UDPHS;
01838 
01839     UDPHS_EnablePeripheralClock();
01840     UDPHS_EnableUsbClock();
01841 
01842     TRACE_INFO_WP("RWUp ");
01843 
01844     /* Activates a remote wakeup (edge on ESR), then clear ESR */
01845     pUdp->UDPHS_CTRL |= UDPHS_CTRL_REWAKEUP;
01846     while (pUdp->UDPHS_CTRL & UDPHS_CTRL_REWAKEUP)
01847     {
01848         TRACE_DEBUG_WP("w");
01849     }
01850     UDPHS_EnableBIAS();
01851 }
01852 
01853 /**
01854  * Sets the device address to the given value.
01855  * \param address New device address.
01856  */
01857 void USBD_HAL_SetAddress(uint8_t address)
01858 {
01859     Udphs *pUdp = UDPHS;
01860 
01861     if (address)
01862     {
01863         pUdp->UDPHS_CTRL &= ~(uint32_t)UDPHS_CTRL_DEV_ADDR_Msk;
01864         pUdp->UDPHS_CTRL |= address | UDPHS_CTRL_FADDR_EN;
01865     }
01866     else
01867     {
01868         pUdp->UDPHS_CTRL &= ~(uint32_t)UDPHS_CTRL_FADDR_EN;
01869     }
01870 }
01871 
01872 /**
01873  * Sets the current device configuration.
01874  * \param cfgnum - Configuration number to set.
01875  */
01876 void USBD_HAL_SetConfiguration(uint8_t cfgnum)
01877 {
01878     /* Nothing to do now */
01879     cfgnum = cfgnum;
01880 }
01881 
01882 /**
01883  * Initializes the USB HW Access driver.
01884  */
01885 void USBD_HAL_Init(void)
01886 {
01887     Udphs *pUdp = UDPHS;
01888     UdphsEpt *pEpt;
01889     UdphsDma *pDma;
01890     uint32_t i;
01891 #ifdef DMA
01892     /* DMA Link list should be 16-bytes aligned */
01893     if ((uint32_t)dmaLL & 0xFFFFFFF0)
01894         pDmaLL = (UdphsDmaDescriptor*)((uint32_t)&dmaLL[1] & 0xFFFFFFF0);
01895     else
01896         pDmaLL = (UdphsDmaDescriptor*)((uint32_t)&dmaLL[0]);
01897 #endif
01898     /* Must before USB & TXVC access! */
01899     UDPHS_EnablePeripheralClock();
01900 
01901     /* Reset & disable endpoints */
01902     USBD_HAL_ResetEPs(0xFFFFFFFF, USBD_STATUS_RESET, 0);
01903 
01904     /* Configure the pull-up on D+ and disconnect it */
01905     pUdp->UDPHS_CTRL |= UDPHS_CTRL_DETACH;
01906     pUdp->UDPHS_CTRL |= UDPHS_CTRL_PULLD_DIS;
01907 
01908     /* Reset IP */
01909     pUdp->UDPHS_CTRL &= ~(uint32_t)UDPHS_CTRL_EN_UDPHS;
01910     pUdp->UDPHS_CTRL |= UDPHS_CTRL_EN_UDPHS;
01911 
01912     /* (XCHQ[2010.1.21], IP recomendation, setup clock after reset IP) */
01913     UDPHS_EnableUsbClock();
01914 
01915     /* Initialize DMA */
01916     for (i = 1;
01917          i < ((pUdp->UDPHS_IPFEATURES & UDPHS_IPFEATURES_DMA_CHANNEL_NBR_Msk) >> 4);
01918          i ++)
01919     {
01920         pEpt = &pUdp->UDPHS_EPT[i];
01921         pDma = &pUdp->UDPHS_DMA[i];
01922         /* DMA stop */
01923         pDma->UDPHS_DMACONTROL = 0;
01924         /* Disable endpoint */
01925         pEpt->UDPHS_EPTCTLDIS = (uint32_t)UDPHS_EPTCTLDIS_SHRT_PCKT
01926                               | UDPHS_EPTCTLDIS_BUSY_BANK
01927                               | UDPHS_EPTCTLDIS_NAK_OUT
01928                               | UDPHS_EPTCTLDIS_NAK_IN
01929                               | UDPHS_EPTCTLDIS_STALL_SNT
01930                               | UDPHS_EPTCTLDIS_RX_SETUP
01931                               | UDPHS_EPTCTLDIS_TX_PK_RDY
01932                               | UDPHS_EPTCTLDIS_TX_COMPLT
01933                               | UDPHS_EPTCTLDIS_RX_BK_RDY
01934                               | UDPHS_EPTCTLDIS_ERR_OVFLW
01935                               | UDPHS_EPTCTLDIS_MDATA_RX
01936                               | UDPHS_EPTCTLDIS_DATAX_RX
01937                               | UDPHS_EPTCTLDIS_NYET_DIS
01938                               | UDPHS_EPTCTLDIS_INTDIS_DMA
01939                               | UDPHS_EPTCTLDIS_AUTO_VALID
01940                               | UDPHS_EPTCTLDIS_EPT_DISABL
01941                              ;
01942         /* Clear status endpoint */
01943         pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TOGGLESQ
01944                               | UDPHS_EPTCLRSTA_FRCESTALL
01945                               | UDPHS_EPTCLRSTA_RX_BK_RDY
01946                               | UDPHS_EPTCLRSTA_TX_COMPLT
01947                               | UDPHS_EPTCLRSTA_RX_SETUP
01948                               | UDPHS_EPTCLRSTA_STALL_SNT
01949                               | UDPHS_EPTCLRSTA_NAK_IN
01950                               | UDPHS_EPTCLRSTA_NAK_OUT
01951                              ;
01952         /* Reset endpoint config */
01953         pEpt->UDPHS_EPTCTLENB = 0;
01954         /* Reset DMA channel (Buffer count and Control field) */
01955         pDma->UDPHS_DMACONTROL = UDPHS_DMACONTROL_LDNXT_DSC;
01956         /* Reset DMA channel */
01957         pDma->UDPHS_DMACONTROL = 0;
01958         /* Clear DMA channel status (read to clear) */
01959         pDma->UDPHS_DMASTATUS = pDma->UDPHS_DMASTATUS;
01960     }
01961 
01962     /* Force Full-Speed */
01963     pUdp->UDPHS_TST = forceUsbFS ? UDPHS_TST_SPEED_CFG_FULL_SPEED : 0;
01964 
01965     pUdp->UDPHS_IEN = 0;
01966     pUdp->UDPHS_CLRINT = UDPHS_CLRINT_UPSTR_RES
01967                        | UDPHS_CLRINT_ENDOFRSM
01968                        | UDPHS_CLRINT_WAKE_UP
01969                        | UDPHS_CLRINT_ENDRESET
01970                        | UDPHS_CLRINT_INT_SOF
01971                        | UDPHS_CLRINT_MICRO_SOF
01972                        | UDPHS_CLRINT_DET_SUSPD
01973                       ;
01974 
01975     /* Enable interrupts */
01976     pUdp->UDPHS_IEN = UDPHS_IEN_ENDOFRSM
01977                     | UDPHS_IEN_WAKE_UP
01978                     | UDPHS_IEN_DET_SUSPD;
01979 
01980     /* Disable USB clocks */
01981     UDPHS_DisableUsbClock();
01982 }
01983 
01984 /**
01985  * Causes the given endpoint to acknowledge the next packet it receives
01986  * with a STALL handshake except setup request.
01987  * \param bEP Endpoint number.
01988  * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED.
01989  */
01990 uint8_t USBD_HAL_Stall(uint8_t bEP)
01991 {
01992     Udphs    *pUdp = UDPHS;
01993     UdphsEpt *pEpt = &pUdp->UDPHS_EPT[bEP];
01994 
01995     Endpoint *pEndpoint = &(endpoints[bEP]);
01996 
01997     /* Check that endpoint is in Idle state */
01998     if (pEndpoint->state != UDPHS_ENDPOINT_IDLE)
01999     {
02000         TRACE_WARNING("UDP_Stall: EP%d locked\n\r", bEP);
02001         return USBD_STATUS_LOCKED;
02002     }
02003     /* STALL endpoint */
02004     pEpt->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_FRCESTALL;
02005 
02006     TRACE_DEBUG_WP("Stall%d ", bEP);
02007     return USBD_STATUS_SUCCESS;
02008 }
02009 
02010 /**
02011  * Sets/Clear/Get the HALT state on the endpoint.
02012  * In HALT state, the endpoint should keep stalling any packet.
02013  * \param bEndpoint Endpoint number.
02014  * \param ctl       Control code CLR/HALT/READ.
02015  *                  0: Clear HALT state;
02016  *                  1: Set HALT state;
02017  *                  .: Return HALT status.
02018  * \return USBD_STATUS_INVALID_PARAMETER if endpoint not exist,
02019  *         otherwise endpoint halt status.
02020  */
02021 uint8_t USBD_HAL_Halt(uint8_t bEndpoint, uint8_t ctl)
02022 {
02023     Udphs    *pUdp = UDPHS;
02024     UdphsEpt *pEpt = &pUdp->UDPHS_EPT[bEndpoint];
02025 
02026     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
02027     uint8_t status = 0;
02028 
02029     /* SET Halt */
02030     if (ctl == 1)
02031     {
02032         /* Check that endpoint is enabled and not already in Halt state */
02033         if ((pEndpoint->state != UDPHS_ENDPOINT_DISABLED)
02034             && (pEndpoint->state != UDPHS_ENDPOINT_HALTED))
02035         {
02036 
02037             TRACE_DEBUG_WP("Halt%d ", bEndpoint);
02038 
02039             /* Abort the current transfer if necessary */
02040             UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
02041 
02042             /* Put endpoint into Halt state */
02043             pEndpoint->state = UDPHS_ENDPOINT_HALTED;
02044             pEpt->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_FRCESTALL;
02045 
02046           #ifdef DMA
02047             if (CHIP_USB_ENDPOINTS_DMA(bEndpoint))
02048             {
02049                 /* Enable the endpoint DMA interrupt */
02050                 pUdp->UDPHS_IEN |= ( 1 << SHIFT_DMA << bEndpoint );
02051             }
02052             else
02053             {
02054                 /* Enable the endpoint interrupt */
02055                 pUdp->UDPHS_IEN |= ( UDPHS_IEN_EPT_0 << bEndpoint );
02056             }
02057           #else
02058             /* Enable the endpoint interrupt */
02059             pUdp->UDPHS_IEN |= ( UDPHS_IEN_EPT_0 << bEndpoint );
02060           #endif
02061         }
02062     }
02063     /* CLEAR Halt */
02064     else if (ctl == 0)
02065     {
02066         /* Check if the endpoint is halted */
02067         if (pEndpoint->state == UDPHS_ENDPOINT_HALTED)
02068         {
02069 
02070             TRACE_DEBUG_WP("Unhalt%d ", bEndpoint);
02071 
02072             /* Return endpoint to Idle state */
02073             pEndpoint->state = UDPHS_ENDPOINT_IDLE;
02074 
02075             /* Clear FORCESTALL flag */
02076             pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TOGGLESQ
02077                                   | UDPHS_EPTCLRSTA_FRCESTALL;
02078 
02079             /* Reset Endpoint Fifos */
02080             pUdp->UDPHS_EPTRST = (1 << bEndpoint);
02081         }
02082     }
02083 
02084     /* Return Halt status */
02085     if (pEndpoint->state == UDPHS_ENDPOINT_HALTED)
02086     {
02087         status = 1;
02088     }
02089     return( status );
02090 }
02091 
02092 /**
02093  * Indicates if the device is running in high or full-speed. Always returns 0
02094  * since UDP does not support high-speed mode.
02095  */
02096 uint8_t USBD_HAL_IsHighSpeed(void)
02097 {
02098     Udphs    *pUdp = UDPHS;
02099     return (pUdp->UDPHS_INTSTA & UDPHS_INTSTA_SPEED);
02100 }
02101 
02102 /**
02103  * Suspend USB Device HW Interface
02104  *
02105  * -# Disable transceiver
02106  * -# Disable USB Clock
02107  * -# Disable USB Peripheral
02108  */
02109 void USBD_HAL_Suspend(void)
02110 {
02111     /* The device enters the Suspended state */
02112     UDPHS_DisableBIAS();
02113     UDPHS_DisableUsbClock();
02114     UDPHS_DisablePeripheralClock();
02115 }
02116 
02117 /**
02118  * Activate USB Device HW Interface
02119  * -# Enable USB Peripheral
02120  * -# Enable USB Clock
02121  * -# Enable transceiver
02122  */
02123 void USBD_HAL_Activate(void)
02124 {
02125     UDPHS_EnablePeripheralClock();
02126     UDPHS_EnableUsbClock();
02127     UDPHS_EnableBIAS();
02128 }
02129 
02130 /**
02131  * Certification test for High Speed device.
02132  * \param bIndex Test to be done
02133  */
02134 void USBD_HAL_Test( uint8_t bIndex )
02135 {
02136     Udphs *pUdp = UDPHS;
02137     uint8_t      *pFifo;
02138     uint32_t      i;
02139 
02140     /* remove suspend for TEST */
02141     pUdp->UDPHS_IEN &= ~UDPHS_IEN_DET_SUSPD;
02142     /* force High Speed (remove suspend) */
02143     pUdp->UDPHS_TST |= UDPHS_TST_SPEED_CFG_HIGH_SPEED;
02144 
02145     switch ( bIndex ) {
02146 
02147         case USBFeatureRequest_TESTPACKET:
02148             TRACE_DEBUG_WP("TEST_PACKET ");
02149 
02150             pUdp->UDPHS_DMA[1].UDPHS_DMACONTROL = 0;
02151             pUdp->UDPHS_DMA[2].UDPHS_DMACONTROL = 0;
02152 
02153             /* Configure endpoint 2, 64 bytes, direction IN, type BULK, 1 bank */
02154             pUdp->UDPHS_EPT[2].UDPHS_EPTCFG = UDPHS_EPTCFG_EPT_SIZE_64
02155                                             | UDPHS_EPTCFG_EPT_DIR
02156                                             | UDPHS_EPTCFG_EPT_TYPE_BULK
02157                                             | UDPHS_EPTCFG_BK_NUMBER_1;
02158             while ( (pUdp->UDPHS_EPT[2].UDPHS_EPTCFG & UDPHS_EPTCFG_EPT_MAPD) != UDPHS_EPTCFG_EPT_MAPD );
02159             pUdp->UDPHS_EPT[2].UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_EPT_ENABL;
02160 
02161             /* Write FIFO */
02162             pFifo = (uint8_t*)((uint32_t *)(UDPHS_RAM_ADDR) + (EPT_VIRTUAL_SIZE * 2));
02163             for( i=0; i<sizeof(test_packet_buffer); i++) {
02164                 pFifo[i] = test_packet_buffer[i];
02165             }
02166             /* Tst PACKET */
02167             pUdp->UDPHS_TST |= UDPHS_TST_TST_PKT;
02168             /* Send packet */
02169             pUdp->UDPHS_EPT[2].UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_TX_PK_RDY;
02170             break;
02171 
02172         case USBFeatureRequest_TESTJ:
02173             TRACE_DEBUG_WP("TEST_J ");
02174             pUdp->UDPHS_TST = UDPHS_TST_TST_J;
02175             break;
02176 
02177         case USBFeatureRequest_TESTK:
02178             TRACE_DEBUG_WP("TEST_K ");
02179             pUdp->UDPHS_TST = UDPHS_TST_TST_K;
02180             break;
02181 
02182         case USBFeatureRequest_TESTSE0NAK:
02183             TRACE_DEBUG_WP("TEST_SEO_NAK ");
02184             pUdp->UDPHS_IEN = 0;  // for test
02185             break;
02186 
02187         case USBFeatureRequest_TESTSENDZLP:
02188             //while ( 0 != (pUdp->UDPHS_EPT[0].UDPHS_EPTSTA & UDPHS_EPTSETSTA_TX_PK_RDY ) ) {}
02189             pUdp->UDPHS_EPT[0].UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_TX_PK_RDY;
02190             //while ( 0 != (pUdp->UDPHS_EPT[0].UDPHS_EPTSTA & UDPHS_EPTSETSTA_TX_PK_RDY ) ) {}
02191             TRACE_DEBUG_WP("SEND_ZLP ");
02192             break;
02193     }
02194     TRACE_DEBUG_WP("\n\r");
02195 }
02196 
02197 /**@}*/
02198 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines