void stellaris_usbc_init(void) { LTRACE_ENTRY; SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0); SysCtlPeripheralReset(SYSCTL_PERIPH_USB0); SysCtlUSBPLLEnable(); GPIOPinTypeUSBAnalog(GPIO_PORTD_AHB_BASE, GPIO_PIN_4 | GPIO_PIN_5); USBDevMode(USB0_BASE); USBPHYPowerOn(USB0_BASE); #if LOCAL_TRACE usbc_dump_regs(); printf("addr %lu\n", USBDevAddrGet(USB0_BASE)); printf("ep0 status 0x%lx\n", USBEndpointStatus(USB0_BASE, USB_EP_0)); #endif NVIC_EnableIRQ(INT_USB0 - 16); USBIntDisableControl(USB0_BASE, USB_INTCTRL_ALL); LTRACE_EXIT; }
static void ep0_irq(void) { uint status = USBEndpointStatus(USB0_BASE, USB_EP_0); LTRACEF("ep0 status 0x%x\n", status); /* delay setting the address until the ack as completed */ if (pending_addr_change) { LTRACEF("pending addr change\n"); USBDevAddrSet(USB0_BASE, addr); pending_addr_change = false; } if (status & USB_DEV_EP0_OUT_PKTRDY) { LTRACEF("pktrdy\n"); uchar buf[sizeof(struct usb_setup)]; ulong avail = sizeof(buf); if (USBEndpointDataGet(USB0_BASE, USB_EP_0, buf, &avail) < 0 || avail != sizeof(buf)) { LTRACEF("short setup packet, size %lu\n", avail); } else { union usb_callback_args args; args.setup = (void *)buf; usb_callback(USB_CB_SETUP_MSG, &args); } } if (status & USB_DEV_EP0_SENT_STALL) { LTRACEF("stall complete\n"); USBDevEndpointStallClear(USB0_BASE, USB_EP_0, 0); } }
//***************************************************************************** // // Receives notifications related to data sent to the host. // // \param psDevice is the device instance whose endpoint is to be processed. // \param ulStatus is the USB interrupt status that caused this function to // be called. // // This function is called from HandleEndpoints for all interrupts originating // from the bulk IN endpoint (in other words, whenever data has been // transmitted to the USB host). We examine the cause of the interrupt and, // if due to completion of a transmission, notify the client. // // \return Returns \b true on success or \b false on failure. // //***************************************************************************** static tBoolean ProcessDataToHost(const tUSBDBulkDevice *psDevice, unsigned int ulStatus, unsigned int ulIndex) { tBulkInstance *psInst; unsigned int ulEPStatus; unsigned int ulSize; // // Get a pointer to our instance data. // psInst = psDevice->psPrivateBulkData; // // Get the endpoint status to see why we were called. // ulEPStatus = USBEndpointStatus(psInst->ulUSBBase, psInst->ucINEndpoint); // // Clear the status bits. // USBDevEndpointStatusClear(psInst->ulUSBBase, psInst->ucINEndpoint, ulEPStatus); // // Our last transmission completed. Clear our state back to idle and // see if we need to send any more data. // psInst->eBulkTxState = BULK_STATE_IDLE; // // Notify the client that the last transmission completed. // ulSize = psInst->usLastTxSize; psInst->usLastTxSize = 0; psDevice->pfnTxCallback(psDevice->pvTxCBData, USB_EVENT_TX_COMPLETE, ulSize, (void *)0); return (true); }
//***************************************************************************** // //! Determines whether a packet is available and, if so, the size of the //! buffer required to read it. //! //! \param pvInstance is the pointer to the device instance structure as //! returned by USBDBulkInit(). //! //! This function may be used to determine if a received packet remains to be //! read and allows the application to determine the buffer size needed to //! read the data. //! //! \return Returns 0 if no received packet remains unprocessed or the //! size of the packet if a packet is waiting to be read. // //***************************************************************************** unsigned int USBDBulkRxPacketAvailable(void *pvInstance) { unsigned int ulEPStatus; unsigned int ulSize; tBulkInstance *psInst; ASSERT(pvInstance); // // Get our instance data pointer // psInst = ((tUSBDBulkDevice *)pvInstance)->psPrivateBulkData; // // Does the relevant endpoint FIFO have a packet waiting for us? // ulEPStatus = USBEndpointStatus(psInst->ulUSBBase, psInst->ucOUTEndpoint); if(ulEPStatus & USB_DEV_RX_PKT_RDY) { // // Yes - a packet is waiting. How big is it? // ulSize = USBEndpointDataAvail(psInst->ulUSBBase, psInst->ucOUTEndpoint); return (ulSize); } else { // // There is no packet waiting to be received. // return (0); } }
//***************************************************************************** // // Receives notifications related to data received from the host. // // \param psDevice is the device instance whose endpoint is to be processed. // \param ulStatus is the USB interrupt status that caused this function to // be called. // // This function is called from HandleEndpoints for all interrupts signaling // the arrival of data on the bulk OUT endpoint (in other words, whenever the // host has sent us a packet of data). We inform the client that a packet // is available and, on return, check to see if the packet has been read. If // not, we schedule another notification to the client for a later time. // // \return Returns \b true on success or \b false on failure. // //***************************************************************************** static tBoolean ProcessDataFromHost(const tUSBDBulkDevice *psDevice, unsigned int ulStatus, unsigned int ulIndex) { unsigned int ulEPStatus; unsigned int ulSize; tBulkInstance *psInst; // // Get a pointer to our instance data. // psInst = psDevice->psPrivateBulkData; // // Get the endpoint status to see why we were called. // ulEPStatus = USBEndpointStatus(g_USBInstance[ulIndex].uiBaseAddr, psInst->ucOUTEndpoint); // // Clear the status bits. // USBDevEndpointStatusClear(g_USBInstance[ulIndex].uiBaseAddr, psInst->ucOUTEndpoint, ulEPStatus); // // Has a packet been received? // if(ulEPStatus & USB_DEV_RX_PKT_RDY) { // // Set the flag we use to indicate that a packet read is pending. This // will be cleared if the packet is read. If the client doesn't read // the packet in the context of the USB_EVENT_RX_AVAILABLE callback, // the event will be signaled later during tick processing. // SetDeferredOpFlag(&psInst->usDeferredOpFlags, BULK_DO_PACKET_RX, true); // // How big is the packet we've just been sent? // ulSize = USBEndpointDataAvail(psInst->ulUSBBase, psInst->ucOUTEndpoint); // // The receive channel is not blocked so let the caller know // that a packet is waiting. The parameters are set to indicate // that the packet has not been read from the hardware FIFO yet. // psDevice->pfnRxCallback(psDevice->pvRxCBData, USB_EVENT_RX_AVAILABLE, ulSize, (void *)0); } else { // // No packet was received. Some error must have been reported. Check // and pass this on to the client if necessary. // if(ulEPStatus & USB_RX_ERROR_FLAGS) { // // This is an error we report to the client so... // psDevice->pfnRxCallback(psDevice->pvRxCBData, USB_EVENT_ERROR, (ulEPStatus & USB_RX_ERROR_FLAGS), (void *)0); } return (false); } return (true); }
//***************************************************************************** // //! Reads a packet of data received from the USB host via the bulk data //! interface. //! //! \param pvInstance is the pointer to the device instance structure as //! returned by USBDBulkInit(). //! \param pcData points to a buffer into which the received data will be //! written. //! \param ulLength is the size of the buffer pointed to by pcData. //! \param bLast indicates whether the client will make a further call to //! read additional data from the packet. //! //! This function reads up to \e ulLength bytes of data received from the USB //! host into the supplied application buffer. If the driver detects that the //! entire packet has been read, it is acknowledged to the host. //! //! The \e bLast parameter is ignored in this implementation since the end of //! a packet can be determined without relying upon the client to provide //! this information. //! //! \return Returns the number of bytes of data read. // //***************************************************************************** unsigned int USBDBulkPacketRead(void *pvInstance, unsigned char *pcData, unsigned int ulLength, tBoolean bLast) { unsigned int ulEPStatus, ulPkt; unsigned int ulCount; tBulkInstance *psInst; int iRetcode; ASSERT(pvInstance); // // Get our instance data pointer // psInst = ((tUSBDBulkDevice *)pvInstance)->psPrivateBulkData; // // Does the relevant endpoint FIFO have a packet waiting for us? // ulEPStatus = USBEndpointStatus(psInst->ulUSBBase, psInst->ucOUTEndpoint); if(ulEPStatus & USB_DEV_RX_PKT_RDY) { // // How many bytes are available for us to receive? // ulPkt = USBEndpointDataAvail(psInst->ulUSBBase, psInst->ucOUTEndpoint); // // Get as much data as we can. // ulCount = ulLength; iRetcode = USBEndpointDataGet(psInst->ulUSBBase, psInst->ucOUTEndpoint, pcData, &ulCount); // // Did we read the last of the packet data? // if(ulCount == ulPkt) { // // Clear the endpoint status so that we know no packet is // waiting. // USBDevEndpointStatusClear(psInst->ulUSBBase, psInst->ucOUTEndpoint, ulEPStatus); // // Acknowledge the data, thus freeing the host to send the // next packet. // USBDevEndpointDataAck(psInst->ulUSBBase, psInst->ucOUTEndpoint, true); // // Clear the flag we set to indicate that a packet read is // pending. // SetDeferredOpFlag(&psInst->usDeferredOpFlags, BULK_DO_PACKET_RX, false); } // // If all went well, tell the caller how many bytes they got. // if(iRetcode != -1) { return (ulCount); } } // // No packet was available or an error occurred while reading so tell // the caller no bytes were returned. // return (0); }