void MSC_Init(void) { /* Configure USB controller */ /* Enable USB BUS, CEP and EPA , EPB global interrupt */ UBSD_ENABLE_USB_INT(USBD_GINTEN_USBIE_Msk|USBD_GINTEN_CEPIE_Msk|USBD_GINTEN_EPAIE_Msk|USBD_GINTEN_EPBIE_Msk); /* Enable BUS interrupt */ UBSD_ENABLE_BUS_INT(USBD_BUSINTEN_DMADONEIEN_Msk|USBD_BUSINTEN_RESUMEIEN_Msk|USBD_BUSINTEN_RSTIEN_Msk|USBD_BUSINTEN_VBUSDETIEN_Msk); /* Reset Address to 0 */ USBD_SET_ADDR(0); /*****************************************************/ /* Control endpoint */ USBD_SetEpBufAddr(CEP, CEP_BUF_BASE, CEP_BUF_LEN); UBSD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk|USBD_CEPINTEN_STSDONEIEN_Msk); /*****************************************************/ /* EPA ==> Bulk IN endpoint, address 1 */ USBD_SetEpBufAddr(EPA, EPA_BUF_BASE, EPA_BUF_LEN); UBSD_SET_MAX_PAYLOAD(EPA, EPA_MAX_PKT_SIZE); USBD_ConfigEp(EPA, BULK_IN_EP_NUM, USB_EP_CFG_TYPE_BULK, USB_EP_CFG_DIR_IN); /* EPB ==> Bulk OUT endpoint, address 2 */ USBD_SetEpBufAddr(EPB, EPB_BUF_BASE, EPB_BUF_LEN); UBSD_SET_MAX_PAYLOAD(EPB, EPB_MAX_PKT_SIZE); USBD_ConfigEp(EPB, BULK_OUT_EP_NUM, USB_EP_CFG_TYPE_BULK, USB_EP_CFG_DIR_OUT); UBSD_ENABLE_EP_INT(EPB, USBD_EPINTEN_RXPKIEN_Msk); g_sCSW.dCSWSignature = CSW_SIGNATURE; g_TotalSectors = 60; g_u32MassBase = 0x20007000; g_u32StorageBase = 0x20008000; }
/** * @brief Repeat Control IN pipe * * @param None * * @return None * * @details This function processes the remained data of Control IN transfer. * */ void USBD_CtrlIn(void) { static uint8_t u8ZeroFlag = 0; if(g_usbd_CtrlInSize) { // Process remained data if(g_usbd_CtrlInSize > g_usbd_CtrlMaxPktSize) { // Data size > MXPLD USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlMaxPktSize); USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize); g_usbd_CtrlInPointer += g_usbd_CtrlMaxPktSize; g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize; } else { // Data size <= MXPLD USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlInSize); USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlInSize); if(g_usbd_CtrlInSize == g_usbd_CtrlMaxPktSize) u8ZeroFlag = 1; g_usbd_CtrlInPointer = 0; g_usbd_CtrlInSize = 0; } } else { // In ACK for Set address if((g_usbd_SetupPacket[0] == 0) && (g_usbd_SetupPacket[1] == 5)) { if((USBD_GET_ADDR() != g_usbd_UsbAddr) && (USBD_GET_ADDR() == 0)) { USBD_SET_ADDR(g_usbd_UsbAddr); } } // For size if n x MXPLD if(u8ZeroFlag) { USBD_SET_PAYLOAD_LEN(EP0, 0); u8ZeroFlag = 0; } // No more data for IN token USBD_PrepareCtrlOut(0, 0); DBG_PRINTF("Ctrl In Done.\n"); } }
/** * @brief Reset software flags * * @param None * * @return None * * @details This function resets all variables for protocol and resets USB device address to 0. * */ void USBD_SwReset(void) { // Reset all variables for protocol g_usbd_CtrlInPointer = 0; g_usbd_CtrlInSize = 0; g_usbd_CtrlOutPointer = 0; g_usbd_CtrlOutSize = 0; g_usbd_CtrlOutSizeLimit = 0; g_u32EpStallLock = 0; memset(g_usbd_SetupPacket, 0, 8); // Reset USB device address USBD_SET_ADDR(0); }
/** * @brief Repeat Control IN pipe * * @param None * * @return None * * @details This function processes the remained data of Control IN transfer. * */ void USBD_CtrlIn(void) { static uint8_t u8ZeroFlag = 0; DBG_PRINTF("Ctrl In Ack. residue %d\n", g_usbd_CtrlInSize); if(g_usbd_CtrlInSize) { // Process remained data if(g_usbd_CtrlInSize > g_usbd_CtrlMaxPktSize) { // Data size > MXPLD USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlMaxPktSize); USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize); g_usbd_CtrlInPointer += g_usbd_CtrlMaxPktSize; g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize; } else { // Data size <= MXPLD USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlInSize); USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlInSize); if(g_usbd_CtrlInSize == g_usbd_CtrlMaxPktSize) u8ZeroFlag = 1; g_usbd_CtrlInPointer = 0; g_usbd_CtrlInSize = 0; } } else // No more data for IN token { // In ACK for Set address if((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == USBD_SET_ADDRESS)) { if((USBD_GET_ADDR() != g_usbd_UsbAddr) && (USBD_GET_ADDR() == 0)) { USBD_SET_ADDR(g_usbd_UsbAddr); } } /* For the case of data size is integral times maximum packet size */ if(u8ZeroFlag) { USBD_SET_PAYLOAD_LEN(EP0, 0); u8ZeroFlag = 0; } DBG_PRINTF("Ctrl In done.\n"); } }
/** * @brief Reset software flags * * @param None * * @return None * * @details This function resets all variables for protocol and resets USB device address to 0. * */ void USBD_SwReset(void) { int i; // Reset all variables for protocol g_usbd_CtrlInPointer = 0; g_usbd_CtrlInSize = 0; g_usbd_CtrlOutPointer = 0; g_usbd_CtrlOutSize = 0; g_usbd_CtrlOutSizeLimit = 0; g_u32EpStallLock = 0; memset(g_usbd_SetupPacket, 0, 8); /* Reset PID DATA0 */ for(i=0; i<USBD_MAX_EP; i++) USBD->EP[i].CFG &= ~USBD_CFG_DSQSYNC_Msk; // Reset USB device address USBD_SET_ADDR(0); }
void USBD_IRQHandler(void) { __IO uint32_t IrqStL, IrqSt; IrqStL = USBD->GINTSTS & USBD->GINTEN; /* get interrupt status */ if (!IrqStL) return; /* USB interrupt */ if (IrqStL & USBD_GINTSTS_USBIF_Msk) { IrqSt = USBD->BUSINTSTS & USBD->BUSINTEN; if (IrqSt & USBD_BUSINTSTS_SOFIF_Msk) USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_SOFIF_Msk); if (IrqSt & USBD_BUSINTSTS_RSTIF_Msk) { USBD_SwReset(); g_u8MscStart = 0; g_u8BulkState = BULK_NORMAL; USBD_ResetDMA(); USBD->EPARSPCTL = USBD_EPRSPCTL_FLUSH_Msk; USBD->EPBRSPCTL = USBD_EPRSPCTL_FLUSH_Msk; UBSD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk); USBD_SET_ADDR(0); UBSD_ENABLE_BUS_INT(USBD_BUSINTEN_RSTIEN_Msk|USBD_BUSINTEN_RESUMEIEN_Msk|USBD_BUSINTEN_SUSPENDIEN_Msk); USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_RSTIF_Msk); USBD_CLR_CEP_INT_FLAG(0x1ffc); } if (IrqSt & USBD_BUSINTSTS_RESUMEIF_Msk) { UBSD_ENABLE_BUS_INT(USBD_BUSINTEN_RSTIEN_Msk|USBD_BUSINTEN_SUSPENDIEN_Msk); USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_RESUMEIF_Msk); } if (IrqSt & USBD_BUSINTSTS_SUSPENDIF_Msk) { UBSD_ENABLE_BUS_INT(USBD_BUSINTEN_RSTIEN_Msk | USBD_BUSINTEN_RESUMEIEN_Msk); USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_SUSPENDIF_Msk); } if (IrqSt & USBD_BUSINTSTS_HISPDIF_Msk) { UBSD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk); USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_HISPDIF_Msk); } if (IrqSt & USBD_BUSINTSTS_DMADONEIF_Msk) { g_usbd_DmaDone = 1; USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_DMADONEIF_Msk); if (!(USBD->DMACTL & USBD_DMACTL_DMARD_Msk)) { // if (g_u8BulkState == BULK_OUT) // g_u8BulkState = BULK_CBW; UBSD_ENABLE_EP_INT(EPB, USBD_EPINTEN_RXPKIEN_Msk); } if (USBD->DMACTL & USBD_DMACTL_DMARD_Msk) { if (g_usbd_ShortPacket == 1) { USBD->EPARSPCTL = USB_EP_RSPCTL_SHORTTXEN; // packet end g_usbd_ShortPacket = 0; } } } if (IrqSt & USBD_BUSINTSTS_PHYCLKVLDIF_Msk) USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_PHYCLKVLDIF_Msk); if (IrqSt & USBD_BUSINTSTS_VBUSDETIF_Msk) { if (USBD_IS_ATTACHED()) { /* USB Plug In */ USBD_ENABLE_USB(); } else { /* USB Un-plug */ USBD_DISABLE_USB(); } USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_VBUSDETIF_Msk); } } if (IrqStL & USBD_GINTSTS_CEPIF_Msk) { IrqSt = USBD->CEPINTSTS & USBD->CEPINTEN; if (IrqSt & USBD_CEPINTSTS_SETUPTKIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPTKIF_Msk); return; } if (IrqSt & USBD_CEPINTSTS_SETUPPKIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPPKIF_Msk); USBD_ProcessSetupPacket(); return; } if (IrqSt & USBD_CEPINTSTS_OUTTKIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_OUTTKIF_Msk); UBSD_ENABLE_CEP_INT(USBD_CEPINTEN_STSDONEIEN_Msk); return; } if (IrqSt & USBD_CEPINTSTS_INTKIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk); if (!(IrqSt & USBD_CEPINTSTS_STSDONEIF_Msk)) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_TXPKIF_Msk); UBSD_ENABLE_CEP_INT(USBD_CEPINTEN_TXPKIEN_Msk); USBD_CtrlIn(); } else { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_TXPKIF_Msk); UBSD_ENABLE_CEP_INT(USBD_CEPINTEN_TXPKIEN_Msk|USBD_CEPINTEN_STSDONEIEN_Msk); } return; } if (IrqSt & USBD_CEPINTSTS_PINGIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_PINGIF_Msk); return; } if (IrqSt & USBD_CEPINTSTS_TXPKIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk); USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); if (g_usbd_CtrlInSize) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk); UBSD_ENABLE_CEP_INT(USBD_CEPINTEN_INTKIEN_Msk); } else { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk); UBSD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk|USBD_CEPINTEN_STSDONEIEN_Msk); } USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_TXPKIF_Msk); return; } if (IrqSt & USBD_CEPINTSTS_RXPKIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_RXPKIF_Msk); USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); UBSD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk|USBD_CEPINTEN_STSDONEIEN_Msk); return; } if (IrqSt & USBD_CEPINTSTS_NAKIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_NAKIF_Msk); return; } if (IrqSt & USBD_CEPINTSTS_STALLIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STALLIF_Msk); return; } if (IrqSt & USBD_CEPINTSTS_ERRIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_ERRIF_Msk); return; } if (IrqSt & USBD_CEPINTSTS_STSDONEIF_Msk) { USBD_UpdateDeviceState(); USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk); UBSD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk); return; } if (IrqSt & USBD_CEPINTSTS_BUFFULLIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_BUFFULLIF_Msk); return; } if (IrqSt & USBD_CEPINTSTS_BUFEMPTYIF_Msk) { USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_BUFEMPTYIF_Msk); return; } } /* bulk in */ if (IrqStL & USBD_GINTSTS_EPAIF_Msk) { IrqSt = USBD->EPAINTSTS & USBD->EPAINTEN; UBSD_ENABLE_EP_INT(EPA, 0); USBD_CLR_EP_INT_FLAG(EPA, IrqSt); } /* bulk out */ if (IrqStL & USBD_GINTSTS_EPBIF_Msk) { IrqSt = USBD->EPBINTSTS & USBD->EPBINTEN; if (IrqSt & USBD_EPINTSTS_SHORTRXIF_Msk) g_u8MscOutShortPacket = 0; UBSD_ENABLE_EP_INT(EPB, 0); USBD_CLR_EP_INT_FLAG(EPB, IrqSt); } if (IrqStL & USBD_GINTSTS_EPCIF_Msk) { IrqSt = USBD->EPCINTSTS & USBD->EPCINTEN; USBD_CLR_EP_INT_FLAG(EPC, IrqSt); } if (IrqStL & USBD_GINTSTS_EPDIF_Msk) { IrqSt = USBD->EPDINTSTS & USBD->EPDINTEN; USBD_CLR_EP_INT_FLAG(EPD, IrqSt); } if (IrqStL & USBD_GINTSTS_EPEIF_Msk) { IrqSt = USBD->EPEINTSTS & USBD->EPEINTEN; USBD_CLR_EP_INT_FLAG(EPE, IrqSt); } if (IrqStL & USBD_GINTSTS_EPFIF_Msk) { IrqSt = USBD->EPFINTSTS & USBD->EPFINTEN; USBD_CLR_EP_INT_FLAG(EPF, IrqSt); } if (IrqStL & USBD_GINTSTS_EPGIF_Msk) { IrqSt = USBD->EPGINTSTS & USBD->EPGINTEN; USBD_CLR_EP_INT_FLAG(EPG, IrqSt); } if (IrqStL & USBD_GINTSTS_EPHIF_Msk) { IrqSt = USBD->EPHINTSTS & USBD->EPHINTEN; USBD_CLR_EP_INT_FLAG(EPH, IrqSt); } if (IrqStL & USBD_GINTSTS_EPIIF_Msk) { IrqSt = USBD->EPIINTSTS & USBD->EPIINTEN; USBD_CLR_EP_INT_FLAG(EPI, IrqSt); } if (IrqStL & USBD_GINTSTS_EPJIF_Msk) { IrqSt = USBD->EPJINTSTS & USBD->EPJINTEN; USBD_CLR_EP_INT_FLAG(EPJ, IrqSt); } if (IrqStL & USBD_GINTSTS_EPKIF_Msk) { IrqSt = USBD->EPKINTSTS & USBD->EPKINTEN; USBD_CLR_EP_INT_FLAG(EPK, IrqSt); } if (IrqStL & USBD_GINTSTS_EPLIF_Msk) { IrqSt = USBD->EPLINTSTS & USBD->EPLINTEN; USBD_CLR_EP_INT_FLAG(EPL, IrqSt); } }