1 /**
2  * @file xmc_usbd.c
3  * @date 2015-06-20
4  *
5  * @cond
6  **********************************************************************************
7  * XMClib v2.1.24 - XMC Peripheral Driver Library
8  *
9  * Copyright (c) 2015-2019, Infineon Technologies AG
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification,are permitted provided that the following conditions are met:
14  *
15  *   Redistributions of source code must retain the above copyright notice,
16  *   this list of conditions and the following disclaimer.
17  *
18  *   Redistributions in binary form must reproduce the above copyright notice,
19  *   this list of conditions and the following disclaimer in the documentation
20  *   and/or other materials provided with the distribution.
21  *
22  *   Neither the name of the copyright holders nor the names of its contributors
23  *   may be used to endorse or promote products derived from this software without
24  *   specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
30  * LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * To improve the quality of the software, users are encouraged to share
39  * modifications, enhancements or bug fixes with Infineon Technologies AG
40  * dave@infineon.com).
41  **********************************************************************************
42  *
43  * Change History
44  * --------------
45  *
46  * 2015-02-16:
47  *     - Initial Version.<br>
48  * 2015-03-18:
49  *     - Updated the XMC_USBD_EndpointStall() to fix issue on USB clear stall. <br>
50  *     - Updated the XMC_USBD_EndpointConfigure() to fix issue in EP0 configuration.<br>
51  *     - Updated the XMC_USBD_IRQHandler()(Removed the DAVE_CE check on SOF event).<br>
52  * 2015-06-20:
53  *     - Removed GetDriverVersion API.<br>
54  *     - Updated the XMC_USBD_IsEnumDone() API.<br>
55  *     - Updated the copy right in the file header.<br>
56  *     - Updated the XMC_USBD_Disable() API to gate the clock after programming the SCU registers.<br>
57  *
58  * @endcond
59  *
60  */
61 
62 
63 /*******************************************************************************
64  * HEADER FILES
65  *******************************************************************************/
66 #include <xmc_usbd.h>
67 
68 #if defined(USB0)
69 
70 /**< macro to check the maximum number of endpoints used*/
71 #define XMC_USBD_CHECK_INPUT_MAX_NUM_EPS(usbd_max_num_eps) \
72   ((usbd_max_num_eps ==  XMC_USBD_MAX_NUM_EPS_1 ) || \
73    (usbd_max_num_eps ==  XMC_USBD_MAX_NUM_EPS_2 ) || \
74    (usbd_max_num_eps ==  XMC_USBD_MAX_NUM_EPS_3 ) || \
75    (usbd_max_num_eps ==  XMC_USBD_MAX_NUM_EPS_4 ) || \
76    (usbd_max_num_eps ==  XMC_USBD_MAX_NUM_EPS_5 ) || \
77    (usbd_max_num_eps ==  XMC_USBD_MAX_NUM_EPS_6 ) || \
78    (usbd_max_num_eps == XMC_USBD_MAX_NUM_EPS_7 ))
79 
80 /*******************************************************************************
81  *GLOBAL DATA
82  *******************************************************************************/
83 /*
84  * Endpoint Out Fifo Size
85  */
86 uint32_t XMC_USBD_EP_OUT_BUFFERSIZE[7] = {0U,0U,0U,0U,0U,0U,0U};
87 /*
88  * Endpoint In Fifo Size
89  */
90 uint32_t XMC_USBD_EP_IN_BUFFERSIZE[7] = {0U,0U,0U,0U,0U,0U,0U};
91 /*
92  * Device definition
93  */
94  XMC_USBD_DEVICE_t xmc_device;
95 #ifdef __GNUC__															  /*GCC*/
96 /*
97  * Endpoint Out Fifo
98  */
99 static __attribute__((aligned(4))) uint8_t XMC_USBD_EP_OUT_BUFFER[7][256] __attribute__((section("USB_RAM")));
100 /*
101  * Endpoint In Fifo
102  */
103 static __attribute__((aligned(4))) uint8_t XMC_USBD_EP_IN_BUFFER[7][256] __attribute__((section("USB_RAM")));
104 #endif
105 #if defined(__ICCARM__)
106 #pragma data_alignment=4
107 /*
108  * Endpoint Out Fifo
109  */
110 static uint8_t XMC_USBD_EP_OUT_BUFFER[7][256] @ ".dram";
111 /*
112  * Endpoint In Fifo
113  */
114 #pragma data_alignment=4
115 static uint8_t XMC_USBD_EP_IN_BUFFER[7][256] @ ".dram";
116 #endif
117 #if defined(__CC_ARM)
118 /*
119  * Endpoint Out Fifo
120  */
121 static __attribute__((aligned(4))) uint8_t XMC_USBD_EP_OUT_BUFFER[7][256] __attribute__((section ("RW_IRAM1")));
122 /*
123  * Endpoint In Fifo
124  */
125 static __attribute__((aligned(4))) uint8_t XMC_USBD_EP_IN_BUFFER[7][256] __attribute__((section ("RW_IRAM1")));
126 #endif
127 XMC_USBD_t *usbd_init;
128 
129 /*******************************************************************************
130  *LOCAL ROUTINES
131  *******************************************************************************/
132 /*Local routines prototypes*/
133 uint8_t XMC_USBD_lDeviceActive(const XMC_USBD_t *const obj);
134 static void XMC_USBD_lReadFifo(const uint32_t ep_num,const uint32_t byte_count);
135 static uint32_t XMC_USBD_lWriteFifo(XMC_USBD_EP_t *ep);
136 static void XMC_USBD_lFlushTXFifo(const uint8_t fifo_num);
137 static void XMC_USBD_lFlushRXFifo(void);
138 static uint8_t XMC_USBD_lAssignTXFifo(void);
139 static void XMC_USBD_lStartReadXfer(XMC_USBD_EP_t *const ep);
140 static void XMC_USBD_lStartWriteXfer(XMC_USBD_EP_t *const ep);
141 static void XMC_USBD_lHandleEnumDone(void);
142 static void XMC_USBD_lHandleOEPInt(const XMC_USBD_t *const obj);
143 static void XMC_USBD_lHandleRxFLvl(void);
144 static void XMC_USBD_lHandleIEPInt(const XMC_USBD_t *const obj);
145 static void XMC_USBD_lUnassignFifo(const uint8_t fifo_nr);
146 static void XMC_USBD_lHandleUSBReset(const XMC_USBD_t *const obj);
147 static void XMC_USBD_lHandleOTGInt(void);
148 static void XMC_USBD_lClearEventOTG(uint32_t event);
149 
150 /**
151  *  The device driver
152  */
153 const XMC_USBD_DRIVER_t Driver_USBD0 =
154 {
155   .GetCapabilities = XMC_USBD_GetCapabilities,
156   .Initialize = XMC_USBD_Init,
157   .Uninitialize = XMC_USBD_Uninitialize,
158   .DeviceConnect = XMC_USBD_DeviceConnect,
159   .DeviceDisconnect = XMC_USBD_DeviceDisconnect,
160   .DeviceGetState = XMC_USBD_DeviceGetState,
161   .DeviceSetAddress = XMC_USBD_DeviceSetAddress,
162   .EndpointConfigure = XMC_USBD_EndpointConfigure,
163   .EndpointUnconfigure = XMC_USBD_EndpointUnconfigure,
164   .EndpointStall = XMC_USBD_EndpointStall,
165   .EndpointReadStart = XMC_USBD_EndpointReadStart,
166   .EndpointRead = XMC_USBD_EndpointRead,
167   .EndpointWrite = XMC_USBD_EndpointWrite,
168   .EndpointAbort = XMC_USBD_EndpointAbort,
169   .GetFrameNumber = XMC_USBD_GetFrameNumber,
170   .IsEnumDone = XMC_USBD_IsEnumDone
171 };
172 
173 /**
174  * @brief Checks if device is active
175  *
176  * Therefore the endpoint inInUse flag are checked and if one endpoint is in use, 1 is returned,
177  * else 0 is returned.
178  * @return 1 if an endpoint is active else 0
179  */
XMC_USBD_lDeviceActive(const XMC_USBD_t * const obj)180 uint8_t XMC_USBD_lDeviceActive(const XMC_USBD_t *const obj)
181 {
182   uint8_t i;
183   uint8_t result = 0U;
184   for (i = 0U; i < (uint8_t)obj->usbd_max_num_eps; i++)
185   {
186     if (xmc_device.ep[i].inInUse || xmc_device.ep[i].outInUse)
187     {
188       result = 1U;
189     }
190   }
191   return result;
192 }
193 
194 
195 /**
196  * @brief Read data from the rx fifo
197  *
198  * The data from the fifo is copied in to the buffer specified by @ref xfer_buffer and
199  * the transfer values get updated. If the endpoint is disabled or the buffer not existent
200  * the function exits.
201  *
202  * @arg ep_num the endpoint to read for
203  * @arg byte_count the byte count to read
204  */
XMC_USBD_lReadFifo(const uint32_t ep_num,const uint32_t byte_count)205 static void XMC_USBD_lReadFifo(const uint32_t ep_num,const uint32_t byte_count)
206 {
207   XMC_USBD_EP_t * ep = &xmc_device.ep[ep_num];
208   uint32_t word_count;
209   uint32_t temp_data;
210   uint32_t temp_word_count;
211   volatile uint32_t *fifo = xmc_device.fifo[0U];
212   uint32_t i;
213   depctl_data_t data;
214   data.d32 = xmc_device.endpoint_out_register[ep_num]->doepctl;
215   word_count = (byte_count >> 2U );
216   temp_word_count = (word_count << 2U);
217   /* Check if ep is enabled and has buffer */
218   if (!data.b.usbactep)
219   {
220     /*Do Nothing*/
221   }
222   else if (ep->xferBuffer == NULL)
223   {
224 	/*Do Nothing*/
225   }
226   else
227   {
228     /* store the data */
229     for (i = 0U;i < word_count; i++)
230     {
231       *(((uint32_t*)ep->xferBuffer)+i) = *fifo;
232     }
233     /* space is not devidable by 4 */
234     if (byte_count!=temp_word_count)
235     {
236       temp_data = *fifo;
237       for (i = 0U;(temp_word_count + i) < byte_count;i++)
238       {
239         ep->xferBuffer[(word_count << 2)+i] = (uint8_t)((temp_data & ((uint32_t)0xFFU << (i * 8U))) >> (i * 8U));
240       }
241     }
242 
243     /* save the amount of data */
244     ep->xferCount += byte_count;
245     ep->xferBuffer += byte_count;
246   }
247 }
248 
249 /**
250  * @brief Write data to an endpoint fifo
251  *
252  * The data from the @ref xfer_buffer gets copied in to the tx fifo of the endpoint until the buffer has been read
253  *completely or the tx fifo is full. The transfer values are not updated.
254  *
255  * @arg[in] ep the endpoint to use
256  * @return the number of bytes written to the fifo
257  */
XMC_USBD_lWriteFifo(XMC_USBD_EP_t * const ep)258 static uint32_t XMC_USBD_lWriteFifo(XMC_USBD_EP_t *const ep)
259 {
260   dtxfsts_data_t freeSpace;
261   volatile uint32_t *fifo;
262   uint32_t byte_count;
263   uint32_t word_count;
264   uint32_t result;
265   uint32_t i;
266   fifo = xmc_device.fifo[ep->address_u.address_st.number]; /* fifo */
267   freeSpace.d32 = xmc_device.endpoint_in_register[ep->address_u.address_st.number]->dtxfsts;
268   /* calculate the length and the amount of dwords to copy based on the fifo status */
269   byte_count = ep->xferLength - ep->xferCount;
270   if (!byte_count)
271   {
272     result = 0U;
273   }
274   else
275   {
276     /* add the unaligned bytes to the word count to compare with the fifo space */
277     word_count = ((uint32_t)byte_count + 3U) >> 2U;
278     if (word_count > (uint32_t)freeSpace.b.txfspcavail )
279     {
280       word_count = (uint32_t)freeSpace.b.txfspcavail;
281       byte_count = (uint32_t)word_count << (uint32_t)2U;
282     }
283 
284     /* copy data dword wise */
285     for (i = 0U; i < word_count;ep->xferBuffer+= 4U)
286     {
287       *fifo = *(uint32_t*)ep->xferBuffer;
288       i++;
289     }
290     result=byte_count;
291   }
292   return result;
293 }
294 
295 /**
296  * @brief Flush a tx fifo
297  *
298  * @param[in] fifo_num Fifo number to flush
299  *
300  * @note Use 0x10 as parameter to flush all tx fifos.
301  */
XMC_USBD_lFlushTXFifo(const uint8_t fifo_num)302 static void XMC_USBD_lFlushTXFifo(const uint8_t fifo_num)
303 {
304   volatile grstctl_t data;
305   uint32_t count;
306   data.d32 = 0U;
307   /*flush fifo */
308   data.b.txfflsh = 1U;
309   data.b.txfnum = fifo_num;
310   xmc_device.global_register->grstctl = data.d32;
311   for (count = 0U;count < 1000U; count++){}
312   do
313   {
314    data.d32 = xmc_device.global_register->grstctl;
315   } while (data.b.txfflsh);
316     count = 0U;
317   while (count++ < 1000U)
318   {
319     /* wait 3 phy clocks */
320   }
321 }
322 
323 /**
324  * @brief Flush the rx fifo
325  */
XMC_USBD_lFlushRXFifo(void)326 static void XMC_USBD_lFlushRXFifo(void)
327 {
328   volatile grstctl_t data;
329   uint32_t count;
330 
331 	data.d32 = 0U;
332   data.b.rxfflsh = 1U;
333   /* flush FIFO */
334   xmc_device.global_register->grstctl = data.d32;
335   do
336   {
337     for (count = 0U; count < 1000U; count++){}
338     data.d32 = xmc_device.global_register->grstctl;
339   } while (data.b.rxfflsh);
340   count = 0U;
341   while (count++ < 1000U)
342   {
343     /* wait 3 phy clocks */
344   }
345 }
346 
347 /*
348  * Support Functions
349  */
350 
351 /**
352  * @brief Assign a free tx fifo
353  *
354  * A free tx fifo will be searched and the number will be returned.
355  *
356  * @return Fifo number for a free fifo
357  */
XMC_USBD_lAssignTXFifo(void)358 static uint8_t XMC_USBD_lAssignTXFifo(void)
359 {
360   uint16_t mask = 1U;
361   uint8_t i = 0U;
362   uint8_t result = 0U;
363   while( (i < (uint8_t)XMC_USBD_NUM_TX_FIFOS)&&((xmc_device.txfifomsk & mask) != 0U))
364   {
365     mask = (uint16_t)(mask << 1U);
366     i++;
367   }
368   if ((xmc_device.txfifomsk & mask) == 0U)
369   {
370     xmc_device.txfifomsk |= mask;
371     result=i;
372   }
373   return result;
374 }
375 
376 /**
377  * @brief Free a tx fifo
378  *
379  * Mark an used tx fifo as free.
380  * @param[in] fifo_nr Fifo number to free
381  */
XMC_USBD_lUnassignFifo(const uint8_t fifo_nr)382 static void XMC_USBD_lUnassignFifo(const uint8_t fifo_nr)
383 {
384   xmc_device.txfifomsk = (uint16_t)((uint32_t)xmc_device.txfifomsk & (uint32_t)(~((uint32_t)((uint32_t)1U << fifo_nr))));
385 }
386 
387 /**
388  * @brief Start a transfer for an out endpoint
389  *
390  * Based on the transfer values of the endpoint, the out endpoint registers will be programmed
391  * to start a new out transfer.
392  *
393  * @note No checking of the transfer values are done in this function. Be sure,
394  * that the transfer values are reasonable (e.g. buffer size is not exceeded).
395  *
396  * @param[in] ep Endpoint to start the transfer
397  */
XMC_USBD_lStartReadXfer(XMC_USBD_EP_t * const ep)398 static void XMC_USBD_lStartReadXfer(XMC_USBD_EP_t *const ep)
399 {
400   deptsiz_data_t data;
401   depctl_data_t epctl;
402 
403   data.d32 =  0U;
404   if ((ep->xferTotal - ep->xferLength) > ep->maxTransferSize)
405   {
406     ep->xferLength += ep->maxTransferSize;
407   }
408   else
409   {
410     ep->xferLength = ep->xferTotal;
411   }
412   if (ep->address_u.address_st.number == 0U)
413   {
414 	/* Setup the endpoint to receive 3 setup packages and one normal package.*/
415 	/* Cast the data pointer to use only one variable */
416     deptsiz0_data_t *ep0_data = (deptsiz0_data_t*)&data;
417     ep0_data->b.pktcnt = 0x1U;
418     ep0_data->b.supcnt = 0x3U;
419     ep0_data->b.xfersize = (uint8_t)ep->xferTotal;
420   }
421   else
422   {
423     /* If requested length is zero, just receive one zero length packet */
424     if (ep->xferLength == 0U)
425     {
426       data.b.xfersize = 0U;
427       data.b.pktcnt = 1U;
428     }
429     else
430     {
431       /* setup endpoint to recive a amount of packages by given size */
432       data.b.pktcnt = (uint16_t)(((ep->xferLength - ep->xferCount) + (ep->maxPacketSize -(uint32_t)1U))/ep->maxPacketSize);
433       data.b.xfersize =(uint32_t)(ep->xferLength - ep->xferCount);
434     }
435   }
436   if(usbd_init->usbd_transfer_mode == XMC_USBD_USE_DMA)
437   {
438     /* Programm dma address if needed */
439     xmc_device.endpoint_out_register[ep->address_u.address_st.number]->doepdma = (uint32_t)(ep->xferBuffer);
440   }
441   /* setup endpoint size and enable endpoint */
442   xmc_device.endpoint_out_register[ep->address_u.address_st.number]->doeptsiz = data.d32;
443 
444   epctl.d32 = xmc_device.endpoint_out_register[ep->address_u.address_st.number]->doepctl;
445   epctl.b.cnak = 1U;
446   epctl.b.epena = 1U;
447   xmc_device.endpoint_out_register[ep->address_u.address_st.number]->doepctl = epctl.d32;
448 }
449 
450 /**
451  * @brief Start a new in transfer
452  *
453  * Based on the transfer values of the endpoint the in endpoint registers will be programmed
454  * to start a new in transfer
455  *
456  * @param[in] ep Endpoint to start the transfer
457  */
XMC_USBD_lStartWriteXfer(XMC_USBD_EP_t * const ep)458 static void XMC_USBD_lStartWriteXfer(XMC_USBD_EP_t *const ep)
459 {
460   deptsiz_data_t size;
461   depctl_data_t ctl;
462 
463   size.d32 = 0U;
464   ctl.d32 = xmc_device.endpoint_in_register[ep->address_u.address_st.number]->diepctl;
465 
466   if ((ep->xferTotal - ep->xferLength)  < ep->maxTransferSize)
467   {
468     ep->xferLength = ep->xferTotal;
469   }
470   else
471   {
472     ep->xferLength += ep->maxTransferSize;
473   }
474   if (ep->xferLength == 0U)
475   {
476     size.b.xfersize = 0U;
477     size.b.pktcnt = 1U;
478   }
479   else
480   {
481     if (ep->address_u.address_st.number == 0U)
482     {
483       size.b.pktcnt = 1U;
484       /* ep->maxXferSize equals maxPacketSize */
485       size.b.xfersize = (uint32_t)(ep->xferLength - ep->xferCount);
486     }
487     else
488     {
489       size.b.xfersize =(uint32_t)(ep->xferLength - ep->xferCount);
490       size.b.pktcnt = (uint16_t)(((uint16_t)(ep->xferLength - ep->xferCount) + (uint16_t)((uint16_t)ep->maxPacketSize - 1U))/
491     		 ep->maxPacketSize);
492     }
493     if(usbd_init->usbd_transfer_mode == XMC_USBD_USE_DMA)
494     {
495       /* Program dma*/
496       xmc_device.endpoint_in_register[ep->address_u.address_st.number]->diepdma = (uint32_t)ep->xferBuffer;
497     }
498     if(usbd_init->usbd_transfer_mode == XMC_USBD_USE_FIFO)
499     {
500       /* enable fifo empty interrupt */
501 			xmc_device.device_register->dtknqr4_fifoemptymsk |= (uint32_t)((uint32_t)1U << (uint8_t)ep->address_u.address_st.number);
502     }
503   }
504 
505   /* Program size of transfer and enable endpoint */
506   xmc_device.endpoint_in_register[ep->address_u.address_st.number]->dieptsiz = size.d32;
507   ctl.b.epena = 1U;
508   ctl.b.cnak = 1U;
509   xmc_device.endpoint_in_register[ep->address_u.address_st.number]->diepctl = ctl.d32;
510 }
511 
512 
513 /**
514  * @brief Handles the USBD reset interrupt
515  *
516  * When ever the host sets the bus into reset condition the usb otg_core generates
517  * an interrupt, which is handled by this function. It resets the complete otg_core
518  * into the default state.
519  */
XMC_USBD_lHandleUSBReset(const XMC_USBD_t * const obj)520 static void XMC_USBD_lHandleUSBReset(const XMC_USBD_t *const obj)
521 {
522   uint32_t i;
523   depctl_data_t epctl;
524   dctl_data_t dctl;
525   fifosize_data_t gnptxfsiz;
526   daint_data_t daint;
527   dcfg_data_t dcfg;
528 
529   /* Clear the Remote Wakeup Signaling */
530   dctl.d32 = xmc_device.device_register->dctl;
531   dctl.b.rmtwkupsig = 1U;
532   xmc_device.device_register->dctl = dctl.d32;
533 
534   /* enable naks for all eps */
535   for (i = 0U;i < (uint8_t)XMC_USBD_NUM_EPS;i++)
536   {
537     epctl.d32 = xmc_device.endpoint_out_register[i]->doepctl;
538 		epctl.b.snak = 1U;
539 		epctl.b.stall = 0U;
540 		xmc_device.endpoint_out_register[i]->doepctl = epctl.d32;
541   }
542 
543   /* Configure fifos */
544   /* Calculate the size of the rx fifo */
545   xmc_device.global_register->grxfsiz = 64U;
546   /* Calculate the size of the tx fifo for ep 0 */
547   gnptxfsiz.d32 = 0U;
548   gnptxfsiz.b.depth = 16U;
549   gnptxfsiz.b.startaddr = 64U;
550   xmc_device.global_register->gnptxfsiz = gnptxfsiz.d32;
551   /* calculate the size for the rest */
552   for (i = 1U;i < (uint8_t)XMC_USBD_NUM_TX_FIFOS;i++)
553   {
554     xmc_device.global_register->dtxfsiz[i- 1U] = (uint32_t)(((256U + (i*(64U)))/4U) | ((uint32_t)16U << 16U));
555   }
556 
557   /* flush the fifos for proper operation */
558   XMC_USBD_lFlushTXFifo(0x10U); /* 0x10 == all fifos, see doc */
559   XMC_USBD_lFlushTXFifo(0x0U);
560   XMC_USBD_lFlushRXFifo();
561   /* Flush learning queue not needed due to fifo config */
562   /* enable ep0 interrupts */
563   daint.d32 = 0U;
564   daint.b.inep0 = 1U;
565   daint.b.outep0 = 1U;
566   xmc_device.device_register->daintmsk = daint.d32;
567 
568   /* enable endpoint interrupts */
569   /* out ep interrupts */
570   XMC_USBD_EnableEventOUTEP(((uint32_t)XMC_USBD_EVENT_OUT_EP_TX_COMPLET | (uint32_t)XMC_USBD_EVENT_OUT_EP_DISABLED |
571 		  	  	  	  	  	  (uint32_t)XMC_USBD_EVENT_OUT_EP_SETUP | (uint32_t)XMC_USBD_EVENT_OUT_EP_AHB_ERROR));
572 
573   /*in ep interrupts */
574   XMC_USBD_EnableEventINEP(((uint32_t)XMC_USBD_EVENT_IN_EP_TX_COMPLET | (uint32_t)XMC_USBD_EVENT_IN_EP_DISABLED |
575 		  (uint32_t)XMC_USBD_EVENT_IN_EP_AHB_ERROR | (uint32_t)XMC_USBD_EVENT_IN_EP_TIMEOUT));
576 
577 
578   /* Clear device Address */
579   dcfg.d32 = xmc_device.device_register->dcfg;
580   dcfg.b.devaddr = 0U;
581   xmc_device.device_register->dcfg = dcfg.d32;
582 
583   if(obj->usbd_transfer_mode == XMC_USBD_USE_FIFO)
584   {
585     /* Clear Empty interrupt */
586     xmc_device.device_register->dtknqr4_fifoemptymsk = 0U;
587   }
588 
589   xmc_device.ep[0U].outInUse = 0U;
590   xmc_device.ep[0U].inInUse = 0U;
591 
592   xmc_device.DeviceEvent_cb(XMC_USBD_EVENT_RESET);
593 
594   /* clear reset intr */
595   XMC_USBD_ClearEvent(XMC_USBD_EVENT_RESET);
596 }
597 
598 /**
599 * @brief Handle OTG Interrupt
600 *
601 * It detects especially connect and disconnect events.
602 */
XMC_USBD_lHandleOTGInt(void)603 static void XMC_USBD_lHandleOTGInt(void)
604 {
605   gotgint_data_t data;
606   data.d32 = xmc_device.global_register->gotgint;
607   if (data.b.sesenddet)
608   {
609 		xmc_device.IsPowered = 0U;
610 		xmc_device.DeviceEvent_cb(XMC_USBD_EVENT_POWER_OFF);
611   }
612   XMC_USBD_lClearEventOTG(data.d32);
613 
614 }
615 
616 /**
617  * @brief Interrupt handler for device enumeration done.
618  *
619  * Handles the enumeration done from dwc_otg, when the host has enumerated the device.
620  */
XMC_USBD_lHandleEnumDone(void)621 static void XMC_USBD_lHandleEnumDone(void)
622 {
623   /* Normaly we need to check dctl
624    * We are always fullspeed, so max it up. */
625   depctl_data_t epctl;
626   gusbcfg_data_t gusbcfg;
627 
628   epctl.d32=xmc_device.endpoint_in_register[0U]->diepctl;
629   epctl.b.mps = 0x00U; /* 64 Byte, this is also automatically set for out ep */
630   xmc_device.endpoint_in_register[0U]->diepctl = epctl.d32;
631 
632   /* update device connected flag */
633   xmc_device.IsConnected = 1U;
634   xmc_device.IsPowered = 1U;
635 
636   xmc_device.DeviceEvent_cb(XMC_USBD_EVENT_CONNECT);
637 
638   /* Set Trim */
639   gusbcfg.d32 = xmc_device.global_register->gusbcfg;
640   gusbcfg.b.usbtrdtim = 9U; /* default value for LS/FS */
641   xmc_device.global_register->gusbcfg = gusbcfg.d32;
642 
643   /* clear interrupt */
644   XMC_USBD_ClearEvent(XMC_USBD_EVENT_ENUMDONE);
645 }
646 
647 
648 /**
649  * @brief Handles all interrupts for all out endpoints
650  *
651  * The interrupt handler first checks, which endpoint has caused the interrupt and then
652  * determines, which interrupt should be handled.
653  */
XMC_USBD_lHandleOEPInt(const XMC_USBD_t * const obj)654 static void XMC_USBD_lHandleOEPInt(const XMC_USBD_t *const obj)
655 {
656   daint_data_t daint;
657   daint_data_t daintmsk;
658   doepmsk_data_t doepmsk;
659   doepint_data_t doepint;
660   deptsiz_data_t doeptsiz;
661   XMC_USBD_EP_t *ep;
662   uint16_t temp;
663   uint16_t temp1;
664   uint16_t mask;
665   uint8_t ep_num;
666 
667   daint.d32 = xmc_device.device_register->daint;
668 
669   daintmsk.d32 = xmc_device.device_register->daintmsk;
670 
671   doepmsk.d32 = xmc_device.device_register->doepmsk;
672 
673   mask = daint.ep.out & daintmsk.ep.out;
674   ep_num = 0U;
675   doeptsiz.d32 = 0U;
676 
677   while ((uint16_t)mask >> ep_num)
678   {
679     temp1 = (mask >> (uint16_t)ep_num);
680     temp = temp1 & 0x1U;
681     if (temp)
682     {
683       /* load register data for endpoint */
684       ep = &xmc_device.ep[ep_num];
685       doepint.d32 = xmc_device.endpoint_out_register[ep_num]->doepint & doepmsk.d32;
686       if(obj->usbd_transfer_mode == XMC_USBD_USE_DMA)
687       {
688         doeptsiz.d32 = xmc_device.endpoint_out_register[ep_num]->doeptsiz;
689       }
690 	  /* Setup Phase Complete */
691       if (doepint.b.setup)
692       {
693         /* ep0 not stalled any more */
694         ep->isStalled = 0U;
695         if(obj->usbd_transfer_mode == XMC_USBD_USE_DMA)
696         {
697           /* calculate size for setup packet */
698 		  ep->outBytesAvailable = (uint32_t)(((uint32_t)XMC_USBD_SETUP_COUNT -
699 		  (uint32_t)((deptsiz0_data_t*)&doeptsiz)->b.supcnt)*(uint32_t)XMC_USBD_SETUP_SIZE);
700         }
701 		if(obj->usbd_transfer_mode == XMC_USBD_USE_FIFO)
702 		{
703 			ep->outBytesAvailable += ep->xferCount;
704 		}
705 		ep->outInUse = 0U;
706 		xmc_device.EndpointEvent_cb(0U,XMC_USBD_EP_EVENT_SETUP); /* signal endpoint event */
707 				/* clear the interrupt */
708 		XMC_USBD_ClearEventOUTEP((uint32_t)XMC_USBD_EVENT_OUT_EP_SETUP,ep_num);
709       }
710       if (doepint.b.xfercompl)
711       {
712         if(obj->usbd_transfer_mode == XMC_USBD_USE_DMA)
713         {
714           uint32_t bytes = (ep->xferLength - ep->xferCount) - doeptsiz.b.xfersize;
715           ep->xferCount += bytes;
716           ep->xferBuffer += bytes;
717 				}
718         if (ep->xferTotal == ep->xferLength)
719         {
720           ep->outBytesAvailable = ep->xferCount;
721           ep->outInUse = 0U;
722           xmc_device.EndpointEvent_cb(ep_num,XMC_USBD_EP_EVENT_OUT);
723         }
724         else
725         {
726           XMC_USBD_lStartReadXfer(ep);
727         }
728 
729       }
730 
731       XMC_USBD_ClearEventOUTEP(doepint.d32,ep_num);
732     }
733     ep_num++;
734   }
735 
736   /* clear interrupt */
737   XMC_USBD_ClearEvent(XMC_USBD_EVENT_OUTEP);
738 }
739 
740 /**
741  * @brief Handles all interrupts for all in endpoints
742  *
743  * The interrupt handler first checks, which endpoint has caused the interrupt and then
744  * determines, which interrupt should be handled.
745  */
XMC_USBD_lHandleIEPInt(const XMC_USBD_t * const obj)746 static void XMC_USBD_lHandleIEPInt(const XMC_USBD_t *const obj)
747 {
748   XMC_USBD_EP_t *ep;
749   daint_data_t daint;
750   diepmsk_data_t diepmsk;
751   diepint_data_t diepint;
752   deptsiz_data_t dieptsiz;
753   uint16_t temp;
754   uint16_t temp1;
755   uint16_t mask;
756   uint8_t ep_num;
757   uint32_t inepint;
758 
759   daint.d32 = xmc_device.device_register->daint;
760 
761   diepmsk.d32 = xmc_device.device_register->diepmsk;
762 
763   dieptsiz.d32 = 0U;
764   mask = daint.ep.in;
765   ep_num = 0U;
766 
767   while ((uint16_t)mask >> ep_num)
768   {
769     temp1 = ((uint16_t)mask >> (uint16_t)ep_num);
770     temp = (uint16_t)temp1 & (uint16_t)0x1U;
771     if ((uint16_t)temp)
772     {
773       ep = &xmc_device.ep[ep_num];
774 			inepint = (uint32_t)xmc_device.endpoint_in_register[ep_num]->diepint;
775       diepint.d32 = inepint &
776       ((((uint32_t)((uint32_t)xmc_device.device_register->dtknqr4_fifoemptymsk >> ep->address_u.address_st.number) &
777                      0x1U) << 7U) | (uint32_t)diepmsk.d32);
778       if(obj->usbd_transfer_mode == XMC_USBD_USE_DMA)
779       {
780         dieptsiz.d32 = xmc_device.endpoint_in_register[ep_num]->dieptsiz;
781       }
782       if(obj->usbd_transfer_mode == XMC_USBD_USE_FIFO)
783       {
784         if (diepint.b.emptyintr)
785         {
786           uint32_t bytes;
787           bytes = XMC_USBD_lWriteFifo(ep);
788           ep->xferCount += bytes;
789           ep->xferBuffer += bytes;
790         }
791       }
792       if (diepint.b.xfercompl)
793       {
794         if(obj->usbd_transfer_mode == XMC_USBD_USE_DMA)
795         {
796           /* update xfer values */
797           if ((dieptsiz.b.pktcnt == 0U) && (dieptsiz.b.xfersize == 0U))
798           {
799             uint32_t Bytes = ep->xferLength - ep->xferCount;
800             ep->xferCount += Bytes;
801             ep->xferBuffer += Bytes;
802           }
803         }
804         if (ep->xferTotal==ep->xferLength)
805         {
806           ep->inInUse = 0U;
807           if(obj->usbd_transfer_mode == XMC_USBD_USE_FIFO)
808           {
809             /* mask fifo empty interrupt */
810             xmc_device.device_register->dtknqr4_fifoemptymsk =
811             (uint32_t)(xmc_device.device_register->dtknqr4_fifoemptymsk & ~(((uint32_t)1U << ep_num)));
812           }
813           xmc_device.EndpointEvent_cb(0x80U | ep_num,XMC_USBD_EP_EVENT_IN);
814         }
815         else
816         {
817           /* start next step of transfer */
818           XMC_USBD_lStartWriteXfer(ep);
819         }
820 
821       }
822 
823       XMC_USBD_ClearEventINEP((uint32_t)diepint.d32,ep_num);
824     }
825     ep_num++;
826   }
827   XMC_USBD_ClearEvent(XMC_USBD_EVENT_INEP);
828 }
829 
830 /**
831  * @brief RX Fifo interrupt handler
832  *
833  * This function handles the interrupt, when the rx fifo is not empty anymore.
834  */
XMC_USBD_lHandleRxFLvl(void)835 static void XMC_USBD_lHandleRxFLvl(void)
836 {
837   device_grxsts_data_t data;
838   data.d32 = xmc_device.global_register->grxstsp;
839 
840   switch (data.b.pktsts)
841 	{
842     case XMC_USBD_GRXSTS_PKTSTS_GOUTNAK:
843       break;
844     case XMC_USBD_GRXSTS_PKTSTS_OUTCMPL:
845       break;
846     case XMC_USBD_GRXSTS_PKTSTS_OUTDATA:
847       XMC_USBD_lReadFifo((uint32_t)data.b.epnum,(uint32_t)data.b.bcnt);
848       break;
849     case XMC_USBD_GRXSTS_PKTSTS_SETUP:
850       XMC_USBD_lReadFifo((uint32_t)data.b.epnum,(uint32_t)data.b.bcnt);
851       break;
852     case XMC_USBD_GRXSTS_PKTSTS_SETUPCMPL:
853       break;
854     default:
855       break;
856 	}
857   /* no need to clear */
858 }
859 
860 /**
861  * @brief Global interrupt handler
862  *
863  * The handler first checks, which global interrupt has caused the interrupt
864  * and then dispatches interrupt to the corresponding sub-handler.
865  */
XMC_USBD_IRQHandler(const XMC_USBD_t * const obj)866 void XMC_USBD_IRQHandler(const XMC_USBD_t *const obj)
867 {
868   gintmsk_data_t gintmsk;
869   gintsts_data_t data;
870 
871   gintmsk.d32 = xmc_device.global_register->gintmsk;
872   data.d32 = xmc_device.global_register->gintsts & gintmsk.d32;
873 
874   if (data.b.sofintr)
875   {
876     xmc_device.DeviceEvent_cb(XMC_USBD_EVENT_SOF);
877     XMC_USBD_ClearEvent(XMC_USBD_EVENT_SOF);
878   }
879   if(obj->usbd_transfer_mode == XMC_USBD_USE_FIFO)
880   {
881     if (data.b.rxstsqlvl)
882     {
883       /* Masked that interrupt so its only done once */
884       gintmsk.b.rxstsqlvl = 0U;
885       xmc_device.global_register->gintmsk = gintmsk.d32;
886       XMC_USBD_lHandleRxFLvl(); /* handle the interrupt */
887       gintmsk.b.rxstsqlvl = 1U;
888       xmc_device.global_register->gintmsk = gintmsk.d32;
889     }
890   }
891   if (data.b.erlysuspend)
892   {
893     XMC_USBD_ClearEvent(XMC_USBD_EVENT_EARLYSUSPEND);
894   }
895   if (data.b.usbsuspend)
896   {
897     xmc_device.DeviceEvent_cb(XMC_USBD_EVENT_SUSPEND);
898     XMC_USBD_ClearEvent(XMC_USBD_EVENT_SUSPEND);
899   }
900   if (data.b.wkupintr)
901   {
902     xmc_device.DeviceEvent_cb(XMC_USBD_EVENT_REMOTE_WAKEUP);
903     XMC_USBD_ClearEvent(XMC_USBD_EVENT_REMOTE_WAKEUP);
904   }
905   if (data.b.sessreqintr)
906   {
907     xmc_device.IsPowered = 1U;
908     xmc_device.DeviceEvent_cb(XMC_USBD_EVENT_POWER_ON);
909     XMC_USBD_ClearEvent(XMC_USBD_EVENT_POWER_ON);
910   }
911   if (data.b.usbreset)
912   {
913     XMC_USBD_lHandleUSBReset(obj);
914   }
915   if (data.b.enumdone)
916   {
917     XMC_USBD_lHandleEnumDone();
918   }
919   if (data.b.inepint)
920   {
921     XMC_USBD_lHandleIEPInt(obj);
922   }
923   if (data.b.outepintr)
924   {
925 		XMC_USBD_lHandleOEPInt(obj);
926   }
927 	if (data.b.otgintr)
928   {
929 	  XMC_USBD_lHandleOTGInt();
930   }
931 
932 }
933 
934 
935 /*******************************************************************************
936  * API IMPLEMENTATION
937  *******************************************************************************/
938 /**
939  * Enables the USB0 module
940  **/
XMC_USBD_Enable(void)941 void XMC_USBD_Enable(void)
942 {
943 #if defined(CLOCK_GATING_SUPPORTED)
944   XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_USB0);
945 #endif
946   /* Reset and power up */
947   XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_USB0);
948   XMC_SCU_POWER_EnableUsb();
949 }
950 
951 /**
952  * Disables the USB0 module
953  **/
XMC_USBD_Disable(void)954 void XMC_USBD_Disable(void)
955 {
956   /* Clear Reset and power up */
957   XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_USB0);
958 #if defined(CLOCK_GATING_SUPPORTED)
959   XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_USB0);
960 #endif
961   XMC_SCU_POWER_DisableUsb();
962 }
963 
964 /**
965  * Clear the USB device event
966  **/
XMC_USBD_ClearEvent(const XMC_USBD_EVENT_t event)967 void XMC_USBD_ClearEvent(const XMC_USBD_EVENT_t event)
968 {
969   gintsts_data_t clear;
970   clear.d32 = 0U;
971   switch(event)
972   {
973     case (XMC_USBD_EVENT_POWER_ON):
974 	  clear.b.sessreqintr = 1U;
975 	  break;
976     case (XMC_USBD_EVENT_RESET):
977 	  clear.b.usbreset = 1U;
978 	  break;
979     case (XMC_USBD_EVENT_SUSPEND):
980 	  clear.b.usbsuspend = 1U;
981 	  break;
982     case (XMC_USBD_EVENT_RESUME):
983 	  clear.b.wkupintr = 1U;
984 	  break;
985     case (XMC_USBD_EVENT_REMOTE_WAKEUP):
986 	  clear.b.wkupintr = 1U;
987 	  break;
988     case (XMC_USBD_EVENT_SOF):
989 	  clear.b.sofintr = 1U;
990 	  break;
991     case (XMC_USBD_EVENT_EARLYSUSPEND):
992 	  clear.b.erlysuspend = 1U;
993 	  break;
994     case (XMC_USBD_EVENT_ENUMDONE):
995 	  clear.b.enumdone = 1U;
996 	  break;
997     case (XMC_USBD_EVENT_OUTEP):
998 	  clear.b.outepintr = 1U;
999 	  break;
1000 		default:
1001 		break;
1002 	}
1003 	xmc_device.global_register->gintsts = clear.d32;
1004 }
1005 
1006 /**
1007  * Clear the USB OTG events
1008  **/
XMC_USBD_lClearEventOTG(uint32_t event)1009 static void XMC_USBD_lClearEventOTG(uint32_t event)
1010 {
1011   gotgint_data_t clear = { .d32 = 0U};
1012   clear.d32 = event;
1013   xmc_device.global_register->gotgint = clear.d32;
1014 }
1015 
1016 /**
1017  * Clear the USB IN EP events
1018  **/
XMC_USBD_ClearEventINEP(uint32_t event,const uint8_t ep_num)1019 void XMC_USBD_ClearEventINEP(uint32_t event,const uint8_t ep_num)
1020 {
1021   diepint_data_t clear;
1022   clear.d32 = event;
1023   xmc_device.endpoint_in_register[ep_num]->diepint = clear.d32;
1024 }
1025 
1026 /**
1027  * Clear the USB OUT EP events
1028  **/
XMC_USBD_ClearEventOUTEP(uint32_t event,const uint8_t ep_num)1029 void XMC_USBD_ClearEventOUTEP(uint32_t event,const uint8_t ep_num)
1030 {
1031   doepint_data_t clear;
1032   clear.d32 = event;
1033   xmc_device.endpoint_out_register[ep_num]->doepint = clear.d32;
1034 }
1035 
1036 /**
1037  * Enable the USB OUT EP events
1038  **/
XMC_USBD_EnableEventOUTEP(uint32_t event)1039 void XMC_USBD_EnableEventOUTEP(uint32_t event)
1040 {
1041 	doepint_data_t doepint;
1042 	doepint.d32 = event;
1043 	xmc_device.device_register->doepmsk |= doepint.d32;
1044 }
1045 
1046 /**
1047  * Enable the USB IN EP events
1048  **/
XMC_USBD_EnableEventINEP(uint32_t event)1049 void XMC_USBD_EnableEventINEP(uint32_t event)
1050 {
1051 	diepint_data_t diepint;
1052 	diepint.d32 = event;
1053 	xmc_device.device_register->diepmsk |= diepint.d32;
1054 }
1055 
1056 /**
1057  * Gets the USB device capabilities
1058  **/
XMC_USBD_GetCapabilities()1059 XMC_USBD_CAPABILITIES_t XMC_USBD_GetCapabilities()
1060 {
1061   XMC_USBD_CAPABILITIES_t cap={0U};
1062   cap.event_connect = 1U;
1063   cap.event_disconnect = 1U;
1064 #if UC_SERIES == 45
1065   cap.event_power_off = 1U;
1066   cap.event_power_on = 1U;
1067 #else
1068   cap.event_power_off = 0U;
1069   cap.event_power_on = 0U;
1070 #endif
1071   cap.event_high_speed = 0U;
1072   cap.event_remote_wakeup = 1U;
1073   cap.event_reset = 1U;
1074   cap.event_resume = 1U;
1075   cap.event_suspend = 1U;
1076   cap.reserved = 0U;
1077   return cap;
1078 }
1079 
1080 /**
1081  * Initializes the USB device
1082  **/
XMC_USBD_Init(XMC_USBD_t * obj)1083 XMC_USBD_STATUS_t XMC_USBD_Init(XMC_USBD_t *obj)
1084 {
1085   uint8_t *XMC_USBD_BASE_ADDRESS;
1086   uint32_t i;
1087   gahbcfg_data_t gahbcfg;
1088   gusbcfg_data_t gusbcfg;
1089   dcfg_data_t dcfg;
1090   dctl_data_t dctl;
1091   gintmsk_data_t gintmsk;
1092 
1093   XMC_ASSERT("XMC_USBD_Init: obj.usbd_max_num_eps not of type XMC_USBD_MAX_NUM_EPS_t",
1094  		      XMC_USBD_CHECK_INPUT_MAX_NUM_EPS(obj->usbd_max_num_eps))
1095 
1096   XMC_USBD_Enable();
1097 
1098   usbd_init = obj;
1099 
1100   /* Filling out buffer size */
1101   for(i = 0U;i < (uint32_t)XMC_USBD_NUM_EPS;i++)
1102   {
1103 	  XMC_USBD_EP_OUT_BUFFERSIZE[i] = XMC_USBD_EP0_BUFFER_SIZE;
1104 	  XMC_USBD_EP_IN_BUFFERSIZE[i] 	= XMC_USBD_EP0_BUFFER_SIZE;
1105   }
1106 
1107   /* clear device status */
1108   memset((void*)&xmc_device,0x0U,sizeof(XMC_USBD_DEVICE_t));
1109 
1110   /* assign callbacks */
1111   xmc_device.DeviceEvent_cb = obj->cb_xmc_device_event;
1112   xmc_device.EndpointEvent_cb = obj->cb_endpoint_event;
1113   XMC_USBD_BASE_ADDRESS = (uint8_t *)(obj->usbd);
1114   /* assign register address */
1115   xmc_device.global_register = (dwc_otg_core_global_regs_t*)(obj->usbd);
1116   xmc_device.device_register = ((dwc_otg_device_global_regs_t*)(XMC_USBD_BASE_ADDRESS + DWC_DEV_GLOBAL_REG_OFFSET));
1117   for (i = 0U;i < (uint32_t)XMC_USBD_NUM_EPS;i++)
1118   {
1119     xmc_device.endpoint_in_register[i] = (dwc_otg_dev_in_ep_regs_t*)(XMC_USBD_BASE_ADDRESS + DWC_DEV_IN_EP_REG_OFFSET +
1120     ((uint32_t)DWC_EP_REG_OFFSET*i));
1121   }
1122   for (i = 0U;i < (uint32_t)XMC_USBD_NUM_EPS;i++)
1123   {
1124     xmc_device.endpoint_out_register[i] = (dwc_otg_dev_out_ep_regs_t*)(XMC_USBD_BASE_ADDRESS +
1125     									  DWC_DEV_OUT_EP_REG_OFFSET +
1126     									  ((uint32_t)DWC_EP_REG_OFFSET*i));
1127   }
1128   for (i = 0U;i < (uint32_t)XMC_USBD_NUM_TX_FIFOS;i++)
1129   {
1130     xmc_device.fifo[i] = (uint32_t*)(XMC_USBD_BASE_ADDRESS +
1131     						XMC_USBD_TX_FIFO_REG_OFFSET +
1132     						(i * XMC_USBD_TX_FIFO_OFFSET));
1133   }
1134   /* obj data structure for endpoint 0 */
1135   /* Done by driver core */
1136   /* configure ahb details */
1137   gahbcfg.d32 = xmc_device.global_register->gahbcfg;
1138   gahbcfg.b.glblintrmsk = 1U; /* enable interrupts ( global mask ) */
1139   gahbcfg.b.nptxfemplvl_txfemplvl = 1U;
1140   if(obj->usbd_transfer_mode == XMC_USBD_USE_DMA)
1141   {
1142     /* Enable dma if needed */
1143     gahbcfg.b.dmaenable = 1U; /* enable dma if needed */
1144   }
1145   else
1146   {
1147     gahbcfg.b.dmaenable = 0U;
1148   }
1149   xmc_device.global_register->gahbcfg = gahbcfg.d32;
1150   /* configure usb details */
1151   gusbcfg.d32= xmc_device.global_register->gusbcfg;
1152   gusbcfg.b.force_dev_mode = 1U; /* force us into device mode */
1153   gusbcfg.b.srpcap = 1U; /* enable session request protocoll */
1154   xmc_device.global_register->gusbcfg = gusbcfg.d32;
1155 
1156   /* Device init */
1157   /* configure device speed */
1158   dcfg.d32 = xmc_device.device_register->dcfg;
1159   dcfg.b.devspd = XMC_USBD_DCFG_DEVSPD_FS;
1160   dcfg.b.descdma = 0U;
1161   xmc_device.device_register->dcfg = dcfg.d32;
1162   /* configure device functions */
1163   dctl.d32 = xmc_device.device_register->dctl;
1164   dctl.b.sftdiscon = 1U; /* disconnect the device until its connected by the user */
1165   /* all other config is done by default register value */
1166   xmc_device.device_register->dctl = dctl.d32;
1167   /* flush the fifos for proper operation */
1168   XMC_USBD_lFlushTXFifo((uint8_t)0x10U); /* 0x10 == all fifos, see doc */
1169   XMC_USBD_lFlushRXFifo();
1170   /* Enable Global Interrupts */
1171   /* clear interrupt status bits prior to unmasking */
1172   xmc_device.global_register->gintmsk = 0U; /* disable all interrupts */
1173   xmc_device.global_register->gintsts = 0xFFFFFFFFU; /* clear all interrupts */
1174 
1175   gintmsk.d32 = 0U;
1176   /* enable common interrupts */
1177   gintmsk.b.modemismatch = 1U;
1178   gintmsk.b.otgintr = 1U;
1179   gintmsk.b.sessreqintr = 1U;
1180   /* enable device interrupts */
1181   gintmsk.b.usbreset = 1U;
1182   gintmsk.b.enumdone = 1U;
1183   gintmsk.b.erlysuspend = 1U;
1184   gintmsk.b.usbsuspend = 1U;
1185   gintmsk.b.wkupintr = 1U;
1186   gintmsk.b.sofintr = 1U;
1187   if(obj->usbd_transfer_mode == XMC_USBD_USE_FIFO)
1188   {
1189     gintmsk.b.rxstsqlvl = 1U;
1190   }
1191   gintmsk.b.outepintr = 1U;
1192   gintmsk.b.inepintr = 1U;
1193   xmc_device.global_register->gintmsk = gintmsk.d32;
1194   return XMC_USBD_STATUS_OK;
1195 }
1196 
1197 /**
1198  * Uninitializes the USB device
1199  **/
XMC_USBD_Uninitialize()1200 XMC_USBD_STATUS_t XMC_USBD_Uninitialize()
1201 {
1202   /* Disconnect the device */
1203   dctl_data_t dctl;
1204 	dctl.d32 = xmc_device.device_register->dctl;
1205   dctl.b.sftdiscon = 1U;
1206   xmc_device.device_register->dctl = dctl.d32;
1207   /* clean up */
1208   memset((void*)&xmc_device,0U,sizeof(xmc_device));
1209   return XMC_USBD_STATUS_OK;
1210 }
1211 
1212 /**
1213  * Connects the USB device to host
1214  **/
XMC_USBD_DeviceConnect()1215 XMC_USBD_STATUS_t XMC_USBD_DeviceConnect()
1216 {
1217   /* Just disable softdisconnect */
1218   dctl_data_t dctl;
1219 	dctl.d32 = xmc_device.device_register->dctl;
1220   dctl.b.sftdiscon = 0U;
1221   xmc_device.device_register->dctl = dctl.d32;
1222   return XMC_USBD_STATUS_OK;
1223 }
1224 
1225 /**
1226  * Disconnects the USB device from host
1227  **/
XMC_USBD_DeviceDisconnect()1228 XMC_USBD_STATUS_t XMC_USBD_DeviceDisconnect()
1229 {
1230   dctl_data_t dctl;
1231 	dctl.d32 = xmc_device.device_register->dctl;
1232   dctl.b.sftdiscon = 1U;
1233   xmc_device.device_register->dctl = dctl.d32;
1234   return XMC_USBD_STATUS_OK;
1235 }
1236 
1237 /**
1238  * Gets the USB device state.
1239  **/
XMC_USBD_DeviceGetState(const XMC_USBD_t * const obj)1240 XMC_USBD_STATE_t XMC_USBD_DeviceGetState(const XMC_USBD_t *const obj)
1241 {
1242   XMC_USBD_STATE_t state={0U};
1243   state.speed = XMC_USBD_SPEED_FULL;
1244   state.connected = xmc_device.IsConnected;
1245   state.active = XMC_USBD_lDeviceActive(obj);
1246   state.powered = xmc_device.IsPowered;
1247   return state;
1248 }
1249 
1250 /**
1251  * Prepares the endpoint to read next OUT packet
1252  **/
XMC_USBD_EndpointReadStart(const uint8_t ep_addr,uint32_t size)1253 XMC_USBD_STATUS_t XMC_USBD_EndpointReadStart(const uint8_t ep_addr, uint32_t size)
1254 {
1255   XMC_USBD_EP_t *ep = &xmc_device.ep[ep_addr & (uint8_t)XMC_USBD_EP_NUM_MASK];
1256   XMC_USBD_STATUS_t result;
1257 
1258   if (ep->outInUse || !ep->isConfigured)
1259   {
1260     result = XMC_USBD_STATUS_ERROR;
1261   }
1262   else
1263   {
1264     /* short the length to buffer size if needed */
1265     if (size > ep->outBufferSize)
1266     {
1267       size = ep->outBufferSize;
1268     }
1269     /* set ep values */
1270     ep->xferTotal = size;
1271     ep->xferCount = 0U;
1272     ep->xferLength = 0U;
1273     ep->xferBuffer = ep->outBuffer;
1274     ep->outBytesAvailable = 0U;
1275     XMC_USBD_lStartReadXfer(ep);
1276     result= XMC_USBD_STATUS_OK;
1277   }
1278   return result;
1279 }
1280 
1281 /**
1282  * Reads the number of bytes from the USB OUT endpoint
1283  **/
XMC_USBD_EndpointRead(const uint8_t ep_num,uint8_t * buffer,uint32_t length)1284 int32_t XMC_USBD_EndpointRead(const uint8_t ep_num,uint8_t * buffer,uint32_t length)
1285 {
1286   XMC_USBD_EP_t *ep = &xmc_device.ep[ep_num];
1287   if (length > ep->outBytesAvailable)
1288   {
1289     length = ep->outBytesAvailable;
1290   }
1291   memcpy(buffer,&ep->outBuffer[ep->outOffset],length);
1292   ep->outBytesAvailable -= length;
1293   if (ep->outBytesAvailable)
1294   {
1295     ep->outOffset += length;
1296   }
1297   else
1298   {
1299     ep->outOffset = 0U;
1300   }
1301   return (int32_t)length;
1302 }
1303 
1304 /**
1305  * Writes number of bytes in to the USB IN endpoint.
1306  **/
XMC_USBD_EndpointWrite(const uint8_t ep_num,const uint8_t * buffer,uint32_t length)1307 int32_t XMC_USBD_EndpointWrite(const uint8_t ep_num,const uint8_t * buffer,uint32_t length)
1308 {
1309   XMC_USBD_EP_t * ep = &xmc_device.ep[ep_num & (uint8_t)XMC_USBD_EP_NUM_MASK];
1310   int32_t result;
1311   if (!ep->isConfigured)
1312   {
1313     result = (int32_t)XMC_USBD_STATUS_ERROR;
1314   }
1315   else if (ep->inInUse == 1U)
1316   {
1317     result=(int32_t)0;
1318   }
1319   else
1320   {
1321     if (length > ep->inBufferSize)
1322     {
1323       length = ep->inBufferSize;
1324     }
1325     /* copy data into input buffer for DMA and FIFO mode */
1326 		memcpy(ep->inBuffer,(const void *)buffer,length);
1327 		ep->xferBuffer = ep->inBuffer;
1328     ep->xferTotal = length;
1329     /* set transfer values */
1330     ep->xferLength = 0U;
1331     ep->xferCount = 0U;
1332     ep->inInUse = 1U;
1333     /* start the transfer */
1334     XMC_USBD_lStartWriteXfer(ep);
1335     result=(int32_t)ep->xferTotal;
1336   }
1337   return result;
1338 }
1339 
1340 /**
1341  * Sets the USB device address.
1342  **/
XMC_USBD_DeviceSetAddress(const uint8_t address,const XMC_USBD_SET_ADDRESS_STAGE_t stage)1343 XMC_USBD_STATUS_t XMC_USBD_DeviceSetAddress(const uint8_t address,const XMC_USBD_SET_ADDRESS_STAGE_t stage)
1344 {
1345   dcfg_data_t data;
1346   data.d32 = xmc_device.device_register->dcfg;
1347   if (stage == XMC_USBD_SET_ADDRESS_STAGE_SETUP)
1348   {
1349     data.b.devaddr = address;
1350     xmc_device.device_register->dcfg = data.d32;
1351   }
1352 	return XMC_USBD_STATUS_OK;
1353 }
1354 
1355 /**
1356  * Set/clear stall on the selected endpoint.
1357  **/
XMC_USBD_EndpointStall(const uint8_t ep_addr,const bool stall)1358 XMC_USBD_STATUS_t XMC_USBD_EndpointStall(const uint8_t ep_addr, const bool stall)
1359 {
1360   depctl_data_t data;
1361   XMC_USBD_EP_t *ep = &xmc_device.ep[(ep_addr & (uint8_t)XMC_USBD_EP_NUM_MASK)];
1362   if (stall)
1363   {
1364     if (ep_addr & (uint8_t)XMC_USBD_ENDPOINT_DIRECTION_MASK)
1365     {
1366       /*set stall bit */
1367       data.d32 = xmc_device.endpoint_in_register[ep->address_u.address_st.number]->diepctl;
1368       data.b.stall = 1U;
1369       xmc_device.endpoint_in_register[ep->address_u.address_st.number]->diepctl = data.d32;
1370     }
1371     else
1372     {
1373       /*set stall bit */
1374       data.d32 = xmc_device.endpoint_out_register[ep->address_u.address_st.number]->doepctl;
1375       data.b.stall = 1U;
1376       xmc_device.endpoint_out_register[ep->address_u.address_st.number]->doepctl = data.d32;
1377     }
1378     ep->isStalled = 1U;
1379   }
1380   else
1381   {
1382     /* just clear stall bit */
1383 		if (ep_addr & (uint8_t)XMC_USBD_ENDPOINT_DIRECTION_MASK)
1384 		{
1385 			data.d32 = xmc_device.endpoint_in_register[ep->address_u.address_st.number]->diepctl;
1386 			data.b.stall = 0U;
1387 			data.b.setd0pid = 1U; /* reset pid to 0 */
1388 			xmc_device.endpoint_in_register[ep->address_u.address_st.number]->diepctl = data.d32;
1389 		}
1390 		else
1391 		{
1392 			data.d32 = xmc_device.endpoint_out_register[ep->address_u.address_st.number]->doepctl;
1393 			data.b.stall = 0U;
1394 			data.b.setd0pid = 1U; /* reset pid to 0 */
1395 			xmc_device.endpoint_out_register[ep->address_u.address_st.number]->doepctl = data.d32;
1396 		}
1397 		ep->isStalled = 0U;
1398 	}
1399 	return XMC_USBD_STATUS_OK;
1400 }
1401 
1402 /**
1403  * Aborts the data transfer on the selected endpoint
1404  **/
XMC_USBD_EndpointAbort(const uint8_t ep_addr)1405 XMC_USBD_STATUS_t XMC_USBD_EndpointAbort(const uint8_t ep_addr) {
1406   XMC_USBD_EP_t *ep = &xmc_device.ep[ep_addr & (uint8_t)XMC_USBD_ENDPOINT_NUMBER_MASK];
1407   if (ep->address_u.address_st.direction)
1408   {
1409     ep->inInUse = 0U;
1410   }
1411   if (!ep->address_u.address_st.direction)
1412   {
1413     ep->outInUse = 0U;
1414   }
1415   ep->isStalled = 0U;
1416   ep->outBytesAvailable = 0U;
1417   ep->outOffset = 0U;
1418   ep->xferLength = 0U;
1419   ep->xferCount = 0U;
1420   ep->xferTotal = 0U;
1421 
1422   return XMC_USBD_STATUS_OK;
1423 }
1424 
1425 /**
1426  * Configures the given endpoint
1427  **/
XMC_USBD_EndpointConfigure(const uint8_t ep_addr,const XMC_USBD_ENDPOINT_TYPE_t ep_type,const uint16_t ep_max_packet_size)1428 XMC_USBD_STATUS_t XMC_USBD_EndpointConfigure(const uint8_t ep_addr,
1429 		                                     const XMC_USBD_ENDPOINT_TYPE_t ep_type,
1430 		                                     const uint16_t ep_max_packet_size)
1431 {
1432   daint_data_t daintmsk;
1433   XMC_USBD_EP_t *ep;
1434   daintmsk.d32 = xmc_device.device_register->daintmsk;
1435   ep =&xmc_device.ep[ep_addr & (uint32_t)XMC_USBD_ENDPOINT_NUMBER_MASK];
1436   memset((void*)ep,0x0U,sizeof(XMC_USBD_EP_t)); /* clear endpoint structure */
1437   /* do ep configuration */
1438   ep->address_u.address = ep_addr;
1439   ep->isConfigured = 1U;
1440   ep->maxPacketSize = (uint8_t)ep_max_packet_size;
1441   if (ep->address_u.address != 0U)
1442   {
1443     ep->maxTransferSize = (uint32_t)XMC_USBD_MAX_TRANSFER_SIZE;
1444   }
1445   else
1446   {
1447     ep->maxTransferSize = (uint32_t)XMC_USBD_MAX_TRANSFER_SIZE_EP0;
1448   }
1449   /* transfer buffer */
1450   ep->inBuffer = XMC_USBD_EP_IN_BUFFER[ep->address_u.address_st.number];
1451   ep->outBuffer = XMC_USBD_EP_OUT_BUFFER[ep->address_u.address_st.number];
1452   /* buffer size*/
1453   ep->inBufferSize = XMC_USBD_EP_IN_BUFFERSIZE[ep->address_u.address_st.number];
1454   ep->outBufferSize = XMC_USBD_EP_OUT_BUFFERSIZE[ep->address_u.address_st.number];
1455   /* is in */
1456   if ((ep->address_u.address_st.direction == 1U) || (ep_type == XMC_USBD_ENDPOINT_TYPE_CONTROL))
1457   {
1458     depctl_data_t data;
1459     data.d32 = xmc_device.endpoint_in_register[ep->address_u.address_st.number]->diepctl;
1460 		/*enable endpoint */
1461 		data.b.usbactep = 1U;
1462 		/* set ep type */
1463 		data.b.eptype = (uint8_t)ep_type;
1464 		/* set mps */
1465     if (ep_type == XMC_USBD_ENDPOINT_TYPE_CONTROL)
1466     {
1467 			switch(ep_max_packet_size)
1468 			{
1469 				case (64U):
1470 				data.b.mps = 0x0U;
1471 				break;
1472 				case (32U):
1473 				data.b.mps = 0x1U;
1474 				break;
1475 				case (16U):
1476 				data.b.mps = 0x2U;
1477 				break;
1478 				case (8U):
1479 				data.b.mps = 0x3U;
1480 				break;
1481 				default:
1482 				break;
1483 			}
1484 		}
1485 		else
1486 		{
1487 			data.b.mps = ep_max_packet_size;
1488 		}
1489 		/* set first data0 pid */
1490 		data.b.setd0pid = 1U;
1491 		/* clear stall */
1492 		data.b.stall = 0U;
1493 		/* set tx fifo */
1494 		ep->txFifoNum = XMC_USBD_lAssignTXFifo(); /* get tx fifo */
1495 		data.b.txfnum = ep->txFifoNum;
1496 		xmc_device.endpoint_in_register[ep->address_u.address_st.number]->diepctl = data.d32; /* configure endpoint */
1497 		daintmsk.ep.in |= (uint16_t)((uint16_t)1U << (uint8_t)ep->address_u.address_st.number); /* enable interrupts for endpoint */
1498   }
1499   if ((ep->address_u.address_st.direction == 0U) || (ep_type == XMC_USBD_ENDPOINT_TYPE_CONTROL))
1500   {
1501     /* is out */
1502 		depctl_data_t data;
1503 		data.d32 = xmc_device.endpoint_out_register[ep->address_u.address_st.number]->doepctl;
1504 		/*enable endpoint */
1505 		data.b.usbactep = 1U;
1506 		/* set ep type */
1507 		data.b.eptype = (uint8_t)ep_type;
1508     /* set mps */
1509     if (ep_type == XMC_USBD_ENDPOINT_TYPE_CONTROL)
1510 		{
1511 			switch(ep_max_packet_size)
1512 			{
1513 				case (64U):
1514 					data.b.mps = 0x0U;
1515 					break;
1516 				case (32U):
1517 					data.b.mps = 0x1U;
1518 					break;
1519 				case (16U):
1520 					data.b.mps = 0x2U;
1521 					break;
1522 				case (8U):
1523 					data.b.mps = 0x3U;
1524 					break;
1525 				default:
1526 					break;
1527 			}
1528 		}
1529 		else
1530 		{
1531 			data.b.mps = ep_max_packet_size;
1532 		}
1533 		/* set first data0 pid */
1534 		data.b.setd0pid = 1U;
1535 		/* clear stall */
1536 		data.b.stall =(uint8_t) 0U;
1537 		xmc_device.endpoint_out_register[ep->address_u.address_st.number]->doepctl = data.d32; /* configure endpoint */
1538 		daintmsk.ep.out |=(uint16_t) ((uint16_t)1U << (uint8_t)ep->address_u.address_st.number); /* enable interrupts */
1539   }
1540   xmc_device.device_register->daintmsk = daintmsk.d32;
1541   return XMC_USBD_STATUS_OK;
1542 }
1543 
1544 /**
1545  * Unconfigure the selected endpoint.
1546  **/
XMC_USBD_EndpointUnconfigure(const uint8_t ep_addr)1547 XMC_USBD_STATUS_t XMC_USBD_EndpointUnconfigure(const uint8_t ep_addr)
1548 {
1549   XMC_USBD_EP_t *ep = &xmc_device.ep[ep_addr & (uint8_t)XMC_USBD_ENDPOINT_NUMBER_MASK];
1550   depctl_data_t data;
1551 	daint_data_t daintmsk;
1552 	XMC_USBD_STATUS_t result;
1553 	uint32_t number_temp;
1554   data.d32 = 0U;
1555   daintmsk.d32 = xmc_device.device_register->daintmsk;
1556   number_temp = (uint32_t)((uint32_t)1U << (uint8_t)ep->address_u.address_st.number);
1557   /* if not configured return an error */
1558   if (!ep->isConfigured)
1559   {
1560      result = XMC_USBD_STATUS_ERROR;
1561   }
1562   else
1563   {
1564     /* disable the endpoint, deactivate it and only send naks */
1565     data.b.usbactep = 0U;
1566     data.b.epdis =  1U;
1567     data.b.snak =  1U;
1568     data.b.stall =  0U;
1569     ep->isConfigured =  0U;
1570     ep->isStalled =  0U;
1571     ep->outInUse =  0U;
1572     ep->inInUse =  0U;
1573     /* chose register based on the direction. Control Endpoint need both */
1574     if ((ep->address_u.address_st.direction == 1U) || (ep->type == (uint8_t)XMC_USBD_ENDPOINT_TYPE_CONTROL))
1575     {
1576       /* disable endpoint configuration */
1577       xmc_device.endpoint_in_register[ep->address_u.address_st.number]->diepctl = data.d32;
1578       /* disable interrupts */
1579       daintmsk.ep.in = (uint16_t)((uint32_t)daintmsk.ep.in & (~(uint32_t)number_temp));
1580     }
1581     if ((ep->address_u.address_st.direction == 0U) || (ep->type == (uint8_t)XMC_USBD_ENDPOINT_TYPE_CONTROL))
1582     {
1583       xmc_device.endpoint_out_register[ep->address_u.address_st.number]->doepctl = data.d32;
1584       daintmsk.ep.out = (uint16_t)((uint32_t)daintmsk.ep.out & (~(uint32_t)number_temp));
1585       if(usbd_init->usbd_transfer_mode == XMC_USBD_USE_FIFO)
1586       {
1587         xmc_device.device_register->dtknqr4_fifoemptymsk &= ~number_temp;
1588       }
1589     }
1590     xmc_device.device_register->daintmsk = daintmsk.d32;
1591     XMC_USBD_lUnassignFifo(ep->txFifoNum); /* free fifo */
1592     result = XMC_USBD_STATUS_OK;
1593   }
1594   return result;
1595 }
1596 
1597 /**
1598  * Gets the current USB frame number
1599  **/
XMC_USBD_GetFrameNumber(void)1600 uint16_t XMC_USBD_GetFrameNumber(void)
1601 {
1602   uint16_t result;
1603   dsts_data_t dsts;
1604   dsts.d32 = xmc_device.device_register->dsts;
1605   result = (uint16_t)dsts.b.soffn;
1606   return result;
1607 }
1608 
1609 /**
1610  * Gets the USB speed enumeration completion status.
1611  * This should not be used for the actual USB enumeration completion status. For the actual USB enumeration status,
1612  * the application layer should check for the completion of USB standard request Set configuration.
1613  **/
XMC_USBD_IsEnumDone(void)1614 uint32_t XMC_USBD_IsEnumDone(void)
1615 {
1616   return (uint32_t)((uint8_t)xmc_device.IsConnected && (uint8_t)xmc_device.IsPowered);
1617 }
1618 
1619 /***
1620  * MISRA C 2004 Deviations
1621  *
1622  *	1. cast from pointer to pointer [MISRA 2004 Rule 11.4]
1623  *  2. cast from pointer to unsigned int [Encompasses MISRA 2004 Rule 11.1], [MISRA 2004 Rule 11.3]
1624  *  3. call to function 'memset()' not made in the  presence of a prototype [MISRA 2004 Rule 8.1]
1625  *  4. No explicit type for symbol '_Bool', int assumed
1626  */
1627 #endif /* defined(USB0) */
1628