SAMV71 Xplained Ultra Software Package 1.4

USBD_HAL.c

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