38
|
1 /**
|
|
2 ******************************************************************************
|
|
3 * @file stm32f4xx_hal_hcd.c
|
|
4 * @author MCD Application Team
|
|
5 * @version V1.2.0
|
|
6 * @date 26-December-2014
|
|
7 * @brief HCD HAL module driver.
|
|
8 * This file provides firmware functions to manage the following
|
|
9 * functionalities of the USB Peripheral Controller:
|
|
10 * + Initialization and de-initialization functions
|
|
11 * + IO operation functions
|
|
12 * + Peripheral Control functions
|
|
13 * + Peripheral State functions
|
|
14 *
|
|
15 @verbatim
|
|
16 ==============================================================================
|
|
17 ##### How to use this driver #####
|
|
18 ==============================================================================
|
|
19 [..]
|
|
20 (#)Declare a HCD_HandleTypeDef handle structure, for example:
|
|
21 HCD_HandleTypeDef hhcd;
|
|
22
|
|
23 (#)Fill parameters of Init structure in HCD handle
|
|
24
|
|
25 (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
|
|
26
|
|
27 (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
|
|
28 (##) Enable the HCD/USB Low Level interface clock using the following macros
|
|
29 (+++) __OTGFS-OTG_CLK_ENABLE() or __OTGHS-OTG_CLK_ENABLE()
|
|
30 (+++) __OTGHSULPI_CLK_ENABLE() For High Speed Mode
|
|
31
|
|
32 (##) Initialize the related GPIO clocks
|
|
33 (##) Configure HCD pin-out
|
|
34 (##) Configure HCD NVIC interrupt
|
|
35
|
|
36 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
|
|
37 (##) hhcd.pData = phost;
|
|
38
|
|
39 (#)Enable HCD transmission and reception:
|
|
40 (##) HAL_HCD_Start();
|
|
41
|
|
42 @endverbatim
|
|
43 ******************************************************************************
|
|
44 * @attention
|
|
45 *
|
|
46 * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
|
|
47 *
|
|
48 * Redistribution and use in source and binary forms, with or without modification,
|
|
49 * are permitted provided that the following conditions are met:
|
|
50 * 1. Redistributions of source code must retain the above copyright notice,
|
|
51 * this list of conditions and the following disclaimer.
|
|
52 * 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
53 * this list of conditions and the following disclaimer in the documentation
|
|
54 * and/or other materials provided with the distribution.
|
|
55 * 3. Neither the name of STMicroelectronics nor the names of its contributors
|
|
56 * may be used to endorse or promote products derived from this software
|
|
57 * without specific prior written permission.
|
|
58 *
|
|
59 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
60 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
62 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
65 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
66 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
67 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
68 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
69 *
|
|
70 ******************************************************************************
|
|
71 */
|
|
72
|
|
73 /* Includes ------------------------------------------------------------------*/
|
|
74 #include "stm32f4xx_hal.h"
|
|
75
|
|
76 /** @addtogroup STM32F4xx_HAL_Driver
|
|
77 * @{
|
|
78 */
|
|
79
|
|
80 /** @addtogroup HCD
|
|
81 * @{
|
|
82 */
|
|
83
|
|
84 #ifdef HAL_HCD_MODULE_ENABLED
|
|
85
|
|
86 /* Private typedef -----------------------------------------------------------*/
|
|
87 /* Private define ------------------------------------------------------------*/
|
|
88 /* Private macro -------------------------------------------------------------*/
|
|
89 /* Private variables ---------------------------------------------------------*/
|
|
90 /* Private function ----------------------------------------------------------*/
|
|
91 /** @addtogroup HCD_Private_Functions
|
|
92 * @{
|
|
93 */
|
|
94 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
|
|
95 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
|
|
96 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
|
|
97 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
|
|
98 /**
|
|
99 * @}
|
|
100 */
|
|
101
|
|
102 /* Exported functions --------------------------------------------------------*/
|
|
103 /** @addtogroup HCD_Exported_Functions
|
|
104 * @{
|
|
105 */
|
|
106
|
|
107 /** @addtogroup HCD_Exported_Functions_Group1
|
|
108 * @brief Initialization and de-initialization functions
|
|
109 *
|
|
110 @verbatim
|
|
111 ===============================================================================
|
|
112 ##### Initialization and de-initialization functions #####
|
|
113 ===============================================================================
|
|
114 [..] This section provides functions allowing to:
|
|
115
|
|
116 @endverbatim
|
|
117 * @{
|
|
118 */
|
|
119
|
|
120 /**
|
|
121 * @brief Initialize the host driver
|
|
122 * @param hhcd: HCD handle
|
|
123 * @retval HAL status
|
|
124 */
|
|
125 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
|
|
126 {
|
|
127 /* Check the HCD handle allocation */
|
|
128 if(hhcd == NULL)
|
|
129 {
|
|
130 return HAL_ERROR;
|
|
131 }
|
|
132
|
|
133 /* Check the parameters */
|
|
134 assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
|
|
135
|
|
136 hhcd->State = HAL_HCD_STATE_BUSY;
|
|
137
|
|
138 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
|
|
139 HAL_HCD_MspInit(hhcd);
|
|
140
|
|
141 /* Disable the Interrupts */
|
|
142 __HAL_HCD_DISABLE(hhcd);
|
|
143
|
|
144 /* Init the Core (common init.) */
|
|
145 USB_CoreInit(hhcd->Instance, hhcd->Init);
|
|
146
|
|
147 /* Force Host Mode*/
|
|
148 USB_SetCurrentMode(hhcd->Instance , USB_OTG_HOST_MODE);
|
|
149
|
|
150 /* Init Host */
|
|
151 USB_HostInit(hhcd->Instance, hhcd->Init);
|
|
152
|
|
153 hhcd->State= HAL_HCD_STATE_READY;
|
|
154
|
|
155 return HAL_OK;
|
|
156 }
|
|
157
|
|
158 /**
|
|
159 * @brief Initialize a host channel
|
|
160 * @param hhcd: HCD handle
|
|
161 * @param ch_num: Channel number.
|
|
162 * This parameter can be a value from 1 to 15
|
|
163 * @param epnum: Endpoint number.
|
|
164 * This parameter can be a value from 1 to 15
|
|
165 * @param dev_address : Current device address
|
|
166 * This parameter can be a value from 0 to 255
|
|
167 * @param speed: Current device speed.
|
|
168 * This parameter can be one of these values:
|
|
169 * HCD_SPEED_HIGH: High speed mode,
|
|
170 * HCD_SPEED_FULL: Full speed mode,
|
|
171 * HCD_SPEED_LOW: Low speed mode
|
|
172 * @param ep_type: Endpoint Type.
|
|
173 * This parameter can be one of these values:
|
|
174 * EP_TYPE_CTRL: Control type,
|
|
175 * EP_TYPE_ISOC: Isochronous type,
|
|
176 * EP_TYPE_BULK: Bulk type,
|
|
177 * EP_TYPE_INTR: Interrupt type
|
|
178 * @param mps: Max Packet Size.
|
|
179 * This parameter can be a value from 0 to32K
|
|
180 * @retval HAL status
|
|
181 */
|
|
182 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd,
|
|
183 uint8_t ch_num,
|
|
184 uint8_t epnum,
|
|
185 uint8_t dev_address,
|
|
186 uint8_t speed,
|
|
187 uint8_t ep_type,
|
|
188 uint16_t mps)
|
|
189 {
|
|
190 HAL_StatusTypeDef status = HAL_OK;
|
|
191
|
|
192 __HAL_LOCK(hhcd);
|
|
193
|
|
194 hhcd->hc[ch_num].dev_addr = dev_address;
|
|
195 hhcd->hc[ch_num].max_packet = mps;
|
|
196 hhcd->hc[ch_num].ch_num = ch_num;
|
|
197 hhcd->hc[ch_num].ep_type = ep_type;
|
|
198 hhcd->hc[ch_num].ep_num = epnum & 0x7F;
|
|
199 hhcd->hc[ch_num].ep_is_in = ((epnum & 0x80) == 0x80);
|
|
200 hhcd->hc[ch_num].speed = speed;
|
|
201
|
|
202 status = USB_HC_Init(hhcd->Instance,
|
|
203 ch_num,
|
|
204 epnum,
|
|
205 dev_address,
|
|
206 speed,
|
|
207 ep_type,
|
|
208 mps);
|
|
209 __HAL_UNLOCK(hhcd);
|
|
210
|
|
211 return status;
|
|
212 }
|
|
213
|
|
214 /**
|
|
215 * @brief Halt a host channel
|
|
216 * @param hhcd: HCD handle
|
|
217 * @param ch_num: Channel number.
|
|
218 * This parameter can be a value from 1 to 15
|
|
219 * @retval HAL status
|
|
220 */
|
|
221 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
|
|
222 {
|
|
223 HAL_StatusTypeDef status = HAL_OK;
|
|
224
|
|
225 __HAL_LOCK(hhcd);
|
|
226 USB_HC_Halt(hhcd->Instance, ch_num);
|
|
227 __HAL_UNLOCK(hhcd);
|
|
228
|
|
229 return status;
|
|
230 }
|
|
231
|
|
232 /**
|
|
233 * @brief DeInitialize the host driver
|
|
234 * @param hhcd: HCD handle
|
|
235 * @retval HAL status
|
|
236 */
|
|
237 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
|
|
238 {
|
|
239 /* Check the HCD handle allocation */
|
|
240 if(hhcd == NULL)
|
|
241 {
|
|
242 return HAL_ERROR;
|
|
243 }
|
|
244
|
|
245 hhcd->State = HAL_HCD_STATE_BUSY;
|
|
246
|
|
247 /* DeInit the low level hardware */
|
|
248 HAL_HCD_MspDeInit(hhcd);
|
|
249
|
|
250 __HAL_HCD_DISABLE(hhcd);
|
|
251
|
|
252 hhcd->State = HAL_HCD_STATE_RESET;
|
|
253
|
|
254 return HAL_OK;
|
|
255 }
|
|
256
|
|
257 /**
|
|
258 * @brief Initializes the HCD MSP.
|
|
259 * @param hhcd: HCD handle
|
|
260 * @retval None
|
|
261 */
|
|
262 __weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
|
|
263 {
|
|
264 /* NOTE : This function Should not be modified, when the callback is needed,
|
|
265 the HAL_PCD_MspInit could be implemented in the user file
|
|
266 */
|
|
267 }
|
|
268
|
|
269 /**
|
|
270 * @brief DeInitializes HCD MSP.
|
|
271 * @param hhcd: HCD handle
|
|
272 * @retval None
|
|
273 */
|
|
274 __weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
|
|
275 {
|
|
276 /* NOTE : This function Should not be modified, when the callback is needed,
|
|
277 the HAL_PCD_MspDeInit could be implemented in the user file
|
|
278 */
|
|
279 }
|
|
280
|
|
281 /**
|
|
282 * @}
|
|
283 */
|
|
284
|
|
285 /** @addtogroup HCD_Exported_Functions_Group2
|
|
286 * @brief HCD IO operation functions
|
|
287 *
|
|
288 @verbatim
|
|
289 ===============================================================================
|
|
290 ##### IO operation functions #####
|
|
291 ===============================================================================
|
|
292 This subsection provides a set of functions allowing to manage the USB Host Data
|
|
293 Transfer
|
|
294
|
|
295 @endverbatim
|
|
296 * @{
|
|
297 */
|
|
298
|
|
299 /**
|
|
300 * @brief Submit a new URB for processing
|
|
301 * @param hhcd: HCD handle
|
|
302 * @param ch_num: Channel number.
|
|
303 * This parameter can be a value from 1 to 15
|
|
304 * @param direction: Channel number.
|
|
305 * This parameter can be one of these values:
|
|
306 * 0 : Output / 1 : Input
|
|
307 * @param ep_type: Endpoint Type.
|
|
308 * This parameter can be one of these values:
|
|
309 * EP_TYPE_CTRL: Control type/
|
|
310 * EP_TYPE_ISOC: Isochronous type/
|
|
311 * EP_TYPE_BULK: Bulk type/
|
|
312 * EP_TYPE_INTR: Interrupt type/
|
|
313 * @param token: Endpoint Type.
|
|
314 * This parameter can be one of these values:
|
|
315 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
|
|
316 * @param pbuff: pointer to URB data
|
|
317 * @param length: Length of URB data
|
|
318 * @param do_ping: activate do ping protocol (for high speed only).
|
|
319 * This parameter can be one of these values:
|
|
320 * 0 : do ping inactive / 1 : do ping active
|
|
321 * @retval HAL status
|
|
322 */
|
|
323 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
|
|
324 uint8_t ch_num,
|
|
325 uint8_t direction,
|
|
326 uint8_t ep_type,
|
|
327 uint8_t token,
|
|
328 uint8_t* pbuff,
|
|
329 uint16_t length,
|
|
330 uint8_t do_ping)
|
|
331 {
|
|
332 hhcd->hc[ch_num].ep_is_in = direction;
|
|
333 hhcd->hc[ch_num].ep_type = ep_type;
|
|
334
|
|
335 if(token == 0)
|
|
336 {
|
|
337 hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
|
|
338 }
|
|
339 else
|
|
340 {
|
|
341 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
|
342 }
|
|
343
|
|
344 /* Manage Data Toggle */
|
|
345 switch(ep_type)
|
|
346 {
|
|
347 case EP_TYPE_CTRL:
|
|
348 if((token == 1) && (direction == 0)) /*send data */
|
|
349 {
|
|
350 if ( length == 0 )
|
|
351 { /* For Status OUT stage, Length==0, Status Out PID = 1 */
|
|
352 hhcd->hc[ch_num].toggle_out = 1;
|
|
353 }
|
|
354
|
|
355 /* Set the Data Toggle bit as per the Flag */
|
|
356 if ( hhcd->hc[ch_num].toggle_out == 0)
|
|
357 { /* Put the PID 0 */
|
|
358 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
|
359 }
|
|
360 else
|
|
361 { /* Put the PID 1 */
|
|
362 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
|
363 }
|
|
364 if(hhcd->hc[ch_num].urb_state != URB_NOTREADY)
|
|
365 {
|
|
366 hhcd->hc[ch_num].do_ping = do_ping;
|
|
367 }
|
|
368 }
|
|
369 break;
|
|
370
|
|
371 case EP_TYPE_BULK:
|
|
372 if(direction == 0)
|
|
373 {
|
|
374 /* Set the Data Toggle bit as per the Flag */
|
|
375 if ( hhcd->hc[ch_num].toggle_out == 0)
|
|
376 { /* Put the PID 0 */
|
|
377 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
|
378 }
|
|
379 else
|
|
380 { /* Put the PID 1 */
|
|
381 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
|
382 }
|
|
383 if(hhcd->hc[ch_num].urb_state != URB_NOTREADY)
|
|
384 {
|
|
385 hhcd->hc[ch_num].do_ping = do_ping;
|
|
386 }
|
|
387 }
|
|
388 else
|
|
389 {
|
|
390 if( hhcd->hc[ch_num].toggle_in == 0)
|
|
391 {
|
|
392 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
|
393 }
|
|
394 else
|
|
395 {
|
|
396 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
|
397 }
|
|
398 }
|
|
399
|
|
400 break;
|
|
401 case EP_TYPE_INTR:
|
|
402 if(direction == 0)
|
|
403 {
|
|
404 /* Set the Data Toggle bit as per the Flag */
|
|
405 if ( hhcd->hc[ch_num].toggle_out == 0)
|
|
406 { /* Put the PID 0 */
|
|
407 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
|
408 }
|
|
409 else
|
|
410 { /* Put the PID 1 */
|
|
411 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
|
412 }
|
|
413 }
|
|
414 else
|
|
415 {
|
|
416 if( hhcd->hc[ch_num].toggle_in == 0)
|
|
417 {
|
|
418 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
|
419 }
|
|
420 else
|
|
421 {
|
|
422 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
|
423 }
|
|
424 }
|
|
425 break;
|
|
426
|
|
427 case EP_TYPE_ISOC:
|
|
428 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
|
429 break;
|
|
430 }
|
|
431
|
|
432 hhcd->hc[ch_num].xfer_buff = pbuff;
|
|
433 hhcd->hc[ch_num].xfer_len = length;
|
|
434 hhcd->hc[ch_num].urb_state = URB_IDLE;
|
|
435 hhcd->hc[ch_num].xfer_count = 0;
|
|
436 hhcd->hc[ch_num].ch_num = ch_num;
|
|
437 hhcd->hc[ch_num].state = HC_IDLE;
|
|
438
|
|
439 return USB_HC_StartXfer(hhcd->Instance, &(hhcd->hc[ch_num]), hhcd->Init.dma_enable);
|
|
440 }
|
|
441
|
|
442 /**
|
|
443 * @brief This function handles HCD interrupt request.
|
|
444 * @param hhcd: HCD handle
|
|
445 * @retval None
|
|
446 */
|
|
447 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
|
|
448 {
|
|
449 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
|
450 uint32_t i = 0 , interrupt = 0;
|
|
451
|
|
452 /* Ensure that we are in device mode */
|
|
453 if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
|
|
454 {
|
|
455 /* Avoid spurious interrupt */
|
|
456 if(__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
|
|
457 {
|
|
458 return;
|
|
459 }
|
|
460
|
|
461 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
|
|
462 {
|
|
463 /* Incorrect mode, acknowledge the interrupt */
|
|
464 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
|
|
465 }
|
|
466
|
|
467 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
|
|
468 {
|
|
469 /* Incorrect mode, acknowledge the interrupt */
|
|
470 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
|
|
471 }
|
|
472
|
|
473 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
|
|
474 {
|
|
475 /* Incorrect mode, acknowledge the interrupt */
|
|
476 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
|
|
477 }
|
|
478
|
|
479 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
|
|
480 {
|
|
481 /* Incorrect mode, acknowledge the interrupt */
|
|
482 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
|
|
483 }
|
|
484
|
|
485 /* Handle Host Disconnect Interrupts */
|
|
486 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
|
|
487 {
|
|
488
|
|
489 /* Cleanup HPRT */
|
|
490 USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
|
|
491 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
|
|
492
|
|
493 /* Handle Host Port Interrupts */
|
|
494 HAL_HCD_Disconnect_Callback(hhcd);
|
|
495 USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ );
|
|
496 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
|
|
497 }
|
|
498
|
|
499 /* Handle Host Port Interrupts */
|
|
500 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
|
|
501 {
|
|
502 HCD_Port_IRQHandler (hhcd);
|
|
503 }
|
|
504
|
|
505 /* Handle Host SOF Interrupts */
|
|
506 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
|
|
507 {
|
|
508 HAL_HCD_SOF_Callback(hhcd);
|
|
509 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
|
|
510 }
|
|
511
|
|
512 /* Handle Host channel Interrupts */
|
|
513 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
|
|
514 {
|
|
515 interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
|
|
516 for (i = 0; i < hhcd->Init.Host_channels; i++)
|
|
517 {
|
|
518 if (interrupt & (1 << i))
|
|
519 {
|
|
520 if ((USBx_HC(i)->HCCHAR) & USB_OTG_HCCHAR_EPDIR)
|
|
521 {
|
|
522 HCD_HC_IN_IRQHandler(hhcd, i);
|
|
523 }
|
|
524 else
|
|
525 {
|
|
526 HCD_HC_OUT_IRQHandler (hhcd, i);
|
|
527 }
|
|
528 }
|
|
529 }
|
|
530 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
|
|
531 }
|
|
532
|
|
533 /* Handle Rx Queue Level Interrupts */
|
|
534 if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL))
|
|
535 {
|
|
536 USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
|
|
537
|
|
538 HCD_RXQLVL_IRQHandler (hhcd);
|
|
539
|
|
540 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
|
|
541 }
|
|
542 }
|
|
543 }
|
|
544
|
|
545 /**
|
|
546 * @brief SOF callback.
|
|
547 * @param hhcd: HCD handle
|
|
548 * @retval None
|
|
549 */
|
|
550 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
|
|
551 {
|
|
552 /* NOTE : This function Should not be modified, when the callback is needed,
|
|
553 the HAL_HCD_SOF_Callback could be implemented in the user file
|
|
554 */
|
|
555 }
|
|
556
|
|
557 /**
|
|
558 * @brief Connexion Event callback.
|
|
559 * @param hhcd: HCD handle
|
|
560 * @retval None
|
|
561 */
|
|
562 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
|
|
563 {
|
|
564 /* NOTE : This function Should not be modified, when the callback is needed,
|
|
565 the HAL_HCD_Connect_Callback could be implemented in the user file
|
|
566 */
|
|
567 }
|
|
568
|
|
569 /**
|
|
570 * @brief Disconnexion Event callback.
|
|
571 * @param hhcd: HCD handle
|
|
572 * @retval None
|
|
573 */
|
|
574 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
|
|
575 {
|
|
576 /* NOTE : This function Should not be modified, when the callback is needed,
|
|
577 the HAL_HCD_Disconnect_Callback could be implemented in the user file
|
|
578 */
|
|
579 }
|
|
580
|
|
581 /**
|
|
582 * @brief Notify URB state change callback.
|
|
583 * @param hhcd: HCD handle
|
|
584 * @param chnum: Channel number.
|
|
585 * This parameter can be a value from 1 to 15
|
|
586 * @param urb_state:
|
|
587 * This parameter can be one of these values:
|
|
588 * URB_IDLE/
|
|
589 * URB_DONE/
|
|
590 * URB_NOTREADY/
|
|
591 * URB_NYET/
|
|
592 * URB_ERROR/
|
|
593 * URB_STALL/
|
|
594 * @retval None
|
|
595 */
|
|
596 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
|
|
597 {
|
|
598 /* NOTE : This function Should not be modified, when the callback is needed,
|
|
599 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
|
|
600 */
|
|
601 }
|
|
602
|
|
603 /**
|
|
604 * @}
|
|
605 */
|
|
606
|
|
607 /** @addtogroup HCD_Exported_Functions_Group3
|
|
608 * @brief Peripheral State functions
|
|
609 *
|
|
610 @verbatim
|
|
611 ===============================================================================
|
|
612 ##### Peripheral Control functions #####
|
|
613 ===============================================================================
|
|
614 [..]
|
|
615 This subsection provides a set of functions allowing to control the HCD data
|
|
616 transfers.
|
|
617
|
|
618 @endverbatim
|
|
619 * @{
|
|
620 */
|
|
621
|
|
622 /**
|
|
623 * @brief Start the host driver
|
|
624 * @param hhcd: HCD handle
|
|
625 * @retval HAL status
|
|
626 */
|
|
627 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
|
|
628 {
|
|
629 __HAL_LOCK(hhcd);
|
|
630 __HAL_HCD_ENABLE(hhcd);
|
|
631 USB_DriveVbus(hhcd->Instance, 1);
|
|
632 __HAL_UNLOCK(hhcd);
|
|
633 return HAL_OK;
|
|
634 }
|
|
635
|
|
636 /**
|
|
637 * @brief Stop the host driver
|
|
638 * @param hhcd: HCD handle
|
|
639 * @retval HAL status
|
|
640 */
|
|
641
|
|
642 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
|
|
643 {
|
|
644 __HAL_LOCK(hhcd);
|
|
645 USB_StopHost(hhcd->Instance);
|
|
646 __HAL_UNLOCK(hhcd);
|
|
647 return HAL_OK;
|
|
648 }
|
|
649
|
|
650 /**
|
|
651 * @brief Reset the host port
|
|
652 * @param hhcd: HCD handle
|
|
653 * @retval HAL status
|
|
654 */
|
|
655 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
|
|
656 {
|
|
657 return (USB_ResetPort(hhcd->Instance));
|
|
658 }
|
|
659
|
|
660 /**
|
|
661 * @}
|
|
662 */
|
|
663
|
|
664 /** @addtogroup HCD_Exported_Functions_Group4
|
|
665 * @brief Peripheral State functions
|
|
666 *
|
|
667 @verbatim
|
|
668 ===============================================================================
|
|
669 ##### Peripheral State functions #####
|
|
670 ===============================================================================
|
|
671 [..]
|
|
672 This subsection permits to get in run-time the status of the peripheral
|
|
673 and the data flow.
|
|
674
|
|
675 @endverbatim
|
|
676 * @{
|
|
677 */
|
|
678
|
|
679 /**
|
|
680 * @brief Return the HCD state
|
|
681 * @param hhcd: HCD handle
|
|
682 * @retval HAL state
|
|
683 */
|
|
684 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd)
|
|
685 {
|
|
686 return hhcd->State;
|
|
687 }
|
|
688
|
|
689 /**
|
|
690 * @brief Return URB state for a channel
|
|
691 * @param hhcd: HCD handle
|
|
692 * @param chnum: Channel number.
|
|
693 * This parameter can be a value from 1 to 15
|
|
694 * @retval URB state.
|
|
695 * This parameter can be one of these values:
|
|
696 * URB_IDLE/
|
|
697 * URB_DONE/
|
|
698 * URB_NOTREADY/
|
|
699 * URB_NYET/
|
|
700 * URB_ERROR/
|
|
701 * URB_STALL/
|
|
702 */
|
|
703 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
|
|
704 {
|
|
705 return hhcd->hc[chnum].urb_state;
|
|
706 }
|
|
707
|
|
708
|
|
709 /**
|
|
710 * @brief Return the last host transfer size
|
|
711 * @param hhcd: HCD handle
|
|
712 * @param chnum: Channel number.
|
|
713 * This parameter can be a value from 1 to 15
|
|
714 * @retval last transfer size in byte
|
|
715 */
|
|
716 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum)
|
|
717 {
|
|
718 return hhcd->hc[chnum].xfer_count;
|
|
719 }
|
|
720
|
|
721 /**
|
|
722 * @brief Return the Host Channel state
|
|
723 * @param hhcd: HCD handle
|
|
724 * @param chnum: Channel number.
|
|
725 * This parameter can be a value from 1 to 15
|
|
726 * @retval Host channel state
|
|
727 * This parameter can be one of the these values:
|
|
728 * HC_IDLE/
|
|
729 * HC_XFRC/
|
|
730 * HC_HALTED/
|
|
731 * HC_NYET/
|
|
732 * HC_NAK/
|
|
733 * HC_STALL/
|
|
734 * HC_XACTERR/
|
|
735 * HC_BBLERR/
|
|
736 * HC_DATATGLERR/
|
|
737 */
|
|
738 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
|
|
739 {
|
|
740 return hhcd->hc[chnum].state;
|
|
741 }
|
|
742
|
|
743 /**
|
|
744 * @brief Return the current Host frame number
|
|
745 * @param hhcd: HCD handle
|
|
746 * @retval Current Host frame number
|
|
747 */
|
|
748 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
|
|
749 {
|
|
750 return (USB_GetCurrentFrame(hhcd->Instance));
|
|
751 }
|
|
752
|
|
753 /**
|
|
754 * @brief Return the Host enumeration speed
|
|
755 * @param hhcd: HCD handle
|
|
756 * @retval Enumeration speed
|
|
757 */
|
|
758 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
|
|
759 {
|
|
760 return (USB_GetHostSpeed(hhcd->Instance));
|
|
761 }
|
|
762 /**
|
|
763 * @}
|
|
764 */
|
|
765
|
|
766 /**
|
|
767 * @}
|
|
768 */
|
|
769
|
|
770 /** @addtogroup HCD_Private_Functions
|
|
771 * @{
|
|
772 */
|
|
773 /**
|
|
774 * @brief This function handles Host Channel IN interrupt requests.
|
|
775 * @param hhcd: HCD handle
|
|
776 * @param chnum: Channel number.
|
|
777 * This parameter can be a value from 1 to 15
|
|
778 * @retval None
|
|
779 */
|
|
780 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
|
|
781 {
|
|
782 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
|
783
|
|
784 if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_AHBERR)
|
|
785 {
|
|
786 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
|
|
787 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
788 }
|
|
789 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_ACK)
|
|
790 {
|
|
791 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
|
|
792 }
|
|
793
|
|
794 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_STALL)
|
|
795 {
|
|
796 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
797 hhcd->hc[chnum].state = HC_STALL;
|
|
798 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
|
799 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
|
|
800 USB_HC_Halt(hhcd->Instance, chnum);
|
|
801 }
|
|
802 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_DTERR)
|
|
803 {
|
|
804 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
805 USB_HC_Halt(hhcd->Instance, chnum);
|
|
806 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
|
807 hhcd->hc[chnum].state = HC_DATATGLERR;
|
|
808 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
|
|
809 }
|
|
810
|
|
811 if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_FRMOR)
|
|
812 {
|
|
813 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
814 USB_HC_Halt(hhcd->Instance, chnum);
|
|
815 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
|
|
816 }
|
|
817
|
|
818 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_XFRC)
|
|
819 {
|
|
820
|
|
821 if (hhcd->Init.dma_enable)
|
|
822 {
|
|
823 hhcd->hc[chnum].xfer_count = hhcd->hc[chnum].xfer_len - \
|
|
824 (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
|
|
825 }
|
|
826
|
|
827 hhcd->hc[chnum].state = HC_XFRC;
|
|
828 hhcd->hc[chnum].ErrCnt = 0;
|
|
829 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
|
|
830
|
|
831
|
|
832 if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)||
|
|
833 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
|
|
834 {
|
|
835 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
836 USB_HC_Halt(hhcd->Instance, chnum);
|
|
837 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
|
838
|
|
839 }
|
|
840 else if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
|
|
841 {
|
|
842 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
|
|
843 hhcd->hc[chnum].urb_state = URB_DONE;
|
|
844 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
|
845 }
|
|
846 hhcd->hc[chnum].toggle_in ^= 1;
|
|
847
|
|
848 }
|
|
849 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_CHH)
|
|
850 {
|
|
851 __HAL_HCD_MASK_HALT_HC_INT(chnum);
|
|
852
|
|
853 if(hhcd->hc[chnum].state == HC_XFRC)
|
|
854 {
|
|
855 hhcd->hc[chnum].urb_state = URB_DONE;
|
|
856 }
|
|
857
|
|
858 else if (hhcd->hc[chnum].state == HC_STALL)
|
|
859 {
|
|
860 hhcd->hc[chnum].urb_state = URB_STALL;
|
|
861 }
|
|
862
|
|
863 else if((hhcd->hc[chnum].state == HC_XACTERR) ||
|
|
864 (hhcd->hc[chnum].state == HC_DATATGLERR))
|
|
865 {
|
|
866 if(hhcd->hc[chnum].ErrCnt++ > 3)
|
|
867 {
|
|
868 hhcd->hc[chnum].ErrCnt = 0;
|
|
869 hhcd->hc[chnum].urb_state = URB_ERROR;
|
|
870 }
|
|
871 else
|
|
872 {
|
|
873 hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
|
874 }
|
|
875
|
|
876 /* re-activate the channel */
|
|
877 USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
|
|
878 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
|
|
879 }
|
|
880 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
|
|
881 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
|
882 }
|
|
883
|
|
884 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_TXERR)
|
|
885 {
|
|
886 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
887 hhcd->hc[chnum].ErrCnt++;
|
|
888 hhcd->hc[chnum].state = HC_XACTERR;
|
|
889 USB_HC_Halt(hhcd->Instance, chnum);
|
|
890 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
|
|
891 }
|
|
892 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NAK)
|
|
893 {
|
|
894 if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
|
|
895 {
|
|
896 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
897 USB_HC_Halt(hhcd->Instance, chnum);
|
|
898 }
|
|
899 else if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)||
|
|
900 (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
|
|
901 {
|
|
902 /* re-activate the channel */
|
|
903 USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
|
|
904 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
|
|
905
|
|
906 }
|
|
907 hhcd->hc[chnum].state = HC_NAK;
|
|
908 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
|
909 }
|
|
910 }
|
|
911
|
|
912 /**
|
|
913 * @brief This function handles Host Channel OUT interrupt requests.
|
|
914 * @param hhcd: HCD handle
|
|
915 * @param chnum: Channel number.
|
|
916 * This parameter can be a value from 1 to 15
|
|
917 * @retval None
|
|
918 */
|
|
919 static void HCD_HC_OUT_IRQHandler (HCD_HandleTypeDef *hhcd, uint8_t chnum)
|
|
920 {
|
|
921 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
|
922
|
|
923 if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_AHBERR)
|
|
924 {
|
|
925 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
|
|
926 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
927 }
|
|
928 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_ACK)
|
|
929 {
|
|
930 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
|
|
931
|
|
932 if( hhcd->hc[chnum].do_ping == 1)
|
|
933 {
|
|
934 hhcd->hc[chnum].state = HC_NYET;
|
|
935 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
936 USB_HC_Halt(hhcd->Instance, chnum);
|
|
937 hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
|
938 }
|
|
939 }
|
|
940
|
|
941 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NYET)
|
|
942 {
|
|
943 hhcd->hc[chnum].state = HC_NYET;
|
|
944 hhcd->hc[chnum].ErrCnt= 0;
|
|
945 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
946 USB_HC_Halt(hhcd->Instance, chnum);
|
|
947 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
|
|
948
|
|
949 }
|
|
950
|
|
951 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_FRMOR)
|
|
952 {
|
|
953 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
954 USB_HC_Halt(hhcd->Instance, chnum);
|
|
955 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
|
|
956 }
|
|
957
|
|
958 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_XFRC)
|
|
959 {
|
|
960 hhcd->hc[chnum].ErrCnt = 0;
|
|
961 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
962 USB_HC_Halt(hhcd->Instance, chnum);
|
|
963 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
|
|
964 hhcd->hc[chnum].state = HC_XFRC;
|
|
965
|
|
966 }
|
|
967
|
|
968 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_STALL)
|
|
969 {
|
|
970 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
|
|
971 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
972 USB_HC_Halt(hhcd->Instance, chnum);
|
|
973 hhcd->hc[chnum].state = HC_STALL;
|
|
974 }
|
|
975
|
|
976 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NAK)
|
|
977 {
|
|
978 hhcd->hc[chnum].ErrCnt = 0;
|
|
979 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
980 USB_HC_Halt(hhcd->Instance, chnum);
|
|
981 hhcd->hc[chnum].state = HC_NAK;
|
|
982 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
|
983 }
|
|
984
|
|
985 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_TXERR)
|
|
986 {
|
|
987 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
988 USB_HC_Halt(hhcd->Instance, chnum);
|
|
989 hhcd->hc[chnum].state = HC_XACTERR;
|
|
990 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
|
|
991 }
|
|
992
|
|
993 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_DTERR)
|
|
994 {
|
|
995 __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
|
|
996 USB_HC_Halt(hhcd->Instance, chnum);
|
|
997 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
|
998 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
|
|
999 hhcd->hc[chnum].state = HC_DATATGLERR;
|
|
1000 }
|
|
1001
|
|
1002
|
|
1003 else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_CHH)
|
|
1004 {
|
|
1005 __HAL_HCD_MASK_HALT_HC_INT(chnum);
|
|
1006
|
|
1007 if(hhcd->hc[chnum].state == HC_XFRC)
|
|
1008 {
|
|
1009 hhcd->hc[chnum].urb_state = URB_DONE;
|
|
1010 if (hhcd->hc[chnum].ep_type == EP_TYPE_BULK)
|
|
1011 {
|
|
1012 hhcd->hc[chnum].toggle_out ^= 1;
|
|
1013 }
|
|
1014 }
|
|
1015 else if (hhcd->hc[chnum].state == HC_NAK)
|
|
1016 {
|
|
1017 hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
|
1018 }
|
|
1019
|
|
1020 else if (hhcd->hc[chnum].state == HC_NYET)
|
|
1021 {
|
|
1022 hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
|
1023 hhcd->hc[chnum].do_ping = 0;
|
|
1024 }
|
|
1025
|
|
1026 else if (hhcd->hc[chnum].state == HC_STALL)
|
|
1027 {
|
|
1028 hhcd->hc[chnum].urb_state = URB_STALL;
|
|
1029 }
|
|
1030
|
|
1031 else if((hhcd->hc[chnum].state == HC_XACTERR) ||
|
|
1032 (hhcd->hc[chnum].state == HC_DATATGLERR))
|
|
1033 {
|
|
1034 if(hhcd->hc[chnum].ErrCnt++ > 3)
|
|
1035 {
|
|
1036 hhcd->hc[chnum].ErrCnt = 0;
|
|
1037 hhcd->hc[chnum].urb_state = URB_ERROR;
|
|
1038 }
|
|
1039 else
|
|
1040 {
|
|
1041 hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
|
1042 }
|
|
1043
|
|
1044 /* re-activate the channel */
|
|
1045 USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
|
|
1046 USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
|
|
1047 }
|
|
1048
|
|
1049 __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
|
|
1050 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
|
1051 }
|
|
1052 }
|
|
1053
|
|
1054 /**
|
|
1055 * @brief This function handles Rx Queue Level interrupt requests.
|
|
1056 * @param hhcd: HCD handle
|
|
1057 * @retval None
|
|
1058 */
|
|
1059 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
|
|
1060 {
|
|
1061 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
|
1062 uint8_t channelnum = 0;
|
|
1063 uint32_t pktsts;
|
|
1064 uint32_t pktcnt;
|
|
1065 uint32_t temp = 0;
|
|
1066
|
|
1067 temp = hhcd->Instance->GRXSTSP;
|
|
1068 channelnum = temp & USB_OTG_GRXSTSP_EPNUM;
|
|
1069 pktsts = (temp & USB_OTG_GRXSTSP_PKTSTS) >> 17;
|
|
1070 pktcnt = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
|
|
1071
|
|
1072 switch (pktsts)
|
|
1073 {
|
|
1074 case GRXSTS_PKTSTS_IN:
|
|
1075 /* Read the data into the host buffer. */
|
|
1076 if ((pktcnt > 0) && (hhcd->hc[channelnum].xfer_buff != (void *)0))
|
|
1077 {
|
|
1078
|
|
1079 USB_ReadPacket(hhcd->Instance, hhcd->hc[channelnum].xfer_buff, pktcnt);
|
|
1080
|
|
1081 /*manage multiple Xfer */
|
|
1082 hhcd->hc[channelnum].xfer_buff += pktcnt;
|
|
1083 hhcd->hc[channelnum].xfer_count += pktcnt;
|
|
1084
|
|
1085 if((USBx_HC(channelnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0)
|
|
1086 {
|
|
1087 /* re-activate the channel when more packets are expected */
|
|
1088 USBx_HC(channelnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
|
|
1089 USBx_HC(channelnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
|
|
1090 hhcd->hc[channelnum].toggle_in ^= 1;
|
|
1091 }
|
|
1092 }
|
|
1093 break;
|
|
1094
|
|
1095 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
|
|
1096 break;
|
|
1097 case GRXSTS_PKTSTS_IN_XFER_COMP:
|
|
1098 case GRXSTS_PKTSTS_CH_HALTED:
|
|
1099 default:
|
|
1100 break;
|
|
1101 }
|
|
1102 }
|
|
1103
|
|
1104 /**
|
|
1105 * @brief This function handles Host Port interrupt requests.
|
|
1106 * @param hhcd: HCD handle
|
|
1107 * @retval None
|
|
1108 */
|
|
1109 static void HCD_Port_IRQHandler (HCD_HandleTypeDef *hhcd)
|
|
1110 {
|
|
1111 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
|
1112 __IO uint32_t hprt0, hprt0_dup;
|
|
1113
|
|
1114 /* Handle Host Port Interrupts */
|
|
1115 hprt0 = USBx_HPRT0;
|
|
1116 hprt0_dup = USBx_HPRT0;
|
|
1117
|
|
1118 hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
|
|
1119 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
|
|
1120
|
|
1121 /* Check whether Port Connect Detected */
|
|
1122 if((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
|
|
1123 {
|
|
1124 if((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
|
|
1125 {
|
|
1126 USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT);
|
|
1127 HAL_HCD_Connect_Callback(hhcd);
|
|
1128 }
|
|
1129 hprt0_dup |= USB_OTG_HPRT_PCDET;
|
|
1130
|
|
1131 }
|
|
1132
|
|
1133 /* Check whether Port Enable Changed */
|
|
1134 if((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
|
|
1135 {
|
|
1136 hprt0_dup |= USB_OTG_HPRT_PENCHNG;
|
|
1137
|
|
1138 if((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
|
|
1139 {
|
|
1140 if(hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
|
|
1141 {
|
|
1142 if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
|
|
1143 {
|
|
1144 USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_6_MHZ );
|
|
1145 }
|
|
1146 else
|
|
1147 {
|
|
1148 USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ );
|
|
1149 }
|
|
1150 }
|
|
1151 else
|
|
1152 {
|
|
1153 if(hhcd->Init.speed == HCD_SPEED_FULL)
|
|
1154 {
|
|
1155 USBx_HOST->HFIR = (uint32_t)60000;
|
|
1156 }
|
|
1157 }
|
|
1158 HAL_HCD_Connect_Callback(hhcd);
|
|
1159
|
|
1160 if(hhcd->Init.speed == HCD_SPEED_HIGH)
|
|
1161 {
|
|
1162 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT);
|
|
1163 }
|
|
1164 }
|
|
1165 else
|
|
1166 {
|
|
1167 /* Cleanup HPRT */
|
|
1168 USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
|
|
1169 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
|
|
1170
|
|
1171 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT);
|
|
1172 }
|
|
1173 }
|
|
1174
|
|
1175 /* Check for an overcurrent */
|
|
1176 if((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
|
|
1177 {
|
|
1178 hprt0_dup |= USB_OTG_HPRT_POCCHNG;
|
|
1179 }
|
|
1180
|
|
1181 /* Clear Port Interrupts */
|
|
1182 USBx_HPRT0 = hprt0_dup;
|
|
1183 }
|
|
1184
|
|
1185 /**
|
|
1186 * @}
|
|
1187 */
|
|
1188
|
|
1189 #endif /* HAL_HCD_MODULE_ENABLED */
|
|
1190 /**
|
|
1191 * @}
|
|
1192 */
|
|
1193
|
|
1194 /**
|
|
1195 * @}
|
|
1196 */
|
|
1197
|
|
1198 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|