2 ******************************************************************************
3 * @file stm32f1xx_hal_pcd.c
4 * @author MCD Application Team
6 * @date 15-December-2014
7 * @brief PCD 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
16 ==============================================================================
17 ##### How to use this driver #####
18 ==============================================================================
20 The PCD HAL driver can be used as follows:
22 (#) Declare a PCD_HandleTypeDef handle structure, for example:
23 PCD_HandleTypeDef hpcd;
25 (#) Fill parameters of Init structure in HCD handle
27 (#) Call HAL_PCD_Init() API to initialize the HCD peripheral (Core, Device core, ...)
29 (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
30 (##) Enable the PCD/USB Low Level interface clock using the following macro
31 (+++) __HAL_RCC_USB_CLK_ENABLE(); For USB Device FS peripheral available
32 on STM32F102xx and STM32F103xx devices
33 (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); For USB OTG FS peripheral available
34 on STM32F105xx and STM32F107xx devices
36 (##) Initialize the related GPIO clocks
37 (##) Configure PCD pin-out
38 (##) Configure PCD NVIC interrupt
40 (#)Associate the Upper USB device stack to the HAL PCD Driver:
41 (##) hpcd.pData = pdev;
43 (#)Enable HCD transmission and reception:
47 ******************************************************************************
50 * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
52 * Redistribution and use in source and binary forms, with or without modification,
53 * are permitted provided that the following conditions are met:
54 * 1. Redistributions of source code must retain the above copyright notice,
55 * this list of conditions and the following disclaimer.
56 * 2. Redistributions in binary form must reproduce the above copyright notice,
57 * this list of conditions and the following disclaimer in the documentation
58 * and/or other materials provided with the distribution.
59 * 3. Neither the name of STMicroelectronics nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
64 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
69 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
70 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
71 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
72 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
74 ******************************************************************************
77 /* Includes ------------------------------------------------------------------*/
78 #include "stm32f1xx_hal.h"
80 /** @addtogroup STM32F1xx_HAL_Driver
86 #ifdef HAL_PCD_MODULE_ENABLED
88 #if defined(STM32F102x6) || defined(STM32F102xB) || \
89 defined(STM32F103x6) || defined(STM32F103xB) || \
90 defined(STM32F103xE) || defined(STM32F103xG) || \
91 defined(STM32F105xC) || defined(STM32F107xC)
94 * @brief PCD HAL module driver
98 /* Private types -------------------------------------------------------------*/
99 /* Private variables ---------------------------------------------------------*/
100 /* Private constants ---------------------------------------------------------*/
101 /* Private macros ------------------------------------------------------------*/
102 /** @defgroup PCD_Private_Macros PCD Private Macros
105 #define PCD_MIN(a, b) (((a) < (b)) ? (a) : (b))
106 #define PCD_MAX(a, b) (((a) > (b)) ? (a) : (b))
111 /* Private functions ---------------------------------------------------------*/
112 /** @defgroup PCD_Private_Functions PCD Private Functions
115 #if defined (USB_OTG_FS)
116 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
117 #endif /* USB_OTG_FS */
120 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
126 /* Exported functions --------------------------------------------------------*/
127 /** @defgroup PCD_Exported_Functions PCD Exported Functions
131 /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
132 * @brief Initialization and Configuration functions
135 ===============================================================================
136 ##### Initialization and de-initialization functions #####
137 ===============================================================================
138 [..] This section provides functions allowing to:
145 * @brief Initializes the PCD according to the specified
146 * parameters in the PCD_InitTypeDef and create the associated handle.
147 * @param hpcd: PCD handle
150 HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
154 /* Check the PCD handle allocation */
160 /* Check the parameters */
161 assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
163 if(hpcd->State == HAL_PCD_STATE_RESET)
165 /* Allocate lock resource and initialize it */
166 hpcd-> Lock = HAL_UNLOCKED;
168 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
169 HAL_PCD_MspInit(hpcd);
172 hpcd->State = HAL_PCD_STATE_BUSY;
174 /* Disable the Interrupts */
175 __HAL_PCD_DISABLE(hpcd);
177 /*Init the Core (common init.) */
178 USB_CoreInit(hpcd->Instance, hpcd->Init);
180 /* Force Device Mode*/
181 USB_SetCurrentMode(hpcd->Instance , USB_DEVICE_MODE);
183 /* Init endpoints structures */
184 for (index = 0; index < 15 ; index++)
186 /* Init ep structure */
187 hpcd->IN_ep[index].is_in = 1;
188 hpcd->IN_ep[index].num = index;
189 hpcd->IN_ep[index].tx_fifo_num = index;
190 /* Control until ep is actvated */
191 hpcd->IN_ep[index].type = EP_TYPE_CTRL;
192 hpcd->IN_ep[index].maxpacket = 0;
193 hpcd->IN_ep[index].xfer_buff = 0;
194 hpcd->IN_ep[index].xfer_len = 0;
197 for (index = 0; index < 15 ; index++)
199 hpcd->OUT_ep[index].is_in = 0;
200 hpcd->OUT_ep[index].num = index;
201 hpcd->IN_ep[index].tx_fifo_num = index;
202 /* Control until ep is activated */
203 hpcd->OUT_ep[index].type = EP_TYPE_CTRL;
204 hpcd->OUT_ep[index].maxpacket = 0;
205 hpcd->OUT_ep[index].xfer_buff = 0;
206 hpcd->OUT_ep[index].xfer_len = 0;
210 USB_DevInit(hpcd->Instance, hpcd->Init);
212 hpcd->USB_Address = 0;
213 hpcd->State= HAL_PCD_STATE_READY;
215 USB_DevDisconnect (hpcd->Instance);
220 * @brief DeInitializes the PCD peripheral
221 * @param hpcd: PCD handle
224 HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
226 /* Check the PCD handle allocation */
232 hpcd->State = HAL_PCD_STATE_BUSY;
237 /* DeInit the low level hardware */
238 HAL_PCD_MspDeInit(hpcd);
240 hpcd->State = HAL_PCD_STATE_RESET;
246 * @brief Initializes the PCD MSP.
247 * @param hpcd: PCD handle
250 __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
252 /* NOTE : This function should not be modified, when the callback is needed,
253 the HAL_PCD_MspInit could be implemented in the user file
258 * @brief DeInitializes PCD MSP.
259 * @param hpcd: PCD handle
262 __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
264 /* NOTE : This function should not be modified, when the callback is needed,
265 the HAL_PCD_MspDeInit could be implemented in the user file
273 /** @defgroup PCD_Exported_Functions_Group2 IO operation functions
274 * @brief Data transfers functions
277 ===============================================================================
278 ##### IO operation functions #####
279 ===============================================================================
281 This subsection provides a set of functions allowing to manage the PCD data
289 * @brief Start The USB Device.
290 * @param hpcd: PCD handle
293 HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
296 HAL_PCDEx_SetConnectionState (hpcd, 1);
297 USB_DevConnect (hpcd->Instance);
298 __HAL_PCD_ENABLE(hpcd);
304 * @brief Stop The USB Device.
305 * @param hpcd: PCD handle
308 HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
311 __HAL_PCD_DISABLE(hpcd);
312 USB_StopDevice(hpcd->Instance);
313 USB_DevDisconnect (hpcd->Instance);
318 #if defined (USB_OTG_FS)
320 * @brief This function handles PCD interrupt request.
321 * @param hpcd: PCD handle
324 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
326 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
327 uint32_t index = 0, ep_intr = 0, epint = 0, epnum = 0;
328 uint32_t fifoemptymsk = 0, temp = 0;
329 USB_OTG_EPTypeDef *ep = NULL;
331 /* ensure that we are in device mode */
332 if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
334 /* avoid spurious interrupt */
335 if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
340 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
342 /* incorrect mode, acknowledge the interrupt */
343 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
346 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
350 /* Read in the device interrupt bits */
351 ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
357 epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum);
359 if(( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
361 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
363 HAL_PCD_DataOutStageCallback(hpcd, epnum);
366 if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
368 /* Inform the upper layer that a setup packet is available */
369 HAL_PCD_SetupStageCallback(hpcd);
370 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
373 if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
375 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
383 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
385 /* Read in the device interrupt bits */
386 ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
392 if (ep_intr & 0x1) /* In ITR */
394 epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum);
396 if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
398 fifoemptymsk = 0x1 << epnum;
399 USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
401 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
403 HAL_PCD_DataInStageCallback(hpcd, epnum);
405 if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
407 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
409 if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
411 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
413 if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
415 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
417 if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
419 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
421 if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
423 PCD_WriteEmptyTxFifo(hpcd , epnum);
431 /* Handle Resume Interrupt */
432 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
434 /* Clear the Remote Wake-up signalling */
435 USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
437 HAL_PCD_ResumeCallback(hpcd);
439 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
442 /* Handle Suspend Interrupt */
443 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
445 if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
448 HAL_PCD_SuspendCallback(hpcd);
450 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
453 /* Handle Reset Interrupt */
454 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
456 USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
457 USB_FlushTxFifo(hpcd->Instance , 0 );
459 for (index = 0; index < hpcd->Init.dev_endpoints ; index++)
461 USBx_INEP(index)->DIEPINT = 0xFF;
462 USBx_OUTEP(index)->DOEPINT = 0xFF;
464 USBx_DEVICE->DAINT = 0xFFFFFFFF;
465 USBx_DEVICE->DAINTMSK |= 0x10001;
467 USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
468 USBx_DEVICE->DIEPMSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
470 /* Set Default Address to 0 */
471 USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
473 /* setup EP0 to receive SETUP packets */
474 USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
476 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
479 /* Handle Enumeration done Interrupt */
480 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
482 USB_ActivateSetup(hpcd->Instance);
483 hpcd->Instance->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
485 hpcd->Init.speed = USB_OTG_SPEED_FULL;
486 hpcd->Init.ep0_mps = USB_OTG_FS_MAX_PACKET_SIZE ;
487 hpcd->Instance->GUSBCFG |= (USB_OTG_GUSBCFG_TRDT_0 | USB_OTG_GUSBCFG_TRDT_2);
489 HAL_PCD_ResetCallback(hpcd);
491 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
494 /* Handle RxQLevel Interrupt */
495 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
497 USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
498 temp = USBx->GRXSTSP;
499 ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
501 if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT)
503 if((temp & USB_OTG_GRXSTSP_BCNT) != 0)
505 USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4);
506 ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
507 ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
510 else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
512 USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8);
513 ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
515 USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
518 /* Handle SOF Interrupt */
519 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
521 HAL_PCD_SOFCallback(hpcd);
522 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
525 /* Handle Incomplete ISO IN Interrupt */
526 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
528 HAL_PCD_ISOINIncompleteCallback(hpcd, epnum);
529 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
532 /* Handle Incomplete ISO OUT Interrupt */
533 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
535 HAL_PCD_ISOOUTIncompleteCallback(hpcd, epnum);
536 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
539 /* Handle Connection event Interrupt */
540 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
542 HAL_PCD_ConnectCallback(hpcd);
543 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
546 /* Handle Disconnection event Interrupt */
547 if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
549 temp = hpcd->Instance->GOTGINT;
551 if((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
553 HAL_PCD_DisconnectCallback(hpcd);
555 hpcd->Instance->GOTGINT |= temp;
559 #endif /* USB_OTG_FS */
563 * @brief This function handles PCD interrupt request.
564 * @param hpcd: PCD handle
567 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
569 uint32_t wInterrupt_Mask = 0;
571 if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_CTR))
573 /* servicing of the endpoint correct transfer interrupt */
574 /* clear of the CTR flag into the sub */
575 PCD_EP_ISR_Handler(hpcd);
578 if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_RESET))
580 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
581 HAL_PCD_ResetCallback(hpcd);
582 HAL_PCD_SetAddress(hpcd, 0);
585 if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_PMAOVR))
587 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);
589 if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ERR))
591 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
594 if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP))
596 hpcd->Instance->CNTR &= ~(USB_CNTR_LP_MODE);
598 /*set wInterrupt_Mask global variable*/
599 wInterrupt_Mask = USB_CNTR_CTRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \
600 | USB_CNTR_ESOFM | USB_CNTR_RESETM;
602 /*Set interrupt mask*/
603 hpcd->Instance->CNTR = wInterrupt_Mask;
605 HAL_PCD_ResumeCallback(hpcd);
607 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);
610 if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SUSP))
612 /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
613 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);
615 /* Force low-power mode in the macrocell */
616 hpcd->Instance->CNTR |= USB_CNTR_FSUSP;
617 hpcd->Instance->CNTR |= USB_CNTR_LP_MODE;
618 if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP) == 0)
620 HAL_PCD_SuspendCallback(hpcd);
624 if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SOF))
626 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
627 HAL_PCD_SOFCallback(hpcd);
630 if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ESOF))
632 /* clear ESOF flag in ISTR */
633 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
639 * @brief Data out stage callbacks
640 * @param hpcd: PCD handle
641 * @param epnum: endpoint number
644 __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
646 /* NOTE : This function should not be modified, when the callback is needed,
647 the HAL_PCD_DataOutStageCallback could be implemented in the user file
652 * @brief Data IN stage callbacks
653 * @param hpcd: PCD handle
654 * @param epnum: endpoint number
657 __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
659 /* NOTE : This function should not be modified, when the callback is needed,
660 the HAL_PCD_DataInStageCallback could be implemented in the user file
664 * @brief Setup stage callback
665 * @param hpcd: PCD handle
668 __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
670 /* NOTE : This function should not be modified, when the callback is needed,
671 the HAL_PCD_SetupStageCallback could be implemented in the user file
676 * @brief USB Start Of Frame callbacks
677 * @param hpcd: PCD handle
680 __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
682 /* NOTE : This function should not be modified, when the callback is needed,
683 the HAL_PCD_SOFCallback could be implemented in the user file
688 * @brief USB Reset callbacks
689 * @param hpcd: PCD handle
692 __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
694 /* NOTE : This function should not be modified, when the callback is needed,
695 the HAL_PCD_ResetCallback could be implemented in the user file
700 * @brief Suspend event callbacks
701 * @param hpcd: PCD handle
704 __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
706 /* NOTE : This function should not be modified, when the callback is needed,
707 the HAL_PCD_SuspendCallback could be implemented in the user file
712 * @brief Resume event callbacks
713 * @param hpcd: PCD handle
716 __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
718 /* NOTE : This function should not be modified, when the callback is needed,
719 the HAL_PCD_ResumeCallback could be implemented in the user file
724 * @brief Incomplete ISO OUT callbacks
725 * @param hpcd: PCD handle
726 * @param epnum: endpoint number
729 __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
731 /* NOTE : This function should not be modified, when the callback is needed,
732 the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
737 * @brief Incomplete ISO IN callbacks
738 * @param hpcd: PCD handle
739 * @param epnum: endpoint number
742 __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
744 /* NOTE : This function should not be modified, when the callback is needed,
745 the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
750 * @brief Connection event callbacks
751 * @param hpcd: PCD handle
754 __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
756 /* NOTE : This function should not be modified, when the callback is needed,
757 the HAL_PCD_ConnectCallback could be implemented in the user file
762 * @brief Disconnection event callbacks
763 * @param hpcd: PCD handle
766 __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
768 /* NOTE : This function should not be modified, when the callback is needed,
769 the HAL_PCD_DisconnectCallback could be implemented in the user file
777 /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
778 * @brief management functions
781 ===============================================================================
782 ##### Peripheral Control functions #####
783 ===============================================================================
785 This subsection provides a set of functions allowing to control the PCD data
793 * @brief Connect the USB device
794 * @param hpcd: PCD handle
797 HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
800 HAL_PCDEx_SetConnectionState (hpcd, 1);
801 USB_DevConnect(hpcd->Instance);
807 * @brief Disconnect the USB device
808 * @param hpcd: PCD handle
811 HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
814 HAL_PCDEx_SetConnectionState (hpcd, 0);
815 USB_DevDisconnect(hpcd->Instance);
821 * @brief Set the USB Device address
822 * @param hpcd: PCD handle
823 * @param address: new device address
826 HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
829 hpcd->USB_Address = address;
830 USB_SetDevAddress(hpcd->Instance, address);
835 * @brief Open and configure an endpoint
836 * @param hpcd: PCD handle
837 * @param ep_addr: endpoint address
838 * @param ep_mps: endpoint max packet size
839 * @param ep_type: endpoint type
842 HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type)
844 HAL_StatusTypeDef ret = HAL_OK;
845 PCD_EPTypeDef *ep = NULL;
847 if ((ep_addr & 0x80) == 0x80)
849 ep = &hpcd->IN_ep[ep_addr & 0x7F];
853 ep = &hpcd->OUT_ep[ep_addr & 0x7F];
855 ep->num = ep_addr & 0x7F;
857 ep->is_in = (0x80 & ep_addr) != 0;
858 ep->maxpacket = ep_mps;
862 USB_ActivateEndpoint(hpcd->Instance , ep);
868 * @brief Deactivate an endpoint
869 * @param hpcd: PCD handle
870 * @param ep_addr: endpoint address
873 HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
875 PCD_EPTypeDef *ep = NULL;
877 if ((ep_addr & 0x80) == 0x80)
879 ep = &hpcd->IN_ep[ep_addr & 0x7F];
883 ep = &hpcd->OUT_ep[ep_addr & 0x7F];
885 ep->num = ep_addr & 0x7F;
887 ep->is_in = (0x80 & ep_addr) != 0;
890 USB_DeactivateEndpoint(hpcd->Instance , ep);
897 * @brief Receive an amount of data
898 * @param hpcd: PCD handle
899 * @param ep_addr: endpoint address
900 * @param pBuf: pointer to the reception buffer
901 * @param len: amount of data to be received
904 HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
906 PCD_EPTypeDef *ep = NULL;
908 ep = &hpcd->OUT_ep[ep_addr & 0x7F];
910 /*setup and start the Xfer */
911 ep->xfer_buff = pBuf;
915 ep->num = ep_addr & 0x7F;
919 if ((ep_addr & 0x7F) == 0 )
921 USB_EP0StartXfer(hpcd->Instance , ep);
925 USB_EPStartXfer(hpcd->Instance , ep);
933 * @brief Get Received Data Size
934 * @param hpcd: PCD handle
935 * @param ep_addr: endpoint address
938 uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
940 return hpcd->OUT_ep[ep_addr & 0x7F].xfer_count;
943 * @brief Send an amount of data
944 * @param hpcd: PCD handle
945 * @param ep_addr: endpoint address
946 * @param pBuf: pointer to the transmission buffer
947 * @param len: amount of data to be sent
950 HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
952 PCD_EPTypeDef *ep = NULL;
954 ep = &hpcd->IN_ep[ep_addr & 0x7F];
956 /*setup and start the Xfer */
957 ep->xfer_buff = pBuf;
961 ep->num = ep_addr & 0x7F;
965 if ((ep_addr & 0x7F) == 0 )
967 USB_EP0StartXfer(hpcd->Instance , ep);
971 USB_EPStartXfer(hpcd->Instance , ep);
980 * @brief Set a STALL condition over an endpoint
981 * @param hpcd: PCD handle
982 * @param ep_addr: endpoint address
985 HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
987 PCD_EPTypeDef *ep = NULL;
989 if ((0x80 & ep_addr) == 0x80)
991 ep = &hpcd->IN_ep[ep_addr & 0x7F];
995 ep = &hpcd->OUT_ep[ep_addr];
999 ep->num = ep_addr & 0x7F;
1000 ep->is_in = ((ep_addr & 0x80) == 0x80);
1003 USB_EPSetStall(hpcd->Instance , ep);
1004 if((ep_addr & 0x7F) == 0)
1006 USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
1014 * @brief Clear a STALL condition over in an endpoint
1015 * @param hpcd: PCD handle
1016 * @param ep_addr: endpoint address
1017 * @retval HAL status
1019 HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1021 PCD_EPTypeDef *ep = NULL;
1023 if ((0x80 & ep_addr) == 0x80)
1025 ep = &hpcd->IN_ep[ep_addr & 0x7F];
1029 ep = &hpcd->OUT_ep[ep_addr];
1033 ep->num = ep_addr & 0x7F;
1034 ep->is_in = ((ep_addr & 0x80) == 0x80);
1037 USB_EPClearStall(hpcd->Instance , ep);
1044 * @brief Flush an endpoint
1045 * @param hpcd: PCD handle
1046 * @param ep_addr: endpoint address
1047 * @retval HAL status
1049 HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1053 if ((ep_addr & 0x80) == 0x80)
1055 USB_FlushTxFifo(hpcd->Instance, ep_addr & 0x7F);
1059 USB_FlushRxFifo(hpcd->Instance);
1068 * @brief HAL_PCD_ActivateRemoteWakeup : active remote wakeup signalling
1069 * @param hpcd: PCD handle
1070 * @retval HAL status
1072 HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1074 return(USB_ActivateRemoteWakeup(hpcd->Instance));
1078 * @brief HAL_PCD_DeActivateRemoteWakeup : de-active remote wakeup signalling
1079 * @param hpcd: PCD handle
1080 * @retval HAL status
1082 HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1084 return(USB_DeActivateRemoteWakeup(hpcd->Instance));
1090 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
1091 * @brief Peripheral State functions
1094 ===============================================================================
1095 ##### Peripheral State functions #####
1096 ===============================================================================
1098 This subsection permits to get in run-time the status of the peripheral
1106 * @brief Return the PCD state
1107 * @param hpcd: PCD handle
1110 PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
1123 /** @addtogroup PCD_Private_Functions
1126 #if defined (USB_OTG_FS)
1128 * @brief DCD_WriteEmptyTxFifo
1129 * check FIFO for the next packet to be loaded
1130 * @param hpcd: PCD handle
1131 * @param epnum : endpoint number
1132 * This parameter can be a value from 0 to 15
1133 * @retval HAL status
1135 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
1137 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1138 USB_OTG_EPTypeDef *ep = NULL;
1140 uint32_t len32b = 0;
1141 uint32_t fifoemptymsk = 0;
1143 ep = &hpcd->IN_ep[epnum];
1144 len = ep->xfer_len - ep->xfer_count;
1146 if (len > ep->maxpacket)
1148 len = ep->maxpacket;
1151 len32b = (len + 3) / 4;
1153 while ((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) > len32b &&
1154 ep->xfer_count < ep->xfer_len &&
1157 /* Write the FIFO */
1158 len = ep->xfer_len - ep->xfer_count;
1160 if (len > ep->maxpacket)
1162 len = ep->maxpacket;
1164 len32b = (len + 3) / 4;
1166 USB_WritePacket(USBx, ep->xfer_buff, epnum, len);
1168 ep->xfer_buff += len;
1169 ep->xfer_count += len;
1174 fifoemptymsk = 0x1 << epnum;
1175 USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
1181 #endif /* USB_OTG_FS */
1185 * @brief This function handles PCD Endpoint interrupt request.
1186 * @param hpcd: PCD handle
1187 * @retval HAL status
1189 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
1191 PCD_EPTypeDef *ep = NULL;
1193 uint8_t epindex = 0;
1194 __IO uint16_t wIstr = 0;
1195 __IO uint16_t wEPVal = 0;
1197 /* stay in loop while pending interrupts */
1198 while (((wIstr = hpcd->Instance->ISTR) & USB_ISTR_CTR) != 0)
1200 /* extract highest priority endpoint number */
1201 epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
1205 /* Decode and service control endpoint interrupt */
1207 /* DIR bit = origin of the interrupt */
1208 if ((wIstr & USB_ISTR_DIR) == 0)
1212 /* DIR = 0 => IN int */
1213 /* DIR = 0 implies that (EP_CTR_TX = 1) always */
1214 PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1215 ep = &hpcd->IN_ep[0];
1217 ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1218 ep->xfer_buff += ep->xfer_count;
1221 HAL_PCD_DataInStageCallback(hpcd, 0);
1224 if((hpcd->USB_Address > 0)&& ( ep->xfer_len == 0))
1226 hpcd->Instance->DADDR = (hpcd->USB_Address | USB_DADDR_EF);
1227 hpcd->USB_Address = 0;
1235 /* DIR = 1 & CTR_RX => SETUP or OUT int */
1236 /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
1237 ep = &hpcd->OUT_ep[0];
1238 wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
1240 if ((wEPVal & USB_EP_SETUP) != 0)
1242 /* Get SETUP Packet*/
1243 ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1244 USB_ReadPMA(hpcd->Instance, (uint8_t*)hpcd->Setup ,ep->pmaadress , ep->xfer_count);
1245 /* SETUP bit kept frozen while CTR_RX = 1*/
1246 PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1248 /* Process SETUP Packet*/
1249 HAL_PCD_SetupStageCallback(hpcd);
1252 else if ((wEPVal & USB_EP_CTR_RX) != 0)
1254 PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1255 /* Get Control Data OUT Packet*/
1256 ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1258 if (ep->xfer_count != 0)
1260 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count);
1261 ep->xfer_buff+=ep->xfer_count;
1264 /* Process Control Data OUT Packet*/
1265 HAL_PCD_DataOutStageCallback(hpcd, 0);
1267 PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
1268 PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
1274 /* Decode and service non control endpoints interrupt */
1276 /* process related endpoint register */
1277 wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
1278 if ((wEPVal & USB_EP_CTR_RX) != 0)
1280 /* clear int flag */
1281 PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
1282 ep = &hpcd->OUT_ep[epindex];
1284 /* OUT double Buffering*/
1285 if (ep->doublebuffer == 0)
1287 count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1290 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
1295 if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX)
1297 /*read from endpoint BUF0Addr buffer*/
1298 count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1301 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
1306 /*read from endpoint BUF1Addr buffer*/
1307 count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
1310 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
1313 PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT);
1315 /*multi-packet on the NON control OUT endpoint*/
1316 ep->xfer_count+=count;
1317 ep->xfer_buff+=count;
1319 if ((ep->xfer_len == 0) || (count < ep->maxpacket))
1322 HAL_PCD_DataOutStageCallback(hpcd, ep->num);
1326 HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
1329 } /* if((wEPVal & EP_CTR_RX) */
1331 if ((wEPVal & USB_EP_CTR_TX) != 0)
1333 ep = &hpcd->IN_ep[epindex];
1335 /* clear int flag */
1336 PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
1338 /* IN double Buffering*/
1339 if (ep->doublebuffer == 0)
1341 ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1342 if (ep->xfer_count != 0)
1344 USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count);
1349 if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_TX)
1351 /*read from endpoint BUF0Addr buffer*/
1352 ep->xfer_count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1353 if (ep->xfer_count != 0)
1355 USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, ep->xfer_count);
1360 /*read from endpoint BUF1Addr buffer*/
1361 ep->xfer_count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
1362 if (ep->xfer_count != 0)
1364 USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, ep->xfer_count);
1367 PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_IN);
1369 /*multi-packet on the NON control IN endpoint*/
1370 ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1371 ep->xfer_buff+=ep->xfer_count;
1373 /* Zero Length Packet? */
1374 if (ep->xfer_len == 0)
1377 HAL_PCD_DataInStageCallback(hpcd, ep->num);
1381 HAL_PCD_EP_Transmit(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
1398 #endif /* STM32F102x6 || STM32F102xB || */
1399 /* STM32F103x6 || STM32F103xB || */
1400 /* STM32F103xE || STM32F103xG || */
1401 /* STM32F105xC || STM32F107xC */
1403 #endif /* HAL_PCD_MODULE_ENABLED */
1410 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/