1 /**
2 * @file xmc_usbh.c
3 * @date 2019-05-07
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 modification,are permitted provided that the
13 * following conditions are met:
14 *
15 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided with the distribution.
20 *
21 * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
22 * products derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * (To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
33 * Infineon Technologies AG dave@infineon.com).
34 *
35 *********************************************************************************************************************
36 *
37 * Change History
38 * --------------
39 *
40 * 2016-06-30:
41 * - Initial <br>
42 * 2016-09-01:
43 * - Removed Keil specific exclusion<br>
44 * 2018-06-21:
45 * - Fixed compilation issues for XMC42
46 * 2019-05-07:
47 * - Fixed compilation warnings
48 * @endcond
49 *
50 */
51
52 #include "xmc_usbh.h"
53
54 #if ((UC_SERIES == XMC45) || (UC_SERIES == XMC44) || (UC_SERIES == XMC43) || (UC_SERIES == XMC47) || (UC_SERIES == XMC48))
55
56 /*Function provides transfer result*/
57 static uint32_t XMC_USBH_PipeTransferGetResult (XMC_USBH_PIPE_HANDLE pipe_hndl);
58 /*Updates the power state of the driver*/
59 static int32_t XMC_USBH_PowerControl (XMC_USBH_POWER_STATE_t state);
60
61 /*********************************************************** USBH Driver ***************************************************************** */
62
63 /*Macro to represent USB host driver version*/
64 #define XMC_USBH_DRV_VERSION ((uint16_t)((uint16_t)XMC_LIB_MINOR_VERSION << 8U)|XMC_LIB_PATCH_VERSION)
65 /*Macro used to gate PHY clock and AHB clock*/
66 #define XMC_USBH_PHY_CLK_STOP (0x03U)
67 /*Macro used to ungate PHY clock and AHB clock*/
68 #define XMC_USBH_PHY_CLK_UNGATE (0x100U)
69
70 /* Driver Version */
71 static const XMC_USBH_DRIVER_VERSION_t xmc_usbh_driver_version = { XMC_USBH_API_VERSION, XMC_USBH_DRV_VERSION };
72
73 /*Variables to hold selected VBUS port pin*/
74 XMC_GPIO_PORT_t * VBUS_port = XMC_GPIO_PORT3;
75 uint32_t VBUS_pin = 2U;
76
77 /*Array to track nack events on each pipe*/
78 bool is_nack[USBH0_MAX_PIPE_NUM];
79
80 /* Driver Capabilities */
81 static const XMC_USBH_CAPABILITIES_t xmc_usbh_driver_capabilities = {
82 0x0001U, /* Root HUB available Ports Mask */
83 0U, /* Automatic SPLIT packet handling */
84 1U, /* Signal Connect event */
85 1U, /* Signal Disconnect event */
86 0U /* Signal Overcurrent event */
87 };
88 /* Driver state and registers */
89 static XMC_USBH0_DEVICE_t XMC_USBH0_device/* __attribute__((section ("RW_IRAM1")))*/ = {
90 (USB0_GLOBAL_TypeDef *)(USB0_BASE), /** Global register interface */
91 ((USB0_CH_TypeDef *)(USB0_CH0_BASE)), /** Host channel interface */
92 0, /** Port event callback; set during init */
93 0, /** Pipe event callback; set during init */
94 false, /** init status */
95 XMC_USBH_POWER_OFF, /** USB Power status */
96 false /** Port reset state */
97 };
98
99 /*USB host pipe information. The array stores information related to packet id, data toggle,
100 * pending data transfer information, periodic transfer interval, received data size etc for each
101 * pipe.*/
102 volatile XMC_USBH0_pipe_t pipe[USBH0_MAX_PIPE_NUM];
103
104 /* FIFO sizes in bytes (total available memory for FIFOs is 1.25 kB) */
105 #define RX_FIFO_SIZE (1128U) /* RxFIFO size */
106 #define TX_FIFO_SIZE_NON_PERI (64U) /* Non-periodic Tx FIFO size */
107 #define TX_FIFO_SIZE_PERI (1024U) /* Periodic Tx FIFO size */
108
109 /*Stores data FIFO pointer for each pipe*/
110 static uint32_t *XMC_USBH0_dfifo_ptr[USBH0_MAX_PIPE_NUM];
111
112 /* Local functions */
113 /**
114 * @param enable Enable (XMC_USBH_CLOCK_GATING_ENABLE) or disable(XMC_USBH_CLOCK_GATING_DISABLE) clock gating
115 * @return None
116 * \par<b>Description:</b><br>
117 * Enable/disable clock gating depending if feature is supported.
118 */
XMC_lClockGating(uint8_t enable)119 __INLINE static void XMC_lClockGating(uint8_t enable)
120 {
121 #if defined(CLOCK_GATING_SUPPORTED)
122 if (enable == XMC_USBH_CLOCK_GATING_ENABLE)
123 {
124 XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_USB0);
125 }
126 if (enable == XMC_USBH_CLOCK_GATING_DISABLE)
127 {
128 XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_USB0);
129 }
130 #else
131 XMC_UNUSED_ARG(enable);
132 #endif
133
134 return;
135 }
136
137 /**
138 * @param ptr_ch Pointer to Channel
139 * @return None
140 * \par<b>Description:</b><br>
141 * Triggers halt of a channel.
142 */
XMC_lTriggerHaltChannel(USB0_CH_TypeDef * ptr_ch)143 __INLINE static void XMC_lTriggerHaltChannel(USB0_CH_TypeDef *ptr_ch)
144 {
145 ptr_ch->HCINTMSK = USB_CH_HCINT_ChHltd_Msk; /* Enable halt interrupt */
146 ptr_ch->HCCHAR |= (uint32_t)(USB_CH_HCCHAR_ChEna_Msk | USB_CH_HCCHAR_ChDis_Msk);
147 return;
148 }
149
150 /**
151 * @param ptr_pipe Pointer to Pipe
152 * @param ptr_ch Pointer to Channel
153 * @return bool \n
154 * true = success,\n
155 * false = fail
156 * \par<b>Description:</b><br>
157 * Start transfer on Pipe. The function uses transfer complete interrupts to transfer data more than maximum
158 * packet size. It takes care of updating data toggle information in subsequent packets related to the same data transfer.
159 */
XMC_lStartTransfer(XMC_USBH0_pipe_t * ptr_pipe,USB0_CH_TypeDef * ptr_ch)160 static bool XMC_lStartTransfer (XMC_USBH0_pipe_t *ptr_pipe, USB0_CH_TypeDef *ptr_ch) {
161 uint32_t hcchar;
162 uint32_t hctsiz;
163 uint32_t hcintmsk;
164 uint32_t num_remaining_transfer;
165 uint32_t num_remaining_fifo;
166 uint32_t num_remaining_queue;
167 uint32_t txsts = 0U;
168 uint32_t pckt_num;
169 uint32_t max_pckt_size;
170 uint8_t *ptr_src = ptr_pipe->data;
171 uint32_t *ptr_dest = NULL;
172 uint16_t cnt;
173 uint32_t loc_index;
174 bool status;
175
176 if (!(XMC_USBH0_device.global_register->HPRT & USB_HPRT_PrtConnSts_Msk))
177 {
178 status = false;
179 }
180 else
181 {
182 /* Save channel characteristic register to local variable */
183 hcchar = ptr_ch->HCCHAR;
184 /* Save transfer size register to local variable */
185 hctsiz = ptr_ch->HCTSIZ_BUFFERMODE;
186 hcintmsk = 0U;
187 cnt = 0U;
188
189 /* Prepare transfer */
190 /* Reset EPDir (transfer direction = output) and enable channel */
191 hcchar &= (uint32_t)(~(uint32_t)(USB_CH_HCCHAR_EPDir_Msk | USB_CH_HCCHAR_ChDis_Msk));
192 hcchar |= (uint32_t)USB_CH_HCCHAR_ChEna_Msk;
193
194 /* Enable default interrupts needed for all transfers */
195 hcintmsk = (USB_CH_HCINTMSK_XactErrMsk_Msk |
196 USB_CH_HCINTMSK_XferComplMsk_Msk |
197 USB_CH_HCINTMSK_NakMsk_Msk |
198 USB_CH_HCINTMSK_StallMsk_Msk) ;
199 /* Keep PID */
200 hctsiz &= (uint32_t)USB_CH_HCTSIZ_BUFFERMODE_Pid_Msk;
201
202 /* Packet specific setup */
203 switch (ptr_pipe->packet & XMC_USBH_PACKET_TOKEN_Msk) {
204 case XMC_USBH_PACKET_IN:
205 /* set transfer direction to input */
206 hcchar |= (uint32_t)USB_CH_HCCHAR_EPDir_Msk;
207 /* Enable IN transfer specific interrupts */
208 hcintmsk |= (uint32_t)( USB_CH_HCINTMSK_DataTglErrMsk_Msk |
209 USB_CH_HCINTMSK_BblErrMsk_Msk |
210 USB_CH_HCINTMSK_AckMsk_Msk |
211 USB_CH_HCINTMSK_NakMsk_Msk ) ;
212 break;
213 case XMC_USBH_PACKET_OUT:
214 break;
215 case XMC_USBH_PACKET_SETUP:
216 hctsiz &= (uint32_t)~USB_CH_HCTSIZ_BUFFERMODE_Pid_Msk ;
217 hctsiz |= (uint32_t)USB_CH_HCTSIZx_DPID_MDATA;
218 break;
219 default:
220 break;
221 }
222 /* Prepare PID */
223 switch (ptr_pipe->packet & XMC_USBH_PACKET_DATA_Msk) {
224 case XMC_USBH_PACKET_DATA0:
225 hctsiz &= (uint32_t)~USB_CH_HCTSIZ_BUFFERMODE_Pid_Msk;
226 hctsiz |= (uint32_t)USB_CH_HCTSIZx_DPID_DATA0;
227 break;
228 case XMC_USBH_PACKET_DATA1:
229 hctsiz &= (uint32_t)~USB_CH_HCTSIZ_BUFFERMODE_Pid_Msk;
230 hctsiz |= (uint32_t)USB_CH_HCTSIZx_DPID_DATA1;
231 break;
232 default:
233 break;
234 }
235
236 /* Prepare odd/even frame */
237 if ((XMC_USBH0_device.global_register->HFNUM & 1U) != 0U) {
238 hcchar &= (uint32_t)~USB_CH_HCCHAR_OddFrm_Msk;
239 } else {
240 hcchar |= (uint32_t)USB_CH_HCCHAR_OddFrm_Msk;
241 }
242
243 /* Get transfer type specific status */
244 switch (ptr_pipe->ep_type) {
245 case XMC_USBH_ENDPOINT_CONTROL:
246 case XMC_USBH_ENDPOINT_BULK:
247 if (!(hcchar & USB_CH_HCCHAR_EPDir_Msk)) {
248 txsts = XMC_USBH0_device.global_register->GNPTXSTS;
249 }
250 break;
251 case XMC_USBH_ENDPOINT_ISOCHRONOUS:
252 case XMC_USBH_ENDPOINT_INTERRUPT:
253 if (!(hcchar & USB_CH_HCCHAR_EPDir_Msk)) {
254 txsts = XMC_USBH0_device.global_register->HPTXSTS;
255 }
256 break;
257 default:
258 break;
259 }
260
261 /* Calculate remaining transfer size */
262 num_remaining_transfer = ptr_pipe->num - ptr_pipe->num_transferred_total;
263 /* Limit transfer to available space inside fifo/queue if OUT transaction */
264 if ((uint32_t)(hcchar & USB_CH_HCCHAR_EPDir_Msk) == 0U) {
265 max_pckt_size = ptr_pipe->ep_max_packet_size;
266 num_remaining_fifo = (uint32_t)((uint32_t)(txsts & 0x0000FFFFU) << 2);
267 num_remaining_queue = (uint32_t)((uint32_t)(txsts & 0x00FF0000U) >> 16);
268 if (num_remaining_transfer > num_remaining_fifo) {
269 num_remaining_transfer = num_remaining_fifo;
270 }
271 pckt_num = (uint32_t)((num_remaining_transfer + (max_pckt_size - 1U)) / max_pckt_size);
272 if (pckt_num > num_remaining_queue) {
273 pckt_num = num_remaining_queue;
274 }
275 if (num_remaining_transfer > (pckt_num * max_pckt_size)) {
276 num_remaining_transfer = pckt_num * max_pckt_size;
277 }
278 cnt = (uint16_t)((num_remaining_transfer + 3U) / 4U);
279 ptr_src = ptr_pipe->data + ptr_pipe->num_transferred_total;
280 loc_index = ((USB0_CH_TypeDef *)ptr_ch - (USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers));
281 ptr_dest = (uint32_t *)XMC_USBH0_dfifo_ptr[loc_index];
282 /* For OUT/SETUP transfer num_transferring represents num of bytes to be sent */
283 ptr_pipe->num_transferring = num_remaining_transfer;
284 }
285 else {
286 /* For IN transfer num_transferring is zero */
287 ptr_pipe->num_transferring = 0U;
288 }
289 /* Set packet count and transfer size */
290 if (num_remaining_transfer != 0U) {
291 hctsiz |= (((num_remaining_transfer + ptr_pipe->ep_max_packet_size) - 1U) / ptr_pipe->ep_max_packet_size) << 19U;
292 hctsiz |= num_remaining_transfer;
293 } else { /* Zero length packet */
294 hctsiz |= ((uint32_t)1U << USB_CH_HCTSIZ_BUFFERMODE_PktCnt_Pos); /* Packet count = 1 */
295 hctsiz |= 0U; /* Transfer size = 0 */
296 }
297 NVIC_DisableIRQ (USB0_0_IRQn);
298 ptr_ch->HCINTMSK = hcintmsk; /* Enable channel interrupts */
299 ptr_ch->HCTSIZ_BUFFERMODE = hctsiz; /* Write ch transfer size */
300 ptr_ch->HCCHAR = hcchar; /* Write ch characteristics */
301 while (cnt != 0U) { /* Load data */
302 #if defined __TASKING__/*tasking*/
303 *ptr_dest = *((__unaligned uint32_t *)ptr_src);
304 #else/* defined (__GNUC__) || defined (__CC_ARM) || defined (__ICCARM__)*/
305 *ptr_dest = *((__packed uint32_t *)ptr_src);
306 #endif
307 ptr_src += 4U;
308 cnt--;
309 }
310 NVIC_EnableIRQ (USB0_0_IRQn); /* Enable OTG interrupt */
311 status = true;
312 }
313 return status;
314 }
315
316 /* USB driver API functions */
317 /**
318 * @return \ref XMC_USBH_DRIVER_VERSION_t
319 * \par<b>Description:</b><br>
320 * Get driver version.
321 */
XMC_USBH_GetVersion(void)322 static XMC_USBH_DRIVER_VERSION_t XMC_USBH_GetVersion (void) { return xmc_usbh_driver_version; }
323
324 /**
325 * @return \ref XMC_USBH_CAPABILITIES_t
326 * \par<b>Description:</b><br>
327 * Get driver capabilities.
328 */
XMC_USBH_GetCapabilities(void)329 static XMC_USBH_CAPABILITIES_t XMC_USBH_GetCapabilities (void) { return xmc_usbh_driver_capabilities; }
330
331 /**
332 * @param cb_port_event Pointer to port event callback function \ref ARM_USBH_SignalPortEvent
333 * @param cb_pipe_event Pointer to pipe event callback function \ref ARM_USBH_SignalPipeEvent
334 * @return int32_t \ref Execution_status. 0 if execution is successful.
335 *
336 * \par<b>Description:</b><br>
337 * Initialize USB Host Interface. Registers callback functions to be executed on port event and pipe event.
338 * Initializes FIFO address for each pipe. Configures P3.2 as the VBUS charge pump enable pin.\n
339 *
340 * \par<b>Related APIs:</b><BR>
341 * XMC_USBH_Select_VBUS(), XMC_USBH_Uninitialize() \n
342 */
XMC_USBH_Initialize(XMC_USBH_SignalPortEvent_t cb_port_event,XMC_USBH_SignalPipeEvent_t cb_pipe_event)343 static int32_t XMC_USBH_Initialize (XMC_USBH_SignalPortEvent_t cb_port_event,
344 XMC_USBH_SignalPipeEvent_t cb_pipe_event) {
345
346 uint32_t channel;
347 int32_t status = XMC_USBH_DRIVER_OK;
348 if (XMC_USBH0_device.init_done == true)
349 {
350 /*return ok since initialized*/
351 }
352 else
353 {
354 /* assign callbacks */
355 XMC_USBH0_device.SignalPortEvent_cb = cb_port_event;
356 XMC_USBH0_device.SignalPipeEvent_cb = cb_pipe_event;
357
358 /* assign fifo start addresses */
359 for (channel = 0U; channel < USBH0_MAX_PIPE_NUM; channel++) {
360 XMC_USBH0_dfifo_ptr[channel] = (uint32_t *)((uint32_t)USB0_BASE + ((channel + 1U) * 0x01000U));
361 }
362
363 XMC_GPIO_SetMode(VBUS_port, (uint8_t)VBUS_pin, XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT1);
364
365 XMC_USBH0_device.init_done = true;
366 }
367 return status;
368 }
369
370 /**
371 * @return int32_t \ref Execution_status. Returns 0 to indicate success.
372 * \par<b>Description:</b><br>
373 * De-initialize USB Host Interface. Sets the driver power state as powered off. Disables VBUS.\n
374 *
375 * \par<b>Related APIs:</b><BR>
376 * XMC_USBH_Select_VBUS(), XMC_USBH_Initialize(), XMC_USBH_PortVbusOnOff() \n
377 */
XMC_USBH_Uninitialize(void)378 static int32_t XMC_USBH_Uninitialize (void) {
379 XMC_USBH0_device.init_done = false;
380 (void)XMC_USBH_PowerControl(XMC_USBH_POWER_OFF);
381 return XMC_USBH_DRIVER_OK;
382 }
383
384 /**
385 * @param state Power state. \ref XMC_USBH_POWER_STATE_t
386 * @return int32_t \ref Execution_status. Returns 0 if successful.
387 * \par<b>Description:</b><br>
388 * Control USB Host Interface Power. If power state is set to \ref XMC_USBH_POWER_FULL,
389 * it initializes the peripheral and enables VBUS. If power state is set to \ref XMC_USBH_POWER_OFF,
390 * disables the peripheral and the VBUS.\n
391 *
392 * \par<b>Related APIs:</b><BR>
393 * XMC_USBH_Select_VBUS(), XMC_USBH_Initialize(), XMC_USBH_PortVbusOnOff(), XMC_USBH_Uninitialize() \n
394 */
XMC_USBH_PowerControl(XMC_USBH_POWER_STATE_t state)395 static int32_t XMC_USBH_PowerControl (XMC_USBH_POWER_STATE_t state) {
396 int32_t status = XMC_USBH_DRIVER_OK;
397 uint32_t loc_value;
398 switch (state) {
399 case XMC_USBH_POWER_LOW:
400 status = XMC_USBH_DRIVER_ERROR_UNSUPPORTED;
401 break;
402 case XMC_USBH_POWER_OFF:
403 NVIC_DisableIRQ (USB0_0_IRQn);
404 NVIC_ClearPendingIRQ (USB0_0_IRQn); /* Clear pending interrupt */
405 XMC_USBH0_device.power_state = state; /* Clear powered flag */
406 XMC_USBH0_device.global_register->GAHBCFG &= (uint32_t)(~USB_GAHBCFG_GlblIntrMsk_Msk); /* Disable USB interrupts */
407 XMC_lClockGating((uint8_t)XMC_USBH_CLOCK_GATING_ENABLE); /* Enable Clock Gating */
408 XMC_USBH0_device.global_register->PCGCCTL |= (uint32_t)USB_PCGCCTL_StopPclk_Msk; /* Stop PHY clock */
409 XMC_SCU_POWER_DisableUsb(); /* Disable Power USB */
410 XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_USB0); /* reset USB */
411 XMC_USBH0_device.port_reset_active = false; /* Reset variables */
412 memset((void *)(pipe), 0, (USBH0_MAX_PIPE_NUM * sizeof(XMC_USBH0_pipe_t)));
413 break;
414 case XMC_USBH_POWER_FULL:
415 if (XMC_USBH0_device.init_done == false)
416 {
417 status = XMC_USBH_DRIVER_ERROR;
418 break;
419 } /* not initialized */
420 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_FULL)
421 {
422 status = XMC_USBH_DRIVER_OK;
423 break;
424 } /* already powered */
425 XMC_lClockGating((uint8_t)XMC_USBH_CLOCK_GATING_DISABLE); /* disable clock gating */
426 (void)XMC_USBH_osDelay(2U);
427 XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_USB0); /* deassert reset USB */
428 (void)XMC_USBH_osDelay(2U);
429 (void)XMC_USBH_osDelay(100U);
430 XMC_SCU_POWER_EnableUsb(); /* Enable Power USB */
431
432 /* On-chip Full-speed PHY */
433 XMC_USBH0_device.global_register->PCGCCTL &= (uint32_t)~USB_PCGCCTL_StopPclk_Msk; /* Start PHY clock */
434 XMC_USBH0_device.global_register->GUSBCFG |= (uint32_t)USB_GUSBCFG_PHYSel_Msk; /* Full-speed transceiver */
435
436 while ((XMC_USBH0_device.global_register->GRSTCTL & USB_GRSTCTL_AHBIdle_Msk) == 0U) /* wait until AHB master state machine is idle */
437 {
438 /*Wait*/
439 }
440
441 XMC_USBH0_device.global_register->GRSTCTL |= (uint32_t)USB_GRSTCTL_CSftRst_Msk; /* Core soft reset */
442
443 while ((XMC_USBH0_device.global_register->GRSTCTL & USB_GRSTCTL_CSftRst_Msk) != 0U) /* wait soft reset confirmation */
444 {
445 /*Wait*/
446 }
447 (void)XMC_USBH_osDelay(100U);
448
449 XMC_USBH0_device.port_reset_active = false; /* Reset variables */
450 memset((void *)(pipe), 0, (USBH0_MAX_PIPE_NUM * sizeof(XMC_USBH0_pipe_t)));
451
452 /*Created local copy of GUSBCFG to avoid side effects*/
453 loc_value = XMC_USBH0_device.global_register->GUSBCFG;
454 if (((loc_value & USB_GUSBCFG_ForceHstMode_Msk) == 0U) || \
455 ((loc_value & USB_GUSBCFG_ForceDevMode_Msk) != 0U))
456 {
457 XMC_USBH0_device.global_register->GUSBCFG &= (uint32_t)~USB_GUSBCFG_ForceDevMode_Msk; /* Clear force device mode */
458 XMC_USBH0_device.global_register->GUSBCFG |= (uint32_t)USB_GUSBCFG_ForceHstMode_Msk; /* Force host mode */
459 (void)XMC_USBH_osDelay(100U);
460 }
461
462 /* FS only, even if HS is supported */
463 XMC_USBH0_device.global_register->HCFG |= (uint32_t)(0x200U | USB_CH_HCFG_FSLSSUP(1));
464
465 /* Rx FIFO setting */
466 XMC_USBH0_device.global_register->GRXFSIZ = (RX_FIFO_SIZE/4U);
467 /* Non-periodic Tx FIFO setting */
468 XMC_USBH0_device.global_register->GNPTXFSIZ_HOSTMODE = (((uint32_t)(TX_FIFO_SIZE_NON_PERI/4U) << 16) | (RX_FIFO_SIZE / 4U));
469 /* Periodic Tx FIFO setting */
470 XMC_USBH0_device.global_register->HPTXFSIZ = ((uint32_t)(TX_FIFO_SIZE_PERI / 4U) << 16U) | ((RX_FIFO_SIZE + TX_FIFO_SIZE_NON_PERI) / 4U);
471 /* Enable channel interrupts */
472 XMC_USBH0_device.global_register->HAINTMSK = ((uint32_t)1U << USBH0_MAX_PIPE_NUM) - 1U;
473 /* Unmask interrupts */
474 XMC_USBH0_device.global_register->GINTMSK_HOSTMODE = (
475 USB_GINTSTS_HOSTMODE_DisconnInt_Msk |
476 USB_GINTMSK_HOSTMODE_HChIntMsk_Msk |
477 USB_GINTMSK_HOSTMODE_PrtIntMsk_Msk |
478 USB_GINTMSK_HOSTMODE_RxFLvlMsk_Msk |
479 USB_GINTMSK_HOSTMODE_SofMsk_Msk |
480 USB_GINTMSK_HOSTMODE_WkUpIntMsk_Msk
481 ) ;
482 /* Set powered state */
483 XMC_USBH0_device.power_state = state;
484 /* Enable interrupts */
485 XMC_USBH0_device.global_register->GAHBCFG |= (uint32_t)USB_GAHBCFG_GlblIntrMsk_Msk;
486 /* Set highest interrupt priority */
487 NVIC_SetPriority (USB0_0_IRQn, 0U);
488 NVIC_EnableIRQ (USB0_0_IRQn);
489 break;
490 default:
491 status = XMC_USBH_DRIVER_ERROR_UNSUPPORTED;
492 }
493 return status;
494 }
495
496 /**
497 * @param port Root HUB Port Number. Only one port(0) is supported.
498 * @param vbus VBUS state - \n
499 * - \b false VBUS off
500 * - \b true VBUS on
501 * @return int32_t \ref Execution_status. Returns 0 if successful.
502 *
503 * \par<b>Description:</b><br>
504 * Set USB port VBUS on/off.
505 */
XMC_USBH_PortVbusOnOff(uint8_t port,bool vbus)506 static int32_t XMC_USBH_PortVbusOnOff (uint8_t port, bool vbus) {
507 int32_t status = XMC_USBH_DRIVER_OK;
508 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
509 {
510 status = XMC_USBH_DRIVER_ERROR;
511 }
512 else
513 {
514 if (port != 0U)
515 {
516 status = XMC_USBH_DRIVER_ERROR_PARAMETER;
517 }
518 else
519 {
520 if (vbus != 0U) {
521 /* Port power on */
522 XMC_USBH0_device.global_register->HPRT |= (uint32_t)USB_HPRT_PrtPwr_Msk;
523 XMC_GPIO_SetMode(VBUS_port, (uint8_t)VBUS_pin, XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT1);
524 } else {
525 /* Port power off */
526 XMC_USBH0_device.global_register->HPRT &= (uint32_t)~USB_HPRT_PrtPwr_Msk;
527 XMC_GPIO_SetMode(VBUS_port, (uint8_t)VBUS_pin, XMC_GPIO_MODE_INPUT_TRISTATE);
528 }
529 }
530 }
531 return status;
532 }
533
534 /**
535 * @param port Root HUB Port Number. Only one port(0) is supported.
536 * @return int32_t Execution status. \ref Execution_status
537 * \par<b>Description:</b><br>
538 * Do USB port reset. Port reset should honor the requirement of 50ms delay before enabling.
539 * The function depends on implementation of XMC_USBH_osDelay() for 1ms delay to achieve required delay.
540 *
541 */
XMC_USBH_PortReset(uint8_t port)542 static int32_t XMC_USBH_PortReset (uint8_t port) {
543 uint32_t hprt;
544 int32_t status = XMC_USBH_DRIVER_OK;
545 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
546 {
547 status = XMC_USBH_DRIVER_ERROR;
548 }
549 else
550 {
551 if (port != 0U)
552 {
553 status = XMC_USBH_DRIVER_ERROR_PARAMETER;
554 }
555
556 XMC_USBH0_device.port_reset_active = true;
557 hprt = XMC_USBH0_device.global_register->HPRT;
558 hprt &= (uint32_t)~USB_HPRT_PrtEna_Msk; /* Disable port */
559 hprt |= (uint32_t)USB_HPRT_PrtRst_Msk; /* Port reset */
560 XMC_USBH0_device.global_register->HPRT = hprt;
561 (void)XMC_USBH_osDelay(50U); /* wait at least 50ms */
562 hprt &= (uint32_t)~USB_HPRT_PrtRst_Msk; /* Clear port reset */
563 XMC_USBH0_device.global_register->HPRT = hprt;
564 (void)XMC_USBH_osDelay(50U); /* wait for ISR */
565
566 /*Wait for the port to be enabled*/
567 while ((XMC_USBH0_device.global_register->HPRT & USB_HPRT_PrtEna_Msk) == 0U)
568 {
569 /*wait*/
570 }
571
572 if (XMC_USBH0_device.port_reset_active == true)
573 {
574 XMC_USBH0_device.port_reset_active = false;
575 status = XMC_USBH_DRIVER_ERROR; /* reset not confirmed inside ISR */
576 }
577 }
578
579 return status;
580 }
581
582 /**
583 * @param port USB port number. Only one port(0) is supported.
584 * @return \ref Execution_status
585 * \par<b>Description:</b><br>
586 * Suspend USB Port (stop generating SOFs).\n
587 *
588 * \par<b>Related APIs:</b><BR>
589 * XMC_USBH_PortResume() \n
590 */
XMC_USBH_PortSuspend(uint8_t port)591 static int32_t XMC_USBH_PortSuspend (uint8_t port)
592 {
593 int32_t status = XMC_USBH_DRIVER_OK;
594 uint32_t hprt;
595 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
596 {
597 status = XMC_USBH_DRIVER_ERROR;
598 }
599 else
600 {
601 if (port != 0U)
602 {
603 status = XMC_USBH_DRIVER_ERROR_PARAMETER;
604 }
605 else
606 {
607 hprt = XMC_USBH0_device.global_register->HPRT;
608 hprt &= (uint32_t)~(USB_HPRT_PrtEna_Msk);
609 hprt |= (uint32_t)USB_HPRT_PrtSusp_Msk;
610 XMC_USBH0_device.global_register->HPRT = hprt;
611 /* Stop PHY clock after suspending the bus*/
612 XMC_USBH0_device.global_register->PCGCCTL |= XMC_USBH_PHY_CLK_STOP;
613
614 }
615 }
616 return status;
617 }
618
619 /**
620 * @param port USB port number. Only one port(0) is supported.
621 * @return \ref Execution_status
622 * \par<b>Description:</b><br>
623 * Resume suspended USB port (start generating SOFs).\n
624 *
625 * \par<b>Related APIs:</b><BR>
626 * XMC_USBH_PortSuspend() \n
627 */
XMC_USBH_PortResume(uint8_t port)628 static int32_t XMC_USBH_PortResume (uint8_t port)
629 {
630 int32_t status = XMC_USBH_DRIVER_OK;
631 uint32_t hprt;
632 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
633 {
634 status = XMC_USBH_DRIVER_ERROR;
635 }
636 else
637 {
638 if (port != 0U)
639 {
640 status = XMC_USBH_DRIVER_ERROR_PARAMETER;
641 }
642 else
643 {
644 /*Ungate PHY clock*/
645 XMC_USBH0_device.global_register->PCGCCTL = XMC_USBH_PHY_CLK_UNGATE;
646 /*Set resume bit*/
647 hprt = XMC_USBH0_device.global_register->HPRT;
648 hprt &= (uint32_t)~(USB_HPRT_PrtEna_Msk);
649 hprt |= (uint32_t)USB_HPRT_PrtRes_Msk;
650 XMC_USBH0_device.global_register->HPRT = hprt;
651
652 (void)XMC_USBH_osDelay(20U);
653
654 hprt = XMC_USBH0_device.global_register->HPRT;
655 hprt &= (uint32_t)~(USB_HPRT_PrtEna_Msk);
656 hprt &= (uint32_t)~((uint32_t)USB_HPRT_PrtRes_Msk);
657 XMC_USBH0_device.global_register->HPRT = hprt;
658 }
659 }
660
661 return status;
662 }
663
664 /**
665 * @param port USB port number. Only one port(0) is supported.
666 * @return XMC_USBH_PORT_STATE_t Port State
667 *
668 * \par<b>Description:</b><br>
669 * Get current USB port state. The state indicates if the port is connected, port speed
670 * and port overcurrent status.
671 */
XMC_USBH_PortGetState(uint8_t port)672 static XMC_USBH_PORT_STATE_t XMC_USBH_PortGetState (uint8_t port)
673 {
674 XMC_USBH_PORT_STATE_t port_state = { 0U, 0U, 0U };
675 uint32_t hprt;
676
677 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
678 {
679 /*Do not update the port state*/
680 }
681 else
682 {
683 if (port != 0U)
684 {
685 /*Do not update the port state*/
686 }
687 else
688 {
689 hprt = XMC_USBH0_device.global_register->HPRT;
690 if(((hprt & USB_HPRT_PrtConnSts_Msk) != 0U))
691 {
692 port_state.connected = 1U;
693 }
694 else
695 {
696 port_state.connected = 0U;
697 }
698 port_state.overcurrent = 0U;
699
700 switch ((uint32_t)((uint32_t)(hprt & USB_HPRT_PrtSpd_Msk) >> USB_HPRT_PrtSpd_Pos)) {
701 case 1U: /* Full speed */
702 port_state.speed = XMC_USBH_SPEED_FULL;
703 break;
704 default:
705 break;
706 }
707 }
708 }
709 return port_state;
710 }
711
712 /**
713 * @param dev_addr Device address
714 * @param dev_speed Device speed
715 * @param hub_addr Hub address. This value should be 0 since hub is not supported.
716 * @param hub_port USB port number. Only one port(0) is supported.
717 * @param ep_addr Device endpoint address \n
718 * - ep_addr.0..3: Address \n
719 * - ep_addr.7: Direction\n
720 * @param ep_type Endpoint type (ARM_USB_ENDPOINT_xxx)
721 * @param ep_max_packet_size Endpoint maximum packet size
722 * @param ep_interval Endpoint polling interval
723 * @return XMC_USBH_PIPE_HANDLE Pipe handle is a pointer to pipe hardware base address.
724 *
725 * \par<b>Description:</b><br>
726 * Create/allocate a pipe configured with input parameters. The function looks for an unused pipe and configures with input parameters.
727 *
728 * \par<b>Related APIs:</b><BR>
729 * XMC_USBH_PipeModify(), XMC_USBH_PipeDelete(), XMC_USBH_PipeReset(), XMC_USBH_PipeTransfer() \n
730 */
XMC_USBH_PipeCreate(uint8_t dev_addr,uint8_t dev_speed,uint8_t hub_addr,uint8_t hub_port,uint8_t ep_addr,uint8_t ep_type,uint16_t ep_max_packet_size,uint8_t ep_interval)731 static XMC_USBH_PIPE_HANDLE XMC_USBH_PipeCreate (uint8_t dev_addr, uint8_t dev_speed, uint8_t hub_addr, uint8_t hub_port, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_max_packet_size, uint8_t ep_interval) {
732 XMC_USBH0_pipe_t *ptr_pipe;
733 USB0_CH_TypeDef *ptr_ch;
734 uint32_t i;
735 uint32_t loc_val;
736
737 XMC_UNUSED_ARG(hub_addr);
738 XMC_UNUSED_ARG(hub_port);
739 XMC_UNUSED_ARG(dev_speed);
740
741 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
742 {
743 ptr_ch = (USB0_CH_TypeDef *)NULL;
744 }
745 else
746 {
747 /* get first free pipe available */
748 ptr_ch = (USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers);
749
750 for (i = 0U; i < USBH0_MAX_PIPE_NUM; i++) {
751 if ((ptr_ch->HCCHAR & 0x3FFFFFFFU) == 0U)
752 {
753 break;
754 }
755 ptr_ch++;
756 }
757
758 /* free pipe found? */
759 if (i == USBH0_MAX_PIPE_NUM)
760 {
761 ptr_ch = (USB0_CH_TypeDef *)NULL;
762 }
763 else
764 {
765 ptr_pipe = (XMC_USBH0_pipe_t *)(&pipe[(ptr_ch - (USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers))]);
766
767 memset((void *)ptr_pipe, 0, sizeof(XMC_USBH0_pipe_t)); /* Initialize pipe structure */
768
769 /* Fill in all fields of Endpoint Descriptor */
770 /*Get the end point direction from the MSB of address*/
771 loc_val = 0U;
772 if (((ep_addr >> 7U) & 0x1U) == 0U)
773 {
774 loc_val = 1U;
775 }
776 ptr_ch->HCCHAR = ((uint32_t)(USB_CH_HCCHARx_MPS(ep_max_packet_size))|
777 USB_CH_HCCHARx_EPNUM(ep_addr)) |
778 (uint32_t)(USB_CH_HCCHAR_EPDir_Msk * loc_val) |
779 (USB_CH_HCCHARx_EPTYPE (ep_type) ) |
780 (USB_CH_HCCHARx_DEVADDR (dev_addr) ) ;
781 /* Store Pipe settings */
782 ptr_pipe->ep_max_packet_size = ep_max_packet_size;
783 ptr_pipe->ep_type = ep_type;
784 switch (ep_type) {
785 case XMC_USBH_ENDPOINT_CONTROL:
786 case XMC_USBH_ENDPOINT_BULK:
787 break;
788 case XMC_USBH_ENDPOINT_ISOCHRONOUS:
789 case XMC_USBH_ENDPOINT_INTERRUPT:
790 if (ep_interval > 0U) {
791 ptr_pipe->interval_reload = ep_interval;
792 }
793 ptr_pipe->interval = ptr_pipe->interval_reload;
794 loc_val = ((((uint32_t)ep_max_packet_size >> 11U) + 1U) & 3U);
795 ptr_ch->HCCHAR |= (uint32_t)USB_CH_HCCHARx_MCEC(loc_val);
796 break;
797 default:
798 break;
799 }
800 }
801 }
802 return ((XMC_USBH_EP_HANDLE)ptr_ch);
803 }
804
805 /**
806 * @param pipe_hndl Pointer returned by the pipe create function. It is the hardware based address of a USB channel.
807 * @param dev_addr Device address to be configured for the pipe.
808 * @param dev_speed Device speed class.
809 * @param hub_addr Hub address. It should be 0 since hub is not supported.
810 * @param hub_port USB port number. Only one port(0) is supported.
811 * @param ep_max_packet_size Endpoint maximum packet size
812 * @return Execution_status
813 *
814 * \par<b>Description:</b><br>
815 * Modify an existing pipe with input parameters. It can be used to configure the pipe after receiving configuration details from the device.
816 *
817 * \par<b>Related APIs:</b><BR>
818 * XMC_USBH_PipeCreate(), XMC_USBH_PipeDelete(), XMC_USBH_PipeReset(), XMC_USBH_PipeTransfer() \n
819 */
XMC_USBH_PipeModify(XMC_USBH_PIPE_HANDLE pipe_hndl,uint8_t dev_addr,uint8_t dev_speed,uint8_t hub_addr,uint8_t hub_port,uint16_t ep_max_packet_size)820 static int32_t XMC_USBH_PipeModify (XMC_USBH_PIPE_HANDLE pipe_hndl, uint8_t dev_addr, uint8_t dev_speed, uint8_t hub_addr, uint8_t hub_port, uint16_t ep_max_packet_size) {
821 XMC_USBH0_pipe_t *ptr_pipe;
822 USB0_CH_TypeDef *ptr_ch;
823 uint32_t hcchar;
824 int32_t status = XMC_USBH_DRIVER_OK;
825
826 XMC_UNUSED_ARG(hub_addr);
827 XMC_UNUSED_ARG(hub_port);
828 XMC_UNUSED_ARG(dev_speed);
829
830 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
831 {
832 status = XMC_USBH_DRIVER_ERROR;
833 }
834 else
835 {
836 if (pipe_hndl == 0U)
837 {
838 status = XMC_USBH_DRIVER_ERROR_PARAMETER;
839 }
840 else
841 {
842 ptr_ch = (USB0_CH_TypeDef *)(pipe_hndl);
843 ptr_pipe = (XMC_USBH0_pipe_t *)(&pipe[(ptr_ch - (USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers))]);
844 if (ptr_pipe->in_use != 0U)
845 {
846 status = XMC_USBH_DRIVER_ERROR_BUSY;
847 }
848 else
849 {
850 /* Fill in all fields of channel */
851 hcchar = ptr_ch->HCCHAR;
852 /* Clear fields */
853 hcchar &= (uint32_t)~(USB_CH_HCCHAR_MPS_Msk | USB_CH_HCCHAR_DevAddr_Msk) ;
854 /* Set fields */
855 hcchar |= (uint32_t)(USB_CH_HCCHARx_MPS(ep_max_packet_size) | (USB_CH_HCCHARx_DEVADDR(dev_addr)));
856 ptr_ch->HCCHAR = hcchar;
857
858 ptr_pipe->ep_max_packet_size = ep_max_packet_size;
859 }
860 }
861 }
862
863 return status;
864 }
865
866 /**
867 * @param pipe_hndl Pointer returned by the pipe create function. It is the hardware based address of a USB channel.
868 * @return Execution_status
869 *
870 * \par<b>Description:</b><br>
871 * Delete pipe from active pipes list. After it is deleted, it can be assigned to new pipe request.
872 *
873 * \par<b>Related APIs:</b><BR>
874 * XMC_USBH_PipeCreate(), XMC_USBH_PipeModify(), XMC_USBH_PipeReset(), XMC_USBH_PipeTransfer() \n
875 */
XMC_USBH_PipeDelete(XMC_USBH_PIPE_HANDLE pipe_hndl)876 static int32_t XMC_USBH_PipeDelete (XMC_USBH_PIPE_HANDLE pipe_hndl) {
877 XMC_USBH0_pipe_t *ptr_pipe;
878 USB0_CH_TypeDef *ptr_ch;
879 int32_t status = XMC_USBH_DRIVER_OK;
880
881 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
882 {
883 status = XMC_USBH_DRIVER_ERROR;
884 }
885 else
886 {
887 if (pipe_hndl == 0U)
888 {
889 status = XMC_USBH_DRIVER_ERROR_PARAMETER;
890 }
891 else
892 {
893 ptr_ch = (USB0_CH_TypeDef *)(pipe_hndl);
894 ptr_pipe = (XMC_USBH0_pipe_t *)(&pipe[(ptr_ch - (USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers))]);
895 if (ptr_pipe->in_use != 0U)
896 {
897 status = XMC_USBH_DRIVER_ERROR_BUSY;
898 }
899 else
900 {
901 ptr_ch->HCCHAR = 0U;
902 ptr_ch->HCINT = 0U;
903 ptr_ch->HCINTMSK = 0U;
904 ptr_ch->HCTSIZ_BUFFERMODE = 0U;
905
906 memset((void *)ptr_pipe, 0, sizeof(XMC_USBH0_pipe_t));
907 }
908 }
909 }
910
911 return status;
912 }
913
914 /**
915 * @param pipe_hndl Pointer returned by the pipe create function. It is the hardware based address of a USB channel.
916 * @return Execution_status
917 * \par<b>Description:</b><br>
918 * Reset pipe by clearing the interrupt mask and resetting the transfer control register.\n
919 *
920 * \par<b>Related APIs:</b><BR>
921 * XMC_USBH_PipeCreate(), XMC_USBH_PipeModify(), XMC_USBH_PipeDelete(), XMC_USBH_PipeTransfer() \n
922 */
XMC_USBH_PipeReset(XMC_USBH_PIPE_HANDLE pipe_hndl)923 static int32_t XMC_USBH_PipeReset (XMC_USBH_PIPE_HANDLE pipe_hndl) {
924 XMC_USBH0_pipe_t *ptr_pipe;
925 USB0_CH_TypeDef *ptr_ch;
926 int32_t status = XMC_USBH_DRIVER_OK;
927
928 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
929 {
930 status = XMC_USBH_DRIVER_ERROR;
931 }
932 else
933 {
934 if (pipe_hndl == 0U)
935 {
936 status = XMC_USBH_DRIVER_ERROR_PARAMETER;
937 }
938 else
939 {
940 ptr_ch = (USB0_CH_TypeDef *)(pipe_hndl);
941 ptr_pipe = (XMC_USBH0_pipe_t *)(&pipe[(ptr_ch - (USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers))]);
942 if (ptr_pipe->in_use != 0U)
943 {
944 status = XMC_USBH_DRIVER_ERROR_BUSY;
945 }
946 else
947 {
948 ptr_ch->HCINT = 0U;
949 ptr_ch->HCINTMSK = 0U;
950 ptr_ch->HCTSIZ_BUFFERMODE = 0U;
951 }
952 }
953 }
954 return status;
955 }
956
957 /**
958 * @param pipe_hndl Pointer returned by the pipe create function. It is the hardware based address of a USB channel.
959 * @param packet Packet information with bit masks to represent packet data toggle information and packet type.\n
960 * \ref XMC_USBH_PACKET_DATA0 / \ref XMC_USBH_PACKET_DATA1, \ref XMC_USBH_PACKET_SETUP /
961 * \ref XMC_USBH_PACKET_OUT / \ref XMC_USBH_PACKET_IN
962 * @param data Pointer to buffer with data to send or for received data to be stored.
963 * @param num Number of data bytes to transfer
964 * @return Execution_status
965 *
966 * \par<b>Description:</b><BR>
967 * Transfer packets through USB Pipe. Handles transfer of multiple packets using the pipe transfer complete event.
968 * The pipe event callback function will be called when the transfer is completed.\n
969 *
970 * \par<b>Related APIs:</b><BR>
971 * XMC_USBH_PipeCreate(), XMC_USBH_PipeModify(), XMC_USBH_PipeDelete(), XMC_USBH_PipeReset() \n
972 */
XMC_USBH_PipeTransfer(XMC_USBH_PIPE_HANDLE pipe_hndl,uint32_t packet,uint8_t * data,uint32_t num)973 static int32_t XMC_USBH_PipeTransfer (XMC_USBH_PIPE_HANDLE pipe_hndl, uint32_t packet, uint8_t *data, uint32_t num) {
974 XMC_USBH0_pipe_t *ptr_pipe;
975 int32_t status = XMC_USBH_DRIVER_OK;
976
977 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
978 {
979 status = XMC_USBH_DRIVER_ERROR;
980 }
981 else
982 {
983
984 if(!(((((packet & XMC_USBH_PACKET_TOKEN_Msk) == XMC_USBH_PACKET_OUT) ||
985 ((packet & XMC_USBH_PACKET_TOKEN_Msk) == XMC_USBH_PACKET_IN))) ||
986 ((packet & XMC_USBH_PACKET_TOKEN_Msk) == XMC_USBH_PACKET_SETUP )))
987 {
988 status = XMC_USBH_DRIVER_ERROR_PARAMETER;
989 }
990 else
991 {
992 if (pipe_hndl == 0U)
993 {
994 status = XMC_USBH_DRIVER_ERROR_PARAMETER;
995 }
996 else
997 {
998 if ((XMC_USBH0_device.global_register->HPRT & USB_HPRT_PrtConnSts_Msk) == 0U)
999 {
1000 status = XMC_USBH_DRIVER_ERROR;
1001 }
1002 else
1003 {
1004 ptr_pipe = (XMC_USBH0_pipe_t *)(&pipe[((USB0_CH_TypeDef *)pipe_hndl - (USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers))]);
1005 if (ptr_pipe->in_use != 0U)
1006 {
1007 status = XMC_USBH_DRIVER_ERROR_BUSY;
1008 }
1009 else
1010 {
1011 /* Prepare transfer information */
1012 ptr_pipe->packet = packet;
1013 ptr_pipe->data = data;
1014 ptr_pipe->num = num;
1015 ptr_pipe->num_transferred_total = 0U;
1016 ptr_pipe->num_transferring = 0U;
1017 ptr_pipe->in_use = 0U;
1018 ptr_pipe->transfer_active = 0U;
1019 ptr_pipe->interrupt_triggered = 0U;
1020 ptr_pipe->event = 0U;
1021
1022 if ((ptr_pipe->ep_type == (uint8_t)XMC_USBH_ENDPOINT_INTERRUPT) && (ptr_pipe->interval != 0U)) {
1023 ptr_pipe->in_use = 1U; /* transfer will be started inside interrupt (SOF) */
1024 } else {
1025 ptr_pipe->transfer_active = 1U;
1026 ptr_pipe->in_use = 1U;
1027 if(XMC_lStartTransfer (ptr_pipe, (USB0_CH_TypeDef *)pipe_hndl) == false)
1028 {
1029 status = XMC_USBH_DRIVER_ERROR;
1030 }
1031 }
1032 }
1033 }
1034 }
1035 }
1036 }
1037 return status;
1038 }
1039
1040 /**
1041 * @param pipe_hndl Pointer returned by the pipe create function. It is the hardware based address of a USB channel.
1042 * @return uint32_t Number of successfully transferred data bytes
1043 *
1044 * \par<b>Description:</b><BR>
1045 * Get result of USB Pipe transfer.
1046 *
1047 * \par<b>Related APIs:</b><BR>
1048 * XMC_USBH_PipeCreate(), XMC_USBH_PipeModify(), XMC_USBH_PipeDelete(), XMC_USBH_PipeTransfer() \n
1049 */
XMC_USBH_PipeTransferGetResult(XMC_USBH_PIPE_HANDLE pipe_hndl)1050 static uint32_t XMC_USBH_PipeTransferGetResult (XMC_USBH_PIPE_HANDLE pipe_hndl) {
1051 uint32_t status;
1052 if (pipe_hndl == 0U)
1053 {
1054 status = 0U;
1055 }
1056 else
1057 {
1058 status = (pipe[((USB0_CH_TypeDef *)pipe_hndl - (USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers))].num_transferred_total);
1059 }
1060 return status;
1061 }
1062
1063 /**
1064 * @param pipe_hndl Pointer returned by the pipe create function. It is the hardware based address of a USB channel.
1065 * @return Execution_status
1066 *
1067 * \par<b>Description:</b><BR>
1068 * Abort current USB Pipe transfer.\n
1069 *
1070 * \par<b>Related APIs:</b><BR>
1071 * XMC_USBH_PipeCreate(), XMC_USBH_PipeModify(), XMC_USBH_PipeDelete(), XMC_USBH_PipeTransfer() \n
1072 */
XMC_USBH_PipeTransferAbort(XMC_USBH_PIPE_HANDLE pipe_hndl)1073 static int32_t XMC_USBH_PipeTransferAbort (XMC_USBH_PIPE_HANDLE pipe_hndl) {
1074 XMC_USBH0_pipe_t *ptr_pipe;
1075 USB0_CH_TypeDef *ptr_ch;
1076 uint32_t timeout;
1077 int32_t status = XMC_USBH_DRIVER_ERROR;
1078
1079 ptr_ch = (USB0_CH_TypeDef *) pipe_hndl;
1080
1081 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
1082 {
1083 /*Error in power state*/
1084 }
1085 else
1086 {
1087 if (pipe_hndl == 0U)
1088 {
1089 status = XMC_USBH_DRIVER_ERROR_PARAMETER;
1090 }
1091 else
1092 {
1093 ptr_pipe = (XMC_USBH0_pipe_t *)(&pipe[(ptr_ch - (USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers))]);
1094
1095 if (ptr_pipe->in_use != 0U) {
1096 ptr_pipe->in_use = 0U;
1097 /* Disable channel if not yet halted */
1098 if ((ptr_ch->HCINT & USB_CH_HCINT_ChHltd_Msk) == 0U)
1099 {
1100 if (ptr_ch->HCCHAR & USB_CH_HCCHAR_ChEna_Msk)
1101 {
1102 ptr_ch->HCINTMSK = 0U;
1103 (void)XMC_USBH_osDelay(1U);
1104 if (ptr_ch->HCINT & USB_CH_HCINT_NAK_Msk) {
1105 ptr_ch->HCINT = USB_CH_HCINTx_ALL; /* Clear all interrupts */
1106 status = XMC_USBH_DRIVER_OK;
1107 }
1108 else
1109 {
1110 ptr_ch->HCINT = USB_CH_HCINTx_ALL; /* Clear all interrupts */
1111 ptr_ch->HCCHAR = (uint32_t)(ptr_ch->HCCHAR | USB_CH_HCCHAR_ChEna_Msk | USB_CH_HCCHAR_ChDis_Msk);
1112
1113 /* wait until channel is halted */
1114 for (timeout = 0U; timeout < 5000U; timeout++) {
1115 if (ptr_ch->HCINT & USB_CH_HCINT_ChHltd_Msk) {
1116 ptr_ch->HCINT = USB_CH_HCINTx_ALL;
1117 status = XMC_USBH_DRIVER_OK;
1118 }
1119 }
1120 }
1121 }
1122 }
1123 }
1124 }
1125 }
1126
1127 return status;
1128 }
1129
1130 /**
1131 * @return Frame number.
1132 *
1133 * \par<b>Description:</b><BR>
1134 * Get current USB Frame Number.
1135 */
XMC_USBH_GetFrameNumber(void)1136 static uint16_t XMC_USBH_GetFrameNumber (void)
1137 {
1138 uint16_t status;
1139
1140 if (XMC_USBH0_device.power_state == XMC_USBH_POWER_OFF)
1141 {
1142 status = 0U;
1143 }
1144 else
1145 {
1146 status = (uint16_t)((XMC_USBH0_device.global_register->HFNUM) & 0xFFFU);
1147 }
1148 return status;
1149 }
1150
1151 /**
1152 * @param gintsts USB port interrupt status flag.
1153 *
1154 * \par<b>Description:</b><BR>
1155 * USB host interrupt handler. It updates port and pipe state information based on different events
1156 * generated by the peripheral. It propagates the port events to the callback function registered by the user
1157 * during initialization. When a pipe transfer complete event is detected, it checks if any further data is available
1158 * to be transmitted on the same pipe and continues transmission until data is available. A pipe event is also propagated
1159 * to the user provided pipe event callback function. A transfer complete event will be propagated only when all the data
1160 * is transmitted for an OUT transaction.
1161 *
1162 */
XMC_USBH_HandleIrq(uint32_t gintsts)1163 void XMC_USBH_HandleIrq (uint32_t gintsts) {
1164 XMC_USBH0_pipe_t *ptr_pipe;
1165 USB0_CH_TypeDef *ptr_ch;
1166 uint32_t hprt, haint, hcint, pktcnt, mpsiz;
1167 uint32_t ch;
1168 uint8_t *ptr_data;
1169 uint32_t *dfifo;
1170 uint32_t grxsts, bcnt, dat, len, len_rest;
1171
1172 /* Host port interrupt */
1173 if ((gintsts & USB_GINTSTS_HOSTMODE_PrtInt_Msk) != 0U) {
1174 hprt = XMC_USBH0_device.global_register->HPRT;
1175 /* Clear port enable */
1176 XMC_USBH0_device.global_register->HPRT = hprt & (uint32_t)(~USB_HPRT_PrtEna_Msk);
1177 if ((hprt & USB_HPRT_PrtConnDet_Msk) != 0U) {
1178 XMC_USBH0_device.global_register->HCFG = (0x200U | (USB_CH_HCFG_FSLSPCS(1) |
1179 USB_CH_HCFG_FSLSSUP(1)));
1180 /* Ignore connect under reset */
1181 if (XMC_USBH0_device.port_reset_active == false) {
1182 XMC_USBH0_device.SignalPortEvent_cb(0U, XMC_USBH_EVENT_CONNECT);
1183 }
1184 }
1185 if ((hprt & USB_HPRT_PrtEnChng_Msk) != 0U) { /* If port enable changed */
1186 if ((hprt & USB_HPRT_PrtEna_Msk) != 0U) { /* If device connected */
1187 if (XMC_USBH0_device.port_reset_active == true) {
1188 XMC_USBH0_device.port_reset_active = false;
1189 XMC_USBH0_device.SignalPortEvent_cb(0U, XMC_USBH_EVENT_RESET);
1190 }
1191 }
1192 }
1193 }
1194
1195 /* Disconnect interrupt */
1196 if ((gintsts & USB_GINTSTS_HOSTMODE_DisconnInt_Msk) != 0U) {
1197 XMC_USBH0_device.global_register->GINTSTS_HOSTMODE = USB_GINTSTS_HOSTMODE_DisconnInt_Msk; /* Clear disconnect interrupt */
1198 /* Ignore disconnect under reset */
1199 if ( XMC_USBH0_device.port_reset_active == false) {
1200 ptr_ch = (USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers);
1201 ptr_pipe = (XMC_USBH0_pipe_t *)(pipe);
1202 for (ch = 0U; ch < USBH0_MAX_PIPE_NUM; ch++) {
1203 if (ptr_pipe->in_use != 0U) {
1204 ptr_pipe->in_use = 0U;
1205 ptr_ch->HCINT = USB_CH_HCINTx_ALL; /* Clear all interrupts */
1206 ptr_ch->HCINTMSK = USB_CH_HCINT_ChHltd_Msk; /* Enable halt interrupt */
1207 ptr_ch->HCCHAR |= (uint32_t)(USB_CH_HCCHAR_ChEna_Msk | USB_CH_HCCHAR_ChDis_Msk); /* Activate Halt */
1208 XMC_USBH0_device.SignalPipeEvent_cb((XMC_USBH_EP_HANDLE)ptr_ch, XMC_USBH_EVENT_BUS_ERROR);
1209 }
1210 ptr_ch++;
1211 ptr_pipe++;
1212 }
1213 XMC_USBH0_device.SignalPortEvent_cb(0U, XMC_USBH_EVENT_DISCONNECT);
1214 }
1215 }
1216 /* Handle receive fifo not-empty interrupt */
1217 if ((gintsts & USB_GINTSTS_HOSTMODE_RxFLvl_Msk) != 0U) {
1218 XMC_USBH0_device.global_register->GINTMSK_HOSTMODE &= (uint32_t)~USB_GINTMSK_HOSTMODE_RxFLvlMsk_Msk;
1219 grxsts = (XMC_USBH0_device.global_register->GRXSTSP_HOSTMODE);
1220 /* IN Data Packet received ? */
1221 if ((uint32_t)((grxsts >> 17U) & 0x0FU) == (uint32_t)USB_GRXSTSR_HOSTMODE_PktSts_IN_DATA_PKT) {
1222 ch = (uint32_t)(grxsts & USB_GRXSTSR_DEVICEMODE_EPNum_Msk);
1223 bcnt = ((uint32_t)(grxsts & USB_GRXSTSR_DEVICEMODE_BCnt_Msk) >> USB_GRXSTSR_DEVICEMODE_BCnt_Pos);
1224 dfifo = (uint32_t *)XMC_USBH0_dfifo_ptr[ch];
1225 ptr_data = pipe[ch].data + pipe[ch].num_transferred_total;
1226 len = bcnt / 4U; /* Received number of 32-bit data */
1227 len_rest = bcnt & 3U; /* Number of bytes left */
1228 /* Read data from fifo */
1229 /* Read 32 bit sized data */
1230 while (len != 0U) {
1231 #if defined __TASKING__/*tasking*/
1232 *((__unaligned uint32_t *)ptr_data) = *dfifo;
1233 #else /* defined (__GNUC__) || defined (__CC_ARM) || defined (__ICCARM__)*/
1234 *((__packed uint32_t *)ptr_data) = *dfifo;
1235 #endif
1236
1237 ptr_data += 4U;
1238 len--;
1239 }
1240 /* Read 8 bit sized data */
1241 if (len_rest != 0U) {
1242 #if defined __TASKING__/*tasking*/
1243 dat = *((__unaligned uint32_t *)dfifo);
1244 #else /* defined (__GNUC__) || defined (__CC_ARM) || defined (__ICCARM__)*/
1245 dat = *((__packed uint32_t *)dfifo);
1246 #endif
1247 while (len_rest != 0U) {
1248 *ptr_data = (uint8_t)dat;
1249 ptr_data++;
1250 dat >>= 8;
1251 len_rest--;
1252 }
1253 }
1254 pipe[ch].num_transferring += bcnt;
1255 pipe[ch].num_transferred_total += bcnt;
1256 }
1257 XMC_USBH0_device.global_register->GINTMSK_HOSTMODE |= (uint32_t)USB_GINTMSK_HOSTMODE_RxFLvlMsk_Msk;
1258 }
1259
1260 /* Handle sof interrupt */
1261 if ((gintsts & USB_GINTSTS_HOSTMODE_Sof_Msk) != 0U) { /* If start of frame interrupt */
1262 XMC_USBH0_device.global_register->GINTSTS_HOSTMODE = USB_GINTSTS_HOSTMODE_Sof_Msk; /* Clear SOF interrupt */
1263 ptr_pipe = (XMC_USBH0_pipe_t *)(pipe);
1264 for (ch = 0U; ch < USBH0_MAX_PIPE_NUM; ch++) {
1265 /* If interrupt transfer is active handle period (interval) */
1266 if ((ptr_pipe->ep_type == (uint8_t)XMC_USBH_ENDPOINT_INTERRUPT) && (ptr_pipe->in_use == 1U)) {
1267 if (ptr_pipe->interval != 0U)
1268 {
1269 ptr_pipe->interval--;
1270 if (ptr_pipe->interval == 0U)
1271 {
1272 ptr_pipe->interval = ptr_pipe->interval_reload;
1273 ptr_pipe->interrupt_triggered = 1U;
1274 }
1275 }
1276 }
1277 ptr_pipe++;
1278 }
1279 }
1280
1281 /* Handle host ctrl interrupt */
1282 if ((gintsts & USB_GINTSTS_HOSTMODE_HChInt_Msk) != 0U) {
1283 haint = XMC_USBH0_device.global_register->HAINT;
1284 for (ch = 0U; ch < USBH0_MAX_PIPE_NUM; ch++) {
1285 /* Check for interrupt of all channels */
1286 if ((haint & (uint32_t)((uint32_t)1U << ch)) != 0U) {
1287 haint &= (uint32_t)~((uint32_t)1U << ch);
1288 ptr_ch = (USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers) + ch;
1289 ptr_pipe = (XMC_USBH0_pipe_t *)(&pipe[ch]);
1290 /*Local variable for HCINT*/
1291 dat = ptr_ch->HCINT;
1292 hcint = (uint32_t)(dat & ptr_ch->HCINTMSK);
1293 if ((hcint & USB_CH_HCINT_ChHltd_Msk) != 0U) { /* channel halted ? */
1294 ptr_ch->HCINTMSK = 0U; /* disable all channel interrupts */
1295 ptr_ch->HCINT = USB_CH_HCINTx_ALL; /* clear all interrupts */
1296 ptr_pipe->transfer_active = 0U; /* set status transfer not active */
1297 hcint = 0U;
1298 }
1299 if ((hcint & USB_CH_HCINT_XferCompl_Msk) != 0U) { /* data transfer finished ? */
1300 ptr_ch->HCINT = USB_CH_HCINTx_ALL; /* clear all interrupts */
1301 if ((ptr_ch->HCCHAR & USB_CH_HCCHAR_EPDir_Msk) == 0U) { /* endpoint OUT ? */
1302 ptr_ch->HCINTMSK = 0U; /* disable all channel interrupts */
1303 ptr_pipe->transfer_active = 0U; /* transfer not in progress */
1304 ptr_pipe->num_transferred_total += ptr_pipe->num_transferring; /* admin OUT transfer status */
1305 ptr_pipe->num_transferring = 0U; /* admin OUT transfer status */
1306 if (ptr_pipe->num_transferred_total == ptr_pipe->num) { /* all bytes transferred ? */
1307 ptr_pipe->in_use = 0U; /* release pipe */
1308 ptr_pipe->event = (uint8_t)XMC_USBH_EVENT_TRANSFER_COMPLETE; /* prepare event notification */
1309 }
1310 hcint = 0U;
1311 }
1312 if ((ptr_ch->HCCHAR & USB_CH_HCCHAR_EPDir_Msk) != 0U) { /* endpoint IN ? */
1313 ptr_pipe->in_use = 0U; /* release pipe */
1314 ptr_pipe->event = (uint8_t)XMC_USBH_EVENT_TRANSFER_COMPLETE; /* prepare event notification */
1315 XMC_lTriggerHaltChannel(ptr_ch); /* trigger channel halt */
1316 }
1317 }
1318 if ((hcint & USB_CH_HCINTMSK_AckMsk_Msk) != 0U) { /* ACK received ? */
1319 ptr_ch->HCINT = USB_CH_HCINTMSK_AckMsk_Msk; /* clear ACK interrupt */
1320 is_nack[ch] = false;
1321 if ((ptr_ch->HCCHAR & USB_CH_HCCHAR_EPDir_Msk) != 0U) { /* endpoint IN ? */
1322 if ((ptr_pipe->num != ptr_pipe->num_transferred_total) && /* if all data was not transferred */
1323 (ptr_pipe->num_transferring != 0U) && /* if zero-length packet was not received */
1324 ((ptr_pipe->num_transferred_total%ptr_pipe->ep_max_packet_size) == 0U)){ /* if short packet was not received */
1325 ptr_ch->HCCHAR |= (uint32_t)USB_CH_HCCHAR_ChEna_Msk; /* trigger next transfer */
1326 }
1327 } else { /* endpoint OUT */
1328 XMC_lTriggerHaltChannel(ptr_ch); /* trigger channel halt */
1329 }
1330 hcint = 0U;
1331 }
1332 /*local variable for HCCHAR*/
1333 dat = ptr_ch->HCCHAR;
1334 if (((hcint & (USB_CH_HCINTMSK_StallMsk_Msk | /* STALL */
1335 USB_CH_HCINTMSK_NakMsk_Msk | /* or NAK */
1336 USB_CH_HCINTx_ERRORS )) != 0U) && /* or transaction error */
1337 ((dat & USB_CH_HCCHAR_EPDir_Msk) == 0U))
1338 { /* and endpoint OUT */
1339
1340 pktcnt = (uint32_t)((ptr_ch->HCTSIZ_BUFFERMODE & USB_CH_HCTSIZ_BUFFERMODE_PktCnt_Msk) /* administrate OUT transfer status */
1341 >> USB_CH_HCTSIZ_BUFFERMODE_PktCnt_Pos);
1342 mpsiz = (ptr_ch->HCCHAR ) & 0x000007FFU;
1343 if ((ptr_pipe->num_transferring >= mpsiz) && (pktcnt > 0U)) {
1344 ptr_pipe->num_transferred_total += (uint32_t)(ptr_pipe->num_transferring - (mpsiz * pktcnt));
1345 }
1346 ptr_pipe->num_transferring = 0U;
1347 }
1348
1349 if ((hcint & USB_CH_HCINTMSK_NakMsk_Msk)!=0U) { /* if NAK */
1350 is_nack[ch] = true;
1351 ptr_pipe->event |= (uint8_t)XMC_USBH_EVENT_HANDSHAKE_NAK;
1352 ptr_ch->HCINT = USB_CH_HCINTMSK_NakMsk_Msk; /* clear NAK interrupt */
1353 if ((ptr_ch->HCCHAR & USB_CH_HCCHAR_EPDir_Msk) != 0U) { /* endpoint IN ? */
1354 if (ptr_pipe->ep_type == (uint8_t)XMC_USBH_ENDPOINT_INTERRUPT) { /* is endpoint of type interrupt ? */
1355 XMC_lTriggerHaltChannel(ptr_ch); /* trigger channel halt (after halted will be restarted in next sof) */
1356 } else { /* is endpoint not of type interrupt ?*/
1357 ptr_ch->HCCHAR |= (uint32_t)USB_CH_HCCHAR_ChEna_Msk; /* trigger next transfer */
1358 }
1359 } else { /* If endpoint OUT */ /* endpoint OUT ? */
1360 XMC_lTriggerHaltChannel(ptr_ch); /* trigger channel halt */
1361 }
1362 hcint = 0U;
1363 }
1364
1365 if ((hcint & USB_CH_HCINTMSK_StallMsk_Msk) != 0U) { /* if STALL */
1366 /*Reset the packet data toggle*/
1367 ptr_ch->HCINT = USB_CH_HCINTMSK_StallMsk_Msk; /* clear STALL interrupt */
1368 ptr_pipe->in_use = 0U; /* release pipe */
1369 ptr_pipe->packet &= (uint32_t)(~XMC_USBH_PACKET_DATA_Msk);
1370 ptr_pipe->packet |= (uint32_t)XMC_USBH_PACKET_DATA0;
1371 ptr_pipe->event = (uint8_t)XMC_USBH_EVENT_HANDSHAKE_STALL; /* prepare event notification */
1372 XMC_lTriggerHaltChannel(ptr_ch); /* trigger channel halt */
1373 hcint = 0U;
1374 }
1375 if ((hcint & USB_CH_HCINTx_ERRORS) != 0U) { /* if transaction error */
1376 ptr_ch->HCINT = USB_CH_HCINTx_ERRORS; /* clear all error interrupt */
1377 ptr_pipe->in_use = 0U; /* release pipe */
1378 ptr_pipe->event = (uint8_t)XMC_USBH_EVENT_BUS_ERROR; /* prepare event notification */
1379 XMC_lTriggerHaltChannel(ptr_ch); /* trigger channel halt */
1380 hcint = 0U;
1381 }
1382 if ((ptr_pipe->transfer_active == 0U) && (ptr_pipe->in_use == 0U) && (ptr_pipe->event != 0U)) {
1383 XMC_USBH0_device.SignalPipeEvent_cb((XMC_USBH_EP_HANDLE)ptr_ch, (uint32_t)ptr_pipe->event);
1384 ptr_pipe->event = 0U;
1385 }
1386 }
1387 }
1388 }
1389 /*Check if remote wakeup event detected*/
1390 if ((gintsts & USB_GINTSTS_HOSTMODE_WkUpInt_Msk) != 0U)
1391 {
1392 XMC_USBH0_device.global_register->GINTSTS_HOSTMODE = USB_GINTSTS_HOSTMODE_WkUpInt_Msk; /* Clear wakeup interrupt */
1393 /*Recover PHY clock*/
1394 XMC_USBH0_device.global_register->PCGCCTL = XMC_USBH_PHY_CLK_UNGATE;
1395 /*Callback function execution*/
1396 XMC_USBH0_device.SignalPortEvent_cb(0U, XMC_USBH_EVENT_REMOTE_WAKEUP);
1397 }
1398
1399 /* Handle restarts of unfinished transfers (due to NAK or ACK) */
1400 ptr_pipe = (XMC_USBH0_pipe_t *)(pipe);
1401 for (ch = 0U; ch < USBH0_MAX_PIPE_NUM; ch++) {
1402 if ((ptr_pipe->in_use == 1U) && (ptr_pipe->transfer_active == 0U)) {
1403 /* Restart periodic transfer if not in progress and interval expired */
1404 if (ptr_pipe->ep_type != (uint8_t)XMC_USBH_ENDPOINT_INTERRUPT)
1405 {
1406 /*Data toggle if NACK not received*/
1407 if (!is_nack[ch])
1408 {
1409 switch (ptr_pipe->packet & (uint32_t)XMC_USBH_PACKET_DATA_Msk)
1410 {
1411 case XMC_USBH_PACKET_DATA0:
1412 ptr_pipe->packet &= (uint32_t)~XMC_USBH_PACKET_DATA_Msk;
1413 ptr_pipe->packet |= (uint32_t)XMC_USBH_PACKET_DATA1;
1414 break;
1415 case XMC_USBH_PACKET_DATA1:
1416 ptr_pipe->packet &= (uint32_t)~XMC_USBH_PACKET_DATA_Msk;
1417 ptr_pipe->packet |= (uint32_t)XMC_USBH_PACKET_DATA0;
1418 break;
1419 default:
1420 break;
1421 }
1422 }
1423 else
1424 {
1425 is_nack[ch] = false;
1426 }
1427 }
1428 if (((ptr_pipe->ep_type == (uint8_t)XMC_USBH_ENDPOINT_INTERRUPT)&&(ptr_pipe->interrupt_triggered == 1U))||
1429 (ptr_pipe->ep_type != (uint8_t)XMC_USBH_ENDPOINT_INTERRUPT))
1430 {
1431 ptr_pipe->interrupt_triggered = 0U;
1432 ptr_pipe->transfer_active = 1U;
1433 (void)XMC_lStartTransfer (ptr_pipe, (((USB0_CH_TypeDef *)(XMC_USBH0_device.host_channel_registers)) + ch));
1434 }
1435 }
1436 ptr_pipe++;
1437 }
1438 }
1439
1440 /*Function provides host mode interrupt status*/
XMC_USBH_GetInterruptStatus(void)1441 uint32_t XMC_USBH_GetInterruptStatus(void)
1442 {
1443 return XMC_USBH0_device.global_register->GINTSTS_HOSTMODE;
1444 }
1445
1446 /*Function selects the port pin used as DRIVEVBUS*/
XMC_USBH_Select_VBUS(XMC_GPIO_PORT_t * port,uint32_t pin)1447 void XMC_USBH_Select_VBUS(XMC_GPIO_PORT_t* port, uint32_t pin)
1448 {
1449 VBUS_port = port;
1450 VBUS_pin = pin;
1451
1452 /*Configure the port pin alternate function*/
1453 XMC_GPIO_SetMode(VBUS_port, (uint8_t)VBUS_pin, XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT1);
1454 }
1455
1456 /*Function asserts the remote wakeup request by device by clearing the resume bit*/
XMC_USBH_TurnOffResumeBit(void)1457 void XMC_USBH_TurnOffResumeBit(void)
1458 {
1459 uint32_t hprt;
1460 /*Clear resume bit*/
1461 hprt = XMC_USBH0_device.global_register->HPRT;
1462 hprt &= (uint32_t)~(USB_HPRT_PrtEna_Msk);
1463 hprt &= (uint32_t)~((uint32_t)USB_HPRT_PrtRes_Msk);
1464 XMC_USBH0_device.global_register->HPRT = hprt;
1465 }
1466
1467
1468
1469 /*USB host driver assembling all the implementation into a single CMSIS compliant structure type*/
1470 XMC_USBH_DRIVER_t Driver_USBH0 = {
1471 XMC_USBH_GetVersion,
1472 XMC_USBH_GetCapabilities,
1473 XMC_USBH_Initialize,
1474 XMC_USBH_Uninitialize,
1475 XMC_USBH_PowerControl,
1476 XMC_USBH_PortVbusOnOff,
1477 XMC_USBH_PortReset,
1478 XMC_USBH_PortSuspend,
1479 XMC_USBH_PortResume,
1480 XMC_USBH_PortGetState,
1481 XMC_USBH_PipeCreate,
1482 XMC_USBH_PipeModify,
1483 XMC_USBH_PipeDelete,
1484 XMC_USBH_PipeReset,
1485 XMC_USBH_PipeTransfer,
1486 XMC_USBH_PipeTransferGetResult,
1487 XMC_USBH_PipeTransferAbort,
1488 XMC_USBH_GetFrameNumber
1489 };
1490
1491
1492 /*Weak definition of delay function*/
XMC_USBH_osDelay(uint32_t MS)1493 __WEAK uint8_t XMC_USBH_osDelay(uint32_t MS)
1494 {
1495 (void)MS;
1496 /*A precise time delay implementation for this function has to be provided*/
1497 while (1)
1498 {
1499 /*Wait*/
1500 }
1501 }
1502
1503 #endif
1504