SAMV71 Xplained Ultra Software Package 1.5

USBD_HAL.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     Implementation of USB device functions on a UDP controller.
00035 
00036     See \ref usbd_api_method USBD API Methods.
00037 */
00038 
00039 /** \addtogroup usbd_hal
00040  *@{*/
00041 
00042 /*---------------------------------------------------------------------------
00043  *      Headers
00044  *---------------------------------------------------------------------------*/
00045 
00046 #include "chip.h"
00047 #include "USBD_HAL.h"
00048 
00049 #include <stdbool.h>
00050 #include <stdint.h>
00051 #include <stdio.h>
00052 #include <string.h>
00053 
00054 /*---------------------------------------------------------------------------
00055  *      Definitions
00056  *---------------------------------------------------------------------------*/
00057 
00058 #define DMA
00059 
00060 
00061 /** Bits that should be shifted to access interrupt bits. */
00062 #define SHIFT_INTERUPT   12
00063 
00064 /**
00065  * \section endpoint_states_sec "UDP Endpoint states"
00066  *
00067  *  This page lists the endpoint states.
00068  *
00069  *  \subsection States
00070  *  - UDPHS_ENDPOINT_DISABLED
00071  *  - UDPHS_ENDPOINT_HALTED
00072  *  - UDPHS_ENDPOINT_IDLE
00073  *  - UDPHS_ENDPOINT_SENDING
00074  *  - UDPHS_ENDPOINT_RECEIVING
00075  *  - UDPHS_ENDPOINT_SENDINGM
00076  *  - UDPHS_ENDPOINT_RECEIVINGM
00077  */
00078 
00079 /**  Endpoint states: Endpoint is disabled */
00080 #define UDPHS_ENDPOINT_DISABLED       0
00081 /**  Endpoint states: Endpoint is halted (i.e. STALLs every request) */
00082 #define UDPHS_ENDPOINT_HALTED         1
00083 /**  Endpoint states: Endpoint is idle (i.e. ready for transmission) */
00084 #define UDPHS_ENDPOINT_IDLE           2
00085 /**  Endpoint states: Endpoint is sending data */
00086 #define UDPHS_ENDPOINT_SENDING        3
00087 /**  Endpoint states: Endpoint is receiving data */
00088 #define UDPHS_ENDPOINT_RECEIVING      4
00089 /**  Endpoint states: Endpoint is sending MBL */
00090 #define UDPHS_ENDPOINT_SENDINGM       5
00091 /**  Endpoint states: Endpoint is receiving MBL */
00092 #define UDPHS_ENDPOINT_RECEIVINGM     6
00093 
00094 
00095 /** Get Number of buffer in Multi-Buffer-List
00096  *  \param i    input index
00097  *  \param o    output index
00098  *  \param size list size
00099  */
00100 #define MBL_NbBuffer(i, o, size) (((i)>(o))?((i)-(o)):((i)+(size)-(o)))
00101 
00102 /** Buffer list is full */
00103 #define MBL_FULL        1
00104 /** Buffer list is null */
00105 #define MBL_NULL        2
00106 
00107 /*---------------------------------------------------------------------------
00108  *      Types
00109  *---------------------------------------------------------------------------*/
00110 
00111 /** Describes header for UDP endpoint transfer. */
00112 typedef struct {
00113     /** Optional callback to invoke when the transfer completes. */
00114     void *fCallback;
00115     /** Optional argument to the callback function. */
00116     void *pArgument;
00117     /** Transfer type */
00118     uint8_t transType;
00119     /* Reserved to 32-b aligned */
00120     uint8_t reserved[3];
00121 } TransferHeader;
00122 
00123 /** Describes a transfer on a UDP endpoint. */
00124 typedef struct {
00125 
00126     /** Optional callback to invoke when the transfer completes. */
00127     TransferCallback fCallback;
00128     /** Optional argument to the callback function. */
00129     void *pArgument;
00130     /** Transfer type */
00131     uint8_t transType;
00132     uint8_t reserved[3];
00133     /** Number of bytes which have been written into the UDP internal FIFO
00134      * buffers. */
00135     int32_t buffered;
00136     /** Pointer to a data buffer used for emission/reception. */
00137     uint8_t *pData;
00138     /** Number of bytes which have been sent/received. */
00139     int32_t transferred;
00140     /** Number of bytes which have not been buffered/transferred yet. */
00141     int32_t remaining;
00142 } Transfer;
00143 
00144 /** Describes Multi Buffer List transfer on a UDP endpoint. */
00145 typedef struct {
00146     /** Optional callback to invoke when the transfer completes. */
00147     MblTransferCallback fCallback;
00148     /** Optional argument to the callback function. */
00149     void *pArgument;
00150     /** Transfer type */
00151     uint8_t transType;
00152     /** List state (OK, FULL, NULL) (run time) */
00153     uint8_t listState;
00154     /** Multi-Buffer List size */
00155     uint16_t listSize;
00156     /** Pointer to multi-buffer list */
00157     USBDTransferBuffer *pMbl;
00158     /** Offset number of buffers to start transfer */
00159     uint16_t offsetSize;
00160     /** Current processing buffer index (run time) */
00161     uint16_t outCurr;
00162     /** Loaded buffer index (run time) */
00163     uint16_t outLast;
00164     /** Current buffer for input (run time) */
00165     uint16_t inCurr;
00166 } MblTransfer;
00167 
00168 /**
00169  * Describes the state of an endpoint of the UDP controller.
00170  */
00171 typedef struct {
00172     /* CSR */
00173     /** Current endpoint state. */
00174     volatile uint8_t state;
00175     /** Current reception bank (0 or 1). */
00176     volatile uint8_t bank;
00177     /** Maximum packet size for the endpoint. */
00178     volatile uint16_t size;
00179     /** Describes an ongoing transfer (if current state is either */
00180     /** UDPHS_ENDPOINT_SENDING or UDPHS_ENDPOINT_RECEIVING) */
00181     union {
00182         TransferHeader transHdr;
00183         Transfer singleTransfer;
00184         MblTransfer mblTransfer;
00185     } transfer;
00186     /** Special case for send a ZLP */
00187     uint32_t sendZLP;
00188 } Endpoint;
00189 
00190 /**
00191  * DMA Descriptor.
00192  */
00193 typedef struct {
00194     void *pNxtDesc;
00195     void *pAddr;
00196     uint32_t dwCtrl;
00197     uint32_t dw;
00198 } UdphsDmaDescriptor;
00199 
00200 /*---------------------------------------------------------------------------
00201  *      Internal variables
00202  *---------------------------------------------------------------------------*/
00203 
00204 /** Holds the internal state for each endpoint of the UDP. */
00205 static Endpoint endpoints[CHIP_USB_NUMENDPOINTS];
00206 
00207 /** 7.1.20 Test Mode Support
00208  * Test codes for the USB HS test mode. */
00209 static const char test_packet_buffer[] = {
00210     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                   // JKJKJKJK * 9
00211     0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,                         // JJKKJJKK * 8
00212     0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,                         // JJJJKKKK * 8
00213     0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // JJJJJJJKKKKKKK * 8
00214     0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,                               // JJJJJJJK * 8
00215     0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E                    // {JKKKKKKK * 10}, JK
00216 };
00217 
00218 /** DMA link list */
00219 COMPILER_ALIGNED(16) static UdphsDmaDescriptor  dmaLL[5];
00220 COMPILER_ALIGNED(16) static UdphsDmaDescriptor *pDmaLL;
00221 
00222 /*---------------------------------------------------------------------------
00223  *      Internal Functions
00224  *---------------------------------------------------------------------------*/
00225 
00226 /**
00227  * Handles a completed transfer on the given endpoint, invoking the
00228  * configured callback if any.
00229  * \param bEndpoint Number of the endpoint for which the transfer has completed.
00230  * \param bStatus   Status code returned by the transfer operation
00231  */
00232 static void UDPHS_EndOfTransfer(uint8_t bEndpoint, uint8_t bStatus)
00233 {
00234     Endpoint *pEp = &(endpoints[bEndpoint]);
00235 
00236     /* Check that endpoint was sending or receiving data */
00237     if ((pEp->state == UDPHS_ENDPOINT_RECEIVING) ||
00238         (pEp->state == UDPHS_ENDPOINT_SENDING)) {
00239         Transfer *pXfr = (Transfer *)&(pEp->transfer);
00240 
00241         uint32_t transferred = pXfr->transferred;
00242         uint32_t remaining = pXfr->remaining + pXfr->buffered;
00243 
00244         TRACE_DEBUG_WP("EoT ");
00245 
00246         if (pEp->state == UDPHS_ENDPOINT_SENDING)
00247             pEp->sendZLP = 0;
00248 
00249         pEp->state = UDPHS_ENDPOINT_IDLE;
00250         pXfr->pData = 0;
00251         pXfr->transferred = -1;
00252         pXfr->buffered = -1;
00253         pXfr->remaining = -1;
00254 
00255         /* Invoke callback */
00256         if (pXfr->fCallback) {
00257             pXfr->fCallback(pXfr->pArgument, bStatus, transferred, remaining);
00258         }
00259         else {
00260             TRACE_DEBUG_WP("NoCB ");
00261         }
00262     } else if ((pEp->state == UDPHS_ENDPOINT_RECEIVINGM)
00263                || (pEp->state == UDPHS_ENDPOINT_SENDINGM)) {
00264         MblTransfer *pXfr = (MblTransfer *) & (pEp->transfer);
00265         TRACE_DEBUG_WP("EoMT ");
00266 
00267         pEp->state = UDPHS_ENDPOINT_IDLE;
00268         pXfr->listState = 0;
00269         pXfr->outCurr = pXfr->inCurr = pXfr->outLast = 0;
00270 
00271         /* Invoke callback */
00272         if (pXfr->fCallback) {
00273             pXfr->fCallback(pXfr->pArgument, bStatus);
00274         }
00275         else {
00276             TRACE_DEBUG_WP("NoCB ");
00277         }
00278     }
00279 }
00280 
00281 /**
00282  * Update multi-buffer-transfer descriptors.
00283  * \param pTransfer Pointer to instance MblTransfer.
00284  * \param size      Size of bytes that processed.
00285  * \param forceEnd  Force the buffer END.
00286  * \return 1 if current buffer ended.
00287  */
00288 static uint8_t UDPHS_MblUpdate(MblTransfer *pTransfer,
00289                                USBDTransferBuffer *pBi,
00290                                uint16_t size,
00291                                uint8_t forceEnd)
00292 {
00293     /* Update transfer descriptor */
00294     pBi->remaining -= size;
00295 
00296     /* Check if list NULL */
00297     if (pTransfer->listState == MBL_NULL)
00298         return 1;
00299 
00300     /* Check if current buffer ended */
00301     if (pBi->remaining == 0 || forceEnd || size == 0) {
00302         /* Process to next buffer */
00303         if ((++ pTransfer->outCurr) == pTransfer->listSize)
00304             pTransfer->outCurr = 0;
00305 
00306         /* Check buffer NULL case */
00307         if (pTransfer->outCurr == pTransfer->inCurr)
00308             pTransfer->listState = MBL_NULL;
00309         else {
00310             pTransfer->listState = 0;
00311             /* Continue transfer, prepare for next operation */
00312             pBi = &pTransfer->pMbl[pTransfer->outCurr];
00313             pBi->buffered = 0;
00314             pBi->transferred = 0;
00315             pBi->remaining = pBi->size;
00316         }
00317 
00318         return 1;
00319     }
00320 
00321     return 0;
00322 }
00323 
00324 /**
00325  * Transfers a data payload from the current transfer buffer to the endpoint
00326  * FIFO
00327  * \param bEndpoint Number of the endpoint which is sending data.
00328  */
00329 static uint8_t UDPHS_MblWriteFifo(uint8_t bEndpoint)
00330 {
00331     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00332     MblTransfer *pTransfer = (MblTransfer *)&(pEndpoint->transfer);
00333     USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->outCurr]);
00334     uint8_t *pFifo;
00335     int32_t size;
00336 
00337     volatile uint8_t *pBytes;
00338     volatile uint8_t bufferEnd = 1;
00339 
00340     /* Get the number of bytes to send */
00341     size = pEndpoint->size;
00342 
00343     if (size > pBi->remaining) size = pBi->remaining;
00344 
00345     TRACE_DEBUG_WP("w%d.%d ", pTransfer->outCurr, size);
00346 
00347     /* Record last accessed buffer */
00348     pTransfer->outLast = pTransfer->outCurr;
00349 
00350     pBytes = &(pBi->pBuffer[pBi->transferred + pBi->buffered]);
00351     pBi->buffered += size;
00352     bufferEnd = UDPHS_MblUpdate(pTransfer, pBi, size, 0);
00353 
00354     /* Write packet in the FIFO buffer */
00355     pFifo = (uint8_t *)((uint32_t *)USBHS_RAM_ADDR + (EPT_VIRTUAL_SIZE *
00356                         bEndpoint));
00357     memory_sync();
00358 
00359     if (size) {
00360         int32_t c8 = size >> 3;
00361         int32_t c1 = size & 0x7;
00362 
00363         for (; c8; c8 --) {
00364             *(pFifo++) = *(pBytes ++);
00365             *(pFifo++) = *(pBytes ++);
00366             *(pFifo++) = *(pBytes ++);
00367             *(pFifo++) = *(pBytes ++);
00368 
00369             *(pFifo++) = *(pBytes ++);
00370             *(pFifo++) = *(pBytes ++);
00371             *(pFifo++) = *(pBytes ++);
00372             *(pFifo++) = *(pBytes ++);
00373         }
00374 
00375         for (; c1; c1 --)
00376             *(pFifo++) = *(pBytes ++);
00377     }
00378 
00379     return bufferEnd;
00380 }
00381 
00382 /**
00383  * Transfers a data payload from the current transfer buffer to the endpoint
00384  * FIFO
00385  * \param bEndpoint Number of the endpoint which is sending data.
00386  */
00387 static void UDPHS_WritePayload(uint8_t bEndpoint, int32_t size)
00388 {
00389     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00390     Transfer *pTransfer = (Transfer *)&(pEndpoint->transfer);
00391     uint8_t *pFifo;
00392 
00393     /* Get the number of bytes to send */
00394     if (size > pTransfer->remaining)
00395         size = pTransfer->remaining;
00396 
00397     /* Update transfer descriptor information */
00398     pTransfer->buffered += size;
00399     pTransfer->remaining -= size;
00400 
00401     /* Write packet in the FIFO buffer */
00402     pFifo = (uint8_t *)((uint32_t *)USBHS_RAM_ADDR + (EPT_VIRTUAL_SIZE *
00403                         bEndpoint));
00404     memory_sync();
00405 
00406     for (; size; size --)
00407         *(pFifo ++) = *(pTransfer->pData ++);
00408 
00409     memory_sync();
00410 
00411 }
00412 
00413 /**
00414  * Transfers a data payload from an endpoint FIFO to the current transfer buffer
00415  * \param bEndpoint Endpoint number.
00416  * \param wPacketSize Size of received data packet
00417  */
00418 static void UDPHS_ReadPayload(uint8_t bEndpoint, int32_t wPacketSize)
00419 {
00420     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00421     Transfer *pTransfer = (Transfer *)&(pEndpoint->transfer);
00422     uint8_t *pFifo;
00423 
00424     /* Check that the requested size is not bigger than the remaining transfer */
00425     if (wPacketSize > pTransfer->remaining) {
00426         pTransfer->buffered += wPacketSize - pTransfer->remaining;
00427         wPacketSize = pTransfer->remaining;
00428     }
00429 
00430     /* Update transfer descriptor information */
00431     pTransfer->remaining -= wPacketSize;
00432     pTransfer->transferred += wPacketSize;
00433 
00434     /* Retrieve packet */
00435     pFifo = (uint8_t *)((uint32_t *)USBHS_RAM_ADDR
00436                         + (EPT_VIRTUAL_SIZE * bEndpoint));
00437 
00438     while (wPacketSize > 0) {
00439         *(pTransfer->pData++) = *(pFifo++);
00440         memory_sync();
00441         wPacketSize--;
00442     }
00443 }
00444 
00445 /**
00446  * Received SETUP packet from endpoint 0 FIFO
00447  * \param pRequest Generic USB SETUP request sent over Control endpoints
00448  */
00449 static void UDPHS_ReadRequest(USBGenericRequest *pRequest)
00450 {
00451     uint32_t *pData = (uint32_t *)(void *)pRequest;
00452     volatile uint32_t *pFifo;
00453 
00454     pFifo = (volatile uint32_t *)USBHS_RAM_ADDR;
00455     *pData++ = *pFifo;
00456     memory_sync();
00457     pFifo = (volatile uint32_t *)USBHS_RAM_ADDR;
00458     *pData = *pFifo;
00459     memory_sync();
00460 }
00461 
00462 
00463 /**
00464  * Endpoint interrupt handler.
00465  * Handle IN/OUT transfers, received SETUP packets and STALLing
00466  * \param bEndpoint Index of endpoint
00467  */
00468 static void UDPHS_EndpointHandler(uint8_t bEndpoint)
00469 {
00470     Usbhs *pUdp = USBHS;
00471     Endpoint *pEp = &(endpoints[bEndpoint]);
00472     Transfer *pXfr = (Transfer *) & (pEp->transfer);
00473 
00474     uint32_t status = USBHS_ReadEPStatus(pUdp, bEndpoint, 0xFFFFFFFF);
00475     uint32_t type = USBHS_GetEpType(pUdp, bEndpoint);
00476     uint32_t reqBuf[2];
00477     USBGenericRequest *pReq = (USBGenericRequest *)reqBuf;
00478     uint16_t wPktSize;
00479 
00480     TRACE_DEBUG_WP("Ep%d ", bEndpoint);
00481 
00482     /* IN packet sent */
00483     /* When the bank is empty, USBHS_DEVEPTISRx.TXINI and USBHS_DEVEPTIMRx.FIFOCON
00484     are set, which triggers a PEP_x interrupt if USBHS_DEVEPTIMRx.TXINE = 1.*/
00485     if ((status & USBHS_DEVEPTISR_TXINI)
00486         && USBHS_IsEpIntEnable(pUdp, bEndpoint, USBHS_DEVEPTIMR_TXINE)) {
00487         TRACE_DEBUG_WP("Wr ");
00488 
00489         /* Multi-buffer-list transfer state */
00490         if (pEp->state == UDPHS_ENDPOINT_SENDINGM) {
00491         } else if (pEp->state == UDPHS_ENDPOINT_SENDING) {
00492             /* Sending state */
00493             if (pXfr->buffered) {
00494                 pXfr->transferred += pXfr->buffered;
00495                 pXfr->buffered = 0;
00496             }
00497 
00498             /* Force ZLP transmission in total length is a
00499                 multiple of endpoint size */
00500             if (((pXfr->transferred % pEp->size) == 0)
00501                 && (pXfr->remaining == 0)
00502                 && (pXfr->transferred > 0)
00503                 && (pEp->sendZLP == 0))
00504                 pEp->sendZLP = 1;
00505 
00506 
00507             if (pXfr->buffered == 0
00508                 && pXfr->transferred == 0
00509                 && pXfr->remaining == 0
00510                 && pEp->sendZLP == 0)
00511                 pEp->sendZLP = 1;
00512 
00513             /* End of Xfr ? */
00514             if (pXfr->remaining || pEp->sendZLP == 1) {
00515                 if (pEp->sendZLP == 1)
00516                     /* A null packet will be send, keep trace of it :
00517                     Change this value only if ZLP will be send!!! */
00518                     pEp->sendZLP = 2;
00519 
00520                 /* Transfer remaining */
00521                 TRACE_DEBUG_WP("%d ", pEp->size);
00522 
00523                 /* The user writes the data into the current bank by using
00524                 the USB Pipe/Endpoint nFIFO Data */
00525                 UDPHS_WritePayload(bEndpoint, pEp->size);
00526 
00527                 /*Acknowledges the interrupt by clearing TXINIC.*/
00528                 USBHS_AckEpInterrupt(USBHS, bEndpoint, USBHS_DEVEPTICR_TXINIC);
00529 
00530                 if (type != USBHS_DEVEPTCFG_EPTYPE_CTRL >> USBHS_DEVEPTCFG_EPTYPE_Pos)
00531                     /* Send the bank and switch to the next bank (if any) by clearing FIFOCON. */
00532                     USBHS_DisableEPIntType(pUdp, bEndpoint, USBHS_DEVEPTIDR_FIFOCONC);
00533             } else {
00534                 /* Transfer done */
00535                 TRACE_DEBUG_WP("l%d ", pXfr->transferred);
00536 
00537                 /* Disable interrupt on non-control EP */
00538                 if (type != USBHS_DEVEPTCFG_EPTYPE_CTRL >> USBHS_DEVEPTCFG_EPTYPE_Pos)
00539                     USBHS_DisableIntEP(pUdp, bEndpoint);
00540 
00541                 USBHS_DisableEPIntType(pUdp, bEndpoint, USBHS_DEVEPTIDR_TXINEC);
00542                 UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00543                 pEp->sendZLP = 0;
00544             }
00545         } else {
00546             /* Clear interrupt when the state of endpoint0 is not SENDING. */
00547             if (bEndpoint == 0)
00548                 USBHS_AckEpInterrupt(USBHS, bEndpoint, USBHS_DEVEPTICR_TXINIC);
00549 
00550             TRACE_DEBUG("Err Wr %d\n\r", pEp->sendZLP);
00551         }
00552     }
00553 
00554     /* OUT packet received */
00555     if (USBHS_DEVEPTISR_RXOUTI & status) {
00556         TRACE_DEBUG_WP("Rd ");
00557 
00558         /* NOT in receiving state */
00559         if (pEp->state != UDPHS_ENDPOINT_RECEIVING) {
00560             /* Check if ACK received on a Control EP */
00561             if (((USBHS_DEVEPTCFG_EPTYPE_CTRL >> USBHS_DEVEPTCFG_EPTYPE_Pos) == type)
00562                 && (0 == (status & USBHS_DEVEPTISR_BYCT_Msk))) {
00563                 TRACE_INFO_WP("Ack ");
00564                 USBHS_AckEpInterrupt(pUdp, bEndpoint, USBHS_DEVEPTICR_RXOUTIC);
00565                 UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00566             }
00567             /* data has been STALLed */
00568             else if (USBHS_DEVEPTISR_STALLEDI & status) {
00569                 TRACE_INFO_WP("Discard ");
00570                 USBHS_AckEpInterrupt(pUdp, bEndpoint, USBHS_DEVEPTICR_RXOUTIC);
00571             }
00572             /* NAK the data */
00573             else {
00574                 TRACE_INFO_WP("Nak ");
00575                 USBHS_AckEpInterrupt(pUdp, bEndpoint, USBHS_DEVEPTICR_RXOUTIC);
00576             }
00577         }
00578         /* In read state */
00579         else {
00580             TRACE_DEBUG_WP("%d ", wPktSize);
00581 
00582             /*Acknowledge Received OUT Data Interrupt*/
00583             USBHS_AckEpInterrupt(pUdp, bEndpoint, USBHS_DEVEPTICR_RXOUTIC);
00584 
00585             wPktSize = USBHS_ByteCount(pUdp, bEndpoint);
00586             UDPHS_ReadPayload(bEndpoint, wPktSize);
00587 
00588             /*Free the current bank and to switch to the next bank (If any).*/
00589             if (type != USBHS_DEVEPTCFG_EPTYPE_CTRL >> USBHS_DEVEPTCFG_EPTYPE_Pos)
00590                 USBHS_DisableEPIntType(pUdp, bEndpoint, USBHS_DEVEPTIDR_FIFOCONC);
00591 
00592             /* Check if transfer is finished */
00593             if (pXfr->remaining == 0 || wPktSize < pEp->size) {
00594                 USBHS_DisableEPIntType(pUdp, bEndpoint, USBHS_DEVEPTIDR_RXOUTEC);
00595 
00596                 /* Disable interrupt if not control EP */
00597                 if ((USBHS_DEVEPTCFG_EPTYPE_CTRL >> USBHS_DEVEPTCFG_EPTYPE_Pos) != type)
00598                     USBHS_DisableIntEP(pUdp, bEndpoint);
00599 
00600                 UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00601                 USBHS_AckEpInterrupt(pUdp, bEndpoint, USBHS_DEVEPTICR_NAKINIC);
00602                 USBHS_AckEpInterrupt(pUdp, bEndpoint, USBHS_DEVEPTICR_TXINIC);
00603             }
00604         }
00605     }
00606 
00607     /* STALL sent */
00608     if (USBHS_DEVEPTISR_STALLEDI & status) {
00609         /* Acknowledge */
00610         USBHS_AckEpInterrupt(pUdp, bEndpoint, USBHS_DEVEPTICR_STALLEDIC);
00611 
00612         /* ISO error */
00613         if (type == (USBHS_DEVEPTCFG_EPTYPE_ISO >> USBHS_DEVEPTCFG_EPTYPE_Pos)) {
00614             TRACE_WARNING("IsoE[%d]\n\r", bEndpoint);
00615             UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
00616             /* If EP is not halted, clear STALL */
00617         } else {
00618             TRACE_WARNING("Stall[%d]\n\r", bEndpoint);
00619 
00620             if (pEp->state != UDPHS_ENDPOINT_HALTED)
00621                 USBHS_DisableEPIntType(pUdp, bEndpoint, USBHS_DEVEPTIDR_STALLRQC);
00622         }
00623     }
00624 
00625     /* SETUP packet received */
00626     if (USBHS_DEVEPTISR_RXSTPI & status) {
00627         /* If a transfer was pending, complete it
00628            Handles the case where during the status phase of a control write
00629            transfer, the host receives the device ZLP and ack it, but the ack
00630            is not received by the device */
00631         if (pEp->state == UDPHS_ENDPOINT_RECEIVING
00632             || pEp->state == UDPHS_ENDPOINT_RECEIVINGM
00633             || pEp->state == UDPHS_ENDPOINT_SENDING
00634             || pEp->state == UDPHS_ENDPOINT_SENDINGM)
00635             UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00636 
00637         /* ISO Err Flow */
00638         if (type == (USBHS_DEVEPTCFG_EPTYPE_ISO >> USBHS_DEVEPTCFG_EPTYPE_Pos)) {
00639             TRACE_WARNING("IsoFE[%d]\n\r", bEndpoint);
00640             /* Acknowledge setup packet */
00641             USBHS_AckEpInterrupt(pUdp, bEndpoint, USBHS_DEVEPTICR_RXSTPIC);
00642         } else {
00643             TRACE_DEBUG_WP("Stup ");
00644             /* Copy setup */
00645             UDPHS_ReadRequest(pReq);
00646             /* Acknowledge setup packet */
00647             USBHS_AckEpInterrupt(pUdp, bEndpoint, USBHS_DEVEPTICR_RXSTPIC);
00648 
00649             /* Handler */
00650             USBD_RequestHandler(bEndpoint, pReq);
00651         }
00652     }
00653 }
00654 #ifdef DMA
00655 /**
00656  * DMA Single transfer
00657  * \param bEndpoint EP number.
00658  * \pXfr  Pointer to transfer instance.
00659  * \dwCfg DMA Control configuration (excluding length).
00660  */
00661 static inline void UDPHS_DmaSingle(uint8_t bEndpoint, Transfer *pXfr,
00662                                    uint32_t dwCfg)
00663 {
00664     Usbhs *pUdp = USBHS;
00665     UsbhsDevdma *pUsbDma = &pUdp->USBHS_DEVDMA[bEndpoint];
00666 
00667     /* Single transfer */
00668     USBHS_SetDmaBuffAdd(pUsbDma, (uint32_t)&pXfr->pData[pXfr->transferred]);
00669     USBHS_GetDmaStatus(pUsbDma);
00670 
00671     TRACE_DEBUG_WP("Dma[B%d:T%d] ", pXfr->buffered, pXfr->transferred);
00672     /* DMA Configure */
00673     USBHS_ConfigureDma(pUsbDma, 0);
00674     USBHS_ConfigureDma(pUsbDma,
00675                        (USBHS_DEVDMACONTROL_BUFF_LENGTH(pXfr->buffered) | dwCfg));
00676 
00677     /* Interrupt enable */
00678     USBHS_EnableDMAIntEP(pUdp, bEndpoint);
00679 }
00680 /**
00681  * Endpoint DMA interrupt handler.
00682  * This function handles DMA interrupts.
00683  * \param bEndpoint Index of endpoint
00684  */
00685 static void UDPHS_DmaHandler(uint8_t bEndpoint)
00686 {
00687     Usbhs *pUdp = USBHS;
00688     uint8_t bDmaEndpoint = bEndpoint - 1;
00689 
00690     Endpoint *pEp = &(endpoints[bEndpoint]);
00691     Transfer *pXfr = (Transfer *)&(pEp->transfer);
00692 
00693     uint32_t dwDmaSr;
00694     int32_t iRemain, iXfred;
00695     uint8_t iRead = 0;
00696     uint8_t bRc = USBD_STATUS_SUCCESS;
00697     UsbhsDevdma *pUsbDma = &pUdp->USBHS_DEVDMA[bDmaEndpoint];
00698 
00699     dwDmaSr = USBHS_GetDmaStatus(pUsbDma);
00700     TRACE_DEBUG_WP("iDma%d,%x ", bDmaEndpoint, dwDmaSr);
00701 
00702     /* Mbl transfer */
00703     if (pEp->state == UDPHS_ENDPOINT_SENDINGM)
00704         /* Not implemented */
00705         return;
00706     else if (pEp->state == UDPHS_ENDPOINT_RECEIVINGM)
00707         /* Not implemented */
00708         return;
00709 
00710     if ((pUdp->USBHS_DEVDMA[bDmaEndpoint].USBHS_DEVDMACONTROL
00711          & USBHS_DEVDMACONTROL_END_TR_EN) == USBHS_DEVDMACONTROL_END_TR_EN)
00712         iRead = 1;
00713 
00714     /* Disable DMA interrupt to avoid receiving 2 (B_EN and TR_EN) */
00715     pUdp->USBHS_DEVDMA[bDmaEndpoint].USBHS_DEVDMACONTROL &= ~
00716             (USBHS_DEVDMACONTROL_END_TR_EN
00717              | USBHS_DEVDMACONTROL_END_B_EN);
00718 
00719     if (USBHS_DEVDMASTATUS_END_BF_ST & dwDmaSr) {
00720         TRACE_DEBUG_WP("EoDmaB ");
00721         /* BUFF_COUNT holds the number of untransmitted bytes.
00722            BUFF_COUNT is equal to zero in case of good transfer */
00723         iRemain = (dwDmaSr & USBHS_DEVDMASTATUS_BUFF_COUNT_Msk)
00724                   >> USBHS_DEVDMASTATUS_BUFF_COUNT_Pos;
00725         TRACE_DEBUG_WP("C%d ", iRemain);
00726         iXfred = pXfr->buffered - iRemain;
00727 
00728         pXfr->transferred += iXfred;
00729         pXfr->buffered = iRemain;
00730         pXfr->remaining -= iXfred;
00731         TRACE_DEBUG_WP("[B%d:T%d:R%d] ", pXfr->buffered, pXfr->transferred,
00732                        pXfr->remaining);
00733 
00734         /* There is still data */
00735         if (pXfr->remaining + pXfr->buffered > 0) {
00736             if (pXfr->remaining > DMA_MAX_FIFO_SIZE)
00737                 pXfr->buffered = DMA_MAX_FIFO_SIZE;
00738             else
00739                 pXfr->buffered = pXfr->remaining;
00740 
00741             /* Single transfer again */
00742             UDPHS_DmaSingle(bDmaEndpoint, pXfr, USBHS_DEVDMACONTROL_END_TR_EN
00743                             | USBHS_DEVDMACONTROL_END_TR_IT
00744                             | USBHS_DEVDMACONTROL_END_B_EN
00745                             | USBHS_DEVDMACONTROL_END_BUFFIT
00746                             | USBHS_DEVDMACONTROL_CHANN_ENB);
00747         }
00748     } else if (USBHS_DEVDMASTATUS_END_TR_ST & dwDmaSr) {
00749         TRACE_DEBUG_WP("EoDmaT ");
00750         pXfr->transferred = pXfr->buffered -
00751                             ((dwDmaSr & USBHS_DEVDMASTATUS_BUFF_COUNT_Msk)
00752                              >> USBHS_DEVDMASTATUS_BUFF_COUNT_Pos);
00753         pXfr->remaining = 0;
00754 
00755         TRACE_DEBUG_WP("[B%d:T%d] ", pXfr->buffered, pXfr->transferred);
00756     } else {
00757         TRACE_ERROR("UDPHS_DmaHandler: ST 0x%X\n\r", (unsigned int)dwDmaSr);
00758         bRc = USBD_STATUS_ABORTED;
00759     }
00760 
00761     /* Callback */
00762     if (pXfr->remaining == 0) {
00763         if (iRead)
00764             SCB_InvalidateDCache_by_Addr((uint32_t *)pXfr->pData, pXfr->transferred);
00765 
00766         UDPHS_EndOfTransfer(bEndpoint, bRc);
00767     }
00768 }
00769 #endif
00770 /**
00771  * Sends data through a USB endpoint. Sets up the transfer descriptor,
00772  * writes one or two data payloads (depending on the number of FIFO bank
00773  * for the endpoint) and then starts the actual transfer. The operation is
00774  * complete when all the data has been sent.
00775  *
00776  * *If the size of the buffer is greater than the size of the endpoint
00777  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
00778  *  must be kept allocated until the transfer is finished*. This means that
00779  *  it is not possible to declare it on the stack (i.e. as a local variable
00780  *  of a function which returns after starting a transfer).
00781  *
00782  * \param pEndpoint Pointer to Endpoint struct.
00783  * \param pData Pointer to a buffer with the data to send.
00784  * \param dLength Size of the data buffer.
00785  * \return USBD_STATUS_SUCCESS if the transfer has been started;
00786  *         otherwise, the corresponding error status code.
00787  */
00788 static inline uint8_t UDPHS_Write(uint8_t bEndpoint,
00789                                   const void *pData,
00790                                   uint32_t dLength)
00791 {
00792     Usbhs *pUdp = USBHS;
00793     uint8_t bDmaEndpoint = bEndpoint - 1;
00794 
00795     Endpoint *pEp = &(endpoints[bEndpoint]);
00796     Transfer *pXfr = (Transfer *)&(pEp->transfer);
00797 
00798     /* Return if busy */
00799     if (pEp->state != UDPHS_ENDPOINT_IDLE)
00800         return USBD_STATUS_LOCKED;
00801 
00802     /* Sending state */
00803     pEp->state = UDPHS_ENDPOINT_SENDING;
00804     TRACE_DEBUG_WP("Wr%d(%d) ", bEndpoint, dLength);
00805     pEp->sendZLP = 0;
00806     /* Setup transfer descriptor */
00807     pXfr->pData = (void *) pData;
00808     pXfr->remaining = dLength;
00809     pXfr->buffered = 0;
00810     pXfr->transferred = 0;
00811 
00812 #ifdef DMA
00813 
00814     /* 1. DMA supported, 2. Not ZLP */
00815     if (CHIP_USB_ENDPOINTS_DMA(bEndpoint)
00816         && pXfr->remaining > 0) {
00817         /* Enable automatic bank switch for DMA*/
00818         USBHS_AutoSwitchBankEnable(pUdp, bEndpoint, true);
00819 
00820         if (pXfr->remaining > DMA_MAX_FIFO_SIZE)
00821             /* Transfer the max */
00822             pXfr->buffered = DMA_MAX_FIFO_SIZE;
00823         else
00824             /* Good size */
00825             pXfr->buffered = pXfr->remaining;
00826 
00827         /* Single transfer */
00828         SCB_CleanDCache_by_Addr((uint32_t *) pData, dLength);
00829         UDPHS_DmaSingle(bDmaEndpoint, pXfr, USBHS_DEVDMACONTROL_END_B_EN
00830                         | USBHS_DEVDMACONTROL_END_BUFFIT
00831                         | USBHS_DEVDMACONTROL_CHANN_ENB);
00832         return USBD_STATUS_SUCCESS;
00833     }
00834 
00835     /* Wait for the bank to be free in order to transfer data without DMA correctly
00836      * when the last is done with DMA */
00837     if (bEndpoint)
00838         while (USBHS_IsBankFree(pUdp, bEndpoint) == false);
00839 
00840 #endif
00841     /* Disable automatic bank switch*/
00842     USBHS_AutoSwitchBankEnable(pUdp, bEndpoint, false);
00843     /* Enable IT */
00844     USBHS_EnableIntEP(pUdp, bEndpoint);
00845     USBHS_EnableEPIntType(pUdp, bEndpoint, USBHS_DEVEPTIER_TXINES);
00846     return USBD_STATUS_SUCCESS;
00847 }
00848 
00849 /**
00850  * Sends data through a USB endpoint. Sets up the transfer descriptor list,
00851  * writes one or two data payloads (depending on the number of FIFO bank
00852  * for the endpoint) and then starts the actual transfer. The operation is
00853  * complete when all the transfer buffer in the list has been sent.
00854  *
00855  * *If the size of the buffer is greater than the size of the endpoint
00856  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
00857  *  must be kept allocated until the transfer is finished*. This means that
00858  *  it is not possible to declare it on the stack (i.e. as a local variable
00859  *  of a function which returns after starting a transfer).
00860  *
00861  * \param pEndpoint Pointer to Endpoint struct.
00862  * \param pData Pointer to a buffer with the data to send.
00863  * \param dLength Size of the data buffer.
00864  * \return USBD_STATUS_SUCCESS if the transfer has been started;
00865  *         otherwise, the corresponding error status code.
00866  */
00867 static inline uint8_t UDPHS_AddWr(uint8_t bEndpoint,
00868                                   const void *pData,
00869                                   uint32_t dLength)
00870 {
00871     Usbhs *pUdp = USBHS;
00872 
00873     Endpoint *pEp = &(endpoints[bEndpoint]);
00874     MblTransfer *pMbl = (MblTransfer *)&(pEp->transfer);
00875     USBDTransferBuffer *pTx;
00876 
00877     /* Check parameter */
00878     if (dLength >= 0x10000)
00879         return USBD_STATUS_INVALID_PARAMETER;
00880 
00881     /* Data in process */
00882     if (pEp->state > UDPHS_ENDPOINT_IDLE) {
00883         /* MBL transfer */
00884         if (pMbl->transType) {
00885             if (pMbl->listState == MBL_FULL)
00886                 return USBD_STATUS_LOCKED;
00887         } else
00888             return USBD_STATUS_LOCKED;
00889     }
00890 
00891     TRACE_DEBUG_WP("AddW%d(%d) ", bEndpoint, dLength);
00892     /* Add buffer to buffer list and update index */
00893     pTx = &(pMbl->pMbl[pMbl->inCurr]);
00894     pTx->pBuffer = (uint8_t *)pData;
00895     pTx->size = pTx->remaining = dLength;
00896     pTx->transferred = pTx->buffered = 0;
00897 
00898     /* Update input index */
00899     if (pMbl->inCurr >= (pMbl->listSize - 1))
00900         pMbl->inCurr = 0;
00901     else
00902         pMbl->inCurr ++;
00903 
00904     if (pMbl->inCurr == pMbl->outCurr)
00905         pMbl->listState = MBL_FULL;
00906     else
00907         pMbl->listState = 0;
00908 
00909     /* Start sending when offset achieved */
00910     if (MBL_NbBuffer(pMbl->inCurr, pMbl->outCurr, pMbl->listSize)
00911         >= pMbl->offsetSize
00912         && pEp->state == UDPHS_ENDPOINT_IDLE) {
00913         uint8_t nbBanks = CHIP_USB_ENDPOINTS_BANKS(bEndpoint);
00914 
00915         /* Change state */
00916         pEp->state = UDPHS_ENDPOINT_SENDINGM;
00917         TRACE_DEBUG_WP("StartM ");
00918 
00919         /* Fill data into FIFO */
00920         for (; nbBanks && pMbl->pMbl[pMbl->inCurr].remaining; nbBanks --) {
00921             UDPHS_MblWriteFifo(bEndpoint);
00922             USBHS_RaiseEPInt(pUdp, bEndpoint, USBHS_DEVEPTIFR_TXINIS);
00923         }
00924 
00925         /* Enable interrupt */
00926         USBHS_EnableIntEP(pUdp, bEndpoint);
00927         USBHS_EnableEPIntType(pUdp, bEndpoint, USBHS_DEVEPTIER_TXINES);
00928     }
00929 
00930     return USBD_STATUS_SUCCESS;
00931 }
00932 
00933 /**
00934  * Reads incoming data on an USB endpoint This methods sets the transfer
00935  * descriptor and activate the endpoint interrupt. The actual transfer is
00936  * then carried out by the endpoint interrupt handler. The Read operation
00937  * finishes either when the buffer is full, or a short packet (inferior to
00938  * endpoint maximum size) is received.
00939  *
00940  * *The buffer must be kept allocated until the transfer is finished*.
00941  * \param bEndpoint Endpoint number.
00942  * \param pData Pointer to a data buffer.
00943  * \param dLength Size of the data buffer in bytes.
00944  * \return USBD_STATUS_SUCCESS if the read operation has been started;
00945  *         otherwise, the corresponding error code.
00946  */
00947 static inline uint8_t UDPHS_Read(uint8_t bEndpoint,
00948                                  void *pData,
00949                                  uint32_t dLength)
00950 {
00951     Usbhs *pUdp = USBHS;
00952     uint8_t bDmaEndpoint = (bEndpoint - 1);
00953     Endpoint *pEp = &(endpoints[bEndpoint]);
00954     Transfer *pXfr = (Transfer *)&(pEp->transfer);
00955 
00956     /* Return if busy */
00957     if (pEp->state != UDPHS_ENDPOINT_IDLE)
00958         return USBD_STATUS_LOCKED;
00959 
00960     /* Receiving state */
00961     pEp->state = UDPHS_ENDPOINT_RECEIVING;
00962 
00963     TRACE_DEBUG_WP("Rd%d(%d) ", bEndpoint, dLength);
00964     /* Setup transfer descriptor */
00965     pXfr->pData = (void *)pData;
00966     pXfr->remaining = dLength;
00967     pXfr->buffered = 0;
00968     pXfr->transferred = 0;
00969 
00970 #ifdef DMA
00971 
00972     /* If: 1. DMA supported, 2. Has data */
00973     if (CHIP_USB_ENDPOINTS_DMA(bEndpoint) && pXfr->remaining > 0) {
00974         /* DMA XFR size adjust */
00975         if (pXfr->remaining > DMA_MAX_FIFO_SIZE)
00976             pXfr->buffered = DMA_MAX_FIFO_SIZE;
00977         else
00978             pXfr->buffered = pXfr->remaining;
00979 
00980         /* Single transfer */
00981         UDPHS_DmaSingle(bDmaEndpoint, pXfr, USBHS_DEVDMACONTROL_END_TR_EN
00982                         | USBHS_DEVDMACONTROL_END_TR_IT
00983                         | USBHS_DEVDMACONTROL_END_B_EN
00984                         | USBHS_DEVDMACONTROL_END_BUFFIT
00985                         | USBHS_DEVDMACONTROL_CHANN_ENB);
00986         return USBD_STATUS_SUCCESS;
00987     }
00988 
00989 #endif
00990 
00991     /* Enable IT */
00992     USBHS_EnableIntEP(pUdp, bEndpoint);
00993     USBHS_EnableEPIntType(pUdp, bEndpoint, USBHS_DEVEPTIER_RXOUTES);
00994 
00995     return USBD_STATUS_SUCCESS;
00996 }
00997 
00998 /*---------------------------------------------------------------------------
00999  *      Exported functions
01000  *---------------------------------------------------------------------------*/
01001 /**
01002  * USBD (UDP) interrupt handler
01003  * Manages device resume, suspend, end of bus reset.
01004  * Forwards endpoint events to the appropriate handler.
01005  */
01006 void USBHS_Handler(void)
01007 {
01008     Usbhs *pUdp = USBHS;
01009 
01010     uint32_t status;
01011     uint8_t numIt;
01012 
01013     status = USBHS_ReadIntStatus(pUdp, 0xFFFFFFFF);
01014     status &= USBHS_IsIntEnable(pUdp, 0xFFFFFFFF);
01015 
01016     /* Handle all USBHS interrupts */
01017     TRACE_DEBUG_WP("\n\r%c ", USBD_HAL_IsHighSpeed() ? 'H' : 'F');
01018 
01019     while (status) {
01020         /* SOF */
01021         if (status & USBHS_DEVISR_SOF) {
01022             TRACE_DEBUG_WP("SOF ");
01023             /* SOF handler */
01024             /* Acknowledge interrupt */
01025             USBHS_AckInt(pUdp, USBHS_DEVICR_SOFC);
01026         } else if (status & USBHS_DEVISR_MSOF) {
01027             /* MOSF */
01028             TRACE_DEBUG_WP("Mosf ");
01029             /* Acknowledge interrupt */
01030             USBHS_AckInt(pUdp, USBHS_DEVICR_MSOFC);
01031         } else if (status & USBHS_DEVISR_SUSP) {
01032             /* Suspend, treated last */
01033             TRACE_WARNING_WP("Susp ");
01034             USBHS_UnFreezeClock(USBHS);
01035             USBHS_AckInt(pUdp, USBHS_DEVICR_SUSPC);
01036             USBHS_DisableInt(pUdp, USBHS_DEVIDR_SUSPEC);
01037 
01038             /* Enable wakeup */
01039             USBHS_EnableInt(pUdp, USBHS_DEVIER_WAKEUPES);
01040             USBHS_FreezeClock(pUdp);
01041             USBD_SuspendHandler();
01042             USBHS_EnableInt(pUdp, USBHS_DEVIER_UPRSMES);
01043         } else if (status & USBHS_DEVISR_WAKEUP) {
01044             /* Resume */
01045             TRACE_INFO_WP("Rsm ");
01046             USBHS_UnFreezeClock(USBHS);
01047             USBHS_AckInt(pUdp, USBHS_DEVICR_WAKEUPC);
01048             USBHS_DisableInt(pUdp, USBHS_DEVIDR_WAKEUPEC);
01049             /* Acknowledge interrupt */
01050 
01051             USBHS_EnableInt(pUdp, (USBHS_DEVIER_SUSPES | USBHS_DEVIER_EORSMES));
01052             USBD_ResumeHandler();
01053         } else if (status & USBHS_DEVISR_EORSM) {
01054             /* Bus reset */
01055             USBHS_AckInt(pUdp, (USBHS_DEVICR_EORSMC));
01056             USBHS_DisableInt(pUdp, (USBHS_DEVIDR_EORSMEC));
01057         } else if (status & USBHS_DEVISR_EORST) {
01058             TRACE_DEBUG_WP("EoB ");
01059             /* Acknowledge interrupt */
01060             USBHS_AckInt(pUdp, USBHS_DEVICR_EORSTC);
01061             /* Flush and enable the suspend interrupt */
01062             USBHS_AckInt(pUdp, (USBHS_DEVICR_SUSPC | USBHS_DEVICR_WAKEUPC));
01063             USBHS_EnableInt(pUdp, USBHS_DEVIER_SUSPES);
01064 
01065             /* Reset handler */
01066             USBD_ResetHandler();
01067             USBHS_EnableInt(pUdp, USBHS_DEVIER_SUSPES |
01068                             USBHS_DEVIER_SOFES | USBHS_DEVIER_MSOFES);
01069         } else if (status & USBHS_DEVISR_UPRSM) {
01070             /* Upstream resume */
01071             TRACE_DEBUG_WP("ExtRes ");
01072             /* Acknowledge interrupt */
01073             USBHS_AckInt(pUdp, USBHS_DEVICR_UPRSMC);
01074             USBHS_EnableInt(pUdp, (USBHS_DEVIER_EORSMES));
01075         } else {
01076             /* Endpoints */
01077             for (numIt = 0; numIt < CHIP_USB_NUMENDPOINTS; numIt++) {
01078 #ifdef DMA
01079 
01080                 if ((CHIP_USB_ENDPOINTS_DMA(numIt))
01081                     && USBHS_ReadDmaIntStatus(pUdp, numIt - 1))
01082                     UDPHS_DmaHandler(numIt);
01083                 else
01084 #endif
01085                     if (USBHS_ReadEpIntStatus(pUdp, numIt))
01086                         UDPHS_EndpointHandler(numIt);
01087             }
01088         }
01089 
01090         /* Update interrupt status */
01091         status = USBHS_ReadIntStatus(pUdp, 0xFFFFFFFF);
01092         status &= USBHS_IsIntEnable(pUdp, 0xFFFFFFFF);
01093 
01094         TRACE_DEBUG_WP("\n\r");
01095 
01096         if (status) {
01097             TRACE_DEBUG_WP(" - ");
01098         }
01099     }
01100 
01101     NVIC_ClearPendingIRQ(USBHS_IRQn); // clear l'IRQ
01102     memory_sync();
01103 
01104 }
01105 
01106 /**
01107  * \brief Reset endpoints and disable them.
01108  * -# Terminate transfer if there is any, with given status;
01109  * -# Reset the endpoint & disable it.
01110  * \param bmEPs    Bitmap for endpoints to reset.
01111  * \param bStatus  Status passed to terminate transfer on endpoint.
01112  * \param bKeepCfg 1 to keep old endpoint configuration.
01113  * \note Use USBD_HAL_ConfigureEP() to configure and enable endpoint
01114          if not keeping old configuration.
01115  * \sa USBD_HAL_ConfigureEP().
01116  */
01117 void USBD_HAL_ResetEPs(uint32_t bmEPs, uint8_t bStatus, uint8_t bKeepCfg)
01118 {
01119     Usbhs *pUdp = USBHS;
01120 
01121     Endpoint *pEndpoint;
01122     uint32_t tmp = bmEPs & ((1 << CHIP_USB_NUMENDPOINTS) - 1);
01123     uint8_t ep;
01124     uint32_t epBit, epCfg;
01125 
01126     for (ep = 0, epBit = 1; ep < CHIP_USB_NUMENDPOINTS; ep ++) {
01127         if (tmp & epBit) {
01128             /* Disable ISR */
01129             pUdp->USBHS_DEVIDR |= (epBit << SHIFT_INTERUPT);
01130             /* Reset transfer information */
01131             pEndpoint = &(endpoints[ep]);
01132             /* Reset endpoint state */
01133             pEndpoint->bank = 0;
01134             /* Endpoint configure */
01135             epCfg = pUdp->USBHS_DEVEPTCFG[ep];
01136             /* Reset endpoint */
01137             USBHS_ResetEP(pUdp, ep);
01138 
01139             /* Restore configure */
01140             if (bKeepCfg)
01141                 pUdp->USBHS_DEVEPTCFG[ep] = epCfg;
01142             else
01143                 pEndpoint->state = UDPHS_ENDPOINT_DISABLED;
01144 
01145             /*Clear data toggle sequence*/
01146             USBHS_EnableEPIntType(pUdp, ep, USBHS_DEVEPTIER_RSTDTS);
01147 
01148             /* Terminate transfer on this EP */
01149             UDPHS_EndOfTransfer(ep, bStatus);
01150         }
01151 
01152         epBit <<= 1;
01153     }
01154 }
01155 
01156 /**
01157  * Cancel pending READ/WRITE
01158  * \param bmEPs    Bitmap for endpoints to reset.
01159  * \note EP callback is invoked with USBD_STATUS_CANCELED.
01160  */
01161 void USBD_HAL_CancelIo(uint32_t bmEPs)
01162 {
01163     Usbhs *pUdp = USBHS;
01164 
01165     uint32_t tmp = bmEPs & ((1 << CHIP_USB_NUMENDPOINTS) - 1);
01166     uint8_t ep;
01167     uint32_t epBit;
01168 
01169     for (ep = 0, epBit = 1; ep < CHIP_USB_NUMENDPOINTS; ep ++) {
01170         if (tmp & epBit) {
01171             /* Disable ISR */
01172             pUdp->USBHS_DEVIDR |= (epBit << SHIFT_INTERUPT);
01173             /* Terminate transfer on this EP */
01174             UDPHS_EndOfTransfer(ep, USBD_STATUS_CANCELED);
01175         }
01176 
01177         epBit <<= 1;
01178     }
01179 }
01180 
01181 /**
01182  * Configures an endpoint according to its endpoint Descriptor.
01183  * \param pDescriptor Pointer to an endpoint descriptor.
01184  * \return The endpoint address.
01185  */
01186 uint8_t USBD_HAL_ConfigureEP(const USBEndpointDescriptor *pDescriptor)
01187 {
01188     Usbhs *pUdp = USBHS;
01189 
01190     Endpoint *pEndpoint;
01191     uint8_t bEndpoint;
01192     uint8_t bType;
01193     uint8_t bEndpointDir;
01194     uint8_t bNbTrans = 1;
01195     uint8_t bSizeEpt = 0;
01196     uint8_t bHs = ((USBHS_GetUsbSpeed(pUdp) == USBHS_SR_SPEED_HIGH_SPEED) ? true :
01197                    false);
01198 
01199     /* NULL descriptor -> Control endpoint 0 */
01200     if (pDescriptor == 0) {
01201 
01202         bEndpoint = 0;
01203         pEndpoint = &(endpoints[bEndpoint]);
01204         bType = USBEndpointDescriptor_CONTROL;
01205         bEndpointDir = 0;
01206         pEndpoint->size = CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0);
01207         pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(0);
01208     }
01209     /* Device descriptor -> Control endpoint 0 */
01210     else if (pDescriptor->bDescriptorType == USBGenericDescriptor_DEVICE) {
01211         USBDeviceDescriptor *pDevDesc = (USBDeviceDescriptor *)pDescriptor;
01212         bEndpoint = 0;
01213         pEndpoint = &(endpoints[bEndpoint]);
01214         bType = USBEndpointDescriptor_CONTROL;
01215         bEndpointDir = 0;
01216         pEndpoint->size = pDevDesc->bMaxPacketSize0;
01217         pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(0);
01218         /* Endpoint descriptor */
01219     } else {
01220         /* The endpoint number */
01221         bEndpoint = USBEndpointDescriptor_GetNumber(pDescriptor);
01222         pEndpoint = &(endpoints[bEndpoint]);
01223         /* Transfer type: Control, Isochronous, Bulk, Interrupt */
01224         bType = USBEndpointDescriptor_GetType(pDescriptor);
01225         /* Direction, ignored for control endpoints */
01226         bEndpointDir = USBEndpointDescriptor_GetDirection(pDescriptor);
01227         pEndpoint->size = USBEndpointDescriptor_GetMaxPacketSize(pDescriptor);
01228         pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(bEndpoint);
01229 
01230         /* Convert descriptor value to EP configuration */
01231         /* HS Interval, *125us */
01232         if (bHs) {
01233             /* MPS: Bit12,11 specify NB_TRANS, as USB 2.0 Spec. */
01234             bNbTrans = ((pEndpoint->size >> 11) & 0x3);
01235 
01236             if (CHIP_USB_ENDPOINTS_HBW(bEndpoint)) {
01237                 if (bNbTrans == 3)
01238                     bNbTrans = 1;
01239                 else
01240                     bNbTrans ++;
01241             } else
01242                 bNbTrans = 0;
01243 
01244             /* Mask, bit 10..0 is the size */
01245             pEndpoint->size &= 0x7FF;
01246         }
01247     }
01248 
01249     TRACE_DEBUG_WP("CfgE%d ", bEndpoint);
01250 
01251     /* Abort the current transfer is the endpoint was configured and in
01252        Write or Read state */
01253     if ((pEndpoint->state == UDPHS_ENDPOINT_RECEIVING)
01254         || (pEndpoint->state == UDPHS_ENDPOINT_SENDING)
01255         || (pEndpoint->state == UDPHS_ENDPOINT_RECEIVINGM)
01256         || (pEndpoint->state == UDPHS_ENDPOINT_SENDINGM))
01257 
01258         UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_RESET);
01259 
01260     pEndpoint->state = UDPHS_ENDPOINT_IDLE;
01261 
01262 
01263     /* Configure endpoint size */
01264     if (pEndpoint->size <= 8)
01265         bSizeEpt = 0;
01266     else if (pEndpoint->size <= 16)
01267         bSizeEpt = 1;
01268     else if (pEndpoint->size <= 32)
01269         bSizeEpt = 2;
01270     else if (pEndpoint->size <= 64)
01271         bSizeEpt = 3;
01272     else if (pEndpoint->size <= 128)
01273         bSizeEpt = 4;
01274     else if (pEndpoint->size <= 256)
01275         bSizeEpt = 5;
01276     else if (pEndpoint->size <= 512)
01277         bSizeEpt = 6;
01278     else if (pEndpoint->size <= 1024)
01279         bSizeEpt = 7;
01280 
01281     /* Configure endpoint */
01282     if (bType == USBEndpointDescriptor_CONTROL)
01283         USBHS_EnableIntEP(pUdp, bEndpoint);
01284 
01285     USBHS_ConfigureEPs(pUdp, bEndpoint, bType, bEndpointDir, bSizeEpt,
01286                        ((pEndpoint->bank) - 1));
01287 
01288     USBHS_AllocateMemory(pUdp, bEndpoint);
01289 
01290     while ((USBHS_DEVEPTISR_CFGOK & pUdp->USBHS_DEVEPTISR[bEndpoint]) == 0) {
01291 
01292         /* resolved by clearing the reset IT in good place */
01293         TRACE_ERROR("PB bEndpoint: 0x%X\n\r", bEndpoint);
01294         TRACE_ERROR("PB bSizeEpt: 0x%X\n\r", bSizeEpt);
01295         TRACE_ERROR("PB bEndpointDir: 0x%X\n\r", bEndpointDir);
01296         TRACE_ERROR("PB bType: 0x%X\n\r", bType);
01297         TRACE_ERROR("PB pEndpoint->bank: 0x%X\n\r", pEndpoint->bank);
01298         TRACE_ERROR("PB UDPHS_EPTCFG: 0x%X\n\r",
01299                     (unsigned int)pUdp->USBHS_DEVEPTCFG[bEndpoint]);
01300 
01301         for (;;);
01302     }
01303 
01304     if (bType == USBEndpointDescriptor_CONTROL) {
01305         // enable Endpoint
01306         USBHS_EnableEP(pUdp, bEndpoint, true);
01307         // Enable Ep interrupt type
01308         USBHS_EnableEPIntType(pUdp, bEndpoint,
01309                               USBHS_DEVEPTIER_RXOUTES | USBHS_DEVEPTIER_RXSTPES);
01310         // enable endpoint interrupt
01311         USBHS_EnableIntEP(pUdp, bEndpoint);
01312     } else {
01313 #ifndef DMA
01314         USBHS_EnableEP(pUdp, bEndpoint, true);
01315 #else
01316         USBHS_EnableEP(pUdp, bEndpoint, true);
01317 
01318         if (bType == USBEndpointDescriptor_ISOCHRONOUS)
01319             USBHS_SetIsoTrans(pUdp, bEndpoint, bNbTrans);
01320 
01321         USBHS_AutoSwitchBankEnable(pUdp, bEndpoint, true);
01322 #endif
01323     }
01324 
01325     //TRACE_DEBUG_WP("<%x,%x,%x> ", pEpt->UDPHS_EPTCFG, pEpt->UDPHS_EPTCTL, pEpt->UDPHS_EPTSTA);
01326     return bEndpoint;
01327 }
01328 
01329 /**
01330  * Set callback for a USB endpoint for transfer (read/write).
01331  *
01332  * \param bEP       Endpoint number.
01333  * \param fCallback Optional callback function to invoke when the transfer is
01334  *                  complete.
01335  * \param pCbData   Optional pointer to data to the callback function.
01336  * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED if endpoint is busy.
01337  */
01338 uint8_t USBD_HAL_SetTransferCallback(uint8_t bEP,
01339                                      TransferCallback fCallback,
01340                                      void *pCbData)
01341 {
01342     Endpoint *pEndpoint = &(endpoints[bEP]);
01343     TransferHeader *pTransfer = (TransferHeader *) & (pEndpoint->transfer);
01344 
01345     /* Check that the endpoint is not transferring */
01346     if (pEndpoint->state > UDPHS_ENDPOINT_IDLE)
01347         return USBD_STATUS_LOCKED;
01348 
01349     TRACE_DEBUG_WP("sXfrCb ");
01350     /* Setup the transfer callback and extension data */
01351     pTransfer->fCallback = (void *)fCallback;
01352     pTransfer->pArgument = pCbData;
01353     return USBD_STATUS_SUCCESS;
01354 }
01355 
01356 /**
01357  * Configure an endpoint to use multi-buffer-list transfer mode.
01358  * The buffers can be added by _Read/_Write function.
01359  * \param pMbList  Pointer to a multi-buffer list used, NULL to disable MBL.
01360  * \param mblSize  Multi-buffer list size (number of buffers can be queued)
01361  * \param startOffset When number of buffer achieve this offset transfer start
01362  */
01363 uint8_t USBD_HAL_SetupMblTransfer(uint8_t bEndpoint,
01364                                   USBDTransferBuffer *pMbList,
01365                                   uint16_t mblSize,
01366                                   uint16_t startOffset)
01367 {
01368     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
01369     MblTransfer *pXfr = (MblTransfer *)&(pEndpoint->transfer);
01370     uint16_t i;
01371 
01372     /* Check that the endpoint is not transferring */
01373     if (pEndpoint->state > UDPHS_ENDPOINT_IDLE)
01374         return USBD_STATUS_LOCKED;
01375 
01376     TRACE_DEBUG_WP("sMblXfr ");
01377 
01378     /* Enable Multi-Buffer Transfer List */
01379     if (pMbList) {
01380         /* Reset list items */
01381         for (i = 0; i < mblSize; i --) {
01382             pMbList[i].pBuffer = NULL;
01383             pMbList[i].size = 0;
01384             pMbList[i].transferred = 0;
01385             pMbList[i].buffered = 0;
01386             pMbList[i].remaining = 0;
01387         }
01388 
01389         /* Setup transfer */
01390         pXfr->transType = 1;
01391         pXfr->listState = 0; /* OK */
01392         pXfr->listSize = mblSize;
01393         pXfr->pMbl = pMbList;
01394         pXfr->outCurr = pXfr->outLast = 0;
01395         pXfr->inCurr = 0;
01396         pXfr->offsetSize = startOffset;
01397     }
01398     /* Disable Multi-Buffer Transfer */
01399     else {
01400         pXfr->transType = 0;
01401         pXfr->pMbl = NULL;
01402         pXfr->listSize = 0;
01403         pXfr->offsetSize = 1;
01404     }
01405 
01406     return USBD_STATUS_SUCCESS;
01407 }
01408 
01409 /**
01410  * Sends data through a USB endpoint. Sets up the transfer descriptor,
01411  * writes one or two data payloads (depending on the number of FIFO bank
01412  * for the endpoint) and then starts the actual transfer. The operation is
01413  * complete when all the data has been sent.
01414  *
01415  * *If the size of the buffer is greater than the size of the endpoint
01416  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
01417  *  must be kept allocated until the transfer is finished*. This means that
01418  *  it is not possible to declare it on the stack (i.e. as a local variable
01419  *  of a function which returns after starting a transfer).
01420  *
01421  * \param bEndpoint Endpoint number.
01422  * \param pData Pointer to a buffer with the data to send.
01423  * \param dLength Size of the data buffer.
01424  * \return USBD_STATUS_SUCCESS if the transfer has been started;
01425  *         otherwise, the corresponding error status code.
01426  */
01427 uint8_t USBD_HAL_Write(uint8_t bEndpoint,
01428                        const void *pData,
01429                        uint32_t dLength)
01430 {
01431     if (endpoints[bEndpoint].transfer.transHdr.transType)
01432         return UDPHS_AddWr(bEndpoint, pData, dLength);
01433     else
01434         return UDPHS_Write(bEndpoint, pData, dLength);
01435 }
01436 
01437 /**
01438  * Special write function.
01439  * Sends data through a USB endpoint. Sets up the transfer descriptor,
01440  * writes header and one or two data payloads (depending on the number of
01441  * FIFO bank for the endpoint) and then starts the actual transfer. The
01442  * operation is complete when all the data has been sent.
01443  *
01444  * *If the size of the buffer is greater than the size of the endpoint
01445  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
01446  *  must be kept allocated until the transfer is finished*. This means that
01447  *  it is not possible to declare it on the stack (i.e. as a local variable
01448  *  of a function which returns after starting a transfer).
01449  *
01450  * \param bEndpoint Endpoint number.
01451  * \param pData Pointer to a buffer with the data to send.
01452  * \param dLength Size of the data buffer.
01453  * \return USBD_STATUS_SUCCESS if the transfer has been started;
01454  *         otherwise, the corresponding error status code.
01455  */
01456 uint8_t USBD_HAL_WrWithHdr(uint8_t bEndpoint,
01457                            const void *pHdr, uint8_t bHdrLen,
01458                            const void *pData, uint32_t dLength)
01459 {
01460     Usbhs *pUdp = USBHS;
01461 
01462     Endpoint *pEp = &(endpoints[bEndpoint]);
01463     uint8_t bDmaEndpoint = (bEndpoint - 1);
01464     Transfer *pXfr = (Transfer *)&(pEp->transfer);
01465 
01466     /* Return if DMA is not supported */
01467     if (!CHIP_USB_ENDPOINTS_DMA(bEndpoint))
01468         return USBD_STATUS_HW_NOT_SUPPORTED;
01469 
01470 #ifdef DMA
01471 
01472     /* Return if busy */
01473     if (pEp->state != UDPHS_ENDPOINT_IDLE)
01474         return USBD_STATUS_LOCKED;
01475 
01476     /* Sending state */
01477     pEp->state = UDPHS_ENDPOINT_SENDING;
01478     TRACE_DEBUG_WP("Wr%d(%d+%d) ", bEndpoint, bHdrLen, dLength);
01479 
01480     pEp->sendZLP = 0;
01481 
01482     /* Setup transfer descriptor */
01483     pXfr->pData = (void *) pData;
01484     pXfr->remaining = bHdrLen + dLength;
01485     pXfr->buffered = 0;
01486     pXfr->transferred = 0;
01487 
01488     SCB_CleanDCache_by_Addr((uint32_t *)pHdr, bHdrLen);
01489     SCB_CleanDCache_by_Addr((uint32_t *)pData, dLength);
01490 
01491     /* 1. DMA supported always, 2. Not ZLP */
01492     if (bHdrLen + dLength > 0) {
01493         uint8_t bNbTrans = (USBHS_GetConfigureEPs(pUdp, bEndpoint,
01494                             USBHS_DEVEPTCFG_NBTRANS_Msk)
01495                             >> USBHS_DEVEPTCFG_NBTRANS_Pos);
01496 
01497         if (pXfr->remaining > DMA_MAX_FIFO_SIZE)
01498             /* Transfer the max */
01499             pXfr->buffered = DMA_MAX_FIFO_SIZE;
01500         else
01501             /* Good size, total size */
01502             pXfr->buffered = pXfr->remaining;
01503 
01504         /* LD1: header - load to fifo without interrupt */
01505         /* Header discarded if exceed the DMA FIFO length */
01506         //if (bHdrLen > DMA_MAX_FIFO_SIZE) bHdrLen = DMA_MAX_FIFO_SIZE;
01507         pDmaLL[0].pNxtDesc = (void *)&pDmaLL[1];
01508         pDmaLL[0].pAddr = (void *)pHdr;
01509         pDmaLL[0].dwCtrl = USBHS_DEVDMACONTROL_CHANN_ENB
01510                            | USBHS_DEVDMACONTROL_BUFF_LENGTH(bHdrLen)
01511                            | USBHS_DEVDMACONTROL_LDNXT_DSC;
01512 
01513         /* High bandwidth ISO EP, max size n*ep_size */
01514         if (bNbTrans > 1) {
01515             uint8_t *pU8 = (uint8_t *)pData;
01516             uint32_t maxSize = bNbTrans * pEp->size;
01517             dLength = pXfr->buffered - bHdrLen;
01518 
01519             if (dLength > maxSize) dLength = maxSize;
01520 
01521             uint32_t pktLen, ndxData = 0;
01522             /* LD2: data -  bank 0 */
01523             pktLen = pEp->size - bHdrLen;
01524 
01525             /* It's the last DMA LLI */
01526             if (pktLen >= dLength) {
01527                 pDmaLL[1].pNxtDesc = (void *)NULL;
01528                 pDmaLL[1].pAddr = (void *)pU8;
01529                 pDmaLL[1].dwCtrl = USBHS_DEVDMACONTROL_CHANN_ENB
01530                                    | USBHS_DEVDMACONTROL_BUFF_LENGTH(dLength)
01531                                    | USBHS_DEVDMACONTROL_END_B_EN
01532                                    | USBHS_DEVDMACONTROL_END_BUFFIT;
01533             } else {
01534                 pDmaLL[1].pNxtDesc = (void *)&pDmaLL[2];
01535                 pDmaLL[1].pAddr = (void *)pU8;
01536                 pDmaLL[1].dwCtrl = USBHS_DEVDMACONTROL_CHANN_ENB
01537                                    | USBHS_DEVDMACONTROL_BUFF_LENGTH(pktLen)
01538                                    | USBHS_DEVDMACONTROL_END_B_EN
01539                                    | USBHS_DEVDMACONTROL_LDNXT_DSC;
01540 
01541                 dLength -= pktLen;
01542                 ndxData += pktLen;
01543                 /* LD3: data  - bank 1 */
01544                 pktLen = pEp->size;
01545 
01546                 if (pktLen >= dLength) { /* It's the last */
01547                     pDmaLL[1].pNxtDesc = (void *) NULL;
01548                     pDmaLL[1].pAddr = (void *)&pU8[ndxData];
01549                     pDmaLL[1].dwCtrl = USBHS_DEVDMACONTROL_CHANN_ENB
01550                                        | USBHS_DEVDMACONTROL_BUFF_LENGTH(dLength)
01551                                        | USBHS_DEVDMACONTROL_END_B_EN
01552                                        | USBHS_DEVDMACONTROL_END_BUFFIT;
01553                 } else {
01554                     pDmaLL[2].pNxtDesc = (void *)&pDmaLL[3];
01555                     pDmaLL[2].pAddr = (void *)&pU8[ndxData];
01556                     pDmaLL[2].dwCtrl = USBHS_DEVDMACONTROL_CHANN_ENB
01557                                        | USBHS_DEVDMACONTROL_BUFF_LENGTH(pktLen)
01558                                        | USBHS_DEVDMACONTROL_END_B_EN
01559                                        | USBHS_DEVDMACONTROL_LDNXT_DSC;
01560                     dLength -= pktLen; ndxData += pktLen;
01561                     /* LD4: data  - bank 2 */
01562                     pDmaLL[3].pNxtDesc = (void *) NULL;
01563                     pDmaLL[3].pAddr = (void *)&pU8[ndxData];
01564                     pDmaLL[3].dwCtrl = USBHS_DEVDMACONTROL_CHANN_ENB
01565                                        | USBHS_DEVDMACONTROL_BUFF_LENGTH(dLength)
01566                                        | USBHS_DEVDMACONTROL_END_B_EN
01567                                        | USBHS_DEVDMACONTROL_END_BUFFIT;
01568                 }
01569             }
01570 
01571             /* Normal, fill all data */
01572         } else {
01573             /* LD2: data   -  load to fifo with interrupt */
01574             dLength = pXfr->buffered - bHdrLen;
01575             pDmaLL[1].pNxtDesc = (void *)NULL;
01576             pDmaLL[1].pAddr = (void *)pData;
01577             pDmaLL[1].dwCtrl = USBHS_DEVDMACONTROL_CHANN_ENB
01578                                | USBHS_DEVDMACONTROL_BUFF_LENGTH(dLength)
01579                                | USBHS_DEVDMACONTROL_END_B_EN
01580                                | USBHS_DEVDMACONTROL_END_BUFFIT;
01581         }
01582 
01583         SCB_CleanDCache_by_Addr((uint32_t *)dmaLL, sizeof(dmaLL));
01584         /* Interrupt enable */
01585         USBHS_EnableDMAIntEP(pUdp, bDmaEndpoint);
01586         /* Start transfer with LLI */
01587         pUdp->USBHS_DEVDMA[bDmaEndpoint].USBHS_DEVDMANXTDSC = (uint32_t)pDmaLL;
01588         pUdp->USBHS_DEVDMA[bDmaEndpoint].USBHS_DEVDMACONTROL = 0;
01589         pUdp->USBHS_DEVDMA[bDmaEndpoint].USBHS_DEVDMACONTROL =
01590             USBHS_DEVDMACONTROL_LDNXT_DSC;
01591         return USBD_STATUS_SUCCESS;
01592     }
01593 
01594 #endif
01595 
01596     /* Enable IT */
01597     USBHS_EnableIntEP(pUdp, bEndpoint);
01598     USBHS_EnableEPIntType(pUdp, bEndpoint, USBHS_DEVEPTIER_TXINES);
01599     return USBD_STATUS_SUCCESS;
01600 }
01601 
01602 /**
01603  * Reads incoming data on an USB endpoint This methods sets the transfer
01604  * descriptor and activate the endpoint interrupt. The actual transfer is
01605  * then carried out by the endpoint interrupt handler. The Read operation
01606  * finishes either when the buffer is full, or a short packet (inferior to
01607  * endpoint maximum  size) is received.
01608  *
01609  * *The buffer must be kept allocated until the transfer is finished*.
01610  * \param bEndpoint Endpoint number.
01611  * \param pData Pointer to a data buffer.
01612  * \param dLength Size of the data buffer in bytes.
01613  * \return USBD_STATUS_SUCCESS if the read operation has been started;
01614  *         otherwise, the corresponding error code.
01615  */
01616 uint8_t USBD_HAL_Read(uint8_t bEndpoint,
01617                       void *pData,
01618                       uint32_t dLength)
01619 {
01620     if (endpoints[bEndpoint].transfer.transHdr.transType)
01621         return USBD_STATUS_SW_NOT_SUPPORTED;
01622     else
01623         return UDPHS_Read(bEndpoint, pData, dLength);
01624 }
01625 
01626 /**
01627  *  \brief Enable Pull-up, connect.
01628  *
01629  *  -# Enable HW access if needed
01630  *  -# Enable Pull-Up
01631  *  -# Disable HW access if needed
01632  */
01633 void USBD_HAL_Connect(void)
01634 {
01635     uint32_t Interrupt;
01636 
01637     // At startup the USB bus state is unknown,
01638     // therefore the state is considered IDLE to not miss any USB event
01639 
01640     USBHS_UnFreezeClock(USBHS);
01641 
01642     // Authorize attach
01643     USBHS_DetachUsb(USBHS, false);
01644 
01645     // (RESET_AND_WAKEUP)
01646     // After the attach and the first USB suspend, the following USB Reset time can be inferior to CPU restart clock time.
01647     // Thus, the USB Reset state is not detected and endpoint control is not allocated
01648     // In this case, a Reset is do automatically after attach.
01649     USBD_HAL_ConfigureEP(0);
01650 
01651     // Enable USB line events
01652     Interrupt = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_WAKEUPES |
01653                  USBHS_DEVIER_SUSPES);
01654 
01655 #ifdef USB_DEVICE_HS_SUPPORT
01656     Interrupt |= USBHS_DEVIER_MSOFES;
01657 #endif
01658 
01659     USBHS_EnableInt(USBHS, Interrupt);
01660 
01661     // Reset following interrupts flag
01662     Interrupt = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_MSOFC |
01663                  USBHS_DEVICR_SUSPC);
01664     USBHS_AckInt(USBHS, Interrupt);
01665 
01666 
01667     // The first suspend interrupt is not detected else raise it
01668     USBHS_RaiseInt(USBHS, USBHS_DEVIFR_SUSPS);
01669 
01670     USBHS_AckInt(USBHS, USBHS_DEVICR_WAKEUPC);
01671 
01672     USBHS_FreezeClock(USBHS);
01673 }
01674 
01675 /**
01676  *  \brief Disable Pull-up, disconnect.
01677  *
01678  *  -# Enable HW access if needed
01679  *  -# Disable PULL-Up
01680  *  -# Disable HW access if needed
01681  */
01682 void USBD_HAL_Disconnect(void)
01683 {
01684     USBHS_FreezeClock(USBHS);
01685     // Detach device from the bus
01686     USBHS_DetachUsb(USBHS, true);
01687 }
01688 
01689 /**
01690  * Starts a remote wake-up procedure.
01691  */
01692 void USBD_HAL_RemoteWakeUp(void)
01693 {
01694     Usbhs *pUdp = USBHS;
01695     TRACE_INFO_WP("RWUp ");
01696 
01697     /* Activates a remote wakeup (edge on ESR), then clear ESR */
01698     USBHS_SetRemoteWakeUp(pUdp);
01699 
01700     while (pUdp->USBHS_DEVCTRL & USBHS_DEVCTRL_RMWKUP);
01701 
01702     TRACE_DEBUG_WP("w");
01703 }
01704 
01705 /**
01706  * Sets the device address to the given value.
01707  * \param address New device address.
01708  */
01709 void USBD_HAL_SetAddress(uint8_t address)
01710 {
01711     Usbhs *pUdp = USBHS;
01712 
01713     if (address)
01714         USBHS_SetAddress(pUdp, address);
01715     else
01716         USBHS_EnableAddress(pUdp, false);
01717 }
01718 
01719 /**
01720  * Sets the current device configuration.
01721  * \param cfgnum - Configuration number to set.
01722  */
01723 void USBD_HAL_SetConfiguration(uint8_t cfgnum)
01724 {
01725     /* Nothing to do now */
01726     cfgnum = cfgnum;
01727 }
01728 
01729 /**
01730  * Initializes the USB HW Access driver.
01731  */
01732 void USBD_HAL_Init(void)
01733 {
01734 
01735 #ifdef DMA
01736 
01737     /* DMA Link list should be 16-bytes aligned */
01738     if ((uint32_t)dmaLL & 0xFFFFFFF0)
01739         pDmaLL = (UdphsDmaDescriptor *)((uint32_t)&dmaLL[1] & 0xFFFFFFF0);
01740     else
01741         pDmaLL = (UdphsDmaDescriptor *)((uint32_t)&dmaLL[0]);
01742 
01743 #endif
01744     /** Disable USB hardware */
01745     USBHS_UsbEnable(USBHS, false);
01746 
01747     USBHS_UsbMode(USBHS, DEVICE_MODE);
01748 
01749     /** Enable USB hardware*/
01750     USBHS_UsbEnable(USBHS, true);
01751 
01752     USBHS_UnFreezeClock(USBHS);
01753 
01754     if (ForceFS)
01755         USBHS_EnableHighSpeed(USBHS, false);
01756     else
01757         USBHS_EnableHighSpeed(USBHS, true);
01758 
01759     /*  Check USB clock */
01760     while (!USBHS_ISUsableClock(USBHS));
01761 
01762     USBHS_FreezeClock(USBHS);
01763 
01764     /* Clear IRQ */
01765     NVIC_ClearPendingIRQ(USBHS_IRQn);
01766     /* IRQ */
01767     NVIC_EnableIRQ(USBHS_IRQn);
01768 
01769 }
01770 
01771 /**
01772  * Causes the given endpoint to acknowledge the next packet it receives
01773  * with a STALL handshake except setup request.
01774  * \param bEP Endpoint number.
01775  * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED.
01776  */
01777 uint8_t USBD_HAL_Stall(uint8_t bEP)
01778 {
01779     Usbhs *pUdp = USBHS;
01780 
01781     Endpoint *pEndpoint = &(endpoints[bEP]);
01782 
01783     /* Check that endpoint is in Idle state */
01784     if (pEndpoint->state != UDPHS_ENDPOINT_IDLE) {
01785         TRACE_WARNING("UDP_Stall: EP%d locked\n\r", bEP);
01786         return USBD_STATUS_LOCKED;
01787     }
01788 
01789     /* STALL endpoint */
01790     USBHS_EnableEPIntType(pUdp, bEP, USBHS_DEVEPTIER_STALLRQS);
01791 
01792     TRACE_INFO_WP("Stall%d ", bEP);
01793     return USBD_STATUS_SUCCESS;
01794 }
01795 
01796 /**
01797  * Sets/Clear/Get the HALT state on the endpoint.
01798  * In HALT state, the endpoint should keep stalling any packet.
01799  * \param bEndpoint Endpoint number.
01800  * \param ctl       Control code CLR/HALT/READ.
01801  *                  0: Clear HALT state;
01802  *                  1: Set HALT state;
01803  *                  .: Return HALT status.
01804  * \return USBD_STATUS_INVALID_PARAMETER if endpoint not exist,
01805  *         otherwise endpoint halt status.
01806  */
01807 uint8_t USBD_HAL_Halt(uint8_t bEndpoint, uint8_t ctl)
01808 {
01809     Usbhs *pUdp = USBHS;
01810 
01811     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
01812     uint8_t bDmaEndpoint = (bEndpoint - 1);
01813     uint8_t status = 0;
01814 
01815     /* SET Halt */
01816     if (ctl == 1) {
01817         /* Check that endpoint is enabled and not already in Halt state */
01818         if ((pEndpoint->state != UDPHS_ENDPOINT_DISABLED)
01819             && (pEndpoint->state != UDPHS_ENDPOINT_HALTED)) {
01820 
01821             TRACE_INFO_WP("Halt%d ", bEndpoint);
01822 
01823             /* Abort the current transfer if necessary */
01824             UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
01825 
01826             /* Put endpoint into Halt state */
01827             pEndpoint->state = UDPHS_ENDPOINT_HALTED;
01828             memory_sync();
01829 
01830             while (!USBHS_IsBankFree(pUdp, bEndpoint)) {
01831                 USBHS_KillBank(pUdp, bEndpoint);
01832 
01833                 while (USBHS_IsBankKilled(pUdp, bEndpoint));
01834             }
01835 
01836             if (USBHS_IsBankFree(pUdp, bEndpoint)) {
01837                 USBHS_AutoSwitchBankEnable(pUdp, bEndpoint, false);
01838                 USBHS_EnableEPIntType(pUdp, bEndpoint,
01839                                       (USBHS_DEVEPTIER_STALLRQS | USBHS_DEVEPTIER_RSTDTS));
01840             } else {
01841                 USBHS_EnableEPIntType(pUdp, bEndpoint, USBHS_DEVEPTIER_NBUSYBKES);
01842 #ifdef DMA
01843 
01844                 if (CHIP_USB_ENDPOINTS_DMA(bDmaEndpoint)) {
01845                     /* Enable the endpoint DMA interrupt */
01846                     USBHS_EnableDMAIntEP(pUdp, bDmaEndpoint);
01847                 } else {
01848                     /* Enable the endpoint interrupt */
01849                     USBHS_EnableIntEP(pUdp, bEndpoint);
01850                 }
01851 
01852 #else
01853                 /* Enable the endpoint interrupt */
01854                 USBHS_EnableIntEP(pUdp, bEndpoint);
01855 #endif
01856             }
01857         }
01858 
01859         /* CLEAR Halt */
01860     } else if (ctl == 0) {
01861         /* Check if the endpoint is halted */
01862         if ((pEndpoint->state == UDPHS_ENDPOINT_HALTED)
01863             || (USBHS_IsEpIntEnable(pUdp, bEndpoint, USBHS_DEVEPTIMR_STALLRQ))) {
01864             TRACE_INFO_WP("Unhalt%d ", bEndpoint);
01865             /* Return endpoint to Idle state */
01866             pEndpoint->state = UDPHS_ENDPOINT_IDLE;
01867 
01868             /* Clear FORCESTALL flag */
01869             USBHS_DisableEPIntType(pUdp, bEndpoint, USBHS_DEVEPTIDR_STALLRQC);
01870             USBHS_AutoSwitchBankEnable(pUdp, bEndpoint, true);
01871         }
01872     }
01873 
01874     /* Return Halt status */
01875     if (pEndpoint->state == UDPHS_ENDPOINT_HALTED)
01876         status = 1;
01877 
01878     return (status);
01879 }
01880 
01881 /**
01882  * Wait for data to read and then return
01883  * \param bEndpoint Endpoint number
01884  */
01885 void USBD_HAL_WaitReadData(uint8_t bEndpoint)
01886 {
01887     Usbhs *pUdp = USBHS;
01888 
01889     while (USBHS_ByteCount(pUdp, bEndpoint) == 0);
01890 }
01891 
01892 /**
01893  * Indicates if the device is running in high or full-speed. Always returns 0
01894  * since UDP does not support high-speed mode.
01895  */
01896 uint8_t USBD_HAL_IsHighSpeed(void)
01897 {
01898     return USBHS_IsUsbHighSpeed(USBHS);
01899 }
01900 
01901 /**
01902  * Suspend USB Device HW Interface
01903  *
01904  * -# Disable transceiver
01905  * -# Disable USB Clock
01906  * -# Disable USB Peripheral
01907  */
01908 void USBD_HAL_Suspend(void)
01909 {
01910     /* The device enters the Suspended state */
01911     USBHS_FreezeClock(USBHS);
01912 }
01913 
01914 /**
01915  * Activate USB Device HW Interface
01916  * -# Enable USB Peripheral
01917  * -# Enable USB Clock
01918  * -# Enable transceiver
01919  */
01920 void USBD_HAL_Activate(void)
01921 {
01922     USBHS_UnFreezeClock(USBHS);
01923 }
01924 
01925 void USBD_HAL_Disable(void)
01926 {
01927     //** Disable USB hardware
01928     USBHS_UsbEnable(USBHS, false);
01929 
01930     /* Clear IRQ */
01931     NVIC_ClearPendingIRQ(USBHS_IRQn);
01932     /* IRQ */
01933     NVIC_DisableIRQ(USBHS_IRQn);
01934 }
01935 
01936 
01937 /**
01938  * Certification test for High Speed device.
01939  * \param bIndex Test to be done
01940  */
01941 void USBD_HAL_Test(uint8_t bIndex)
01942 {
01943     Usbhs *pUdp = USBHS;
01944     uint8_t *pFifo;
01945     uint32_t i;
01946 
01947     /* remove suspend for TEST */
01948     USBHS_DisableInt(pUdp, USBHS_DEVIDR_SUSPEC);
01949     /* force High Speed (remove suspend) */
01950     pUdp->USBHS_DEVCTRL |= USBHS_DEVCTRL_SPDCONF_HIGH_SPEED;
01951 
01952     USBHS_EnableTestMode(pUdp, USBHS_DEVCTRL_OPMODE2);
01953 
01954     switch (bIndex) {
01955     case USBFeatureRequest_TESTPACKET:
01956         TRACE_DEBUG_WP("TEST_PACKET ");
01957 
01958         pUdp->USBHS_DEVDMA[1].USBHS_DEVDMACONTROL = 0;
01959         pUdp->USBHS_DEVDMA[2].USBHS_DEVDMACONTROL = 0;
01960 
01961         /* Configure endpoint 2, 64 bytes, direction IN, type BULK, 1 bank */
01962         pUdp->USBHS_DEVEPTCFG[2] = USBHS_DEVEPTCFG_EPSIZE_64_BYTE
01963                                    | USBHS_DEVEPTCFG_EPDIR
01964                                    | USBHS_DEVEPTCFG_EPTYPE_BLK
01965                                    | USBHS_DEVEPTCFG_EPBK_1_BANK;
01966         USBHS_AllocateMemory(pUdp, 2);
01967 
01968         while ((USBHS_DEVEPTISR_CFGOK & pUdp->USBHS_DEVEPTISR[2]) !=
01969                USBHS_DEVEPTISR_CFGOK);
01970 
01971         USBHS_EnableEP(pUdp, 2, true);
01972 
01973         /* Write FIFO */
01974         pFifo = (uint8_t *)((uint32_t *)(USBHS_RAM_ADDR) + (EPT_VIRTUAL_SIZE * 2));
01975 
01976         for (i = 0; i < sizeof(test_packet_buffer); i++)
01977             pFifo[i] = test_packet_buffer[i];
01978 
01979         /* Tst PACKET */
01980         USBHS_EnableTestMode(pUdp, USBHS_DEVCTRL_TSTPCKT);
01981         /* Send packet */
01982         USBHS_RaiseEPInt(pUdp, 2, USBHS_DEVEPTIFR_TXINIS);
01983         break;
01984 
01985     case USBFeatureRequest_TESTJ:
01986         TRACE_DEBUG_WP("TEST_J ");
01987         USBHS_EnableTestMode(pUdp, USBHS_DEVCTRL_TSTJ);
01988         break;
01989 
01990     case USBFeatureRequest_TESTK:
01991         TRACE_DEBUG_WP("TEST_K ");
01992         USBHS_EnableTestMode(pUdp, USBHS_DEVCTRL_TSTK);
01993         break;
01994 
01995     case USBFeatureRequest_TESTSE0NAK:
01996         TRACE_DEBUG_WP("TEST_SEO_NAK ");
01997         USBHS_DisableInt(pUdp, 0xFFFFFFFF); // for test
01998         break;
01999 
02000     case USBFeatureRequest_TESTSENDZLP:
02001         USBHS_RaiseEPInt(pUdp, 0, USBHS_DEVEPTIFR_TXINIS);
02002         TRACE_DEBUG_WP("SEND_ZLP ");
02003         break;
02004     }
02005 
02006     TRACE_DEBUG_WP("\n\r");
02007 }
02008 
02009 /**@}*/
02010 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines