/** ************************************************************************** * @file at32f435_437_usb.c * @version v2.0.9 * @date 2022-06-28 * @brief contains all the functions for the usb firmware library ************************************************************************** * Copyright notice & Disclaimer * * The software Board Support Package (BSP) that is made available to * download from Artery official website is the copyrighted work of Artery. * Artery authorizes customers to use, copy, and distribute the BSP * software and its related documentation for the purpose of design and * development in conjunction with Artery microcontrollers. Use of the * software is governed by this copyright notice and the following disclaimer. * * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. * ************************************************************************** */ #include "at32f435_437_conf.h" /** @addtogroup AT32F435_437_periph_driver * @{ */ /** @defgroup USB * @brief USB driver modules * @{ */ #ifdef USB_MODULE_ENABLED /** @defgroup USB_private_functions * @{ */ #ifdef OTGFS_USB_GLOBAL /** * @brief usb global core soft reset * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval error status */ error_status usb_global_reset(otg_global_type *usbx) { uint32_t timeout = 0; while(usbx->grstctl_bit.ahbidle == RESET) { if(timeout ++ > 200000) { break; } } timeout = 0; usbx->grstctl_bit.csftrst = TRUE; while(usbx->grstctl_bit.csftrst == SET) { if(timeout ++ > 200000) { break; } } return SUCCESS; } /** * @brief usb global initialization * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_global_init(otg_global_type *usbx) { /* reset otg moudle */ usb_global_reset(usbx); /* exit power down mode */ usbx->gccfg_bit.pwrdown = TRUE; } /** * @brief usb global select usb core (otg1 or otg2). * @param usb_id: select otg1 or otg2 * this parameter can be one of the following values: * - USB_OTG1_ID * - USB_OTG2_ID * @retval usb global register type pointer */ otg_global_type *usb_global_select_core(uint8_t usb_id) { if(usb_id == USB_OTG1_ID) { /* use otg1 */ return OTG1_GLOBAL; } else { /* use otg2 */ return OTG2_GLOBAL; } } /** * @brief flush tx fifo * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param fifo_num: tx fifo num,when fifo_num=16,flush all tx fifo * parameter as following values: 0-16 * @retval none */ void usb_flush_tx_fifo(otg_global_type *usbx, uint32_t fifo_num) { uint32_t timeout = 0; /* set flush fifo number */ usbx->grstctl_bit.txfnum = fifo_num; /* start flush fifo */ usbx->grstctl_bit.txfflsh = TRUE; while(usbx->grstctl_bit.txfflsh == TRUE) { if(timeout ++ > 200000) { break; } } } /** * @brief flush rx fifo * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_flush_rx_fifo(otg_global_type *usbx) { uint32_t timeout = 0; usbx->grstctl_bit.rxfflsh = TRUE; while(usbx->grstctl_bit.rxfflsh == TRUE) { if(timeout ++ > 200000) { break; } } } /** * @brief usb interrupt mask enable * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param interrupt: * this parameter can be any combination of the following values: * - USB_OTG_MODEMIS_INT * - USB_OTG_OTGINT_INT * - USB_OTG_SOF_INT * - USB_OTG_RXFLVL_INT * - USB_OTG_NPTXFEMP_INT * - USB_OTG_GINNAKEFF_INT * - USB_OTG_GOUTNAKEFF_INT * - USB_OTG_ERLYSUSP_INT * - USB_OTG_USBSUSP_INT * - USB_OTG_USBRST_INT * - USB_OTG_ENUMDONE_INT * - USB_OTG_ISOOUTDROP_INT * - USB_OTG_IEPT_INT * - USB_OTG_OEPT_INT * - USB_OTG_INCOMISOIN_INT * - USB_OTG_INCOMPIP_INCOMPISOOUT_INT * - USB_OTG_PRT_INT * - USB_OTG_HCH_INT * - USB_OTG_PTXFEMP_INT * - USB_OTG_CONIDSCHG_INT * - USB_OTG_DISCON_INT * - USB_OTG_WKUP_INT * @param new_state: TRUE or FALSE * @retval none */ void usb_global_interrupt_enable(otg_global_type *usbx, uint16_t interrupt, confirm_state new_state) { if(new_state == TRUE) { usbx->gintmsk |= interrupt; } else { usbx->gintmsk &= ~interrupt; } } /** * @brief get all global core interrupt flag * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval intterupt flag */ uint32_t usb_global_get_all_interrupt(otg_global_type *usbx) { uint32_t intsts = usbx->gintsts; return intsts & usbx->gintmsk; } /** * @brief clear the global interrupt flag * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param flag: interrupt flag * this parameter can be any combination of the following values: * - USB_OTG_MODEMIS_FLAG * - USB_OTG_OTGINT_FLAG * - USB_OTG_SOF_FLAG * - USB_OTG_RXFLVL_FLAG * - USB_OTG_NPTXFEMP_FLAG * - USB_OTG_GINNAKEFF_FLAG * - USB_OTG_GOUTNAKEFF_FLAG * - USB_OTG_ERLYSUSP_FLAG * - USB_OTG_USBSUSP_FLAG * - USB_OTG_USBRST_FLAG * - USB_OTG_ENUMDONE_FLAG * - USB_OTG_ISOOUTDROP_FLAG * - USB_OTG_EOPF_FLAG * - USB_OTG_IEPT_FLAG * - USB_OTG_OEPT_FLAG * - USB_OTG_INCOMISOIN_FLAG * - USB_OTG_INCOMPIP_INCOMPISOOUT_FLAG * - USB_OTG_PRT_FLAG * - USB_OTG_HCH_FLAG * - USB_OTG_PTXFEMP_FLAG * - USB_OTG_CONIDSCHG_FLAG * - USB_OTG_DISCON_FLAG * - USB_OTG_WKUP_FLAG * @retval none */ void usb_global_clear_interrupt(otg_global_type *usbx, uint32_t flag) { usbx->gintsts = flag; } /** * @brief usb global interrupt enable * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * OTG1_GLOBAL , OTG2_GLOBAL * @retval none */ void usb_interrupt_enable(otg_global_type *usbx) { usbx->gahbcfg_bit.glbintmsk = TRUE; } /** * @brief usb global interrupt disable * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_interrupt_disable(otg_global_type *usbx) { usbx->gahbcfg_bit.glbintmsk = FALSE; } /** * @brief usb set rx fifo size * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param size: rx fifo size * @retval none */ void usb_set_rx_fifo(otg_global_type *usbx, uint16_t size) { usbx->grxfsiz = size; } /** * @brief usb set tx fifo size * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param txfifo: the fifo number * @param size: tx fifo size * @retval none */ void usb_set_tx_fifo(otg_global_type *usbx, uint8_t txfifo, uint16_t size) { uint8_t i_index = 0; uint32_t offset = 0; offset = usbx->grxfsiz; if(txfifo == 0) { usbx->gnptxfsiz_ept0tx = offset | (size << 16); } else { offset += usbx->gnptxfsiz_ept0tx_bit.nptxfdep; for(i_index = 0; i_index < (txfifo - 1); i_index ++) { offset += usbx->dieptxfn_bit[i_index].ineptxfdep; } usbx->dieptxfn[txfifo - 1] = offset | (size << 16); } } /** * @brief set otg mode(device or host mode) * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param mode: this parameter can be one of the following values: * - OTG_DEVICE_MODE * - OTG_HOST_MODE * - OTG_DRD_MODE * @retval none */ void usb_global_set_mode(otg_global_type *usbx, uint32_t mode) { /* set otg to device mode */ if(mode == OTG_DEVICE_MODE) { usbx->gusbcfg_bit.fhstmode = FALSE; usbx->gusbcfg_bit.fdevmode = TRUE; } /* set otg to host mode */ if(mode == OTG_HOST_MODE) { usbx->gusbcfg_bit.fdevmode = FALSE; usbx->gusbcfg_bit.fhstmode = TRUE; } /* set otg to default mode */ if(mode == OTG_DRD_MODE) { usbx->gusbcfg_bit.fdevmode = FALSE; usbx->gusbcfg_bit.fhstmode = FALSE; } } /** * @brief disable the transceiver power down mode * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_global_power_on(otg_global_type *usbx) { /* core soft reset */ usbx->grstctl_bit.csftrst = TRUE; while(usbx->grstctl_bit.csftrst); /* disable power down mode */ usbx->gccfg_bit.pwrdown = TRUE; } /** * @brief usb stop phy clock * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_stop_phy_clk(otg_global_type *usbx) { OTG_PCGCCTL(usbx)->pcgcctl_bit.stoppclk = TRUE; } /** * @brief usb open phy clock * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_open_phy_clk(otg_global_type *usbx) { OTG_PCGCCTL(usbx)->pcgcctl_bit.stoppclk = FALSE; } /** * @brief write data from user memory to usb buffer * @param pusr_buf: point to user buffer * @param offset_addr: endpoint tx offset address * @param nbytes: number of bytes data write to usb buffer * @retval none */ void usb_write_packet(otg_global_type *usbx, uint8_t *pusr_buf, uint16_t num, uint16_t nbytes) { uint32_t n_index; uint32_t nhbytes = (nbytes + 3) / 4; uint32_t *pbuf = (uint32_t *)pusr_buf; for(n_index = 0; n_index < nhbytes; n_index ++) { #if defined (__ICCARM__) && (__VER__ < 7000000) USB_FIFO(usbx, num) = *(__packed uint32_t *)pbuf; #else USB_FIFO(usbx, num) = __UNALIGNED_UINT32_READ(pbuf); #endif pbuf ++; } } /** * @brief read data from usb buffer to user buffer * @param pusr_buf: point to user buffer * @param offset_addr: endpoint rx offset address * @param nbytes: number of bytes data write to usb buffer * @retval none */ void usb_read_packet(otg_global_type *usbx, uint8_t *pusr_buf, uint16_t num, uint16_t nbytes) { uint32_t n_index; uint32_t nhbytes = (nbytes + 3) / 4; uint32_t *pbuf = (uint32_t *)pusr_buf; for(n_index = 0; n_index < nhbytes; n_index ++) { #if defined (__ICCARM__) && (__VER__ < 7000000) *(__packed uint32_t *)pbuf = USB_FIFO(usbx, 0); #else __UNALIGNED_UINT32_WRITE(pbuf, (USB_FIFO(usbx, 0))); #endif pbuf ++; } } #endif #ifdef OTGFS_USB_DEVICE /** * @brief open usb endpoint * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param ept_info: endpoint information structure * @retval none */ void usb_ept_open(otg_global_type *usbx, usb_ept_info *ept_info) { uint8_t mps = USB_EPT0_MPS_64; if(ept_info->eptn == USB_EPT0) { if(ept_info->maxpacket == 0x40) { mps = USB_EPT0_MPS_64; } else if(ept_info->maxpacket == 0x20) { mps = USB_EPT0_MPS_32; } else if(ept_info->maxpacket == 0x10) { mps = USB_EPT0_MPS_16; } else if(ept_info->maxpacket == 0x08) { mps = USB_EPT0_MPS_8; } } /* endpoint direction is in */ if(ept_info->inout == EPT_DIR_IN) { OTG_DEVICE(usbx)->daintmsk |= 1 << ept_info->eptn; if(ept_info->eptn == USB_EPT0) { USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.mps = mps; } else { USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.mps = ept_info->maxpacket; } USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.eptype = ept_info->trans_type; USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.txfnum = ept_info->eptn; USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.setd0pid = TRUE; USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.usbacept = TRUE; } /* endpoint direction is out */ else { OTG_DEVICE(usbx)->daintmsk |= (1 << ept_info->eptn) << 16; if(ept_info->eptn == USB_EPT0) { USB_OUTEPT(usbx, ept_info->eptn)->doepctl_bit.mps = mps; } else { USB_OUTEPT(usbx, ept_info->eptn)->doepctl_bit.mps = ept_info->maxpacket; } USB_OUTEPT(usbx, ept_info->eptn)->doepctl_bit.eptype = ept_info->trans_type; USB_OUTEPT(usbx, ept_info->eptn)->doepctl_bit.setd0pid = TRUE; USB_OUTEPT(usbx, ept_info->eptn)->doepctl_bit.usbacept = TRUE; } } /** * @brief close usb endpoint * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param ept_info: endpoint information structure * @retval none */ void usb_ept_close(otg_global_type *usbx, usb_ept_info *ept_info) { if(ept_info->inout == EPT_DIR_IN) { OTG_DEVICE(usbx)->daintmsk &= ~(1 << ept_info->eptn); USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.usbacept = FALSE; } else { OTG_DEVICE(usbx)->daintmsk &= ~((1 << ept_info->eptn) << 16); USB_OUTEPT(usbx, ept_info->eptn)->doepctl_bit.usbacept = FALSE; } } /** * @brief set endpoint tx or rx status to stall * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param ept_info: endpoint information structure * @retval none */ void usb_ept_stall(otg_global_type *usbx, usb_ept_info *ept_info) { if(ept_info->inout == EPT_DIR_IN) { if(USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.eptena == RESET) { USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.eptdis = FALSE; } USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.stall = SET; } else { if(USB_OUTEPT(usbx, ept_info->eptn)->doepctl_bit.eptena == RESET) { USB_OUTEPT(usbx, ept_info->eptn)->doepctl_bit.eptdis = FALSE; } USB_OUTEPT(usbx, ept_info->eptn)->doepctl_bit.stall = TRUE; } } /** * @brief clear endpoint tx or rx status to stall * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param ept_info: endpoint information structure * @retval none */ void usb_ept_clear_stall(otg_global_type *usbx, usb_ept_info *ept_info) { if(ept_info->inout == EPT_DIR_IN) { USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.stall = FALSE; if(ept_info->trans_type == EPT_INT_TYPE || ept_info->trans_type == EPT_BULK_TYPE) { USB_INEPT(usbx, ept_info->eptn)->diepctl_bit.setd0pid = TRUE; } } else { USB_OUTEPT(usbx, ept_info->eptn)->doepctl_bit.stall = FALSE; if(ept_info->trans_type == EPT_INT_TYPE || ept_info->trans_type == EPT_BULK_TYPE) { USB_OUTEPT(usbx, ept_info->eptn)->doepctl_bit.setd0pid = TRUE; } } } /** * @brief get all out endpoint interrupt bits * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval out endpoint interrupt bits */ uint32_t usb_get_all_out_interrupt(otg_global_type *usbx) { uint32_t intsts = OTG_DEVICE(usbx)->daint; return ((intsts & (OTG_DEVICE(usbx)->daintmsk)) >> 16); } /** * @brief get all in endpoint interrupt bits * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval in endpoint interrupt bits */ uint32_t usb_get_all_in_interrupt(otg_global_type *usbx) { uint32_t intsts = OTG_DEVICE(usbx)->daint; return ((intsts & (OTG_DEVICE(usbx)->daintmsk)) & 0xFFFF); } /** * @brief get out endpoint interrupt flag * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param eptn: endpoint number * @retval out endpoint interrupt flags */ uint32_t usb_ept_out_interrupt(otg_global_type *usbx, uint32_t eptn) { uint32_t intsts = USB_OUTEPT(usbx, eptn)->doepint; return (intsts & (OTG_DEVICE(usbx)->doepmsk)); } /** * @brief get in endpoint interrupt flag * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param eptn: endpoint number * @retval in endpoint intterupt flags */ uint32_t usb_ept_in_interrupt(otg_global_type *usbx, uint32_t eptn) { uint32_t intsts, mask1, mask2; mask1 = OTG_DEVICE(usbx)->diepmsk; mask2 = OTG_DEVICE(usbx)->diepempmsk; mask1 |= ((mask2 >> eptn) & 0x1) << 7; intsts = USB_INEPT(usbx, eptn)->diepint & mask1; return intsts; } /** * @brief clear out endpoint interrupt flag * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param eptn: endpoint number * @retval flag: interrupt flag * this parameter can be any combination of the following values: * - USB_OTG_DOEPINT_XFERC_FLAG * - USB_OTG_DOEPINT_EPTDISD_FLAG * - USB_OTG_DOEPINT_SETUP_FLAG * - USB_OTG_DOEPINT_OTEPDIS_FLAG * - USB_OTG_DOEPINT_B2BSTUP_FLAG */ void usb_ept_out_clear(otg_global_type *usbx, uint32_t eptn, uint32_t flag) { USB_OUTEPT(usbx, eptn)->doepint = flag; } /** * @brief clear in endpoint interrupt flag * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param eptn: endpoint number * @retval flag: interrupt flag * this parameter can be any combination of the following values: * - USB_OTG_DIEPINT_XFERC_FLAG * - USB_OTG_DIEPINT_EPTDISD_FLAG * - USB_OTG_DIEPINT_TMROC_FLAG * - USB_OTG_DIEPINT_INTTXFE_FLAG * - USB_OTG_DIEPINT_INEPNE_FLAG * - USB_OTG_DIEPINT_TXFE_FLAG */ void usb_ept_in_clear(otg_global_type *usbx, uint32_t eptn, uint32_t flag) { USB_INEPT(usbx, eptn)->diepint = flag; } /** * @brief set the host assignment address * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param address: host assignment address * @retval none */ void usb_set_address(otg_global_type *usbx, uint8_t address) { OTG_DEVICE(usbx)->dcfg_bit.devaddr = address; } /** * @brief enable endpoint 0 out * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_ept0_start(otg_global_type *usbx) { otg_eptout_type *usb_outept = USB_OUTEPT(usbx, 0); usb_outept->doeptsiz = 0; usb_outept->doeptsiz_bit.pktcnt = 1; usb_outept->doeptsiz_bit.xfersize = 24; usb_outept->doeptsiz_bit.rxdpid_setupcnt = 3; } /** * @brief endpoint 0 start setup * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_ept0_setup(otg_global_type *usbx) { USB_INEPT(usbx, 0)->diepctl_bit.mps = 0; OTG_DEVICE(usbx)->dctl_bit.cgnpinak = FALSE; } /** * @brief connect usb device by enable pull-up * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_connect(otg_global_type *usbx) { /* D+ 1.5k pull-up enable */ OTG_DEVICE(usbx)->dctl_bit.sftdiscon = FALSE; } /** * @brief disconnect usb device by disable pull-up * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_disconnect(otg_global_type *usbx) { /* D+ 1.5k pull-up disable */ OTG_DEVICE(usbx)->dctl_bit.sftdiscon = TRUE; } /** * @brief usb remote wakeup set * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_remote_wkup_set(otg_global_type *usbx) { OTG_DEVICE(usbx)->dctl_bit.rwkupsig = TRUE; } /** * @brief usb remote wakeup clear * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_remote_wkup_clear(otg_global_type *usbx) { OTG_DEVICE(usbx)->dctl_bit.rwkupsig = FALSE; } /** * @brief usb suspend status get * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval usb suspend status */ uint8_t usb_suspend_status_get(otg_global_type *usbx) { return OTG_DEVICE(usbx)->dsts_bit.suspsts; } #endif #ifdef OTGFS_USB_HOST /** * @brief usb port power on * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param state: state (TRUE or FALSE) * @retval none */ void usb_port_power_on(otg_global_type *usbx, confirm_state state) { otg_host_type *usb_host = OTG_HOST(usbx); uint32_t hprt_val = usb_host->hprt; hprt_val &= ~(USB_OTG_HPRT_PRTENA | USB_OTG_HPRT_PRTENCHNG | USB_OTG_HPRT_PRTOVRCACT | USB_OTG_HPRT_PRTCONDET); if(state == TRUE) { usb_host->hprt = hprt_val | USB_OTG_HPRT_PRTPWR; } else { usb_host->hprt = hprt_val & (~USB_OTG_HPRT_PRTPWR); } } /** * @brief get current frame number * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ uint32_t usbh_get_frame(otg_global_type *usbx) { otg_host_type *usb_host = OTG_HOST(usbx); return usb_host->hfnum & 0xFFFF; } /** * @brief enable one host channel * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param chn: host channel number * @param ept_num: devvice endpoint number * @param dev_address: device address * @param type: channel transfer type * this parameter can be one of the following values: * - EPT_CONTROL_TYPE * - EPT_BULK_TYPE * - EPT_INT_TYPE * - EPT_ISO_TYPE * @param maxpacket: support max packe size for this channel * @param speed: device speed * this parameter can be one of the following values: * - USB_PRTSPD_FULL_SPEED * - USB_PRTSPD_LOW_SPEED * @retval none */ void usb_hc_enable(otg_global_type *usbx, uint8_t chn, uint8_t ept_num, uint8_t dev_address, uint8_t type, uint16_t maxpacket, uint8_t speed) { otg_hchannel_type *hch = USB_CHL(usbx, chn); otg_host_type *usb_host = OTG_HOST(usbx); switch(type) { case EPT_CONTROL_TYPE: case EPT_BULK_TYPE: hch->hcintmsk |= USB_OTG_HC_XFERCM_INT | USB_OTG_HC_STALLM_INT | USB_OTG_HC_XACTERRM_INT | USB_OTG_HC_NAKM_INT | USB_OTG_HC_DTGLERRM_INT; if(ept_num & 0x80) { hch->hcintmsk_bit.bblerrmsk = TRUE; } break; case EPT_INT_TYPE: hch->hcintmsk |= USB_OTG_HC_XFERCM_INT | USB_OTG_HC_STALLM_INT | USB_OTG_HC_XACTERRM_INT | USB_OTG_HC_NAKM_INT | USB_OTG_HC_DTGLERRM_INT | USB_OTG_HC_FRMOVRRUN_INT; break; case EPT_ISO_TYPE: hch->hcintmsk |= USB_OTG_HC_XFERCM_INT | USB_OTG_HC_ACKM_INT | USB_OTG_HC_FRMOVRRUN_INT; break; } usb_host->haintmsk |= 1 << chn; usbx->gintmsk_bit.hchintmsk = TRUE; hch->hcchar_bit.devaddr = dev_address; hch->hcchar_bit.eptnum = ept_num & 0x7F; hch->hcchar_bit.eptdir = (ept_num & 0x80)?1:0; hch->hcchar_bit.lspddev = (speed == USB_PRTSPD_LOW_SPEED)?1:0; hch->hcchar_bit.eptype = type; hch->hcchar_bit.mps = maxpacket; if(type == EPT_INT_TYPE) { hch->hcchar_bit.oddfrm = TRUE; } } /** * @brief host read channel interrupt * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval interrupt flag */ uint32_t usb_hch_read_interrupt(otg_global_type *usbx) { otg_host_type *usb_host = OTG_HOST(usbx); return usb_host->haint & 0xFFFF; } /** * @brief disable host * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @retval none */ void usb_host_disable(otg_global_type *usbx) { uint32_t i_index = 0, count = 0; otg_hchannel_type *hch; otg_host_type *usb_host = OTG_HOST(usbx); usbx->gahbcfg_bit.glbintmsk = FALSE; usb_flush_rx_fifo(usbx); usb_flush_tx_fifo(usbx, 0x10); for(i_index = 0; i_index < 16; i_index ++) { hch = USB_CHL(usbx, i_index); hch->hcchar_bit.chdis = TRUE; hch->hcchar_bit.chena = FALSE; hch->hcchar_bit.eptdir = 0; } for(i_index = 0; i_index < 16; i_index ++) { hch = USB_CHL(usbx, i_index); hch->hcchar_bit.chdis = TRUE; hch->hcchar_bit.chena = TRUE; hch->hcchar_bit.eptdir = 0; do { if(count ++ > 1000) break; }while(hch->hcchar_bit.chena); } usb_host->haint = 0xFFFFFFFF; usbx->gintsts = 0xFFFFFFFF; usbx->gahbcfg_bit.glbintmsk = TRUE; } /** * @brief halt channel * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param chn: channel number * @retval none */ void usb_hch_halt(otg_global_type *usbx, uint8_t chn) { uint32_t count = 0; otg_hchannel_type *usb_chh = USB_CHL(usbx, chn); otg_host_type *usb_host = OTG_HOST(usbx); /* endpoint type is control or bulk */ if(usb_chh->hcchar_bit.eptype == EPT_CONTROL_TYPE || usb_chh->hcchar_bit.eptype == EPT_BULK_TYPE) { usb_chh->hcchar_bit.chdis = TRUE; if((usbx->gnptxsts & 0xFFFF) == 0) { usb_chh->hcchar_bit.chena = FALSE; usb_chh->hcchar_bit.chena = TRUE; usb_chh->hcchar_bit.eptdir = 0; do { if(count ++ > 1000) break; }while(usb_chh->hcchar_bit.chena == SET); } else { usb_chh->hcchar_bit.chena = TRUE; } } else { usb_chh->hcchar_bit.chdis = TRUE; if((usb_host->hptxsts & 0xFFFF) == 0) { usb_chh->hcchar_bit.chena = FALSE; usb_chh->hcchar_bit.chena = TRUE; usb_chh->hcchar_bit.eptdir = 0; do { if(count ++ > 1000) break; }while(usb_chh->hcchar_bit.chena == SET); } else { usb_chh->hcchar_bit.chena = TRUE; } } } /** * @brief select full or low speed clock * @param usbx: to select the otgfs peripheral. * this parameter can be one of the following values: * - OTG1_GLOBAL * - OTG2_GLOBAL * @param clk: clock frequency * @retval none */ void usbh_fsls_clksel(otg_global_type *usbx, uint8_t clk) { otg_host_type *usb_host = OTG_HOST(usbx); usb_host->hcfg_bit.fslspclksel = clk; if(clk == USB_HCFG_CLK_6M) { usb_host->hfir = 6000; } else { usb_host->hfir = 48000; } } #endif /** * @} */ #endif /** * @} */ /** * @} */