]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_IAR_Keil/libchip_samv7/source/USBD_HAL.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained_IAR_Keil / libchip_samv7 / source / USBD_HAL.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License \r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2011, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 /**\r
31 \r
32  \file\r
33 \r
34     Implementation of USB device functions on a UDP controller.\r
35 \r
36     See \ref usbd_api_method USBD API Methods.\r
37 */\r
38 \r
39 /** \addtogroup usbd_hal\r
40  *@{*/\r
41 \r
42 /*---------------------------------------------------------------------------\r
43  *      Headers\r
44  *---------------------------------------------------------------------------*/\r
45 \r
46 #include "chip.h"\r
47 #include "USBD_HAL.h"\r
48 \r
49 #include <stdbool.h>\r
50 #include <stdint.h>\r
51 #include <stdio.h>\r
52 #include <string.h>\r
53 \r
54 /*---------------------------------------------------------------------------\r
55  *      Definitions\r
56  *---------------------------------------------------------------------------*/\r
57 \r
58 #define DMA\r
59 \r
60 /** Maximum number of endpoints interrupts. */\r
61 #define NUM_IT_MAX       \\r
62     ((UDPHS->UDPHS_IPFEATURES & UDPHS_IPFEATURES_EPT_NBR_MAX_Msk) ? \\r
63      (UDPHS->UDPHS_IPFEATURES & UDPHS_IPFEATURES_EPT_NBR_MAX_Msk) : 16)\r
64 /** Maximum number of endpoint DMA interrupts */\r
65 #define NUM_IT_MAX_DMA   \\r
66     ((UDPHS->UDPHS_IPFEATURES \\r
67         & UDPHS_IPFEATURES_DMA_CHANNEL_NBR_Msk) \\r
68       >>UDPHS_IPFEATURES_DMA_CHANNEL_NBR_Pos)\r
69 /** Bits that should be shifted to access DMA control bits. */\r
70 #define SHIFT_DMA        24\r
71 /** Bits that should be shifted to access interrupt bits. */\r
72 #define SHIFT_INTERUPT    8\r
73 \r
74 /** Max size of the FMA FIFO */\r
75 #define DMA_MAX_FIFO_SIZE     (65536/1)\r
76 /** fifo space size in DW */\r
77 #define EPT_VIRTUAL_SIZE      16384\r
78 \r
79 /**\r
80  * \section endpoint_states_sec "UDP Endpoint states"\r
81  *\r
82  *  This page lists the endpoint states.\r
83  *\r
84  *  \subsection States\r
85  *  - UDPHS_ENDPOINT_DISABLED\r
86  *  - UDPHS_ENDPOINT_HALTED\r
87  *  - UDPHS_ENDPOINT_IDLE\r
88  *  - UDPHS_ENDPOINT_SENDING\r
89  *  - UDPHS_ENDPOINT_RECEIVING\r
90  *  - UDPHS_ENDPOINT_SENDINGM\r
91  *  - UDPHS_ENDPOINT_RECEIVINGM\r
92  */\r
93 \r
94 /**  Endpoint states: Endpoint is disabled */\r
95 #define UDPHS_ENDPOINT_DISABLED       0\r
96 /**  Endpoint states: Endpoint is halted (i.e. STALLs every request) */\r
97 #define UDPHS_ENDPOINT_HALTED         1\r
98 /**  Endpoint states: Endpoint is idle (i.e. ready for transmission) */\r
99 #define UDPHS_ENDPOINT_IDLE           2\r
100 /**  Endpoint states: Endpoint is sending data */\r
101 #define UDPHS_ENDPOINT_SENDING        3\r
102 /**  Endpoint states: Endpoint is receiving data */\r
103 #define UDPHS_ENDPOINT_RECEIVING      4\r
104 /**  Endpoint states: Endpoint is sending MBL */\r
105 #define UDPHS_ENDPOINT_SENDINGM       5\r
106 /**  Endpoint states: Endpoint is receiving MBL */\r
107 #define UDPHS_ENDPOINT_RECEIVINGM     6\r
108 \r
109 /** Get Number of buffer in Multi-Buffer-List\r
110  *  \param i    input index\r
111  *  \param o    output index\r
112  *  \param size list size\r
113  */\r
114 #define MBL_NbBuffer(i, o, size) (((i)>(o))?((i)-(o)):((i)+(size)-(o)))\r
115 \r
116 /** Buffer list is full */\r
117 #define MBL_FULL        1\r
118 /** Buffer list is null */\r
119 #define MBL_NULL        2\r
120 \r
121 /*---------------------------------------------------------------------------\r
122  *      Types\r
123  *---------------------------------------------------------------------------*/\r
124 \r
125 /**  Describes header for UDP endpoint transfer. */\r
126 typedef struct {\r
127     /**  Optional callback to invoke when the transfer completes. */\r
128     void*   fCallback;\r
129     /**  Optional argument to the callback function. */\r
130     void*   pArgument;\r
131     /**  Transfer type */\r
132     uint8_t transType;\r
133     /* Reserved to 32-b aligned */\r
134     uint8_t reserved[3];\r
135 } TransferHeader;\r
136 \r
137 /**  Describes a transfer on a UDP endpoint. */\r
138 typedef struct {\r
139 \r
140     /**  Optional callback to invoke when the transfer completes. */\r
141     TransferCallback fCallback;\r
142     /**  Optional argument to the callback function. */\r
143     void             *pArgument;\r
144     /**  Transfer type */\r
145     uint8_t          transType;\r
146     uint8_t          reserved[3];\r
147     /**  Number of bytes which have been written into the UDP internal FIFO\r
148      *   buffers. */\r
149     int32_t          buffered;\r
150     /**  Pointer to a data buffer used for emission/reception. */\r
151     uint8_t          *pData;\r
152     /**  Number of bytes which have been sent/received. */\r
153     int32_t          transferred;\r
154     /**  Number of bytes which have not been buffered/transferred yet. */\r
155     int32_t          remaining;\r
156 } Transfer;\r
157 \r
158 /**  Describes Multi Buffer List transfer on a UDP endpoint. */\r
159 typedef struct {\r
160     /**  Optional callback to invoke when the transfer completes. */\r
161     MblTransferCallback fCallback;\r
162     /**  Optional argument to the callback function. */\r
163     void                *pArgument;\r
164     /** Transfer type */\r
165     uint8_t             transType;\r
166     /** List state (OK, FULL, NULL) (run time) */\r
167     uint8_t             listState;\r
168     /**  Multi-Buffer List size */\r
169     uint16_t            listSize;\r
170     /**  Pointer to multi-buffer list */\r
171     USBDTransferBuffer *pMbl;\r
172     /**  Offset number of buffers to start transfer */\r
173     uint16_t            offsetSize;\r
174     /**  Current processing buffer index (run time) */\r
175     uint16_t            outCurr;\r
176     /**  Loast loaded buffer index (run time) */\r
177     uint16_t            outLast;\r
178     /**  Current buffer for input (run time) */\r
179     uint16_t            inCurr;\r
180 } MblTransfer;\r
181 \r
182 /**\r
183  *  Describes the state of an endpoint of the UDP controller.\r
184  */\r
185 typedef struct {\r
186 \r
187     /* CSR */\r
188     /**  Current endpoint state. */\r
189     volatile uint8_t  state;\r
190     /**  Current reception bank (0 or 1). */\r
191     volatile uint8_t  bank;\r
192     /**  Maximum packet size for the endpoint. */\r
193     volatile uint16_t size;\r
194     /**  Describes an ongoing transfer (if current state is either\r
195      *   UDPHS_ENDPOINT_SENDING or UDPHS_ENDPOINT_RECEIVING) */\r
196     union {\r
197         TransferHeader transHdr;\r
198         Transfer       singleTransfer;\r
199         MblTransfer    mblTransfer;\r
200     } transfer;\r
201     /** Special case for send a ZLP */\r
202     uint32_t sendZLP;\r
203 } Endpoint;\r
204 \r
205 /**\r
206  * DMA Descriptor.\r
207  */\r
208 typedef struct {\r
209     void    *pNxtDesc;\r
210     void    *pAddr;\r
211     uint32_t dwCtrl;\r
212     uint32_t dw;\r
213 } UdphsDmaDescriptor;\r
214 \r
215 /*---------------------------------------------------------------------------\r
216  *      Internal variables\r
217  *---------------------------------------------------------------------------*/\r
218 \r
219 /** Holds the internal state for each endpoint of the UDP. */\r
220 static Endpoint endpoints[CHIP_USB_NUMENDPOINTS];\r
221 \r
222 /** 7.1.20 Test Mode Support\r
223  * Test codes for the USB HS test mode. */\r
224 static const char test_packet_buffer[] = {\r
225     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                // JKJKJKJK * 9\r
226     0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,                     // JJKKJJKK * 8\r
227     0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,                     // JJJJKKKK * 8\r
228     0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8\r
229     0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,                          // JJJJJJJK * 8\r
230     0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E                 // {JKKKKKKK * 10}, JK\r
231 };\r
232 \r
233 /** Force FS mode */\r
234 static const uint8_t forceUsbFS = 0;\r
235 \r
236 /** DMA link list */\r
237 static UdphsDmaDescriptor  dmaLL[5];\r
238 static UdphsDmaDescriptor *pDmaLL;\r
239 \r
240 /*---------------------------------------------------------------------------\r
241  *      Internal Functions\r
242  *---------------------------------------------------------------------------*/\r
243 \r
244 /**\r
245  * Enables the clock of the UDP peripheral.\r
246  * \return 1 if peripheral status changed.\r
247  */\r
248 static uint8_t UDPHS_EnablePeripheralClock(void)\r
249 {\r
250     if (!PMC_IsPeriphEnabled(ID_UDPHS)) {\r
251         PMC_EnablePeripheral(ID_UDPHS);\r
252         return 1;\r
253     }\r
254     return 0;\r
255 }\r
256 \r
257 /**\r
258  * Disables the UDP peripheral clock.\r
259  */\r
260 static inline void UDPHS_DisablePeripheralClock(void)\r
261 {\r
262     PMC_DisablePeripheral(ID_UDPHS);\r
263 }\r
264 \r
265 /**\r
266  * Enables the 480MHz USB clock.\r
267  */\r
268 static inline void UDPHS_EnableUsbClock(void)\r
269 {\r
270     Pmc *pPmc = PMC;\r
271     /* Enable 480Mhz UPLL */\r
272     pPmc->CKGR_UCKR |= CKGR_UCKR_UPLLEN\r
273                        | CKGR_UCKR_UPLLCOUNT(0x3)\r
274                        | CKGR_UCKR_BIASCOUNT(0x1);\r
275     /* Wait until UPLL is locked */\r
276     while((pPmc->PMC_SR & PMC_SR_LOCKU) == 0);\r
277 }\r
278 \r
279 /**\r
280  *  Disables the 480MHz USB clock.\r
281  */\r
282 static inline void UDPHS_DisableUsbClock(void)\r
283 {\r
284     Pmc *pPmc = PMC;\r
285     /* Disable System Clock */\r
286     //pPmc->PMC_SCDR = PMC_SCDR_UDP;\r
287     pPmc->CKGR_UCKR &= ~(uint32_t)CKGR_UCKR_UPLLEN;\r
288 }\r
289 \r
290 /**\r
291  * Enables the BIAS.\r
292  */\r
293 static inline void UDPHS_EnableBIAS(void)\r
294 {\r
295     Pmc *pPmc = PMC;\r
296     pPmc->CKGR_UCKR |= CKGR_UCKR_BIASEN;\r
297 }\r
298 \r
299 /**\r
300  * Disables the BIAS.\r
301  */\r
302 static inline void UDPHS_DisableBIAS(void)\r
303 {\r
304     Pmc *pPmc = PMC;\r
305     pPmc->CKGR_UCKR &= ~(uint32_t)CKGR_UCKR_BIASEN;\r
306 }\r
307 \r
308 /**\r
309  * Handles a completed transfer on the given endpoint, invoking the\r
310  * configured callback if any.\r
311  * \param bEndpoint Number of the endpoint for which the transfer has completed.\r
312  * \param bStatus   Status code returned by the transfer operation\r
313  */\r
314 static void UDPHS_EndOfTransfer(uint8_t bEndpoint, uint8_t bStatus)\r
315 {\r
316     Endpoint *pEp = &(endpoints[bEndpoint]);\r
317 \r
318     /* Check that endpoint was sending or receiving data */\r
319     if ( (pEp->state == UDPHS_ENDPOINT_RECEIVING)\r
320             || (pEp->state == UDPHS_ENDPOINT_SENDING) )\r
321     {\r
322         Transfer *pXfr = (Transfer*)&(pEp->transfer);\r
323         uint32_t transferred = pXfr->transferred;\r
324         uint32_t remaining   = pXfr->remaining + pXfr->buffered;\r
325         \r
326         TRACE_DEBUG_WP("EoT ");\r
327         if (pEp->state == UDPHS_ENDPOINT_SENDING)\r
328             pEp->sendZLP = 0;\r
329         pEp->state = UDPHS_ENDPOINT_IDLE;\r
330         pXfr->pData = 0;\r
331         pXfr->transferred = -1;\r
332         pXfr->buffered    = -1;\r
333         pXfr->remaining   = -1;\r
334 \r
335         /* Invoke callback */\r
336         if (pXfr->fCallback)\r
337         {\r
338             pXfr->fCallback(pXfr->pArgument, bStatus, transferred, remaining);\r
339         }\r
340         else\r
341         {\r
342             TRACE_DEBUG_WP("NoCB ");\r
343         }\r
344     }\r
345     else if ( (pEp->state == UDPHS_ENDPOINT_RECEIVINGM)\r
346                 || (pEp->state == UDPHS_ENDPOINT_SENDINGM) )\r
347     {\r
348         MblTransfer *pXfr = (MblTransfer*)&(pEp->transfer);\r
349         TRACE_DEBUG_WP("EoMT ");\r
350 \r
351         pEp->state = UDPHS_ENDPOINT_IDLE;\r
352         pXfr->listState = 0;\r
353         pXfr->outCurr = pXfr->inCurr = pXfr->outLast = 0;\r
354         /* Invoke callback */\r
355         if (pXfr->fCallback)\r
356         {\r
357             pXfr->fCallback(pXfr->pArgument, bStatus);\r
358         }\r
359         else\r
360         {\r
361             TRACE_DEBUG_WP("NoCB ");\r
362         }\r
363     }\r
364 }\r
365 \r
366 /**\r
367  * Update multi-buffer-transfer descriptors.\r
368  * \param pTransfer Pointer to instance MblTransfer.\r
369  * \param size      Size of bytes that processed.\r
370  * \param forceEnd  Force the buffer END.\r
371  * \return 1 if current buffer ended.\r
372  */\r
373 static uint8_t UDPHS_MblUpdate(MblTransfer *pTransfer,\r
374                           USBDTransferBuffer * pBi,\r
375                           uint16_t size,\r
376                           uint8_t forceEnd)\r
377 {\r
378     /* Update transfer descriptor */\r
379     pBi->remaining -= size;\r
380     /* Check if list NULL */\r
381     if (pTransfer->listState == MBL_NULL) {\r
382         return 1;\r
383     }\r
384     /* Check if current buffer ended */\r
385     if (pBi->remaining == 0 || forceEnd || size == 0) {\r
386 \r
387         /* Process to next buffer */\r
388         if ((++ pTransfer->outCurr) == pTransfer->listSize)\r
389             pTransfer->outCurr = 0;\r
390         /* Check buffer NULL case */\r
391         if (pTransfer->outCurr == pTransfer->inCurr)\r
392             pTransfer->listState = MBL_NULL;\r
393         else {\r
394             pTransfer->listState = 0;\r
395             /* Continue transfer, prepare for next operation */\r
396             pBi = &pTransfer->pMbl[pTransfer->outCurr];\r
397             pBi->buffered    = 0;\r
398             pBi->transferred = 0;\r
399             pBi->remaining   = pBi->size;\r
400         }\r
401         return 1;\r
402     }\r
403     return 0;\r
404 }\r
405 \r
406 /**\r
407  * Transfers a data payload from the current tranfer buffer to the endpoint\r
408  * FIFO\r
409  * \param bEndpoint Number of the endpoint which is sending data.\r
410  */\r
411 static uint8_t UDPHS_MblWriteFifo(uint8_t bEndpoint)\r
412 {\r
413     Endpoint    *pEndpoint   = &(endpoints[bEndpoint]);\r
414     MblTransfer *pTransfer   = (MblTransfer*)&(pEndpoint->transfer);\r
415     USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->outCurr]);\r
416     uint8_t *pFifo;\r
417     int32_t size;\r
418 \r
419     volatile uint8_t * pBytes;\r
420     volatile uint8_t bufferEnd = 1;\r
421 \r
422     /* Get the number of bytes to send */\r
423     size = pEndpoint->size;\r
424     if (size > pBi->remaining) size = pBi->remaining;\r
425 \r
426     TRACE_DEBUG_WP("w%d.%d ", pTransfer->outCurr, size);\r
427 \r
428     /* Record last accessed buffer */\r
429     pTransfer->outLast = pTransfer->outCurr;\r
430 \r
431     pBytes = &(pBi->pBuffer[pBi->transferred + pBi->buffered]);\r
432     pBi->buffered += size;\r
433     bufferEnd = UDPHS_MblUpdate(pTransfer, pBi, size, 0);\r
434 \r
435     /* Write packet in the FIFO buffer */\r
436     pFifo = (uint8_t*)((uint32_t*)UDPHS_RAM_ADDR\r
437                                     + (EPT_VIRTUAL_SIZE * bEndpoint));\r
438     if (size) {\r
439         int32_t c8 = size >> 3;\r
440         int32_t c1 = size & 0x7;\r
441         for (; c8; c8 --) {\r
442             *(pFifo++) = *(pBytes ++);\r
443             *(pFifo++) = *(pBytes ++);\r
444             *(pFifo++) = *(pBytes ++);\r
445             *(pFifo++) = *(pBytes ++);\r
446 \r
447             *(pFifo++) = *(pBytes ++);\r
448             *(pFifo++) = *(pBytes ++);\r
449             *(pFifo++) = *(pBytes ++);\r
450             *(pFifo++) = *(pBytes ++);\r
451         }\r
452         for (; c1; c1 --) {\r
453             *(pFifo++) = *(pBytes ++);\r
454         }\r
455     }\r
456     return bufferEnd;\r
457 }\r
458 \r
459 #if 0\r
460 /**\r
461  *  Transfers a data payload from an endpoint FIFO to the current transfer\r
462  *  buffer, if NULL packet received, the current buffer is ENDed.\r
463  *  \param bEndpoint Endpoint number.\r
464  *  \param wPacketSize Size of received data packet */\r
465  *  \return 1 if the buffer ENDed. */\r
466  */\r
467 static uint8_t UDPHS_MblReadFifo(uint8_t bEndpoint, uint16_t wPacketSize)\r
468 {\r
469    \r
470     return 0;\r
471 }\r
472 */\r
473 #endif\r
474 /**\r
475  * Transfers a data payload from the current tranfer buffer to the endpoint\r
476  * FIFO\r
477  * \param bEndpoint Number of the endpoint which is sending data.\r
478  */\r
479 static void UDPHS_WritePayload(uint8_t bEndpoint, int32_t size)\r
480 {\r
481     Endpoint *pEndpoint = &(endpoints[bEndpoint]);\r
482     Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);\r
483     uint8_t  *pFifo;\r
484 \r
485     /* Get the number of bytes to send */\r
486     if (size > pTransfer->remaining)\r
487     {\r
488         size = pTransfer->remaining;\r
489     }\r
490 \r
491     /* Update transfer descriptor information */\r
492     pTransfer->buffered += size;\r
493     pTransfer->remaining -= size;\r
494 \r
495     /* Write packet in the FIFO buffer */\r
496     pFifo = (uint8_t*)((uint32_t*)UDPHS_RAM_ADDR\r
497                                     + (EPT_VIRTUAL_SIZE * bEndpoint));\r
498     for (; size; size --)\r
499     {\r
500         *(pFifo ++) = *(pTransfer->pData ++);\r
501     }\r
502 }\r
503 \r
504 /**\r
505  * Transfers a data payload from an endpoint FIFO to the current transfer buffer\r
506  * \param bEndpoint Endpoint number.\r
507  * \param wPacketSize Size of received data packet\r
508  */\r
509 static void UDPHS_ReadPayload(uint8_t bEndpoint, int32_t wPacketSize)\r
510 {\r
511     Endpoint *pEndpoint = &(endpoints[bEndpoint]);\r
512     Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);\r
513     uint8_t  *pFifo;\r
514     /* Check that the requested size is not bigger than the remaining transfer */\r
515     if (wPacketSize > pTransfer->remaining) {\r
516 \r
517         pTransfer->buffered += wPacketSize - pTransfer->remaining;\r
518         wPacketSize = pTransfer->remaining;\r
519     }\r
520 \r
521     /* Update transfer descriptor information */\r
522     pTransfer->remaining -= wPacketSize;\r
523     pTransfer->transferred += wPacketSize;\r
524 \r
525     /* Retrieve packet */\r
526     pFifo = (uint8_t*)((uint32_t*)UDPHS_RAM_ADDR\r
527                                     + (EPT_VIRTUAL_SIZE * bEndpoint));\r
528     while (wPacketSize > 0)\r
529     {\r
530         *(pTransfer->pData ++) = *(pFifo ++);\r
531         wPacketSize--;\r
532     }\r
533 }\r
534 \r
535 /**\r
536  * Received SETUP packet from endpoint 0 FIFO\r
537  * \param pRequest Generic USB SETUP request sent over Control endpoints\r
538  */\r
539 static void UDPHS_ReadRequest(USBGenericRequest *pRequest)\r
540 {\r
541     uint32_t *pData = (uint32_t *)(void*)pRequest;\r
542     volatile uint32_t *pFifo;\r
543     pFifo = (volatile uint32_t*)UDPHS_RAM_ADDR;\r
544     *pData ++ = *pFifo;\r
545     pFifo = (volatile uint32_t*)UDPHS_RAM_ADDR;\r
546     *pData    = *pFifo;\r
547 }\r
548 \r
549 /**\r
550  * Endpoint interrupt handler.\r
551  * Handle IN/OUT transfers, received SETUP packets and STALLing\r
552  * \param bEndpoint Index of endpoint\r
553  */\r
554 static void UDPHS_EndpointHandler(uint8_t bEndpoint)\r
555 {\r
556     Udphs    *pUdp = UDPHS;\r
557     UdphsEpt *pEpt = &pUdp->UDPHS_EPT[bEndpoint];\r
558     //UdphsDma *pDma = &pUdp->UDPHS_DMA[bEndpoint];\r
559 \r
560     Endpoint *pEp      = &(endpoints[bEndpoint]);\r
561     Transfer *pXfr     = (Transfer*)&(pEp->transfer);\r
562     //MblTransfer *pMblt = (MblTransfer*)&(pEp->transfer);\r
563     uint32_t status = pEpt->UDPHS_EPTSTA;\r
564     uint32_t type   = pEpt->UDPHS_EPTCFG & UDPHS_EPTCFG_EPT_TYPE_Msk;\r
565     uint32_t reqBuf[2];\r
566     USBGenericRequest *pReq = (USBGenericRequest *)reqBuf;\r
567     uint16_t wPktSize;\r
568 \r
569     TRACE_DEBUG_WP("Ep%d ", bEndpoint);\r
570     //TRACE_DEBUG_WP("St:%x ", status);\r
571     /* IN packet sent */\r
572     if (   (pEpt->UDPHS_EPTCTL & UDPHS_EPTCTL_TX_PK_RDY)\r
573         && (0 == (status & UDPHS_EPTSTA_TX_PK_RDY)) )\r
574     {\r
575         TRACE_DEBUG_WP("Wr ");\r
576 \r
577         /* Multi-buffer-list transfer state */\r
578         if ( pEp->state == UDPHS_ENDPOINT_SENDINGM )\r
579         {\r
580         }\r
581         /* Sending state */\r
582         else if ( pEp->state == UDPHS_ENDPOINT_SENDING )\r
583         {\r
584             if (pXfr->buffered)\r
585             {\r
586                 pXfr->transferred += pXfr->buffered;\r
587                 pXfr->buffered = 0;\r
588             }\r
589             if (   pXfr->buffered == 0\r
590                 && pXfr->transferred == 0\r
591                 && pXfr->remaining == 0\r
592                 && pEp->sendZLP == 0 )\r
593             {\r
594                 pEp->sendZLP = 1;\r
595             }\r
596 \r
597             /* End of Xfr ? */\r
598             if (   pXfr->remaining\r
599                 || pEp->sendZLP == 1)\r
600             {\r
601                 pEp->sendZLP = 2;\r
602 \r
603                 /* Transfer remaining */\r
604                 TRACE_DEBUG_WP("%d ", pEp->size);\r
605                 /* Send next packet */\r
606                 UDPHS_WritePayload(bEndpoint, pEp->size);\r
607                 pEpt->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_TX_PK_RDY;\r
608             }\r
609             else\r
610             {\r
611                 TRACE_DEBUG_WP("l%d ", pXfr->transferred);\r
612                 /* Disable interrupt on none-control EP */\r
613                 if (type != UDPHS_EPTCFG_EPT_TYPE_CTRL8)\r
614                 {\r
615                     pUdp->UDPHS_IEN &= ~(UDPHS_IEN_EPT_0 << bEndpoint);\r
616                 }\r
617                 pEpt->UDPHS_EPTCTLDIS = UDPHS_EPTCTLDIS_TX_PK_RDY;\r
618 \r
619                 UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);\r
620                 pEp->sendZLP = 0;\r
621             }\r
622         }\r
623         else\r
624         {\r
625             TRACE_DEBUG("Err Wr %d\n\r", pEp->sendZLP);\r
626         }\r
627     }\r
628     /* OUT packet received */\r
629     if ( UDPHS_EPTSTA_RX_BK_RDY & status )\r
630     {\r
631         TRACE_DEBUG_WP("Rd ");\r
632 \r
633         /* NOT in receiving state */\r
634         if (pEp->state != UDPHS_ENDPOINT_RECEIVING)\r
635         {\r
636             /* Check if ACK received on a Control EP */\r
637             if (   (UDPHS_EPTCFG_EPT_TYPE_CTRL8 == type)\r
638                 && (0 == (status & UDPHS_EPTSTA_BYTE_COUNT_Msk)) )\r
639             {\r
640                 TRACE_DEBUG_WP("Ack ");\r
641                 pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY;\r
642                 UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);\r
643             }\r
644             /* data has been STALLed */\r
645             else if (UDPHS_EPTSTA_FRCESTALL & status)\r
646             {\r
647                 TRACE_DEBUG_WP("Discard ");\r
648                 pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY;\r
649             }\r
650             /* NAK the data */\r
651             else\r
652             {\r
653                 TRACE_DEBUG_WP("Nak ");\r
654                 pUdp->UDPHS_IEN &= ~(UDPHS_IEN_EPT_0 << bEndpoint);\r
655             }\r
656         }\r
657         /* In read state */\r
658         else\r
659         {\r
660             wPktSize = (uint16_t)((status & UDPHS_EPTSTA_BYTE_COUNT_Msk) >> UDPHS_EPTSTA_BYTE_COUNT_Pos);\r
661 \r
662             TRACE_DEBUG_WP("%d ", wPktSize);\r
663             UDPHS_ReadPayload(bEndpoint, wPktSize);\r
664             pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY;\r
665             /* Check if transfer is finished */\r
666             if (pXfr->remaining == 0 || wPktSize < pEp->size)\r
667             {\r
668                 pEpt->UDPHS_EPTCTLDIS = UDPHS_EPTCTLDIS_RX_BK_RDY;\r
669 \r
670                 /* Disable interrupt if not control EP */\r
671                 if (UDPHS_EPTCFG_EPT_TYPE_CTRL8 != type)\r
672                 {\r
673                     pUdp->UDPHS_IEN &= ~(UDPHS_IEN_EPT_0 << bEndpoint);\r
674                 }\r
675                 UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);\r
676             }\r
677         }\r
678     }\r
679     /* STALL sent */\r
680     if ( UDPHS_EPTSTA_STALL_SNT & status )\r
681     {\r
682         /* Acknowledge */\r
683         pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_STALL_SNT;\r
684 \r
685         /* ISO error */\r
686         if (type == UDPHS_EPTCFG_EPT_TYPE_ISO)\r
687         {\r
688             TRACE_WARNING("IsoE[%d]\n\r", bEndpoint);\r
689 \r
690             UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);\r
691         }\r
692         /* If EP is not halted, clear STALL */\r
693         else\r
694         {\r
695             TRACE_WARNING("Stall[%d]\n\r", bEndpoint);\r
696 \r
697             if (pEp->state != UDPHS_ENDPOINT_HALTED)\r
698             {\r
699                 pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_FRCESTALL;\r
700             }\r
701         }\r
702     }\r
703     /* SETUP packet received */\r
704     if ( UDPHS_EPTSTA_RX_SETUP & status )\r
705     {\r
706         /* If a transfer was pending, complete it\r
707            Handles the case where during the status phase of a control write\r
708            transfer, the host receives the device ZLP and ack it, but the ack\r
709            is not received by the device */\r
710         if (pEp->state == UDPHS_ENDPOINT_RECEIVING\r
711             || pEp->state == UDPHS_ENDPOINT_RECEIVINGM\r
712             || pEp->state == UDPHS_ENDPOINT_SENDING\r
713             || pEp->state == UDPHS_ENDPOINT_SENDINGM)\r
714         {\r
715             UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);\r
716         }\r
717 \r
718         /* ISO Err Flow */\r
719         if (type == UDPHS_EPTCFG_EPT_TYPE_ISO)\r
720         {\r
721             TRACE_WARNING("IsoFE[%d]\n\r", bEndpoint);\r
722             /* Acknowledge setup packet */\r
723             pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_SETUP;\r
724         }\r
725         else\r
726         {\r
727             TRACE_DEBUG_WP("Stup ");\r
728             \r
729             /* Copy setup */\r
730             UDPHS_ReadRequest(pReq);\r
731             /* Acknowledge setup packet */\r
732             pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_SETUP;\r
733             /* Handler */\r
734             USBD_RequestHandler(bEndpoint, pReq);\r
735         }\r
736     }\r
737 }\r
738 #ifdef DMA\r
739 /**\r
740  * DMA Single transfer\r
741  * \param bEndpoint EP number.\r
742  * \pXfr  Pointer to transfer instance.\r
743  * \dwCfg DMA Control configuration (excluding length).\r
744  */\r
745 static inline void UDPHS_DmaSingle(uint8_t bEndpoint, Transfer *pXfr, uint32_t dwCfg)\r
746 {\r
747     Udphs *pUdp = UDPHS;\r
748 \r
749     /* Single transfer */\r
750     CP15_coherent_dcache_for_dma ((uint32_t)&pXfr->pData[pXfr->transferred], ((uint32_t)&pXfr->pData[pXfr->transferred]) + pXfr->buffered);\r
751     pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMAADDRESS =\r
752                 (uint32_t)&pXfr->pData[pXfr->transferred];\r
753     pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;\r
754     /* Interrupt enable */\r
755     pUdp->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);\r
756     \r
757     TRACE_DEBUG_WP("Dma[B%d:T%d] ", pXfr->buffered, pXfr->transferred);\r
758     /* DMA Configure */\r
759     pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0;\r
760     pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0\r
761                             | UDPHS_DMACONTROL_BUFF_LENGTH(pXfr->buffered)\r
762                             | dwCfg;\r
763 }\r
764 /**\r
765  * Endpoint DMA interrupt handler.\r
766  * This function handles DMA interrupts.\r
767  * \param bEndpoint Index of endpoint\r
768  */\r
769 static void UDPHS_DmaHandler(uint8_t bEndpoint)\r
770 {\r
771     Udphs    *pUdp  = UDPHS;\r
772     //UdphsEpt *pHwEp = &pUdp->UDPHS_EPT[bEndpoint];\r
773 \r
774     Endpoint *pEp  = &(endpoints[bEndpoint]);\r
775     Transfer *pXfr = (Transfer*)&(pEp->transfer);\r
776 \r
777     uint32_t dwDmaSr;\r
778     int32_t iRemain, iXfred;\r
779     uint8_t bRc = USBD_STATUS_SUCCESS;\r
780 \r
781     CP15_flush_dcache_for_dma ((uint32_t)&pXfr->pData[pXfr->transferred], ((uint32_t)&pXfr->pData[pXfr->transferred]) + pXfr->buffered);\r
782     dwDmaSr = pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;\r
783     TRACE_DEBUG_WP("iDma%d,%x ", bEndpoint, dwDmaSr);\r
784     /* Mbl transfer */\r
785     if (pEp->state == UDPHS_ENDPOINT_SENDINGM)\r
786     {\r
787         /* Not implemented */\r
788         return;\r
789     }\r
790     else if (pEp->state == UDPHS_ENDPOINT_RECEIVINGM)\r
791     {\r
792         /* Not implemented */\r
793         return;\r
794     }\r
795 \r
796     /* Disable DMA interrupt to avoid receiving 2 (B_EN and TR_EN) */\r
797     pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL &= ~(UDPHS_DMACONTROL_END_TR_EN\r
798                                                     |UDPHS_DMACONTROL_END_B_EN);\r
799     if (UDPHS_DMASTATUS_END_BF_ST & dwDmaSr)\r
800     {\r
801         TRACE_DEBUG_WP("EoDmaB ");\r
802         /* BUFF_COUNT holds the number of untransmitted bytes.\r
803            BUFF_COUNT is equal to zero in case of good transfer */\r
804         iRemain = (dwDmaSr & UDPHS_DMASTATUS_BUFF_COUNT_Msk)\r
805                         >> UDPHS_DMASTATUS_BUFF_COUNT_Pos;\r
806         TRACE_DEBUG_WP("C%d ", iRemain);\r
807         iXfred  = pXfr->buffered - iRemain;\r
808 \r
809         pXfr->transferred += iXfred;\r
810         pXfr->buffered     = iRemain;\r
811         pXfr->remaining   -= iXfred;\r
812         TRACE_DEBUG_WP("[B%d:T%d:R%d] ", pXfr->buffered, pXfr->transferred, pXfr->remaining);\r
813         /* There is still data */\r
814         if (pXfr->remaining + pXfr->buffered > 0)\r
815         {   \r
816             if (pXfr->remaining > DMA_MAX_FIFO_SIZE)\r
817             {\r
818                 pXfr->buffered = DMA_MAX_FIFO_SIZE;\r
819             }\r
820             else\r
821             {\r
822                 pXfr->buffered = pXfr->remaining;\r
823             }\r
824             /* Single transfer again */\r
825             UDPHS_DmaSingle(bEndpoint, pXfr, UDPHS_DMACONTROL_END_TR_EN\r
826                                              | UDPHS_DMACONTROL_END_TR_IT\r
827                                              | UDPHS_DMACONTROL_END_B_EN\r
828                                              | UDPHS_DMACONTROL_END_BUFFIT\r
829                                              | UDPHS_DMACONTROL_CHANN_ENB);\r
830         }\r
831     }\r
832     else if (UDPHS_DMASTATUS_END_TR_ST & dwDmaSr)\r
833     {\r
834         TRACE_DEBUG_WP("EoDmaT ");\r
835         pXfr->transferred = pXfr->buffered -\r
836             ((dwDmaSr & UDPHS_DMASTATUS_BUFF_COUNT_Msk)\r
837                     >> UDPHS_DMASTATUS_BUFF_COUNT_Pos);\r
838         pXfr->remaining = 0;\r
839 \r
840         TRACE_DEBUG_WP("[B%d:T%d] ", pXfr->buffered, pXfr->transferred);\r
841     }\r
842     else\r
843     {\r
844         TRACE_ERROR("UDPHS_DmaHandler: ST 0x%X\n\r", (unsigned int)dwDmaSr);\r
845         bRc = USBD_STATUS_ABORTED;\r
846     }\r
847     /* Callback */\r
848     if (pXfr->remaining == 0)\r
849     {\r
850         UDPHS_EndOfTransfer(bEndpoint, bRc);\r
851         \r
852     }\r
853     \r
854 }\r
855 #endif\r
856 /**\r
857  * Sends data through a USB endpoint. Sets up the transfer descriptor,\r
858  * writes one or two data payloads (depending on the number of FIFO bank\r
859  * for the endpoint) and then starts the actual transfer. The operation is\r
860  * complete when all the data has been sent.\r
861  *\r
862  * *If the size of the buffer is greater than the size of the endpoint\r
863  *  (or twice the size if the endpoint has two FIFO banks), then the buffer\r
864  *  must be kept allocated until the transfer is finished*. This means that\r
865  *  it is not possible to declare it on the stack (i.e. as a local variable\r
866  *  of a function which returns after starting a transfer).\r
867  *\r
868  * \param pEndpoint Pointer to Endpoint struct.\r
869  * \param pData Pointer to a buffer with the data to send.\r
870  * \param dLength Size of the data buffer.\r
871  * \return USBD_STATUS_SUCCESS if the transfer has been started;\r
872  *         otherwise, the corresponding error status code.\r
873  */\r
874 static inline uint8_t UDPHS_Write(uint8_t    bEndpoint,\r
875                                 const void *pData,\r
876                                 uint32_t   dLength)\r
877 {\r
878     Udphs    *pUdp  = UDPHS;\r
879     UdphsEpt *pHwEp = &pUdp->UDPHS_EPT[bEndpoint];\r
880   \r
881     Endpoint *pEp  = &(endpoints[bEndpoint]);\r
882     Transfer *pXfr = (Transfer*)&(pEp->transfer);\r
883     /* Return if busy */\r
884     if (pEp->state != UDPHS_ENDPOINT_IDLE)\r
885     {\r
886         return USBD_STATUS_LOCKED;\r
887     }\r
888     /* Sending state */\r
889     pEp->state = UDPHS_ENDPOINT_SENDING;\r
890     TRACE_DEBUG_WP("Wr%d(%d) ", bEndpoint, dLength);\r
891     pEp->sendZLP = 0;\r
892     /* Setup transfer descriptor */\r
893     pXfr->pData       = (void*) pData;\r
894     pXfr->remaining   = dLength;\r
895     pXfr->buffered    = 0;\r
896     pXfr->transferred = 0;\r
897   #ifdef DMA\r
898     /* 1. DMA supported, 2. Not ZLP */\r
899     if (CHIP_USB_ENDPOINTS_DMA(bEndpoint)\r
900         && pXfr->remaining > 0)\r
901     {\r
902         if (pXfr->remaining > DMA_MAX_FIFO_SIZE)\r
903         {\r
904             /* Transfer the max */\r
905             pXfr->buffered = DMA_MAX_FIFO_SIZE;\r
906         }\r
907         else\r
908         {\r
909             /* Good size */\r
910             pXfr->buffered = pXfr->remaining;\r
911         }\r
912         /* Single transfer */\r
913         UDPHS_DmaSingle(bEndpoint, pXfr, UDPHS_DMACONTROL_END_B_EN\r
914                                          | UDPHS_DMACONTROL_END_BUFFIT\r
915                                          | UDPHS_DMACONTROL_CHANN_ENB);\r
916         return USBD_STATUS_SUCCESS;\r
917     }\r
918   #endif\r
919 \r
920     /* Enable IT */\r
921     pUdp->UDPHS_IEN |= ( UDPHS_IEN_EPT_0 << bEndpoint );\r
922     pHwEp->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_TX_PK_RDY;\r
923     return USBD_STATUS_SUCCESS;\r
924 }\r
925 \r
926 /**\r
927  * Sends data through a USB endpoint. Sets up the transfer descriptor list,\r
928  * writes one or two data payloads (depending on the number of FIFO bank\r
929  * for the endpoint) and then starts the actual transfer. The operation is\r
930  * complete when all the transfer buffer in the list has been sent.\r
931  *\r
932  * *If the size of the buffer is greater than the size of the endpoint\r
933  *  (or twice the size if the endpoint has two FIFO banks), then the buffer\r
934  *  must be kept allocated until the transfer is finished*. This means that\r
935  *  it is not possible to declare it on the stack (i.e. as a local variable\r
936  *  of a function which returns after starting a transfer).\r
937  *\r
938  * \param pEndpoint Pointer to Endpoint struct.\r
939  * \param pData Pointer to a buffer with the data to send.\r
940  * \param dLength Size of the data buffer.\r
941  * \return USBD_STATUS_SUCCESS if the transfer has been started;\r
942  *         otherwise, the corresponding error status code.\r
943  */\r
944 static inline uint8_t UDPHS_AddWr(uint8_t   bEndpoint,\r
945                                 const void *pData,\r
946                                 uint32_t    dLength)\r
947 {\r
948     Udphs    *pUdp  = UDPHS;\r
949     UdphsEpt *pHwEp = &pUdp->UDPHS_EPT[bEndpoint];\r
950 \r
951     Endpoint *pEp  = &(endpoints[bEndpoint]);\r
952     MblTransfer *pMbl = (MblTransfer*)&(pEp->transfer);\r
953     USBDTransferBuffer *pTx;\r
954     /* Check parameter */\r
955     if (dLength >= 0x10000)\r
956     {\r
957         return USBD_STATUS_INVALID_PARAMETER;\r
958     }\r
959     /* Data in process */\r
960     if (pEp->state > UDPHS_ENDPOINT_IDLE)\r
961     {   /* MBL transfer */\r
962         if (pMbl->transType)\r
963         {\r
964             if (pMbl->listState == MBL_FULL)\r
965             {\r
966                 return USBD_STATUS_LOCKED;\r
967             }\r
968         }\r
969         else\r
970         {\r
971             return USBD_STATUS_LOCKED;\r
972         }\r
973     }\r
974 \r
975     TRACE_DEBUG_WP("AddW%d(%d) ", bEndpoint, dLength);\r
976     /* Add buffer to buffer list and update index */\r
977     pTx = &(pMbl->pMbl[pMbl->inCurr]);\r
978     pTx->pBuffer = (uint8_t*)pData;\r
979     pTx->size = pTx->remaining = dLength;\r
980     pTx->transferred = pTx->buffered = 0;\r
981     /* Update input index */\r
982     if (pMbl->inCurr >= (pMbl->listSize-1)) pMbl->inCurr = 0;\r
983     else                                    pMbl->inCurr ++;\r
984     if (pMbl->inCurr == pMbl->outCurr)      pMbl->listState = MBL_FULL;\r
985     else                                    pMbl->listState = 0;\r
986     /* Start sending when offset achieved */\r
987     if (MBL_NbBuffer(pMbl->inCurr, pMbl->outCurr, pMbl->listSize)\r
988             >= pMbl->offsetSize\r
989         && pEp->state == UDPHS_ENDPOINT_IDLE)\r
990     {\r
991         uint8_t nbBanks = CHIP_USB_ENDPOINTS_BANKS(bEndpoint);\r
992 \r
993         /* Change state */\r
994         pEp->state = UDPHS_ENDPOINT_SENDINGM;\r
995 \r
996         TRACE_DEBUG_WP("StartM ");\r
997 \r
998         /* Fill data into FIFO */\r
999         for (;\r
1000              nbBanks && pMbl->pMbl[pMbl->inCurr].remaining;\r
1001              nbBanks --)\r
1002         {\r
1003             UDPHS_MblWriteFifo(bEndpoint);\r
1004             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_TX_PK_RDY;\r
1005         }\r
1006 \r
1007         /* Enable interrupt */\r
1008         pUdp->UDPHS_IEN |= (UDPHS_IEN_EPT_0 << bEndpoint);\r
1009         pHwEp->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_TX_PK_RDY;\r
1010 \r
1011     }\r
1012 \r
1013     return USBD_STATUS_SUCCESS;\r
1014 }\r
1015 \r
1016 /**\r
1017  * Reads incoming data on an USB endpoint This methods sets the transfer\r
1018  * descriptor and activate the endpoint interrupt. The actual transfer is\r
1019  * then carried out by the endpoint interrupt handler. The Read operation\r
1020  * finishes either when the buffer is full, or a short packet (inferior to\r
1021  * endpoint maximum  size) is received.\r
1022  *\r
1023  * *The buffer must be kept allocated until the transfer is finished*.\r
1024  * \param bEndpoint Endpoint number.\r
1025  * \param pData Pointer to a data buffer.\r
1026  * \param dLength Size of the data buffer in bytes.\r
1027  * \return USBD_STATUS_SUCCESS if the read operation has been started;\r
1028  *         otherwise, the corresponding error code.\r
1029  */\r
1030 static inline uint8_t UDPHS_Read(uint8_t  bEndpoint,\r
1031                                  void     *pData,\r
1032                                  uint32_t dLength)\r
1033 {\r
1034     Udphs    *pUdp  = UDPHS;\r
1035     UdphsEpt *pHwEp = &pUdp->UDPHS_EPT[bEndpoint];\r
1036 \r
1037     Endpoint *pEp  = &(endpoints[bEndpoint]);\r
1038     Transfer *pXfr = (Transfer*)&(pEp->transfer);\r
1039     /* Return if busy */\r
1040     if (pEp->state != UDPHS_ENDPOINT_IDLE)\r
1041     {\r
1042         return USBD_STATUS_LOCKED;\r
1043     }\r
1044     /* Receiving state */\r
1045     pEp->state = UDPHS_ENDPOINT_RECEIVING;\r
1046 \r
1047     TRACE_DEBUG_WP("Rd%d(%d) ", bEndpoint, dLength);\r
1048     /* Setup transfer descriptor */\r
1049     pXfr->pData       = (void*) pData;\r
1050     pXfr->remaining   = dLength;\r
1051     pXfr->buffered    = 0;\r
1052     pXfr->transferred = 0;\r
1053 \r
1054   #ifdef DMA\r
1055     /* If: 1. DMA supported, 2. Has data */\r
1056     if (CHIP_USB_ENDPOINTS_DMA(bEndpoint)\r
1057         && pXfr->remaining > 0)\r
1058     {\r
1059         /* DMA XFR size adjust */\r
1060         if (pXfr->remaining > DMA_MAX_FIFO_SIZE)\r
1061             pXfr->buffered = DMA_MAX_FIFO_SIZE;\r
1062         else\r
1063             pXfr->buffered = pXfr->remaining;\r
1064         /* Single transfer */\r
1065         UDPHS_DmaSingle(bEndpoint, pXfr, UDPHS_DMACONTROL_END_TR_EN\r
1066                                          | UDPHS_DMACONTROL_END_TR_IT\r
1067                                          | UDPHS_DMACONTROL_END_B_EN\r
1068                                          | UDPHS_DMACONTROL_END_BUFFIT\r
1069                                          | UDPHS_DMACONTROL_CHANN_ENB);\r
1070         return USBD_STATUS_SUCCESS;\r
1071     }\r
1072   #endif\r
1073 \r
1074     /* Enable IT */\r
1075     pUdp->UDPHS_IEN |= ( UDPHS_IEN_EPT_0 << bEndpoint );\r
1076     pHwEp->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_RX_BK_RDY;\r
1077     \r
1078     return USBD_STATUS_SUCCESS;\r
1079 }\r
1080 #if 0\r
1081 /**\r
1082  * Reads incoming data on an USB endpoint This methods sets the transfer\r
1083  * descriptor and activate the endpoint interrupt. The actual transfer is\r
1084  * then carried out by the endpoint interrupt handler. The Read operation\r
1085  * finishes either when the buffer is full, or a short packet (inferior to\r
1086  * endpoint maximum  size) is received.\r
1087  *\r
1088  * *The buffer must be kept allocated until the transfer is finished*.\r
1089  * \param bEndpoint Endpoint number.\r
1090  * \param pData Pointer to a data buffer.\r
1091  * \param dLength Size of the data buffer in bytes.\r
1092  * \return USBD_STATUS_SUCCESS if the read operation has been started;\r
1093  *         otherwise, the corresponding error code.\r
1094  */\r
1095 static inline uint8_t UDPHS_AddRd(uint8_t  bEndpoint,\r
1096                                 void     *pData,\r
1097                                 uint32_t dLength)\r
1098 {\r
1099     return USBD_STATUS_SW_NOT_SUPPORTED;\r
1100 }\r
1101 #endif\r
1102 /*---------------------------------------------------------------------------\r
1103  *      Exported functions\r
1104  *---------------------------------------------------------------------------*/\r
1105 extern void USBD_IrqHandler(void);\r
1106 /**\r
1107  * USBD (UDP) interrupt handler\r
1108  * Manages device resume, suspend, end of bus reset.\r
1109  * Forwards endpoint events to the appropriate handler.\r
1110  */\r
1111 void USBD_IrqHandler(void)\r
1112 {\r
1113     Udphs *pUdp = UDPHS;\r
1114 \r
1115     uint32_t status;\r
1116     uint8_t  numIt;\r
1117 \r
1118     status  = pUdp->UDPHS_INTSTA;\r
1119     status &= pUdp->UDPHS_IEN;\r
1120 \r
1121     /* Handle all UDPHS interrupts */\r
1122     TRACE_DEBUG_WP("\n\r%c ", USBD_HAL_IsHighSpeed() ? 'H' : 'F');\r
1123     while( status )\r
1124     {\r
1125         /* SOF */\r
1126         if (status & UDPHS_INTSTA_INT_SOF)\r
1127         {\r
1128             TRACE_DEBUG_WP("SOF ");\r
1129             /* SOF handler */\r
1130             //USBD_SofHandler();\r
1131 \r
1132             /* Acknowledge interrupt */\r
1133             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_INT_SOF;\r
1134             status &= ~(uint32_t)UDPHS_INTSTA_INT_SOF;\r
1135         }\r
1136         /* Suspend, treated last */\r
1137         else if (status == UDPHS_INTSTA_DET_SUSPD)\r
1138         {\r
1139             TRACE_WARNING_WP("Susp ");\r
1140             /* Enable wakeup */\r
1141             pUdp->UDPHS_IEN |= (UDPHS_IEN_WAKE_UP | UDPHS_IEN_ENDOFRSM);\r
1142             pUdp->UDPHS_IEN &= ~(uint32_t)UDPHS_IEN_DET_SUSPD;\r
1143 \r
1144             /* Acknowledge interrupt */\r
1145             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_DET_SUSPD | UDPHS_CLRINT_WAKE_UP;\r
1146 \r
1147             USBD_SuspendHandler();\r
1148         }\r
1149         /* Resume */\r
1150         else if ( (status & UDPHS_INTSTA_WAKE_UP)\r
1151                || (status & UDPHS_INTSTA_ENDOFRSM) )\r
1152         {\r
1153             USBD_ResumeHandler();\r
1154 \r
1155             TRACE_INFO_WP("Rsm ");\r
1156 \r
1157             /* Acknowledge interrupt */\r
1158             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP\r
1159                                | UDPHS_CLRINT_ENDOFRSM\r
1160                                | UDPHS_CLRINT_DET_SUSPD;\r
1161 \r
1162             pUdp->UDPHS_IEN |= UDPHS_IEN_ENDOFRSM | UDPHS_IEN_DET_SUSPD;\r
1163             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP | UDPHS_CLRINT_ENDOFRSM;\r
1164             pUdp->UDPHS_IEN &= ~(uint32_t)UDPHS_IEN_WAKE_UP;\r
1165         }\r
1166         /* Bus reset */\r
1167         else if (status & UDPHS_INTSTA_ENDRESET)\r
1168         {\r
1169             TRACE_DEBUG_WP("EoB ");\r
1170             /* Flush and enable the suspend interrupt */\r
1171             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP | UDPHS_CLRINT_DET_SUSPD;\r
1172             pUdp->UDPHS_IEN |= UDPHS_IEN_DET_SUSPD;\r
1173 \r
1174             /* Reset handler */\r
1175             USBD_ResetHandler();\r
1176 \r
1177             /* Acknowledge interrupt */\r
1178             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_ENDRESET;\r
1179         }\r
1180         /* Upstream resume */\r
1181         else if (status & UDPHS_INTSTA_UPSTR_RES)\r
1182         {\r
1183             TRACE_DEBUG_WP("ExtRes ");\r
1184             /* Acknowledge interrupt */\r
1185             pUdp->UDPHS_CLRINT = UDPHS_CLRINT_UPSTR_RES;\r
1186         }\r
1187         /* Endpoints */\r
1188         else\r
1189         {\r
1190           #ifdef DMA\r
1191             for (numIt = 0; numIt < NUM_IT_MAX; numIt ++)\r
1192             {\r
1193                 if (status & (1 << SHIFT_DMA << numIt))\r
1194                 {\r
1195                     UDPHS_DmaHandler(numIt);\r
1196                 }\r
1197                 else if (status & (UDPHS_INTSTA_EPT_0 << numIt))\r
1198                 {\r
1199                     UDPHS_EndpointHandler(numIt);\r
1200                 }\r
1201             }\r
1202           #else\r
1203             for (numIt = 0; numIt < NUM_IT_MAX; numIt ++)\r
1204             {\r
1205                 if (status & (UDPHS_INTSTA_EPT_0 << numIt))\r
1206                 {\r
1207                     UDPHS_EndpointHandler(numIt);\r
1208                 }\r
1209             }\r
1210           #endif\r
1211         }\r
1212 \r
1213         /* Update interrupt status */\r
1214         status  = pUdp->UDPHS_INTSTA;\r
1215         status &= pUdp->UDPHS_IEN;\r
1216 \r
1217         TRACE_DEBUG_WP("\n\r");\r
1218         if (status)\r
1219         {\r
1220             TRACE_DEBUG_WP(" - ");\r
1221         }\r
1222     }\r
1223 }\r
1224 \r
1225 /**\r
1226  * \brief Reset endpoints and disable them.\r
1227  * -# Terminate transfer if there is any, with given status;\r
1228  * -# Reset the endpoint & disable it.\r
1229  * \param bmEPs    Bitmap for endpoints to reset.\r
1230  * \param bStatus  Status passed to terminate transfer on endpoint.\r
1231  * \param bKeepCfg 1 to keep old endpoint configuration.\r
1232  * \note Use USBD_HAL_ConfigureEP() to configure and enable endpoint\r
1233          if not keeping old configuration.\r
1234  * \sa USBD_HAL_ConfigureEP().\r
1235  */\r
1236 void USBD_HAL_ResetEPs(uint32_t bmEPs, uint8_t bStatus, uint8_t bKeepCfg)\r
1237 {\r
1238     Udphs *pUdp = UDPHS;\r
1239     UdphsEpt *pHwEp;\r
1240 \r
1241     Endpoint *pEndpoint;\r
1242     uint32_t tmp = bmEPs & ((1<<CHIP_USB_NUMENDPOINTS)-1);\r
1243     uint8_t  ep;\r
1244     uint32_t epBit, epCfg;\r
1245 \r
1246     for (ep = 0, epBit = 1; ep < CHIP_USB_NUMENDPOINTS; ep ++)\r
1247     {\r
1248         if (tmp & epBit)\r
1249         {\r
1250             pHwEp = &pUdp->UDPHS_EPT[ep];\r
1251 \r
1252             /* Disable ISR */\r
1253             pUdp->UDPHS_IEN &= ~(epBit << SHIFT_INTERUPT);\r
1254             /* Kill pending Banks ?? */\r
1255             #if 0\r
1256             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;\r
1257             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;\r
1258             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;\r
1259             #endif\r
1260             \r
1261             /* Reset transfer information */\r
1262             pEndpoint = &(endpoints[ep]);\r
1263             /* Reset endpoint state */\r
1264             pEndpoint->bank = 0;\r
1265             /* Endpoint configure */\r
1266             epCfg = pHwEp->UDPHS_EPTCFG;\r
1267             /* Reset endpoint */\r
1268             pUdp->UDPHS_EPTRST = epBit;\r
1269             /* Restore configure */\r
1270             if (bKeepCfg)\r
1271             {\r
1272                 pHwEp->UDPHS_EPTCFG = epCfg;\r
1273             }\r
1274             else\r
1275             {\r
1276                 pEndpoint->state = UDPHS_ENDPOINT_DISABLED;\r
1277             }\r
1278 \r
1279             /* Terminate transfer on this EP */\r
1280             UDPHS_EndOfTransfer(ep, bStatus);\r
1281         }\r
1282         epBit <<= 1;\r
1283     }\r
1284 }\r
1285 \r
1286 /**\r
1287  * Cancel pending READ/WRITE\r
1288  * \param bmEPs    Bitmap for endpoints to reset.\r
1289  * \note EP callback is invoked with USBD_STATUS_CANCELED.\r
1290  */\r
1291 void USBD_HAL_CancelIo(uint32_t bmEPs)\r
1292 {\r
1293     Udphs *pUdp = UDPHS;\r
1294     //UdphsEpt *pHwEp = NULL;\r
1295 \r
1296     uint32_t tmp = bmEPs & ((1<<CHIP_USB_NUMENDPOINTS)-1);\r
1297     uint8_t  ep;\r
1298     uint32_t epBit;\r
1299     for (ep = 0, epBit = 1; ep < CHIP_USB_NUMENDPOINTS; ep ++)\r
1300     {\r
1301         if (tmp & epBit)\r
1302         {\r
1303             //pHwEp = &pUdp->UDPHS_EPT[ep];\r
1304 \r
1305             /* Disable ISR */\r
1306             pUdp->UDPHS_IEN &= ~(epBit << SHIFT_INTERUPT);\r
1307             /* Kill pending Banks ?? */\r
1308             #if 0\r
1309             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;\r
1310             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;\r
1311             pHwEp->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_KILL_BANK;\r
1312             #endif\r
1313 \r
1314             /* Terminate transfer on this EP */\r
1315             UDPHS_EndOfTransfer(ep, USBD_STATUS_CANCELED);\r
1316         }\r
1317         epBit <<= 1;\r
1318     }\r
1319 }\r
1320 \r
1321 /**\r
1322  * Configures an endpoint according to its endpoint Descriptor.\r
1323  * \param pDescriptor Pointer to an endpoint descriptor.\r
1324  * \return The endpoint address.\r
1325  */\r
1326 uint8_t USBD_HAL_ConfigureEP(const USBEndpointDescriptor *pDescriptor)\r
1327 {\r
1328     Udphs    *pUdp = UDPHS;\r
1329     UdphsEpt *pEpt;\r
1330     //UdphsDma *pDma;\r
1331 \r
1332     Endpoint *pEndpoint;\r
1333     uint8_t  bEndpoint;\r
1334     uint8_t  bType;\r
1335     uint8_t  bEndpointDir;\r
1336     //uint8_t bInterval = 0;\r
1337     uint8_t  bNbTrans  = 1;\r
1338     uint8_t  bSizeEpt  = 0;\r
1339     uint8_t  bHs = ((pUdp->UDPHS_INTSTA & UDPHS_INTSTA_SPEED) > 0);\r
1340 \r
1341     /* NULL descriptor -> Control endpoint 0 */\r
1342     if (pDescriptor == 0)\r
1343     {\r
1344 \r
1345         bEndpoint = 0;\r
1346         pEndpoint = &(endpoints[bEndpoint]);\r
1347         pEpt      = &(pUdp->UDPHS_EPT[0]);\r
1348         bType = USBEndpointDescriptor_CONTROL;\r
1349         bEndpointDir = 0;\r
1350         pEndpoint->size = CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0);\r
1351         pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(0);\r
1352     }\r
1353     /* Device descriptor -> Control endpoint 0 */\r
1354     else if (pDescriptor->bDescriptorType == USBGenericDescriptor_DEVICE)\r
1355     {\r
1356         USBDeviceDescriptor *pDevDesc = (USBDeviceDescriptor*)pDescriptor;\r
1357         bEndpoint = 0;\r
1358         pEndpoint = &(endpoints[bEndpoint]);\r
1359         pEpt      = &(pUdp->UDPHS_EPT[0]);\r
1360         bType = USBEndpointDescriptor_CONTROL;\r
1361         bEndpointDir = 0;\r
1362         pEndpoint->size =pDevDesc->bMaxPacketSize0;\r
1363         pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(0);\r
1364     }\r
1365     /* Endpoint descriptor */\r
1366     else\r
1367     {\r
1368         /* The endpoint number */\r
1369         bEndpoint = USBEndpointDescriptor_GetNumber(pDescriptor);\r
1370         pEndpoint = &(endpoints[bEndpoint]);\r
1371         pEpt      = &(pUdp->UDPHS_EPT[bEndpoint]);\r
1372         /* Transfer type: Control, Isochronous, Bulk, Interrupt */\r
1373         bType = USBEndpointDescriptor_GetType(pDescriptor);\r
1374         /* interval */\r
1375         //bInterval = USBEndpointDescriptor_GetInterval(pDescriptor);\r
1376         /* Direction, ignored for control endpoints */\r
1377         bEndpointDir = USBEndpointDescriptor_GetDirection(pDescriptor);\r
1378         pEndpoint->size = USBEndpointDescriptor_GetMaxPacketSize(pDescriptor);\r
1379         pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(bEndpoint);\r
1380 \r
1381         /* Convert descriptor value to EP configuration */\r
1382         if (bHs) {  /* HS Interval, *125us */\r
1383 \r
1384             /* MPS: Bit12,11 specify NB_TRANS, as USB 2.0 Spec. */\r
1385             bNbTrans = ((pEndpoint->size >> 11) & 0x3);\r
1386             if (bNbTrans == 3)\r
1387                 bNbTrans = 1;\r
1388             else\r
1389                 bNbTrans ++;\r
1390 \r
1391             /* Mask, bit 10..0 is the size */\r
1392             pEndpoint->size &= 0x7FF;\r
1393         }\r
1394     }\r
1395 \r
1396     //TRACE_DEBUG_WP("CfgE%d ", bEndpoint);\r
1397 \r
1398     /* Abort the current transfer is the endpoint was configured and in\r
1399        Write or Read state */\r
1400     if( (pEndpoint->state == UDPHS_ENDPOINT_RECEIVING)\r
1401      || (pEndpoint->state == UDPHS_ENDPOINT_SENDING)\r
1402      || (pEndpoint->state == UDPHS_ENDPOINT_RECEIVINGM)\r
1403      || (pEndpoint->state == UDPHS_ENDPOINT_SENDINGM) ) {\r
1404 \r
1405         UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_RESET);\r
1406     }\r
1407     pEndpoint->state = UDPHS_ENDPOINT_IDLE;\r
1408 \r
1409     /* Disable endpoint */\r
1410     pEpt->UDPHS_EPTCTLDIS = UDPHS_EPTCTLDIS_SHRT_PCKT\r
1411                           | UDPHS_EPTCTLDIS_BUSY_BANK\r
1412                           | UDPHS_EPTCTLDIS_NAK_OUT\r
1413                           | UDPHS_EPTCTLDIS_NAK_IN\r
1414                           | UDPHS_EPTCTLDIS_STALL_SNT\r
1415                           | UDPHS_EPTCTLDIS_RX_SETUP\r
1416                           | UDPHS_EPTCTLDIS_TX_PK_RDY\r
1417                           | UDPHS_EPTCTLDIS_RX_BK_RDY\r
1418                           | UDPHS_EPTCTLDIS_ERR_OVFLW\r
1419                           | UDPHS_EPTCTLDIS_MDATA_RX\r
1420                           | UDPHS_EPTCTLDIS_DATAX_RX\r
1421                           | UDPHS_EPTCTLDIS_NYET_DIS\r
1422                           | UDPHS_EPTCTLDIS_INTDIS_DMA\r
1423                           | UDPHS_EPTCTLDIS_AUTO_VALID\r
1424                           | UDPHS_EPTCTLDIS_EPT_DISABL\r
1425                           ;\r
1426     /* Reset Endpoint Fifos */\r
1427     pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TOGGLESQ | UDPHS_EPTCLRSTA_FRCESTALL;\r
1428     pUdp->UDPHS_EPTRST = 1 << bEndpoint;\r
1429     /* Configure endpoint size */\r
1430     if( pEndpoint->size <= 8 )\r
1431         bSizeEpt = 0;\r
1432     else if ( pEndpoint->size <= 16 )\r
1433         bSizeEpt = 1;\r
1434     else if ( pEndpoint->size <= 32 )\r
1435         bSizeEpt = 2;\r
1436     else if ( pEndpoint->size <= 64 )\r
1437         bSizeEpt = 3;\r
1438     else if ( pEndpoint->size <= 128 )\r
1439         bSizeEpt = 4;\r
1440     else if ( pEndpoint->size <= 256 )\r
1441         bSizeEpt = 5;\r
1442     else if ( pEndpoint->size <= 512 )\r
1443         bSizeEpt = 6;\r
1444     else if ( pEndpoint->size <= 1024 )\r
1445         bSizeEpt = 7;\r
1446 \r
1447     /* Configure endpoint */\r
1448     if (bType == USBEndpointDescriptor_CONTROL)\r
1449     {\r
1450         pUdp->UDPHS_IEN |= (UDPHS_IEN_EPT_0 << bEndpoint);\r
1451     }\r
1452 \r
1453     pEpt->UDPHS_EPTCFG =    bSizeEpt \r
1454                         | ( bEndpointDir << 3) \r
1455                         | ( bType << 4) \r
1456                         | ((pEndpoint->bank) << 6)\r
1457                         | ( bNbTrans << 8)\r
1458                         ;\r
1459     while( (UDPHS_EPTCFG_EPT_MAPD & pEpt->UDPHS_EPTCFG) == 0 ) {\r
1460 \r
1461         /* resolved by clearing the reset IT in good place */\r
1462         TRACE_ERROR("PB bEndpoint: 0x%X\n\r", bEndpoint);\r
1463         TRACE_ERROR("PB bSizeEpt: 0x%X\n\r", bSizeEpt);\r
1464         TRACE_ERROR("PB bEndpointDir: 0x%X\n\r", bEndpointDir);\r
1465         TRACE_ERROR("PB bType: 0x%X\n\r", bType);\r
1466         TRACE_ERROR("PB pEndpoint->bank: 0x%X\n\r", pEndpoint->bank);\r
1467         TRACE_ERROR("PB UDPHS_EPTCFG: 0x%X\n\r", (unsigned int)pEpt->UDPHS_EPTCFG);\r
1468         for(;;);\r
1469     }\r
1470 \r
1471     if (bType == USBEndpointDescriptor_CONTROL)\r
1472     {\r
1473         pEpt->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_RX_BK_RDY \r
1474                               | UDPHS_EPTCTLENB_RX_SETUP\r
1475                               | UDPHS_EPTCTLENB_EPT_ENABL;\r
1476     }\r
1477     else\r
1478     {\r
1479 #ifndef DMA\r
1480         pEpt->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_EPT_ENABL;\r
1481 #else\r
1482         pEpt->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_AUTO_VALID | UDPHS_EPTCTLENB_EPT_ENABL;\r
1483 #endif\r
1484     }\r
1485 \r
1486     //TRACE_DEBUG_WP("<%x,%x,%x> ", pEpt->UDPHS_EPTCFG, pEpt->UDPHS_EPTCTL, pEpt->UDPHS_EPTSTA);\r
1487     return bEndpoint;\r
1488 }\r
1489 \r
1490 /**\r
1491  * Set callback for a USB endpoint for transfer (read/write).\r
1492  *\r
1493  * \param bEP       Endpoint number.\r
1494  * \param fCallback Optional callback function to invoke when the transfer is\r
1495  *                  complete.\r
1496  * \param pCbData   Optional pointer to data to the callback function.\r
1497  * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED if endpoint is busy.\r
1498  */\r
1499 uint8_t USBD_HAL_SetTransferCallback(uint8_t          bEP,\r
1500                                   TransferCallback fCallback,\r
1501                                   void             *pCbData)\r
1502 {\r
1503     Endpoint *pEndpoint = &(endpoints[bEP]);\r
1504     TransferHeader *pTransfer = (TransferHeader*)&(pEndpoint->transfer);\r
1505     /* Check that the endpoint is not transferring */\r
1506     if (pEndpoint->state > UDPHS_ENDPOINT_IDLE) {\r
1507         return USBD_STATUS_LOCKED;\r
1508     }\r
1509     TRACE_DEBUG_WP("sXfrCb ");\r
1510     /* Setup the transfer callback and extension data */\r
1511     pTransfer->fCallback = (void*)fCallback;\r
1512     pTransfer->pArgument = pCbData;\r
1513     return USBD_STATUS_SUCCESS;\r
1514 }\r
1515 \r
1516 /**\r
1517  * Configure an endpoint to use multi-buffer-list transfer mode.\r
1518  * The buffers can be added by _Read/_Write function.\r
1519  * \param pMbList  Pointer to a multi-buffer list used, NULL to disable MBL.\r
1520  * \param mblSize  Multi-buffer list size (number of buffers can be queued)\r
1521  * \param startOffset When number of buffer achieve this offset transfer start\r
1522  */\r
1523 uint8_t USBD_HAL_SetupMblTransfer( uint8_t bEndpoint,\r
1524                                    USBDTransferBuffer* pMbList,\r
1525                                    uint16_t mblSize,\r
1526                                    uint16_t startOffset)\r
1527 {\r
1528     Endpoint *pEndpoint = &(endpoints[bEndpoint]);\r
1529     MblTransfer *pXfr = (MblTransfer*)&(pEndpoint->transfer);\r
1530     uint16_t i;\r
1531     /* Check that the endpoint is not transferring */\r
1532     if (pEndpoint->state > UDPHS_ENDPOINT_IDLE) {\r
1533         return USBD_STATUS_LOCKED;\r
1534     }\r
1535     TRACE_DEBUG_WP("sMblXfr ");\r
1536     /* Enable Multi-Buffer Transfer List */\r
1537     if (pMbList) {\r
1538         /* Reset list items */\r
1539         for (i = 0; i < mblSize; i --) {\r
1540             pMbList[i].pBuffer     = NULL;\r
1541             pMbList[i].size        = 0;\r
1542             pMbList[i].transferred = 0;\r
1543             pMbList[i].buffered    = 0;\r
1544             pMbList[i].remaining   = 0;\r
1545         }\r
1546         /* Setup transfer */\r
1547         pXfr->transType  = 1;\r
1548         pXfr->listState  = 0; /* OK */\r
1549         pXfr->listSize   = mblSize;\r
1550         pXfr->pMbl       = pMbList;\r
1551         pXfr->outCurr = pXfr->outLast = 0;\r
1552         pXfr->inCurr  = 0;\r
1553         pXfr->offsetSize = startOffset;\r
1554     }\r
1555     /* Disable Multi-Buffer Transfer */\r
1556     else {\r
1557         pXfr->transType  = 0;\r
1558         pXfr->pMbl       = NULL;\r
1559         pXfr->listSize   = 0;\r
1560         pXfr->offsetSize = 1;\r
1561     }\r
1562     return USBD_STATUS_SUCCESS;\r
1563 }\r
1564 \r
1565 /**\r
1566  * Sends data through a USB endpoint. Sets up the transfer descriptor,\r
1567  * writes one or two data payloads (depending on the number of FIFO bank\r
1568  * for the endpoint) and then starts the actual transfer. The operation is\r
1569  * complete when all the data has been sent.\r
1570  *\r
1571  * *If the size of the buffer is greater than the size of the endpoint\r
1572  *  (or twice the size if the endpoint has two FIFO banks), then the buffer\r
1573  *  must be kept allocated until the transfer is finished*. This means that\r
1574  *  it is not possible to declare it on the stack (i.e. as a local variable\r
1575  *  of a function which returns after starting a transfer).\r
1576  *\r
1577  * \param bEndpoint Endpoint number.\r
1578  * \param pData Pointer to a buffer with the data to send.\r
1579  * \param dLength Size of the data buffer.\r
1580  * \return USBD_STATUS_SUCCESS if the transfer has been started;\r
1581  *         otherwise, the corresponding error status code.\r
1582  */\r
1583 uint8_t USBD_HAL_Write( uint8_t          bEndpoint,\r
1584                         const void       *pData,\r
1585                         uint32_t         dLength)\r
1586 {\r
1587     if (endpoints[bEndpoint].transfer.transHdr.transType)\r
1588         return UDPHS_AddWr(bEndpoint, pData, dLength);\r
1589     else\r
1590         return UDPHS_Write(bEndpoint, pData, dLength);\r
1591 }\r
1592 \r
1593 /**\r
1594  * Special write function.\r
1595  * Sends data through a USB endpoint. Sets up the transfer descriptor,\r
1596  * writes header and one or two data payloads (depending on the number of\r
1597  * FIFO bank for the endpoint) and then starts the actual transfer. The\r
1598  * operation is complete when all the data has been sent.\r
1599  *\r
1600  * *If the size of the buffer is greater than the size of the endpoint\r
1601  *  (or twice the size if the endpoint has two FIFO banks), then the buffer\r
1602  *  must be kept allocated until the transfer is finished*. This means that\r
1603  *  it is not possible to declare it on the stack (i.e. as a local variable\r
1604  *  of a function which returns after starting a transfer).\r
1605  *\r
1606  * \param bEndpoint Endpoint number.\r
1607  * \param pData Pointer to a buffer with the data to send.\r
1608  * \param dLength Size of the data buffer.\r
1609  * \return USBD_STATUS_SUCCESS if the transfer has been started;\r
1610  *         otherwise, the corresponding error status code.\r
1611  */\r
1612 uint8_t USBD_HAL_WrWithHdr(uint8_t bEndpoint,\r
1613                            const void * pHdr, uint8_t bHdrLen,\r
1614                            const void * pData,uint32_t dLength)\r
1615 {\r
1616     Udphs    *pUdp  = UDPHS;\r
1617     UdphsEpt *pHwEp = &pUdp->UDPHS_EPT[bEndpoint];\r
1618     Endpoint *pEp  = &(endpoints[bEndpoint]);\r
1619     Transfer *pXfr = (Transfer*)&(pEp->transfer);\r
1620     /* Return if DMA is not supported */\r
1621     if (!CHIP_USB_ENDPOINTS_DMA(bEndpoint))\r
1622     {\r
1623        return USBD_STATUS_HW_NOT_SUPPORTED;\r
1624     }\r
1625 \r
1626 #ifdef DMA\r
1627     /* Return if busy */\r
1628     if (pEp->state != UDPHS_ENDPOINT_IDLE)\r
1629     {\r
1630         return USBD_STATUS_LOCKED;\r
1631     }\r
1632     /* Sending state */\r
1633     pEp->state = UDPHS_ENDPOINT_SENDING;\r
1634     TRACE_DEBUG_WP("Wr%d(%d+%d) ", bEndpoint, bHdrLen, dLength);\r
1635 \r
1636     pEp->sendZLP = 0;\r
1637 \r
1638     /* Setup transfer descriptor */\r
1639     pXfr->pData       = (void*) pData;\r
1640     pXfr->remaining   = bHdrLen + dLength;\r
1641     pXfr->buffered    = 0;\r
1642     pXfr->transferred = 0;\r
1643 \r
1644     /* 1. DMA supported always, 2. Not ZLP */\r
1645     if (bHdrLen + dLength > 0)\r
1646     {\r
1647         uint8_t bNbTrans = (pHwEp->UDPHS_EPTCFG & UDPHS_EPTCFG_NB_TRANS_Msk)\r
1648                                                   >> UDPHS_EPTCFG_NB_TRANS_Pos;\r
1649         if (pXfr->remaining > DMA_MAX_FIFO_SIZE)\r
1650         {\r
1651             /* Transfer the max */\r
1652             pXfr->buffered = DMA_MAX_FIFO_SIZE;\r
1653         }\r
1654         else\r
1655         {\r
1656             /* Good size, total size */\r
1657             pXfr->buffered = pXfr->remaining;\r
1658         }\r
1659 \r
1660         /* LD1: header - load to fifo without interrupt */\r
1661         /* Header discarded if exceed the DMA FIFO length */\r
1662         //if (bHdrLen > DMA_MAX_FIFO_SIZE) bHdrLen = DMA_MAX_FIFO_SIZE;\r
1663         pDmaLL[0].pNxtDesc = (void*)&pDmaLL[1];\r
1664         pDmaLL[0].pAddr    = (void*)pHdr;\r
1665         pDmaLL[0].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB\r
1666                            | UDPHS_DMACONTROL_BUFF_LENGTH(bHdrLen)\r
1667                            | UDPHS_DMACONTROL_LDNXT_DSC;\r
1668         /* High bandwidth ISO EP, max size n*ep_size */\r
1669         if (bNbTrans > 1) {\r
1670             uint8_t* pU8 = (uint8_t*)pData;\r
1671             uint32_t maxSize = bNbTrans * pEp->size;\r
1672             dLength = pXfr->buffered - bHdrLen;\r
1673             if (dLength > maxSize) dLength = maxSize;\r
1674           #if 0 /* Prepare banks by 1 DMA descriptor -- NK if not standard EP size, works! */\r
1675             /* LD2: data   -  load to fifo with interrupt */\r
1676             pDmaLL[1].pNxtDesc = (void*)NULL;\r
1677             pDmaLL[1].pAddr    = (void*)pU8;\r
1678             pDmaLL[1].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB\r
1679                                | UDPHS_DMACONTROL_BUFF_LENGTH(dLength)\r
1680                                | UDPHS_DMACONTROL_END_B_EN\r
1681                                | UDPHS_DMACONTROL_END_BUFFIT;\r
1682           #else\r
1683             uint32_t pktLen, ndxData = 0;\r
1684             /* LD2: data   -  bank 0 */\r
1685             pktLen = pEp->size - bHdrLen;\r
1686             if (pktLen >= dLength) { /* It's the last DMA LLI */\r
1687                 pDmaLL[1].pNxtDesc = (void*)NULL;\r
1688                 pDmaLL[1].pAddr    = (void*)pU8;\r
1689                 pDmaLL[1].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB\r
1690                                    | UDPHS_DMACONTROL_BUFF_LENGTH(dLength)\r
1691                                    | UDPHS_DMACONTROL_END_B_EN\r
1692                                    | UDPHS_DMACONTROL_END_BUFFIT;\r
1693             }\r
1694             else {\r
1695                 pDmaLL[1].pNxtDesc = (void*)&pDmaLL[2];\r
1696                 pDmaLL[1].pAddr    = (void*)pU8;\r
1697                 pDmaLL[1].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB\r
1698                                    | UDPHS_DMACONTROL_BUFF_LENGTH(pktLen)\r
1699                                    | UDPHS_DMACONTROL_END_B_EN\r
1700                                    | UDPHS_DMACONTROL_LDNXT_DSC;\r
1701                 dLength -= pktLen; ndxData += pktLen;\r
1702                 /* LD3: data  - bank 1 */\r
1703                 pktLen = pEp->size;\r
1704                 if (pktLen >= dLength) { /* It's the last */\r
1705                     pDmaLL[1].pNxtDesc = (void*) NULL;\r
1706                     pDmaLL[1].pAddr    = (void*)&pU8[ndxData];\r
1707                     pDmaLL[1].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB\r
1708                                        | UDPHS_DMACONTROL_BUFF_LENGTH(dLength)\r
1709                                        | UDPHS_DMACONTROL_END_B_EN\r
1710                                        | UDPHS_DMACONTROL_END_BUFFIT;\r
1711                 }\r
1712                 else {\r
1713                     pDmaLL[2].pNxtDesc = (void*)&pDmaLL[3];\r
1714                     pDmaLL[2].pAddr    = (void*)&pU8[ndxData];\r
1715                     pDmaLL[2].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB\r
1716                                        | UDPHS_DMACONTROL_BUFF_LENGTH(pktLen)\r
1717                                        | UDPHS_DMACONTROL_END_B_EN\r
1718                                        | UDPHS_DMACONTROL_LDNXT_DSC;\r
1719                     dLength -= pktLen; ndxData += pktLen;\r
1720                     /* LD4: data  - bank 2 */\r
1721                     pDmaLL[3].pNxtDesc = (void*) NULL;\r
1722                     pDmaLL[3].pAddr    = (void*)&pU8[ndxData];\r
1723                     pDmaLL[3].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB\r
1724                                        | UDPHS_DMACONTROL_BUFF_LENGTH(dLength)\r
1725                                        | UDPHS_DMACONTROL_END_B_EN\r
1726                                        | UDPHS_DMACONTROL_END_BUFFIT;\r
1727                 }\r
1728             }\r
1729           #endif\r
1730         }\r
1731         else { /* Normal, fill all data */\r
1732             /* LD2: data   -  load to fifo with interrupt */\r
1733             dLength = pXfr->buffered - bHdrLen;\r
1734             pDmaLL[1].pNxtDesc = (void*)NULL;\r
1735             pDmaLL[1].pAddr    = (void*)pData;\r
1736             pDmaLL[1].dwCtrl   = UDPHS_DMACONTROL_CHANN_ENB\r
1737                                | UDPHS_DMACONTROL_BUFF_LENGTH(dLength)\r
1738                                | UDPHS_DMACONTROL_END_B_EN\r
1739                                | UDPHS_DMACONTROL_END_BUFFIT;\r
1740         }\r
1741         /* Interrupt enable */\r
1742         pUdp->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);\r
1743         /* Start transfer with LLI */\r
1744         pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMANXTDSC  = (uint32_t)pDmaLL;\r
1745         pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0;\r
1746         pUdp->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = UDPHS_DMACONTROL_LDNXT_DSC;\r
1747         return USBD_STATUS_SUCCESS;\r
1748     }\r
1749 #endif\r
1750     \r
1751     /* Enable IT */\r
1752     pUdp->UDPHS_IEN |= ( UDPHS_IEN_EPT_0 << bEndpoint );\r
1753     pHwEp->UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_TX_PK_RDY;\r
1754     return USBD_STATUS_SUCCESS;\r
1755 }\r
1756 \r
1757 /**\r
1758  * Reads incoming data on an USB endpoint This methods sets the transfer\r
1759  * descriptor and activate the endpoint interrupt. The actual transfer is\r
1760  * then carried out by the endpoint interrupt handler. The Read operation\r
1761  * finishes either when the buffer is full, or a short packet (inferior to\r
1762  * endpoint maximum  size) is received.\r
1763  *\r
1764  * *The buffer must be kept allocated until the transfer is finished*.\r
1765  * \param bEndpoint Endpoint number.\r
1766  * \param pData Pointer to a data buffer.\r
1767  * \param dLength Size of the data buffer in bytes.\r
1768  * \return USBD_STATUS_SUCCESS if the read operation has been started;\r
1769  *         otherwise, the corresponding error code.\r
1770  */\r
1771 uint8_t USBD_HAL_Read(uint8_t    bEndpoint,\r
1772                       void       *pData,\r
1773                       uint32_t   dLength)\r
1774 {\r
1775     if (endpoints[bEndpoint].transfer.transHdr.transType)\r
1776         return USBD_STATUS_SW_NOT_SUPPORTED;\r
1777     else\r
1778         return UDPHS_Read(bEndpoint, pData, dLength);\r
1779 }\r
1780 \r
1781 /**\r
1782  *  \brief Enable Pull-up, connect.\r
1783  *\r
1784  *  -# Enable HW access if needed\r
1785  *  -# Enable Pull-Up\r
1786  *  -# Disable HW access if needed\r
1787  */\r
1788 void USBD_HAL_Connect(void)\r
1789 {\r
1790     Udphs *pUdp = UDPHS;\r
1791 \r
1792     uint8_t dis = UDPHS_EnablePeripheralClock();\r
1793     pUdp->UDPHS_CTRL |= UDPHS_CTRL_PULLD_DIS;\r
1794     pUdp->UDPHS_CTRL &= ~(uint32_t)UDPHS_CTRL_DETACH;\r
1795     if (dis) UDPHS_DisablePeripheralClock();\r
1796 }\r
1797 \r
1798 /**\r
1799  *  \brief Disable Pull-up, disconnect.\r
1800  *\r
1801  *  -# Enable HW access if needed\r
1802  *  -# Disable PULL-Up\r
1803  *  -# Disable HW access if needed\r
1804  */\r
1805 void USBD_HAL_Disconnect(void)\r
1806 {\r
1807     Udphs *pUdp = UDPHS;\r
1808 \r
1809     uint8_t dis = UDPHS_EnablePeripheralClock();\r
1810     pUdp->UDPHS_CTRL |= UDPHS_CTRL_DETACH;\r
1811     pUdp->UDPHS_CTRL &= ~(uint32_t)UDPHS_CTRL_PULLD_DIS;\r
1812     if (dis) UDPHS_DisablePeripheralClock();\r
1813 }\r
1814 \r
1815 /**\r
1816  * Starts a remote wake-up procedure.\r
1817  */\r
1818 void USBD_HAL_RemoteWakeUp(void)\r
1819 {\r
1820     Udphs *pUdp = UDPHS;\r
1821 \r
1822     UDPHS_EnablePeripheralClock();\r
1823     UDPHS_EnableUsbClock();\r
1824 \r
1825     TRACE_INFO_WP("RWUp ");\r
1826 \r
1827     /* Activates a remote wakeup (edge on ESR), then clear ESR */\r
1828     pUdp->UDPHS_CTRL |= UDPHS_CTRL_REWAKEUP;\r
1829     while(pUdp->UDPHS_CTRL & UDPHS_CTRL_REWAKEUP)\r
1830     {\r
1831         TRACE_DEBUG_WP("w");\r
1832     }\r
1833     UDPHS_EnableBIAS();\r
1834 }\r
1835 \r
1836 /**\r
1837  * Sets the device address to the given value.\r
1838  * \param address New device address.\r
1839  */\r
1840 void USBD_HAL_SetAddress(uint8_t address)\r
1841 {\r
1842     Udphs *pUdp = UDPHS;\r
1843 \r
1844     if (address)\r
1845     {\r
1846         pUdp->UDPHS_CTRL &= ~(uint32_t)UDPHS_CTRL_DEV_ADDR_Msk;\r
1847         pUdp->UDPHS_CTRL |= address | UDPHS_CTRL_FADDR_EN;\r
1848     }\r
1849     else\r
1850     {\r
1851         pUdp->UDPHS_CTRL &= ~(uint32_t)UDPHS_CTRL_FADDR_EN;\r
1852     }\r
1853 }\r
1854 \r
1855 /**\r
1856  * Sets the current device configuration.\r
1857  * \param cfgnum - Configuration number to set.\r
1858  */\r
1859 void USBD_HAL_SetConfiguration(uint8_t cfgnum)\r
1860 {\r
1861     /* Nothing to do now */\r
1862     cfgnum = cfgnum;\r
1863 }\r
1864 \r
1865 /**\r
1866  * Initializes the USB HW Access driver.\r
1867  */\r
1868 void USBD_HAL_Init(void)\r
1869 {\r
1870     Udphs *pUdp = UDPHS;\r
1871     UdphsEpt *pEpt;\r
1872     UdphsDma *pDma;\r
1873     uint32_t i;\r
1874 #ifdef DMA\r
1875     /* DMA Link list should be 16-bytes aligned */\r
1876     if ((uint32_t)dmaLL & 0xFFFFFFF0)\r
1877         pDmaLL = (UdphsDmaDescriptor*)((uint32_t)&dmaLL[1] & 0xFFFFFFF0);\r
1878     else\r
1879         pDmaLL = (UdphsDmaDescriptor*)((uint32_t)&dmaLL[0]);\r
1880 #endif\r
1881     /* Must before USB & TXVC access! */\r
1882     UDPHS_EnablePeripheralClock();\r
1883 \r
1884     /* Reset & disable endpoints */\r
1885     USBD_HAL_ResetEPs(0xFFFFFFFF, USBD_STATUS_RESET, 0);\r
1886 \r
1887     /* Configure the pull-up on D+ and disconnect it */\r
1888     pUdp->UDPHS_CTRL |= UDPHS_CTRL_DETACH;\r
1889     pUdp->UDPHS_CTRL |= UDPHS_CTRL_PULLD_DIS;\r
1890 \r
1891     /* Reset IP */\r
1892     pUdp->UDPHS_CTRL &= ~(uint32_t)UDPHS_CTRL_EN_UDPHS;\r
1893     pUdp->UDPHS_CTRL |= UDPHS_CTRL_EN_UDPHS;\r
1894 \r
1895     /* (XCHQ[2010.1.21], IP recomendation, setup clock after reset IP) */\r
1896     UDPHS_EnableUsbClock();\r
1897 \r
1898     /* Initialize DMA */\r
1899     for (i = 1;\r
1900          i < ((pUdp->UDPHS_IPFEATURES & UDPHS_IPFEATURES_DMA_CHANNEL_NBR_Msk) >> 4);\r
1901          i ++)\r
1902     {\r
1903         pEpt = &pUdp->UDPHS_EPT[i];\r
1904         pDma = &pUdp->UDPHS_DMA[i];\r
1905         /* DMA stop */\r
1906         pDma->UDPHS_DMACONTROL = 0;\r
1907         /* Disable endpoint */\r
1908         pEpt->UDPHS_EPTCTLDIS = (uint32_t)UDPHS_EPTCTLDIS_SHRT_PCKT\r
1909                               | UDPHS_EPTCTLDIS_BUSY_BANK\r
1910                               | UDPHS_EPTCTLDIS_NAK_OUT\r
1911                               | UDPHS_EPTCTLDIS_NAK_IN\r
1912                               | UDPHS_EPTCTLDIS_STALL_SNT\r
1913                               | UDPHS_EPTCTLDIS_RX_SETUP\r
1914                               | UDPHS_EPTCTLDIS_TX_PK_RDY\r
1915                               | UDPHS_EPTCTLDIS_TX_COMPLT\r
1916                               | UDPHS_EPTCTLDIS_RX_BK_RDY\r
1917                               | UDPHS_EPTCTLDIS_ERR_OVFLW\r
1918                               | UDPHS_EPTCTLDIS_MDATA_RX\r
1919                               | UDPHS_EPTCTLDIS_DATAX_RX\r
1920                               | UDPHS_EPTCTLDIS_NYET_DIS\r
1921                               | UDPHS_EPTCTLDIS_INTDIS_DMA\r
1922                               | UDPHS_EPTCTLDIS_AUTO_VALID\r
1923                               | UDPHS_EPTCTLDIS_EPT_DISABL\r
1924                               ;\r
1925         /* Clear status endpoint */\r
1926         pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TOGGLESQ\r
1927                               | UDPHS_EPTCLRSTA_FRCESTALL\r
1928                               | UDPHS_EPTCLRSTA_RX_BK_RDY\r
1929                               | UDPHS_EPTCLRSTA_TX_COMPLT\r
1930                               | UDPHS_EPTCLRSTA_RX_SETUP\r
1931                               | UDPHS_EPTCLRSTA_STALL_SNT\r
1932                               | UDPHS_EPTCLRSTA_NAK_IN\r
1933                               | UDPHS_EPTCLRSTA_NAK_OUT\r
1934                               ;\r
1935         /* Reset endpoint config */\r
1936         pEpt->UDPHS_EPTCTLENB = 0;\r
1937         /* Reset DMA channel (Buffer count and Control field) */\r
1938         pDma->UDPHS_DMACONTROL = UDPHS_DMACONTROL_LDNXT_DSC;\r
1939         /* Reset DMA channel */\r
1940         pDma->UDPHS_DMACONTROL = 0;\r
1941         /* Clear DMA channel status (read to clear) */\r
1942         pDma->UDPHS_DMASTATUS = pDma->UDPHS_DMASTATUS;\r
1943     }\r
1944 \r
1945     /* Force Full-Speed */\r
1946     pUdp->UDPHS_TST = forceUsbFS ? UDPHS_TST_SPEED_CFG_FULL_SPEED : 0;\r
1947 \r
1948     pUdp->UDPHS_IEN = 0;\r
1949     pUdp->UDPHS_CLRINT = UDPHS_CLRINT_UPSTR_RES\r
1950                        | UDPHS_CLRINT_ENDOFRSM\r
1951                        | UDPHS_CLRINT_WAKE_UP\r
1952                        | UDPHS_CLRINT_ENDRESET\r
1953                        | UDPHS_CLRINT_INT_SOF\r
1954                        | UDPHS_CLRINT_MICRO_SOF\r
1955                        | UDPHS_CLRINT_DET_SUSPD\r
1956                        ;\r
1957 \r
1958     /* Enable interrupts */\r
1959     pUdp->UDPHS_IEN = UDPHS_IEN_ENDOFRSM\r
1960                     | UDPHS_IEN_WAKE_UP\r
1961                     | UDPHS_IEN_DET_SUSPD;\r
1962 \r
1963     /* Disable USB clocks */\r
1964     UDPHS_DisableUsbClock();\r
1965 }\r
1966 \r
1967 /**\r
1968  * Causes the given endpoint to acknowledge the next packet it receives\r
1969  * with a STALL handshake except setup request.\r
1970  * \param bEP Endpoint number.\r
1971  * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED.\r
1972  */\r
1973 uint8_t USBD_HAL_Stall(uint8_t bEP)\r
1974 {\r
1975     Udphs    *pUdp = UDPHS;\r
1976     UdphsEpt *pEpt = &pUdp->UDPHS_EPT[bEP];\r
1977 \r
1978     Endpoint *pEndpoint = &(endpoints[bEP]);\r
1979 \r
1980     /* Check that endpoint is in Idle state */\r
1981     if (pEndpoint->state != UDPHS_ENDPOINT_IDLE)\r
1982     {\r
1983         TRACE_WARNING("UDP_Stall: EP%d locked\n\r", bEP);\r
1984         return USBD_STATUS_LOCKED;\r
1985     }\r
1986     /* STALL endpoint */\r
1987     pEpt->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_FRCESTALL;\r
1988 \r
1989     TRACE_DEBUG_WP("Stall%d ", bEP);\r
1990     return USBD_STATUS_SUCCESS;\r
1991 }\r
1992 \r
1993 /**\r
1994  * Sets/Clear/Get the HALT state on the endpoint.\r
1995  * In HALT state, the endpoint should keep stalling any packet.\r
1996  * \param bEndpoint Endpoint number.\r
1997  * \param ctl       Control code CLR/HALT/READ.\r
1998  *                  0: Clear HALT state;\r
1999  *                  1: Set HALT state;\r
2000  *                  .: Return HALT status.\r
2001  * \return USBD_STATUS_INVALID_PARAMETER if endpoint not exist,\r
2002  *         otherwise endpoint halt status.\r
2003  */\r
2004 uint8_t USBD_HAL_Halt(uint8_t bEndpoint, uint8_t ctl)\r
2005 {\r
2006     Udphs    *pUdp = UDPHS;\r
2007     UdphsEpt *pEpt = &pUdp->UDPHS_EPT[bEndpoint];\r
2008 \r
2009     Endpoint *pEndpoint = &(endpoints[bEndpoint]);\r
2010     uint8_t status = 0;\r
2011 \r
2012     /* SET Halt */\r
2013     if (ctl == 1)\r
2014     {\r
2015         /* Check that endpoint is enabled and not already in Halt state */\r
2016         if ((pEndpoint->state != UDPHS_ENDPOINT_DISABLED)\r
2017             && (pEndpoint->state != UDPHS_ENDPOINT_HALTED))\r
2018         {\r
2019 \r
2020             TRACE_DEBUG_WP("Halt%d ", bEndpoint);\r
2021 \r
2022             /* Abort the current transfer if necessary */\r
2023             UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);\r
2024 \r
2025             /* Put endpoint into Halt state */\r
2026             pEndpoint->state = UDPHS_ENDPOINT_HALTED;\r
2027             pEpt->UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_FRCESTALL;\r
2028 \r
2029           #ifdef DMA\r
2030             if (CHIP_USB_ENDPOINTS_DMA(bEndpoint))\r
2031             {\r
2032                 /* Enable the endpoint DMA interrupt */\r
2033                 pUdp->UDPHS_IEN |= ( 1 << SHIFT_DMA << bEndpoint );\r
2034             }\r
2035             else\r
2036             {\r
2037                 /* Enable the endpoint interrupt */\r
2038                 pUdp->UDPHS_IEN |= ( UDPHS_IEN_EPT_0 << bEndpoint );\r
2039             }\r
2040           #else\r
2041             /* Enable the endpoint interrupt */\r
2042             pUdp->UDPHS_IEN |= ( UDPHS_IEN_EPT_0 << bEndpoint );\r
2043           #endif\r
2044         }\r
2045     }\r
2046     /* CLEAR Halt */\r
2047     else if (ctl == 0)\r
2048     {\r
2049         /* Check if the endpoint is halted */\r
2050         if (pEndpoint->state == UDPHS_ENDPOINT_HALTED)\r
2051         {\r
2052 \r
2053             TRACE_DEBUG_WP("Unhalt%d ", bEndpoint);\r
2054 \r
2055             /* Return endpoint to Idle state */\r
2056             pEndpoint->state = UDPHS_ENDPOINT_IDLE;\r
2057 \r
2058             /* Clear FORCESTALL flag */\r
2059             pEpt->UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TOGGLESQ\r
2060                                   | UDPHS_EPTCLRSTA_FRCESTALL;\r
2061 \r
2062             /* Reset Endpoint Fifos */\r
2063             pUdp->UDPHS_EPTRST = (1 << bEndpoint);\r
2064         }\r
2065     }\r
2066 \r
2067     /* Return Halt status */\r
2068     if (pEndpoint->state == UDPHS_ENDPOINT_HALTED)\r
2069     {\r
2070         status = 1;\r
2071     }\r
2072     return( status );\r
2073 }\r
2074 \r
2075 /**\r
2076  * Indicates if the device is running in high or full-speed. Always returns 0\r
2077  * since UDP does not support high-speed mode.\r
2078  */\r
2079 uint8_t USBD_HAL_IsHighSpeed(void)\r
2080 {\r
2081     Udphs    *pUdp = UDPHS;\r
2082     return (pUdp->UDPHS_INTSTA & UDPHS_INTSTA_SPEED);\r
2083 }\r
2084 \r
2085 /**\r
2086  * Suspend USB Device HW Interface\r
2087  *\r
2088  * -# Disable transceiver\r
2089  * -# Disable USB Clock\r
2090  * -# Disable USB Peripheral\r
2091  */\r
2092 void USBD_HAL_Suspend(void)\r
2093 {\r
2094     /* The device enters the Suspended state */\r
2095     UDPHS_DisableBIAS();\r
2096     UDPHS_DisableUsbClock();\r
2097     UDPHS_DisablePeripheralClock();\r
2098 }\r
2099 \r
2100 /**\r
2101  * Activate USB Device HW Interface\r
2102  * -# Enable USB Peripheral\r
2103  * -# Enable USB Clock\r
2104  * -# Enable transceiver\r
2105  */\r
2106 void USBD_HAL_Activate(void)\r
2107 {\r
2108     UDPHS_EnablePeripheralClock();\r
2109     UDPHS_EnableUsbClock();\r
2110     UDPHS_EnableBIAS();\r
2111 }\r
2112 \r
2113 /**\r
2114  * Certification test for High Speed device.\r
2115  * \param bIndex Test to be done\r
2116  */\r
2117 void USBD_HAL_Test( uint8_t bIndex )\r
2118 {\r
2119     Udphs *pUdp = UDPHS;\r
2120     uint8_t      *pFifo;\r
2121     uint32_t      i;\r
2122 \r
2123     /* remove suspend for TEST */\r
2124     pUdp->UDPHS_IEN &= ~UDPHS_IEN_DET_SUSPD;\r
2125     /* force High Speed (remove suspend) */\r
2126     pUdp->UDPHS_TST |= UDPHS_TST_SPEED_CFG_HIGH_SPEED;\r
2127 \r
2128     switch( bIndex ) {\r
2129 \r
2130         case USBFeatureRequest_TESTPACKET:\r
2131             TRACE_DEBUG_WP("TEST_PACKET ");\r
2132 \r
2133             pUdp->UDPHS_DMA[1].UDPHS_DMACONTROL = 0;\r
2134             pUdp->UDPHS_DMA[2].UDPHS_DMACONTROL = 0;\r
2135 \r
2136             /* Configure endpoint 2, 64 bytes, direction IN, type BULK, 1 bank */\r
2137             pUdp->UDPHS_EPT[2].UDPHS_EPTCFG = UDPHS_EPTCFG_EPT_SIZE_64\r
2138                                             | UDPHS_EPTCFG_EPT_DIR\r
2139                                             | UDPHS_EPTCFG_EPT_TYPE_BULK\r
2140                                             | UDPHS_EPTCFG_BK_NUMBER_1;\r
2141             while( (pUdp->UDPHS_EPT[2].UDPHS_EPTCFG & UDPHS_EPTCFG_EPT_MAPD) != UDPHS_EPTCFG_EPT_MAPD );\r
2142             pUdp->UDPHS_EPT[2].UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_EPT_ENABL;\r
2143 \r
2144             /* Write FIFO */\r
2145             pFifo = (uint8_t*)((uint32_t *)(UDPHS_RAM_ADDR) + (EPT_VIRTUAL_SIZE * 2));\r
2146             for( i=0; i<sizeof(test_packet_buffer); i++) {\r
2147                 pFifo[i] = test_packet_buffer[i];\r
2148             }\r
2149             /* Tst PACKET */\r
2150             pUdp->UDPHS_TST |= UDPHS_TST_TST_PKT;\r
2151             /* Send packet */\r
2152             pUdp->UDPHS_EPT[2].UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_TX_PK_RDY;\r
2153             break;\r
2154 \r
2155         case USBFeatureRequest_TESTJ:\r
2156             TRACE_DEBUG_WP("TEST_J ");\r
2157             pUdp->UDPHS_TST = UDPHS_TST_TST_J;\r
2158             break;\r
2159 \r
2160         case USBFeatureRequest_TESTK:\r
2161             TRACE_DEBUG_WP("TEST_K ");\r
2162             pUdp->UDPHS_TST = UDPHS_TST_TST_K;\r
2163             break;\r
2164 \r
2165         case USBFeatureRequest_TESTSE0NAK:\r
2166             TRACE_DEBUG_WP("TEST_SEO_NAK ");\r
2167             pUdp->UDPHS_IEN = 0;  // for test\r
2168             break;\r
2169 \r
2170         case USBFeatureRequest_TESTSENDZLP:\r
2171             //while( 0 != (pUdp->UDPHS_EPT[0].UDPHS_EPTSTA & UDPHS_EPTSETSTA_TX_PK_RDY ) ) {}\r
2172             pUdp->UDPHS_EPT[0].UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_TX_PK_RDY;\r
2173             //while( 0 != (pUdp->UDPHS_EPT[0].UDPHS_EPTSTA & UDPHS_EPTSETSTA_TX_PK_RDY ) ) {}\r
2174             TRACE_DEBUG_WP("SEND_ZLP ");\r
2175             break;\r
2176     }\r
2177     TRACE_DEBUG_WP("\n\r");\r
2178 }\r
2179 \r
2180 /**@}*/\r
2181 \r