SAMV71 Xplained Ultra Software Package 1.3

hal_udp.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         ATMEL Microcontroller Software Support
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2008, 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  \section Purpose
00035 
00036     Implementation of USB device functions on a UDP controller.
00037 
00038     See \ref usbd_api_method USBD API Methods.
00039 */
00040 
00041 /** \addtogroup usbd_hal
00042  *@{*/
00043 
00044 /*---------------------------------------------------------------------------
00045  *      Headers
00046  *---------------------------------------------------------------------------*/
00047 
00048 #include "chip.h"
00049 #include "USBD_HAL.h"
00050 
00051 #include <stdbool.h>
00052 #include <stdint.h>
00053 #include <stdio.h>
00054 
00055 /*---------------------------------------------------------------------------
00056  *      Definitions
00057  *---------------------------------------------------------------------------*/
00058 
00059 /** Indicates chip has an UDP Full Speed. */
00060 #define CHIP_USB_UDP
00061 
00062 /** Indicates chip has an internal pull-up. */
00063 #define CHIP_USB_PULLUP_INTERNAL
00064 
00065 /** Number of USB endpoints */
00066 #define CHIP_USB_NUMENDPOINTS 8
00067 
00068 /** Endpoints max paxcket size */
00069 #define CHIP_USB_ENDPOINTS_MAXPACKETSIZE(i) \
00070    ((i == 0) ? 64 : \
00071    ((i == 1) ? 64 : \
00072    ((i == 2) ? 64 : \
00073    ((i == 3) ? 64 : \
00074    ((i == 4) ? 512 : \
00075    ((i == 5) ? 512 : \
00076    ((i == 6) ? 64 : \
00077    ((i == 7) ? 64 : 0 ))))))))
00078 
00079 /** Endpoints Number of Bank */
00080 #define CHIP_USB_ENDPOINTS_BANKS(i) \
00081    ((i == 0) ? 1 : \
00082    ((i == 1) ? 2 : \
00083    ((i == 2) ? 2 : \
00084    ((i == 3) ? 1 : \
00085    ((i == 4) ? 2 : \
00086    ((i == 5) ? 2 : \
00087    ((i == 6) ? 2 : \
00088    ((i == 7) ? 2 : 0 ))))))))
00089 
00090 /**
00091  *  \section UDP_registers_sec "UDP Register field values"
00092  *
00093  *  This section lists the initialize values of UDP registers.
00094  *
00095  *  \subsection Values
00096  *  - UDP_RXDATA
00097  */
00098 /** Bit mask for both banks of the UDP_CSR register. */
00099 #define UDP_CSR_RXDATA_BK      (UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1)
00100 
00101 /**
00102  * \section endpoint_states_sec "UDP Endpoint states"
00103  *
00104  *  This page lists the endpoint states.
00105  *
00106  *  \subsection States
00107  *  - UDP_ENDPOINT_DISABLED
00108  *  - UDP_ENDPOINT_HALTED
00109  *  - UDP_ENDPOINT_IDLE
00110  *  - UDP_ENDPOINT_SENDING
00111  *  - UDP_ENDPOINT_RECEIVING
00112  *  - UDP_ENDPOINT_SENDINGM
00113  *  - UDP_ENDPOINT_RECEIVINGM
00114  */
00115 
00116 /**  Endpoint states: Endpoint is disabled */
00117 #define UDP_ENDPOINT_DISABLED       0
00118 /**  Endpoint states: Endpoint is halted (i.e. STALLs every request) */
00119 #define UDP_ENDPOINT_HALTED         1
00120 /**  Endpoint states: Endpoint is idle (i.e. ready for transmission) */
00121 #define UDP_ENDPOINT_IDLE           2
00122 /**  Endpoint states: Endpoint is sending data */
00123 #define UDP_ENDPOINT_SENDING        3
00124 /**  Endpoint states: Endpoint is receiving data */
00125 #define UDP_ENDPOINT_RECEIVING      4
00126 /**  Endpoint states: Endpoint is sending MBL */
00127 #define UDP_ENDPOINT_SENDINGM       5
00128 /**  Endpoint states: Endpoint is receiving MBL */
00129 #define UDP_ENDPOINT_RECEIVINGM     6
00130 
00131 /**
00132  *  \section udp_csr_register_access_sec "UDP CSR register access"
00133  *
00134  *  This page lists the macros to access UDP CSR register.
00135  *
00136  *  \comment
00137  *  In a preemptive environment, set or clear the flag and wait for a time of
00138  *  1 UDPCK clock cycle and 1 peripheral clock cycle. However, RX_DATA_BK0,
00139  *  TXPKTRDY, RX_DATA_BK1 require wait times of 3 UDPCK clock cycles and
00140  *  5 peripheral clock cycles before accessing DPR.
00141  *  See datasheet
00142  *
00143  *  !Macros
00144  *  - CLEAR_CSR
00145  *  - SET_CSR
00146  */
00147 
00148 #if defined   ( __CC_ARM   )
00149   #define nop() {volatile int h; for(h=0;h<10;h++){}}
00150 #elif defined ( __ICCARM__ )
00151   #include <intrinsics.h>
00152   #define nop() (__no_operation())
00153 #elif defined (  __GNUC__  )
00154   #define nop()   __asm__ __volatile__ ( "nop" )
00155 #endif
00156 
00157 
00158 /**  Bitmap for all status bits in CSR. */
00159 #define REG_NO_EFFECT_1_ALL      UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1 \
00160                                 |UDP_CSR_STALLSENTISOERROR | UDP_CSR_RXSETUP \
00161                                 |UDP_CSR_TXCOMP
00162 
00163 /**
00164  *  Sets the specified bit(s) in the UDP_CSR register.
00165  *
00166  *  \param endpoint The endpoint number of the CSR to process.
00167  *  \param flags The bitmap to set to 1.
00168  */
00169 #define SET_CSR(endpoint, flags) \
00170     { \
00171         volatile uint32_t reg; \
00172         int32_t nop_count ; \
00173         reg = UDP->UDP_CSR[endpoint] ; \
00174         reg |= REG_NO_EFFECT_1_ALL; \
00175         reg |= (flags); \
00176         UDP->UDP_CSR[endpoint] = reg; \
00177         for( nop_count=0; nop_count<15; nop_count++ ) {\
00178             nop();\
00179         }\
00180     }
00181 
00182 /**
00183  *  Clears the specified bit(s) in the UDP_CSR register.
00184  *
00185  *  \param endpoint The endpoint number of the CSR to process.
00186  *  \param flags The bitmap to clear to 0.
00187  */
00188 #define CLEAR_CSR(endpoint, flags) \
00189 { \
00190     volatile uint32_t reg; \
00191     int32_t nop_count ; \
00192     reg = UDP->UDP_CSR[endpoint]; \
00193     reg |= REG_NO_EFFECT_1_ALL; \
00194     reg &= ~((uint32_t)(flags)); \
00195     UDP->UDP_CSR[endpoint] = reg; \
00196     for( nop_count=0; nop_count<15; nop_count++ ) {\
00197         nop();\
00198     }\
00199 }
00200 
00201 
00202 /** Get Number of buffer in Multi-Buffer-List
00203  *  \param i    input index
00204  *  \param o    output index
00205  *  \param size list size
00206  */
00207 #define MBL_NbBuffer(i, o, size) (((i)>(o))?((i)-(o)):((i)+(size)-(o)))
00208 
00209 /** Buffer list is full */
00210 #define MBL_FULL        1
00211 /** Buffer list is null */
00212 #define MBL_NULL        2
00213 
00214 /*---------------------------------------------------------------------------
00215  *      Types
00216  *---------------------------------------------------------------------------*/
00217 
00218 /**  Describes header for UDP endpoint transfer. */
00219 typedef struct {
00220     /**  Optional callback to invoke when the transfer completes. */
00221     void*   fCallback;
00222     /**  Optional argument to the callback function. */
00223     void*   pArgument;
00224     /**  Transfer type */
00225     uint8_t transType;
00226 } TransferHeader;
00227 
00228 /**  Describes a transfer on a UDP endpoint. */
00229 typedef struct {
00230 
00231     /**  Optional callback to invoke when the transfer completes. */
00232     TransferCallback fCallback;
00233     /**  Optional argument to the callback function. */
00234     void             *pArgument;
00235     /**  Transfer type */
00236     uint16_t         transType;
00237     /**  Number of bytes which have been written into the UDP internal FIFO
00238      *   buffers. */
00239     int16_t          buffered;
00240     /**  Pointer to a data buffer used for emission/reception. */
00241     uint8_t          *pData;
00242     /**  Number of bytes which have been sent/received. */
00243     int32_t          transferred;
00244     /**  Number of bytes which have not been buffered/transferred yet. */
00245     int32_t          remaining;
00246 } Transfer;
00247 
00248 /**  Describes Multi Buffer List transfer on a UDP endpoint. */
00249 typedef struct {
00250     /**  Optional callback to invoke when the transfer completes. */
00251     MblTransferCallback fCallback;
00252     /**  Optional argument to the callback function. */
00253     void                *pArgument;
00254     /** Transfer type */
00255     volatile uint8_t    transType;
00256     /** List state (OK, FULL, NULL) (run time) */
00257     uint8_t             listState;
00258     /**  Multi-Buffer List size */
00259     uint16_t            listSize;
00260     /**  Pointer to multi-buffer list */
00261     USBDTransferBuffer *pMbl;
00262     /**  Offset number of buffers to start transfer */
00263     uint16_t            offsetSize;
00264     /**  Current processing buffer index (run time) */
00265     uint16_t            outCurr;
00266     /**  Loast loaded buffer index (run time) */
00267     uint16_t            outLast;
00268     /**  Current buffer for input (run time) */
00269     uint16_t            inCurr;
00270 } MblTransfer;
00271 
00272 /**
00273  *  Describes the state of an endpoint of the UDP controller.
00274  */
00275 typedef struct {
00276 
00277     /* CSR */
00278     //uint32_t          CSR;
00279     /**  Current endpoint state. */
00280     volatile uint8_t  state;
00281     /**  Current reception bank (0 or 1). */
00282     volatile uint8_t  bank;
00283     /**  Maximum packet size for the endpoint. */
00284     volatile uint16_t size;
00285     /**  Describes an ongoing transfer (if current state is either
00286      *   UDP_ENDPOINT_SENDING or UDP_ENDPOINT_RECEIVING) */
00287     union {
00288         TransferHeader transHdr;
00289         Transfer       singleTransfer;
00290         MblTransfer    mblTransfer;
00291     } transfer;
00292 } Endpoint;
00293 
00294 /*---------------------------------------------------------------------------
00295  *      Internal variables
00296  *---------------------------------------------------------------------------*/
00297 
00298 /** Holds the internal state for each endpoint of the UDP. */
00299 static Endpoint endpoints[CHIP_USB_NUMENDPOINTS];
00300 
00301 /*---------------------------------------------------------------------------
00302  *      Internal Functions
00303  *---------------------------------------------------------------------------*/
00304 
00305 /**
00306  * Enables the clock of the UDP peripheral.
00307  * \return 1 if peripheral status changed.
00308  */
00309 static uint8_t UDP_EnablePeripheralClock(void)
00310 {
00311     if (!PMC_IsPeriphEnabled(ID_UDP)) {
00312         PMC_EnablePeripheral(ID_UDP);
00313         return 1;
00314     }
00315     return 0;
00316 }
00317 
00318 /**
00319  * Disables the UDP peripheral clock.
00320  */
00321 static inline void UDP_DisablePeripheralClock(void)
00322 {
00323     PMC_DisablePeripheral(ID_UDP);
00324 }
00325 
00326 /**
00327  * Enables the 48MHz USB clock.
00328  */
00329 static inline void UDP_EnableUsbClock(void)
00330 {
00331     REG_PMC_SCER = PMC_SCER_UDP;
00332 }
00333 
00334 /**
00335  *  Disables the 48MHz USB clock.
00336  */
00337 static inline void UDP_DisableUsbClock(void)
00338 {
00339     REG_PMC_SCDR = PMC_SCER_UDP;
00340 }
00341 
00342 /**
00343  * Enables the UDP transceiver.
00344  */
00345 static inline void UDP_EnableTransceiver(void)
00346 {
00347     UDP->UDP_TXVC &= ~(uint32_t)UDP_TXVC_TXVDIS;
00348 }
00349 
00350 /**
00351  * Disables the UDP transceiver.
00352  */
00353 static inline void UDP_DisableTransceiver(void)
00354 {
00355     UDP->UDP_TXVC |= UDP_TXVC_TXVDIS;
00356 }
00357 
00358 /**
00359  * Handles a completed transfer on the given endpoint, invoking the
00360  * configured callback if any.
00361  * \param bEndpoint Number of the endpoint for which the transfer has completed.
00362  * \param bStatus   Status code returned by the transfer operation
00363  */
00364 static void UDP_EndOfTransfer(uint8_t bEndpoint, uint8_t bStatus)
00365 {
00366     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00367 
00368     // Check that endpoint was sending or receiving data
00369     if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING)
00370         || (pEndpoint->state == UDP_ENDPOINT_SENDING)) {
00371 
00372         Transfer *pTransfer = (Transfer *)&(pEndpoint->transfer);
00373         uint32_t transferred = pTransfer->transferred;
00374         uint32_t remaining   = pTransfer->remaining + pTransfer->buffered;
00375 
00376         TRACE_DEBUG_WP("EoT ");
00377 
00378         /* Endpoint returns in Idle state */
00379         pEndpoint->state = UDP_ENDPOINT_IDLE;
00380         /* Reset descriptor values */
00381         pTransfer->pData = 0;
00382         pTransfer->transferred = -1;
00383         pTransfer->buffered = -1;
00384         pTransfer->remaining = -1;
00385 
00386         // Invoke callback is present
00387         if (pTransfer->fCallback != 0) {
00388 
00389             ((TransferCallback) pTransfer->fCallback)
00390                 (pTransfer->pArgument,
00391                  bStatus,
00392                  transferred,
00393                  remaining);
00394         }
00395         else {
00396             TRACE_DEBUG_WP("NoCB ");
00397         }
00398     }
00399     else if ( (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM)
00400             || (pEndpoint->state == UDP_ENDPOINT_SENDINGM) ) {
00401 
00402         MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer);
00403 
00404         TRACE_DEBUG_WP("EoMT ");
00405 
00406         /* Endpoint returns in Idle state */
00407         pEndpoint->state = UDP_ENDPOINT_IDLE;
00408         /* Reset transfer descriptor */
00409         if (pTransfer->transType) {
00410             MblTransfer *pMblt = (MblTransfer*)&(pEndpoint->transfer);
00411             pMblt->listState = 0;
00412             pMblt->outCurr = pMblt->inCurr = pMblt->outLast = 0;
00413         }
00414         /* Invoke callback */
00415         if (pTransfer->fCallback != 0) {
00416 
00417             ((MblTransferCallback) pTransfer->fCallback)
00418                 (pTransfer->pArgument,
00419                  bStatus);
00420         }
00421         else {
00422             TRACE_DEBUG_WP("NoCB ");
00423         }
00424     }
00425 }
00426 
00427 /**
00428  * Clears the correct reception flag (bank 0 or bank 1) of an endpoint
00429  * \param bEndpoint Index of endpoint
00430  */
00431 static void UDP_ClearRxFlag(uint8_t bEndpoint)
00432 {
00433     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00434 
00435     // Clear flag and change banks
00436     if (pEndpoint->bank == 0) {
00437 
00438         CLEAR_CSR(bEndpoint, UDP_CSR_RX_DATA_BK0);
00439         // Swap bank if in dual-fifo mode
00440         if (CHIP_USB_ENDPOINTS_BANKS(bEndpoint) > 1) {
00441 
00442             pEndpoint->bank = 1;
00443         }
00444     }
00445     else {
00446 
00447         CLEAR_CSR(bEndpoint, UDP_CSR_RX_DATA_BK1);
00448         pEndpoint->bank = 0;
00449     }
00450 }
00451 
00452 /**
00453  * Update multi-buffer-transfer descriptors.
00454  * \param pTransfer Pointer to instance MblTransfer.
00455  * \param size      Size of bytes that processed.
00456  * \param forceEnd  Force the buffer END.
00457  * \return 1 if current buffer ended.
00458  */
00459 static uint8_t UDP_MblUpdate(MblTransfer *pTransfer,
00460                           USBDTransferBuffer * pBi,
00461                           uint16_t size,
00462                           uint8_t forceEnd)
00463 {
00464     /* Update transfer descriptor */
00465     pBi->remaining -= size;
00466     /* Check if list NULL */
00467     if (pTransfer->listState == MBL_NULL) {
00468         return 1;
00469     }
00470     /* Check if current buffer ended */
00471     if (pBi->remaining == 0 || forceEnd || size == 0) {
00472 
00473         /* Process to next buffer */
00474         if ((++ pTransfer->outCurr) == pTransfer->listSize)
00475             pTransfer->outCurr = 0;
00476         /* Check buffer NULL case */
00477         if (pTransfer->outCurr == pTransfer->inCurr)
00478             pTransfer->listState = MBL_NULL;
00479         else {
00480             pTransfer->listState = 0;
00481             /* Continue transfer, prepare for next operation */
00482             pBi = &pTransfer->pMbl[pTransfer->outCurr];
00483             pBi->buffered    = 0;
00484             pBi->transferred = 0;
00485             pBi->remaining   = pBi->size;
00486         }
00487         return 1;
00488     }
00489     return 0;
00490 }
00491 
00492 /**
00493  * Transfers a data payload from the current tranfer buffer to the endpoint
00494  * FIFO
00495  * \param bEndpoint Number of the endpoint which is sending data.
00496  */
00497 static uint8_t UDP_MblWriteFifo(uint8_t bEndpoint)
00498 {
00499     Endpoint    *pEndpoint   = &(endpoints[bEndpoint]);
00500     MblTransfer *pTransfer   = (MblTransfer*)&(pEndpoint->transfer);
00501     USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->outCurr]);
00502     int32_t size;
00503 
00504     volatile uint8_t * pBytes;
00505     volatile uint8_t bufferEnd = 1;
00506 
00507     /* Get the number of bytes to send */
00508     size = pEndpoint->size;
00509     if (size > pBi->remaining) size = pBi->remaining;
00510 
00511     TRACE_DEBUG_WP("w%d.%d ", pTransfer->outCurr, size);
00512 
00513     /* Record last accessed buffer */
00514     pTransfer->outLast = pTransfer->outCurr;
00515 
00516     pBytes = &(pBi->pBuffer[pBi->transferred + pBi->buffered]);
00517     pBi->buffered += size;
00518     bufferEnd = UDP_MblUpdate(pTransfer, pBi, size, 0);
00519 
00520     /* Write packet in the FIFO buffer */
00521     if (size) {
00522         int32_t c8 = size >> 3;
00523         int32_t c1 = size & 0x7;
00524         for (; c8; c8 --) {
00525             UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
00526             UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
00527             UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
00528             UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
00529 
00530             UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
00531             UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
00532             UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
00533             UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
00534         }
00535         for (; c1; c1 --) {
00536             UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
00537         }
00538     }
00539     return bufferEnd;
00540 }
00541 
00542 /**
00543  * Transfers a data payload from the current tranfer buffer to the endpoint
00544  * FIFO
00545  * \param bEndpoint Number of the endpoint which is sending data.
00546  */
00547 static void UDP_WritePayload(uint8_t bEndpoint)
00548 {
00549     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00550     Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
00551     int32_t size;
00552 
00553     // Get the number of bytes to send
00554     size = pEndpoint->size;
00555     if (size > pTransfer->remaining) {
00556 
00557         size = pTransfer->remaining;
00558     }
00559 
00560     // Update transfer descriptor information
00561     pTransfer->buffered += size;
00562     pTransfer->remaining -= size;
00563 
00564     // Write packet in the FIFO buffer
00565     while (size > 0) {
00566 
00567         UDP->UDP_FDR[bEndpoint] = *(pTransfer->pData);
00568         pTransfer->pData++;
00569         size--;
00570     }
00571 }
00572 
00573 
00574 /**
00575  * Transfers a data payload from an endpoint FIFO to the current transfer buffer
00576  * \param bEndpoint Endpoint number.
00577  * \param wPacketSize Size of received data packet
00578  */
00579 static void UDP_ReadPayload(uint8_t bEndpoint, int32_t wPacketSize)
00580 {
00581     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00582     Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
00583 
00584     // Check that the requested size is not bigger than the remaining transfer
00585     if (wPacketSize > pTransfer->remaining) {
00586 
00587         pTransfer->buffered += wPacketSize - pTransfer->remaining;
00588         wPacketSize = pTransfer->remaining;
00589     }
00590 
00591     // Update transfer descriptor information
00592     pTransfer->remaining -= wPacketSize;
00593     pTransfer->transferred += wPacketSize;
00594 
00595     // Retrieve packet
00596     while (wPacketSize > 0) {
00597 
00598         *(pTransfer->pData) = (uint8_t) UDP->UDP_FDR[bEndpoint];
00599         pTransfer->pData++;
00600         wPacketSize--;
00601     }
00602 }
00603 
00604 /**
00605  * Received SETUP packet from endpoint 0 FIFO
00606  * \param pRequest Generic USB SETUP request sent over Control endpoints
00607  */
00608 static void UDP_ReadRequest(USBGenericRequest *pRequest)
00609 {
00610     uint8_t *pData = (uint8_t *)pRequest;
00611     uint32_t i;
00612 
00613     // Copy packet
00614     for (i = 0; i < 8; i++) {
00615 
00616         *pData = (uint8_t) UDP->UDP_FDR[0];
00617         pData++;
00618     }
00619 }
00620 
00621 /**
00622  * Checks if an ongoing transfer on an endpoint has been completed.
00623  * \param bEndpoint Endpoint number.
00624  * \return 1 if the current transfer on the given endpoint is complete;
00625  *         otherwise 0.
00626  */
00627 static uint8_t UDP_IsTransferFinished(uint8_t bEndpoint)
00628 {
00629     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00630     Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
00631 
00632     // Check if it is a Control endpoint
00633     //  -> Control endpoint must always finish their transfer with a zero-length
00634     //     packet
00635     if ((UDP->UDP_CSR[bEndpoint] & UDP_CSR_EPTYPE_Msk) == UDP_CSR_EPTYPE_CTRL) {
00636 
00637         return (pTransfer->buffered < pEndpoint->size);
00638     }
00639     // Other endpoints only need to transfer all the data
00640     else {
00641 
00642         return (pTransfer->buffered <= pEndpoint->size)
00643                && (pTransfer->remaining == 0);
00644     }
00645 }
00646 
00647 /**
00648  * Endpoint interrupt handler.
00649  * Handle IN/OUT transfers, received SETUP packets and STALLing
00650  * \param bEndpoint Index of endpoint
00651  */
00652 static void UDP_EndpointHandler(uint8_t bEndpoint)
00653 {
00654     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00655     Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
00656     MblTransfer *pMblt  = (MblTransfer*)&(pEndpoint->transfer);
00657     uint32_t status = UDP->UDP_CSR[bEndpoint];
00658     uint16_t wPacketSize;
00659     USBGenericRequest request;
00660 
00661     TRACE_DEBUG_WP("E%d ", bEndpoint);
00662     TRACE_DEBUG_WP("st:0x%X ", status);
00663 
00664     // Handle interrupts
00665     // IN packet sent
00666     if ((status & UDP_CSR_TXCOMP) != 0) {
00667 
00668         TRACE_DEBUG_WP("Wr ");
00669 
00670         // Check that endpoint was in MBL Sending state
00671         if (pEndpoint->state == UDP_ENDPOINT_SENDINGM) {
00672 
00673             USBDTransferBuffer * pMbli = &(pMblt->pMbl[pMblt->outLast]);
00674             uint8_t bufferEnd = 0;
00675 
00676             TRACE_DEBUG_WP("TxM%d.%d ", pMblt->listState, pMbli->buffered);
00677 
00678             // End of transfer ?
00679             if (pMblt->listState == MBL_NULL && pMbli->buffered == 0) {
00680 
00681                 pMbli->transferred += pMbli->buffered;
00682                 pMbli->buffered = 0;
00683 
00684                 // Disable interrupt
00685                 UDP->UDP_IDR = 1 << bEndpoint;
00686                 UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00687                 CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP);
00688             }
00689             else {
00690 
00691                 // Transfer remaining data
00692                 TRACE_DEBUG_WP("%d ", pEndpoint->size);
00693 
00694                 if (pMbli->buffered  > pEndpoint->size) {
00695                     pMbli->transferred += pEndpoint->size;
00696                     pMbli->buffered -= pEndpoint->size;
00697                 }
00698                 else {
00699                     pMbli->transferred += pMbli->buffered;
00700                     pMbli->buffered  = 0;
00701                 }
00702 
00703                 // Send next packet
00704                 if (CHIP_USB_ENDPOINTS_BANKS(bEndpoint) == 1) {
00705 
00706                     // No double buffering
00707                     bufferEnd = UDP_MblWriteFifo(bEndpoint);
00708                     SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY);
00709                     CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP);
00710                 }
00711                 else {
00712                     // Double buffering
00713                     SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY);
00714                     CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP);
00715                     bufferEnd = UDP_MblWriteFifo(bEndpoint);
00716                 }
00717 
00718                 if (bufferEnd && pMblt->fCallback) {
00719                     ((MblTransferCallback) pTransfer->fCallback)
00720                         (pTransfer->pArgument,
00721                          USBD_STATUS_PARTIAL_DONE);
00722                 }
00723             }
00724         }
00725         // Check that endpoint was in Sending state
00726         else if (pEndpoint->state == UDP_ENDPOINT_SENDING) {
00727 
00728             // End of transfer ?
00729             if (UDP_IsTransferFinished(bEndpoint)) {
00730 
00731                 pTransfer->transferred += pTransfer->buffered;
00732                 pTransfer->buffered = 0;
00733 
00734                 // Disable interrupt if this is not a control endpoint
00735                 if ((status & UDP_CSR_EPTYPE_Msk) != UDP_CSR_EPTYPE_CTRL) {
00736 
00737                     UDP->UDP_IDR = 1 << bEndpoint;
00738                 }
00739 
00740                 UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00741                 CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP);
00742             }
00743             else {
00744 
00745                 // Transfer remaining data
00746                 TRACE_DEBUG_WP(" %d ", pEndpoint->size);
00747 
00748                 pTransfer->transferred += pEndpoint->size;
00749                 pTransfer->buffered -= pEndpoint->size;
00750 
00751                 // Send next packet
00752                 if (CHIP_USB_ENDPOINTS_BANKS(bEndpoint) == 1) {
00753 
00754                     // No double buffering
00755                     UDP_WritePayload(bEndpoint);
00756                     SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY);
00757                     CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP);
00758                 }
00759                 else {
00760                     // Double buffering
00761                     SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY);
00762                     CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP);
00763                     UDP_WritePayload(bEndpoint);
00764                 }
00765             }
00766         }
00767         else {
00768             // Acknowledge interrupt
00769             TRACE_ERROR("Error Wr%d, %x\n\r", bEndpoint, pEndpoint->state);
00770             CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP);
00771         }
00772     }
00773 
00774     // OUT packet received
00775     if ((status & UDP_CSR_RXDATA_BK) != 0) {
00776 
00777         TRACE_DEBUG_WP("Rd ");
00778 
00779         // Check that the endpoint is in Receiving state
00780         if (pEndpoint->state != UDP_ENDPOINT_RECEIVING) {
00781 
00782             // Check if an ACK has been received on a Control endpoint
00783             if (((status & UDP_CSR_EPTYPE_Msk) == UDP_CSR_EPTYPE_CTRL)
00784                 && ((status & UDP_CSR_RXBYTECNT_Msk) == 0)) {
00785 
00786                 // Acknowledge the data and finish the current transfer
00787                 UDP_ClearRxFlag(bEndpoint);
00788                 UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00789             }
00790             // Check if the data has been STALLed
00791             else if ((status & UDP_CSR_FORCESTALL) != 0) {
00792 
00793                 // Discard STALLed data
00794                 TRACE_DEBUG_WP("Discard ");
00795                 UDP_ClearRxFlag(bEndpoint);
00796             }
00797             // NAK the data
00798             else {
00799 
00800                 TRACE_DEBUG_WP("Nak ");
00801                 UDP->UDP_IDR = 1 << bEndpoint;
00802             }
00803         }
00804         // Endpoint is in Read state
00805         else {
00806 
00807             // Retrieve data and store it into the current transfer buffer
00808             wPacketSize = (uint16_t) (status >> 16);
00809             TRACE_DEBUG_WP("%d ", wPacketSize);
00810             UDP_ReadPayload(bEndpoint, wPacketSize);
00811             UDP_ClearRxFlag(bEndpoint);
00812 
00813             // Check if the transfer is finished
00814             if ((pTransfer->remaining == 0) || (wPacketSize < pEndpoint->size)) {
00815 
00816                 // Disable interrupt if this is not a control endpoint
00817                 if ((status & UDP_CSR_EPTYPE_Msk) != UDP_CSR_EPTYPE_CTRL) {
00818 
00819                     UDP->UDP_IDR = 1 << bEndpoint;
00820                 }
00821                 UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00822             }
00823         }
00824     }
00825 
00826     // STALL sent
00827     if ((status & UDP_CSR_STALLSENTISOERROR) != 0) {
00828 
00829         CLEAR_CSR(bEndpoint, UDP_CSR_STALLSENTISOERROR);
00830 
00831         if (   (status & UDP_CSR_EPTYPE_Msk) == UDP_CSR_EPTYPE_ISO_IN
00832             || (status & UDP_CSR_EPTYPE_Msk) == UDP_CSR_EPTYPE_ISO_OUT ) {
00833 
00834             TRACE_WARNING("Isoe [%d] ", bEndpoint);
00835             UDP_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
00836         }
00837         else {
00838 
00839             TRACE_WARNING("Sta 0x%X [%d] ", (int)status, bEndpoint);
00840 
00841             if (pEndpoint->state != UDP_ENDPOINT_HALTED) {
00842 
00843                 TRACE_WARNING( "_ " );
00844                 // If the endpoint is not halted, clear the STALL condition
00845                 CLEAR_CSR(bEndpoint, UDP_CSR_FORCESTALL);
00846             }
00847         }
00848     }
00849 
00850     // SETUP packet received
00851     if ((status & UDP_CSR_RXSETUP) != 0) {
00852 
00853         TRACE_DEBUG_WP("Stp ");
00854 
00855         // If a transfer was pending, complete it
00856         // Handles the case where during the status phase of a control write
00857         // transfer, the host receives the device ZLP and ack it, but the ack
00858         // is not received by the device
00859         if ((pEndpoint->state == UDP_ENDPOINT_RECEIVING)
00860             || (pEndpoint->state == UDP_ENDPOINT_SENDING)) {
00861 
00862             UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
00863         }
00864         // Copy the setup packet
00865         UDP_ReadRequest(&request);
00866 
00867         // Set the DIR bit before clearing RXSETUP in Control IN sequence
00868         if (USBGenericRequest_GetDirection(&request) == USBGenericRequest_IN) {
00869 
00870             SET_CSR(bEndpoint, UDP_CSR_DIR);
00871         }
00872         // Acknowledge setup packet
00873         CLEAR_CSR(bEndpoint, UDP_CSR_RXSETUP);
00874 
00875         // Forward the request to the upper layer
00876         USBD_RequestHandler(0, &request);
00877     }
00878 
00879 }
00880 
00881 /**
00882  * Sends data through a USB endpoint. Sets up the transfer descriptor,
00883  * writes one or two data payloads (depending on the number of FIFO bank
00884  * for the endpoint) and then starts the actual transfer. The operation is
00885  * complete when all the data has been sent.
00886  *
00887  * *If the size of the buffer is greater than the size of the endpoint
00888  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
00889  *  must be kept allocated until the transfer is finished*. This means that
00890  *  it is not possible to declare it on the stack (i.e. as a local variable
00891  *  of a function which returns after starting a transfer).
00892  *
00893  * \param pEndpoint Pointer to Endpoint struct.
00894  * \param pData Pointer to a buffer with the data to send.
00895  * \param dLength Size of the data buffer.
00896  * \return USBD_STATUS_SUCCESS if the transfer has been started;
00897  *         otherwise, the corresponding error status code.
00898  */
00899 static inline uint8_t UDP_Write(uint8_t    bEndpoint,
00900                                 const void *pData,
00901                                 uint32_t   dLength)
00902 {
00903     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00904     Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
00905 
00906     /* Check that the endpoint is in Idle state */
00907     if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
00908 
00909         return USBD_STATUS_LOCKED;
00910     }
00911     TRACE_DEBUG_WP("Write%d(%d) ", bEndpoint, dLength);
00912 
00913     /* Setup the transfer descriptor */
00914     pTransfer->pData = (void *) pData;
00915     pTransfer->remaining = dLength;
00916     pTransfer->buffered = 0;
00917     pTransfer->transferred = 0;
00918 
00919     /* Send the first packet */
00920     pEndpoint->state = UDP_ENDPOINT_SENDING;
00921     while((UDP->UDP_CSR[bEndpoint]&UDP_CSR_TXPKTRDY)==UDP_CSR_TXPKTRDY);
00922     UDP_WritePayload(bEndpoint);
00923     SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY);
00924 
00925     /* If double buffering is enabled and there is data remaining,
00926        prepare another packet */
00927     if ((CHIP_USB_ENDPOINTS_BANKS(bEndpoint) > 1) && (pTransfer->remaining > 0)) {
00928 
00929         UDP_WritePayload(bEndpoint);
00930     }
00931 
00932     /* Enable interrupt on endpoint */
00933     UDP->UDP_IER = 1 << bEndpoint;
00934 
00935     return USBD_STATUS_SUCCESS;
00936 }
00937 
00938 /**
00939  * Sends data through a USB endpoint. Sets up the transfer descriptor list,
00940  * writes one or two data payloads (depending on the number of FIFO bank
00941  * for the endpoint) and then starts the actual transfer. The operation is
00942  * complete when all the transfer buffer in the list has been sent.
00943  *
00944  * *If the size of the buffer is greater than the size of the endpoint
00945  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
00946  *  must be kept allocated until the transfer is finished*. This means that
00947  *  it is not possible to declare it on the stack (i.e. as a local variable
00948  *  of a function which returns after starting a transfer).
00949  *
00950  * \param pEndpoint Pointer to Endpoint struct.
00951  * \param pData Pointer to a buffer with the data to send.
00952  * \param dLength Size of the data buffer.
00953  * \return USBD_STATUS_SUCCESS if the transfer has been started;
00954  *         otherwise, the corresponding error status code.
00955  */
00956 static inline uint8_t UDP_AddWr(uint8_t    bEndpoint,
00957                                 const void *pData,
00958                                 uint32_t   dLength)
00959 {
00960     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00961     MblTransfer *pMbl = (MblTransfer*)&(pEndpoint->transfer);
00962     USBDTransferBuffer *pTx;
00963 
00964     /* Check parameter */
00965     if (dLength >= 0x10000)
00966         return USBD_STATUS_INVALID_PARAMETER;
00967 
00968     /* Data in progressing */
00969     if (pEndpoint->state > UDP_ENDPOINT_IDLE) {
00970         /* If list full */
00971         if (pMbl->listState == MBL_FULL) {
00972             return USBD_STATUS_LOCKED;
00973         }
00974     }
00975 
00976     TRACE_DEBUG_WP("AddW%d(%d) ", bEndpoint, dLength);
00977 
00978     /* Add buffer to buffer list and update index */
00979     pTx = &(pMbl->pMbl[pMbl->inCurr]);
00980     pTx->pBuffer = (uint8_t*)pData;
00981     pTx->size = pTx->remaining = dLength;
00982     pTx->transferred = pTx->buffered = 0;
00983     /* Update input index */
00984     if (pMbl->inCurr >= (pMbl->listSize-1)) pMbl->inCurr = 0;
00985     else                                    pMbl->inCurr ++;
00986     if (pMbl->inCurr == pMbl->outCurr)      pMbl->listState = MBL_FULL;
00987     else                                    pMbl->listState = 0;
00988     /* Start sending when offset achieved */
00989     if (MBL_NbBuffer(pMbl->inCurr, pMbl->outCurr, pMbl->listSize)
00990             >= pMbl->offsetSize
00991         && pEndpoint->state == UDP_ENDPOINT_IDLE) {
00992         TRACE_DEBUG_WP("StartT ");
00993         /* Change state */
00994         pEndpoint->state = UDP_ENDPOINT_SENDINGM;
00995         while((UDP->UDP_CSR[bEndpoint]&UDP_CSR_TXPKTRDY)==UDP_CSR_TXPKTRDY);
00996         /* Send first packet */
00997         UDP_MblWriteFifo(bEndpoint);
00998         SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY);
00999         /* If double buffering is enabled and there is remaining, continue */
01000         if ((CHIP_USB_ENDPOINTS_BANKS(bEndpoint) > 1)
01001             && pMbl->pMbl[pMbl->outCurr].remaining) {
01002             UDP_MblWriteFifo(bEndpoint);
01003         }
01004         /* Enable interrupt on endpoint */
01005         UDP->UDP_IER = 1 << bEndpoint;
01006     }
01007 
01008     return USBD_STATUS_SUCCESS;
01009 }
01010 
01011 /**
01012  * Reads incoming data on an USB endpoint This methods sets the transfer
01013  * descriptor and activate the endpoint interrupt. The actual transfer is
01014  * then carried out by the endpoint interrupt handler. The Read operation
01015  * finishes either when the buffer is full, or a short packet (inferior to
01016  * endpoint maximum  size) is received.
01017  *
01018  * *The buffer must be kept allocated until the transfer is finished*.
01019  * \param bEndpoint Endpoint number.
01020  * \param pData Pointer to a data buffer.
01021  * \param dLength Size of the data buffer in bytes.
01022  * \return USBD_STATUS_SUCCESS if the read operation has been started;
01023  *         otherwise, the corresponding error code.
01024  */
01025 static inline uint8_t UDP_Read(uint8_t  bEndpoint,
01026                                void     *pData,
01027                                uint32_t dLength)
01028 {
01029     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
01030     Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
01031 
01032     /* Return if the endpoint is not in IDLE state */
01033     if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
01034 
01035         return USBD_STATUS_LOCKED;
01036     }
01037 
01038     /* Endpoint enters Receiving state */
01039     pEndpoint->state = UDP_ENDPOINT_RECEIVING;
01040     TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);
01041 
01042     /* Set the transfer descriptor */
01043     pTransfer->pData = pData;
01044     pTransfer->remaining = dLength;
01045     pTransfer->buffered = 0;
01046     pTransfer->transferred = 0;
01047 
01048     /* Enable interrupt on endpoint */
01049     UDP->UDP_IER = 1 << bEndpoint;
01050 
01051     return USBD_STATUS_SUCCESS;
01052 }
01053 
01054 
01055 /*---------------------------------------------------------------------------
01056  *      Exported functions
01057  *---------------------------------------------------------------------------*/
01058 
01059 /**
01060  * USBD (UDP) interrupt handler
01061  * Manages device resume, suspend, end of bus reset.
01062  * Forwards endpoint events to the appropriate handler.
01063  */
01064 void USBD_IrqHandler(void)
01065 {
01066     uint32_t status;
01067     int32_t eptnum = 0;
01068 
01069     /* Enable peripheral ? */
01070     //UDP_EnablePeripheralClock();
01071 
01072     /* Get interrupt status
01073        Some interrupts may get masked depending on the device state */
01074     status = UDP->UDP_ISR;
01075     status &= UDP->UDP_IMR;
01076 
01077     if (USBD_GetState() < USBD_STATE_POWERED) {
01078 
01079         status &= UDP_ICR_WAKEUP | UDP_ICR_RXRSM;
01080         UDP->UDP_ICR = ~status;
01081     }
01082 
01083     /* Return immediately if there is no interrupt to service */
01084     if (status == 0) {
01085 
01086         TRACE_DEBUG_WP(".\n\r");
01087         return;
01088     }
01089 
01090     /* Toggle USB LED if the device is active */
01091     if (USBD_GetState() >= USBD_STATE_POWERED) {
01092 
01093         //LED_Set(USBD_LEDUSB);
01094     }
01095 
01096     /* Service interrupts */
01097 
01098     /** / Start Of Frame (SOF) */
01099     //if (ISSET(dStatus, UDP_ISR_SOFINT)) {
01100     //
01101     //    TRACE_DEBUG("SOF");
01102     //
01103     //    // Invoke the SOF callback
01104     //    USB_StartOfFrameCallback(pUsb);
01105     //
01106     //    // Acknowledge interrupt
01107     //    UDP->UDP_ICR = UDP_ICR_SOFINT;
01108     //    dStatus &= ~UDP_ISR_SOFINT;
01109     //}
01110     /* Resume (Wakeup) */
01111     if ((status & (UDP_ISR_WAKEUP | UDP_ISR_RXRSM)) != 0) {
01112 
01113         TRACE_INFO_WP("Res ");
01114         /* Clear and disable resume interrupts */
01115         UDP->UDP_ICR = UDP_ICR_WAKEUP | UDP_ICR_RXRSM | UDP_ICR_RXSUSP;
01116         UDP->UDP_IDR = UDP_IDR_WAKEUP | UDP_IDR_RXRSM;
01117         /* Do resome operations */
01118         USBD_ResumeHandler();
01119     }
01120 
01121     /* Suspend
01122        This interrupt is always treated last (hence the '==') */
01123     if (status == UDP_ISR_RXSUSP) {
01124 
01125         TRACE_INFO_WP("Susp ");
01126         /* Enable wakeup */
01127         UDP->UDP_IER = UDP_IER_WAKEUP | UDP_IER_RXRSM;
01128         /* Acknowledge interrupt */
01129         UDP->UDP_ICR = UDP_ICR_RXSUSP;
01130         /* Do suspend operations */
01131         USBD_SuspendHandler();
01132     }
01133     /* End of bus reset */
01134     else if ((status & UDP_ISR_ENDBUSRES) != 0) {
01135 
01136         TRACE_INFO_WP("EoBRes ");
01137         /* Flush and enable the Suspend interrupt */
01138         UDP->UDP_ICR = UDP_ICR_WAKEUP | UDP_ICR_RXRSM | UDP_ICR_RXSUSP;
01139         UDP->UDP_IER = UDP_IER_RXSUSP;
01140 
01141         /* Do RESET operations */
01142         USBD_ResetHandler();
01143 
01144         /* Acknowledge end of bus reset interrupt */
01145         UDP->UDP_ICR = UDP_ICR_ENDBUSRES;
01146     }
01147     /* Endpoint interrupts */
01148     else {
01149 
01150         status &= ((1 << CHIP_USB_NUMENDPOINTS) - 1);
01151         while (status != 0) {
01152 
01153             /* Check if endpoint has a pending interrupt */
01154             if ((status & (1 << eptnum)) != 0) {
01155 
01156                 UDP_EndpointHandler(eptnum);
01157                 status &= ~(1 << eptnum);
01158 
01159                 if (status != 0) {
01160 
01161                     TRACE_INFO_WP("\n\r  - ");
01162                 }
01163             }
01164             eptnum++;
01165         }
01166     }
01167 
01168     /* Toggle LED back to its previous state */
01169     TRACE_DEBUG_WP("!");
01170     TRACE_INFO_WP("\n\r");
01171     if (USBD_GetState() >= USBD_STATE_POWERED) {
01172 
01173         //LED_Clear(USBD_LEDUSB);
01174     }
01175 }
01176 
01177 /**
01178  * \brief Reset endpoints and disable them.
01179  * -# Terminate transfer if there is any, with given status;
01180  * -# Reset the endpoint & disable it.
01181  * \param bmEPs    Bitmap for endpoints to reset.
01182  * \param bStatus  Status passed to terminate transfer on endpoint.
01183  * \param bKeepCfg 1 to keep old endpoint configuration.
01184  * \note Use USBD_HAL_ConfigureEP() to configure and enable endpoint
01185          if not keeping old configuration.
01186  * \sa USBD_HAL_ConfigureEP().
01187  */
01188 void USBD_HAL_ResetEPs(uint32_t bmEPs, uint8_t bStatus, uint8_t bKeepCfg)
01189 {
01190     Endpoint *pEndpoint;
01191     uint32_t tmp = bmEPs & ((1<<CHIP_USB_NUMENDPOINTS)-1);
01192     uint8_t  ep;
01193     uint32_t epBit, epCfg;
01194     for (ep = 0, epBit = 1; ep < CHIP_USB_NUMENDPOINTS; ep ++) {
01195         if (tmp & epBit) {
01196 
01197             /* Disable ISR */
01198             UDP->UDP_IDR = epBit;
01199             /* Kill pending TXPKTREADY */
01200             CLEAR_CSR(ep, UDP_CSR_TXPKTRDY);
01201 
01202             /* Reset transfer information */
01203             pEndpoint = &(endpoints[ep]);
01204             /* Reset endpoint state */
01205             pEndpoint->bank = 0;
01206             /* Endpoint configure */
01207             epCfg = UDP->UDP_CSR[ep];
01208             /* Reset endpoint */
01209             UDP->UDP_RST_EP |=  epBit;
01210             UDP->UDP_RST_EP &= ~epBit;
01211             /* Restore configure */
01212             if (bKeepCfg) {
01213                 //SET_CSR(ep, pEndpoint->CSR);
01214                 SET_CSR(ep, epCfg);
01215             }
01216             else {
01217                 //pEndpoint->CSR = 0;
01218                 pEndpoint->state = UDP_ENDPOINT_DISABLED;
01219             }
01220 
01221             /* Terminate transfer on this EP */
01222             UDP_EndOfTransfer(ep, bStatus);
01223         }
01224         epBit <<= 1;
01225     }
01226     /* Reset EPs */
01227     // UDP->UDP_RST_EP |=  bmEPs;
01228     // UDP->UDP_RST_EP &= ~bmEPs;
01229 }
01230 
01231 /**
01232  * Cancel pending READ/WRITE
01233  * \param bmEPs    Bitmap for endpoints to reset.
01234  * \note EP callback is invoked with USBD_STATUS_CANCELED.
01235  */
01236 void USBD_HAL_CancelIo(uint32_t bmEPs)
01237 {
01238     uint32_t tmp = bmEPs & ((1<<CHIP_USB_NUMENDPOINTS)-1);
01239     uint8_t  ep;
01240     uint32_t epBit;
01241     for (ep = 0, epBit = 1; ep < CHIP_USB_NUMENDPOINTS; ep ++) {
01242         if (tmp & epBit) {
01243 
01244             /* Disable ISR */
01245             UDP->UDP_IDR = epBit;
01246             /* Kill pending TXPKTREADY */
01247             CLEAR_CSR(ep, UDP_CSR_TXPKTRDY);
01248 
01249             /* Terminate transfer on this EP */
01250             UDP_EndOfTransfer(ep, USBD_STATUS_CANCELED);
01251         }
01252         epBit <<= 1;
01253     }
01254 }
01255 
01256 /**
01257  * Configures an endpoint according to its endpoint Descriptor.
01258  * \param pDescriptor Pointer to an endpoint descriptor.
01259  */
01260 uint8_t USBD_HAL_ConfigureEP(const USBEndpointDescriptor *pDescriptor)
01261 {
01262     Endpoint *pEndpoint;
01263     uint8_t bEndpoint;
01264     uint8_t bType;
01265     uint8_t bEndpointDir;
01266 
01267     /* NULL descriptor -> Control endpoint 0 in default */
01268     if (pDescriptor == 0) {
01269         bEndpoint = 0;
01270         pEndpoint = &(endpoints[bEndpoint]);
01271         bType= USBEndpointDescriptor_CONTROL;
01272         bEndpointDir = 0;
01273         pEndpoint->size = CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0);
01274     }
01275     /* Device descriptor -> Specific Control EP */
01276     else if (pDescriptor->bDescriptorType == USBGenericDescriptor_DEVICE) {
01277         bEndpoint = 0;
01278         pEndpoint = &(endpoints[bEndpoint]);
01279         bType = USBEndpointDescriptor_CONTROL;
01280         bEndpointDir = 0;
01281         pEndpoint->size = ((USBDeviceDescriptor *)pDescriptor)->bMaxPacketSize0;
01282     }
01283     /* Not endpoint descriptor, ERROR! */
01284     else if (pDescriptor->bDescriptorType != USBGenericDescriptor_ENDPOINT) {
01285         return 0xFF;
01286     }
01287     else {
01288         bEndpoint = USBEndpointDescriptor_GetNumber(pDescriptor);
01289         pEndpoint = &(endpoints[bEndpoint]);
01290         bType = USBEndpointDescriptor_GetType(pDescriptor);
01291         bEndpointDir = USBEndpointDescriptor_GetDirection(pDescriptor);
01292         pEndpoint->size = USBEndpointDescriptor_GetMaxPacketSize(pDescriptor);
01293     }
01294 
01295     /* Abort the current transfer is the endpoint was configured and in
01296        Write or Read state */
01297     if ((pEndpoint->state == UDP_ENDPOINT_RECEIVING)
01298         || (pEndpoint->state == UDP_ENDPOINT_SENDING)
01299         || (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM)
01300         || (pEndpoint->state == UDP_ENDPOINT_SENDINGM)) {
01301         UDP_EndOfTransfer(bEndpoint, USBD_STATUS_RESET);
01302     }
01303     pEndpoint->state = UDP_ENDPOINT_IDLE;
01304 
01305     /* Reset Endpoint Fifos */
01306     UDP->UDP_RST_EP |= (1 << bEndpoint);
01307     UDP->UDP_RST_EP &= ~(1 << bEndpoint);
01308 
01309     /* Configure endpoint */
01310     SET_CSR(bEndpoint, (uint32_t)UDP_CSR_EPEDS
01311                        | (bType << 8) | (bEndpointDir << 10));
01312     if (bType != USBEndpointDescriptor_CONTROL) {
01313 
01314     }
01315     else {
01316 
01317         UDP->UDP_IER = (1 << bEndpoint);
01318     }
01319 
01320     TRACE_INFO_WP("CfgEp%d ", bEndpoint);
01321     return bEndpoint;
01322 }
01323 
01324 /**
01325  * Set callback for a USB endpoint for transfer (read/write).
01326  *
01327  * \param bEP       Endpoint number.
01328  * \param fCallback Optional callback function to invoke when the transfer is
01329  *                  complete.
01330  * \param pCbData   Optional pointer to data to the callback function.
01331  * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED if endpoint is busy.
01332  */
01333 uint8_t USBD_HAL_SetTransferCallback(uint8_t          bEP,
01334                                   TransferCallback fCallback,
01335                                   void             *pCbData)
01336 {
01337     Endpoint *pEndpoint = &(endpoints[bEP]);
01338     TransferHeader *pTransfer = (TransferHeader*)&(pEndpoint->transfer);
01339     /* Check that the endpoint is not transferring */
01340     if (pEndpoint->state > UDP_ENDPOINT_IDLE) {
01341         return USBD_STATUS_LOCKED;
01342     }
01343     TRACE_DEBUG_WP("sXfrCb ");
01344     /* Setup the transfer callback and extension data */
01345     pTransfer->fCallback = (void*)fCallback;
01346     pTransfer->pArgument = pCbData;
01347     return USBD_STATUS_SUCCESS;
01348 }
01349 
01350 /**
01351  * Configure an endpoint to use multi-buffer-list transfer mode.
01352  * The buffers can be added by _Read/_Write function.
01353  * \param pMbList  Pointer to a multi-buffer list used, NULL to disable MBL.
01354  * \param mblSize  Multi-buffer list size (number of buffers can be queued)
01355  * \param startOffset When number of buffer achieve this offset transfer start
01356  */
01357 uint8_t USBD_HAL_SetupMblTransfer( uint8_t bEndpoint,
01358                                    USBDTransferBuffer* pMbList,
01359                                    uint16_t mblSize,
01360                                    uint16_t startOffset)
01361 {
01362     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
01363     MblTransfer *pXfr = (MblTransfer*)&(pEndpoint->transfer);
01364     uint16_t i;
01365     /* Check that the endpoint is not transferring */
01366     if (pEndpoint->state > UDP_ENDPOINT_IDLE) {
01367         return USBD_STATUS_LOCKED;
01368     }
01369     TRACE_DEBUG_WP("sMblXfr ");
01370     /* Enable Multi-Buffer Transfer List */
01371     if (pMbList) {
01372         /* Reset list items */
01373         for (i = 0; i < mblSize; i --) {
01374             pMbList[i].pBuffer     = NULL;
01375             pMbList[i].size        = 0;
01376             pMbList[i].transferred = 0;
01377             pMbList[i].buffered    = 0;
01378             pMbList[i].remaining   = 0;
01379         }
01380         /* Setup transfer */
01381         pXfr->transType  = 1;
01382         pXfr->listState  = 0; /* OK */
01383         pXfr->listSize   = mblSize;
01384         pXfr->pMbl       = pMbList;
01385         pXfr->outCurr = pXfr->outLast = 0;
01386         pXfr->inCurr  = 0;
01387         pXfr->offsetSize = startOffset;
01388     }
01389     /* Disable Multi-Buffer Transfer */
01390     else {
01391         pXfr->transType  = 0;
01392         pXfr->pMbl       = NULL;
01393         pXfr->listSize   = 0;
01394         pXfr->offsetSize = 1;
01395     }
01396     return USBD_STATUS_SUCCESS;
01397 }
01398 
01399 /**
01400  * Sends data through a USB endpoint. Sets up the transfer descriptor,
01401  * writes one or two data payloads (depending on the number of FIFO bank
01402  * for the endpoint) and then starts the actual transfer. The operation is
01403  * complete when all the data has been sent.
01404  *
01405  * *If the size of the buffer is greater than the size of the endpoint
01406  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
01407  *  must be kept allocated until the transfer is finished*. This means that
01408  *  it is not possible to declare it on the stack (i.e. as a local variable
01409  *  of a function which returns after starting a transfer).
01410  *
01411  * \param bEndpoint Endpoint number.
01412  * \param pData Pointer to a buffer with the data to send.
01413  * \param dLength Size of the data buffer.
01414  * \return USBD_STATUS_SUCCESS if the transfer has been started;
01415  *         otherwise, the corresponding error status code.
01416  */
01417 uint8_t USBD_HAL_Write( uint8_t          bEndpoint,
01418                         const void       *pData,
01419                         uint32_t         dLength)
01420 {
01421     if (endpoints[bEndpoint].transfer.transHdr.transType)
01422         return UDP_AddWr(bEndpoint, pData, dLength);
01423     else
01424         return UDP_Write(bEndpoint, pData, dLength);
01425 }
01426 
01427 /**
01428  * Reads incoming data on an USB endpoint This methods sets the transfer
01429  * descriptor and activate the endpoint interrupt. The actual transfer is
01430  * then carried out by the endpoint interrupt handler. The Read operation
01431  * finishes either when the buffer is full, or a short packet (inferior to
01432  * endpoint maximum  size) is received.
01433  *
01434  * *The buffer must be kept allocated until the transfer is finished*.
01435  * \param bEndpoint Endpoint number.
01436  * \param pData Pointer to a data buffer.
01437  * \param dLength Size of the data buffer in bytes.
01438  * \return USBD_STATUS_SUCCESS if the read operation has been started;
01439  *         otherwise, the corresponding error code.
01440  */
01441 uint8_t USBD_HAL_Read(uint8_t    bEndpoint,
01442                       void       *pData,
01443                       uint32_t   dLength)
01444 {
01445     if (endpoints[bEndpoint].transfer.transHdr.transType)
01446         return USBD_STATUS_SW_NOT_SUPPORTED;
01447     else
01448         return UDP_Read(bEndpoint, pData, dLength);
01449 }
01450 
01451 /**
01452  *  \brief Enable Pull-up, connect.
01453  *
01454  *  -# Enable HW access if needed
01455  *  -# Enable Pull-Up
01456  *  -# Disable HW access if needed
01457  */
01458 void USBD_HAL_Connect(void)
01459 {
01460     uint8_t dis = UDP_EnablePeripheralClock();
01461     UDP->UDP_TXVC |= UDP_TXVC_PUON;
01462     if (dis) UDP_DisablePeripheralClock();
01463 }
01464 
01465 /**
01466  *  \brief Disable Pull-up, disconnect.
01467  *
01468  *  -# Enable HW access if needed
01469  *  -# Disable PULL-Up
01470  *  -# Disable HW access if needed
01471  */
01472 void USBD_HAL_Disconnect(void)
01473 {
01474     uint8_t dis = UDP_EnablePeripheralClock();
01475     UDP->UDP_TXVC &= ~(uint32_t)UDP_TXVC_PUON;
01476     if (dis) UDP_DisablePeripheralClock();
01477 }
01478 
01479 /**
01480  * Starts a remote wake-up procedure.
01481  */
01482 void USBD_HAL_RemoteWakeUp(void)
01483 {
01484     UDP_EnablePeripheralClock();
01485     UDP_EnableUsbClock();
01486     UDP_EnableTransceiver();
01487 
01488     TRACE_INFO_WP("RWUp ");
01489 
01490     // Activates a remote wakeup (edge on ESR), then clear ESR
01491     UDP->UDP_GLB_STAT |= UDP_GLB_STAT_ESR;
01492     UDP->UDP_GLB_STAT &= ~(uint32_t)UDP_GLB_STAT_ESR;
01493 }
01494 
01495 /**
01496  * Sets the device address to the given value.
01497  * \param address New device address.
01498  */
01499 void USBD_HAL_SetAddress(uint8_t address)
01500 {
01501     /* Set address */
01502     UDP->UDP_FADDR = UDP_FADDR_FEN | (address & UDP_FADDR_FADD_Msk);
01503     /* If the address is 0, the device returns to the Default state */
01504     if (address == 0)   UDP->UDP_GLB_STAT = 0;
01505     /* If the address is non-zero, the device enters the Address state */
01506     else        UDP->UDP_GLB_STAT = UDP_GLB_STAT_FADDEN;
01507 }
01508 
01509 /**
01510  * Sets the current device configuration.
01511  * \param cfgnum - Configuration number to set.
01512  */
01513 void USBD_HAL_SetConfiguration(uint8_t cfgnum)
01514 {
01515     /* If the configuration number if non-zero, the device enters the
01516        Configured state */
01517     if (cfgnum != 0) UDP->UDP_GLB_STAT |= UDP_GLB_STAT_CONFG;
01518     /* If the configuration number is zero, the device goes back to the Address
01519        state */
01520     else {
01521         UDP->UDP_GLB_STAT = UDP_FADDR_FEN;
01522     }
01523 }
01524 
01525 /**
01526  * Initializes the USB HW Access driver.
01527  */
01528 void USBD_HAL_Init(void)
01529 {
01530     /* Must before USB & TXVC access! */
01531     UDP_EnablePeripheralClock();
01532 
01533     /* Reset & disable endpoints */
01534     USBD_HAL_ResetEPs(0xFFFFFFFF, USBD_STATUS_RESET, 0);
01535 
01536     /* Configure the pull-up on D+ and disconnect it */
01537     UDP->UDP_TXVC &= ~(uint32_t)UDP_TXVC_PUON;
01538 
01539     UDP_EnableUsbClock();
01540 
01541     UDP->UDP_IDR = 0xFE;
01542     UDP->UDP_IER = UDP_IER_WAKEUP;
01543 }
01544 
01545 /**
01546  * Causes the given endpoint to acknowledge the next packet it receives
01547  * with a STALL handshake except setup request.
01548  * \param bEP Endpoint number.
01549  * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED.
01550  */
01551 uint8_t USBD_HAL_Stall(uint8_t bEP)
01552 {
01553     Endpoint *pEndpoint = &(endpoints[bEP]);
01554 
01555     /* Check that endpoint is in Idle state */
01556     if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
01557         TRACE_WARNING("UDP_Stall: EP%d locked\n\r", bEP);
01558         return USBD_STATUS_LOCKED;
01559     }
01560     /* STALL endpoint */
01561     SET_CSR(bEP, UDP_CSR_FORCESTALL);
01562     TRACE_DEBUG_WP("Stall%d ", bEP);
01563     return USBD_STATUS_SUCCESS;
01564 }
01565 
01566 /**
01567  * Sets/Clear/Get the HALT state on the endpoint.
01568  * In HALT state, the endpoint should keep stalling any packet.
01569  * \param bEndpoint Endpoint number.
01570  * \param ctl       Control code CLR/HALT/READ.
01571  *                  0: Clear HALT state;
01572  *                  1: Set HALT state;
01573  *                  .: Return HALT status.
01574  * \return USBD_STATUS_INVALID_PARAMETER if endpoint not exist,
01575  *         otherwise endpoint halt status.
01576  */
01577 uint8_t USBD_HAL_Halt(uint8_t bEndpoint, uint8_t ctl)
01578 {
01579     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
01580     uint8_t status = 0;
01581 
01582     /* SET Halt */
01583     if (ctl == 1) {
01584         /* Check that endpoint is enabled and not already in Halt state */
01585         if ((pEndpoint->state != UDP_ENDPOINT_DISABLED)
01586             && (pEndpoint->state != UDP_ENDPOINT_HALTED)) {
01587 
01588             TRACE_DEBUG_WP("Halt%d ", bEndpoint);
01589 
01590             /* Abort the current transfer if necessary */
01591             UDP_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
01592 
01593             /* Put endpoint into Halt state */
01594             SET_CSR(bEndpoint, UDP_CSR_FORCESTALL);
01595             pEndpoint->state = UDP_ENDPOINT_HALTED;
01596 
01597             /* Enable the endpoint interrupt */
01598             UDP->UDP_IER = 1 << bEndpoint;
01599         }
01600     }
01601     /* CLEAR Halt */
01602     else if (ctl == 0) {
01603         /* Check if the endpoint is halted */
01604         //if (pEndpoint->state != UDP_ENDPOINT_DISABLED) {
01605         if (pEndpoint->state == UDP_ENDPOINT_HALTED) {
01606 
01607             TRACE_DEBUG_WP("Unhalt%d ", bEndpoint);
01608 
01609             /* Return endpoint to Idle state */
01610             pEndpoint->state = UDP_ENDPOINT_IDLE;
01611 
01612             /* Clear FORCESTALL flag */
01613             CLEAR_CSR(bEndpoint, UDP_CSR_FORCESTALL);
01614 
01615             /* Reset Endpoint Fifos, beware this is a 2 steps operation */
01616             UDP->UDP_RST_EP |= 1 << bEndpoint;
01617             UDP->UDP_RST_EP &= ~(1 << bEndpoint);
01618         }
01619     }
01620 
01621     /* Return Halt status */
01622     if (pEndpoint->state == UDP_ENDPOINT_HALTED) {
01623         status = 1;
01624     }
01625     return( status );
01626 }
01627 
01628 /**
01629  * Indicates if the device is running in high or full-speed. Always returns 0
01630  * since UDP does not support high-speed mode.
01631  */
01632 uint8_t USBD_HAL_IsHighSpeed(void)
01633 {
01634     return 0;
01635 }
01636 
01637 /**
01638  * Suspend USB Device HW Interface
01639  *
01640  * -# Disable transceiver
01641  * -# Disable USB Clock
01642  * -# Disable USB Peripheral
01643  */
01644 void USBD_HAL_Suspend(void)
01645 {
01646     /* The device enters the Suspended state */
01647     UDP_DisableTransceiver();
01648     UDP_DisableUsbClock();
01649     UDP_DisablePeripheralClock();
01650 }
01651 
01652 /**
01653  * Activate USB Device HW Interface
01654  * -# Enable USB Peripheral
01655  * -# Enable USB Clock
01656  * -# Enable transceiver
01657  */
01658 void USBD_HAL_Activate(void)
01659 {
01660     UDP_EnablePeripheralClock();
01661     UDP_EnableUsbClock();
01662     UDP_EnableTransceiver();
01663 }
01664 
01665 /**
01666  * Certification test for High Speed device.
01667  * \param bIndex Test to be done
01668  */
01669 void USBD_HAL_Test( uint8_t bIndex )
01670 {
01671     bIndex = bIndex;
01672 }
01673 
01674 /**@}*/
01675 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines