/** * @brief Initialize the host driver * @param hhcd : HCD handle * @retval HAL state */ HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd) { /* Check the HCD handle allocation */ if(hhcd == NULL) { return HAL_ERROR; } /* Check the parameters */ assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance)); hhcd->State = HCD_BUSY; /* Init the low level hardware : GPIO, CLOCK, NVIC... */ HAL_HCD_MspInit(hhcd); /* Disable the Interrupts */ __HAL_HCD_DISABLE(hhcd); /*Init the Core (common init.) */ USB_CoreInit(hhcd->Instance, hhcd->Init); /* Force Host Mode*/ USB_SetCurrentMode(hhcd->Instance , USB_OTG_HOST_MODE); /* Init Host */ USB_HostInit(hhcd->Instance, hhcd->Init); hhcd->State= HCD_READY; return HAL_OK; }
/** * @brief DeInitialize the host driver * @param hhcd : HCD handle * @retval HAL state */ HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd) { /* Check the HCD handle allocation */ if(hhcd == NULL) { return HAL_ERROR; } hhcd->State = HCD_BUSY; /* DeInit the low level hardware */ HAL_HCD_MspDeInit(hhcd); __HAL_HCD_DISABLE(hhcd); hhcd->State = HCD_READY; return HAL_OK; }
/** * @brief Submit a new URB for processing * @param hhcd: HCD handle * @param ch_num: Channel number. * This parameter can be a value from 1 to 15 * @param direction: Channel number. * This parameter can be one of these values: * 0 : Output / 1 : Input * @param ep_type: Endpoint Type. * This parameter can be one of these values: * EP_TYPE_CTRL: Control type/ * EP_TYPE_ISOC: Isochronous type/ * EP_TYPE_BULK: Bulk type/ * EP_TYPE_INTR: Interrupt type/ * @param token: Endpoint Type. * This parameter can be one of these values: * 0: HC_PID_SETUP / 1: HC_PID_DATA1 * @param pbuff: pointer to URB data * @param length: Length of URB data * @param do_ping: activate do ping protocol (for high speed only). * This parameter can be one of these values: * 0 : do ping inactive / 1 : do ping active * @retval HAL status */ HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t direction, uint8_t ep_type, uint8_t token, uint8_t* pbuff, uint16_t length, uint8_t do_ping) { HAL_StatusTypeDef status; hhcd->hc[ch_num].ep_is_in = direction; hhcd->hc[ch_num].ep_type = ep_type; if(token == 0) { hhcd->hc[ch_num].data_pid = HC_PID_SETUP; } else { hhcd->hc[ch_num].data_pid = HC_PID_DATA1; } /* Manage Data Toggle */ switch(ep_type) { case EP_TYPE_CTRL: if((token == 1) && (direction == 0)) /*send data */ { if ( length == 0 ) { /* For Status OUT stage, Length==0, Status Out PID = 1 */ hhcd->hc[ch_num].toggle_out = 1; } /* Set the Data Toggle bit as per the Flag */ if ( hhcd->hc[ch_num].toggle_out == 0) { /* Put the PID 0 */ hhcd->hc[ch_num].data_pid = HC_PID_DATA0; } else { /* Put the PID 1 */ hhcd->hc[ch_num].data_pid = HC_PID_DATA1; } if(hhcd->hc[ch_num].urb_state != URB_NOTREADY) { hhcd->hc[ch_num].do_ping = do_ping; } } break; case EP_TYPE_BULK: if(direction == 0) { /* Set the Data Toggle bit as per the Flag */ if ( hhcd->hc[ch_num].toggle_out == 0) { /* Put the PID 0 */ hhcd->hc[ch_num].data_pid = HC_PID_DATA0; } else { /* Put the PID 1 */ hhcd->hc[ch_num].data_pid = HC_PID_DATA1; } if(hhcd->hc[ch_num].urb_state != URB_NOTREADY) { hhcd->hc[ch_num].do_ping = do_ping; } } else { if( hhcd->hc[ch_num].toggle_in == 0) { hhcd->hc[ch_num].data_pid = HC_PID_DATA0; } else { hhcd->hc[ch_num].data_pid = HC_PID_DATA1; } } break; case EP_TYPE_INTR: if(direction == 0) { /* Set the Data Toggle bit as per the Flag */ if ( hhcd->hc[ch_num].toggle_out == 0) { /* Put the PID 0 */ hhcd->hc[ch_num].data_pid = HC_PID_DATA0; } else { /* Put the PID 1 */ hhcd->hc[ch_num].data_pid = HC_PID_DATA1; } } else { if( hhcd->hc[ch_num].toggle_in == 0) { hhcd->hc[ch_num].data_pid = HC_PID_DATA0; } else { hhcd->hc[ch_num].data_pid = HC_PID_DATA1; } } break; case EP_TYPE_ISOC: hhcd->hc[ch_num].data_pid = HC_PID_DATA0; break; } hhcd->hc[ch_num].xfer_buff = pbuff; hhcd->hc[ch_num].xfer_len = length; hhcd->hc[ch_num].urb_state = URB_IDLE; hhcd->hc[ch_num].xfer_count = 0; hhcd->hc[ch_num].ch_num = ch_num; hhcd->hc[ch_num].state = HC_IDLE; hc_helper_sumbit_request(); __HAL_HCD_DISABLE(hhcd); if (!HAL_HCD_ATTACHED(hhcd)) { USBH_UsrLog("USB_HC_StartXfer run after detached."); status = HAL_ERROR; } else { status = USB_HC_StartXfer(hhcd->Instance, &(hhcd->hc[ch_num]), hhcd->Init.dma_enable); } __HAL_HCD_ENABLE(hhcd); return status; }
/** * @brief This function handles Host Port interrupt requests. * @param hhcd: HCD handle * @retval None */ static void HCD_Port_IRQHandler (HCD_HandleTypeDef *hhcd) { USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; __IO uint32_t hprt0, hprt0_dup; /* Handle Host Port Interrupts */ hprt0 = USBx_HPRT0; hprt0_dup = USBx_HPRT0; hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); /* Check whether Port Connect Detected */ if((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET) { if (DebugConfig.print_hcd_event) { USBH_PutMessage("CONNECT"); } if((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS) { USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); /* connect callback is used for port up only, now */ // HAL_HCD_Connect_Callback(hhcd); } hprt0_dup |= USB_OTG_HPRT_PCDET; } /* Check whether Port Enable Changed */ if((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG) { hprt0_dup |= USB_OTG_HPRT_PENCHNG; if((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA) { if (DebugConfig.print_hcd_event) { USBH_PutMessage("PORTUP"); } if(hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY) { if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17)) { USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_6_MHZ ); } else { USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ ); } } else { if(hhcd->Init.speed == HCD_SPEED_FULL) { USBx_HOST->HFIR = (uint32_t)60000; } } HAL_HCD_Connect_Callback(hhcd); if(hhcd->Init.speed == HCD_SPEED_HIGH) { USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); } } else { if (DebugConfig.print_hcd_event) { USBH_PutMessage("PORTDOWN"); } /* Cleanup HPRT */ USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); // This is EXTREMELY important to clean up hardware here // Other ways won't do if DMA is enabled, you got very unstable // enumeration during disconnect and reconnect if (DebugConfig.do_nothing_after_port_down) { } else if (DebugConfig.do_only_disable_global_int_after_port_down) { __HAL_HCD_DISABLE(hhcd); } else { HAL_HCD_Stop(hhcd); } HAL_HCD_Disconnect_Callback(hhcd); } } /* Check for an overcurrent */ if((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG) { hprt0_dup |= USB_OTG_HPRT_POCCHNG; } /* Clear Port Interrupts */ USBx_HPRT0 = hprt0_dup; }