/** * * This function performs device reset, device is stopped at the end. * * @param InstancePtr is a pointer to XUsbPs instance of the controller. * * @return None. * * @note None. * ******************************************************************************/ void XUsbPs_DeviceReset(XUsbPs *InstancePtr) { int Timeout; /* Clear all setup token semaphores by reading the * XUSBPS_EPSTAT_OFFSET register and writing its value back to * itself. */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET, XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET)); /* Clear all the endpoint complete status bits by reading the * XUSBPS_EPCOMPL_OFFSET register and writings its value back * to itself. */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCOMPL_OFFSET, XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCOMPL_OFFSET)); /* Cancel all endpoint prime status by waiting until all bits * in XUSBPS_EPPRIME_OFFSET are 0 and then writing 0xFFFFFFFF * to XUSBPS_EPFLUSH_OFFSET. * * Avoid hanging here by using a Timeout counter... */ Timeout = XUSBPS_TIMEOUT_COUNTER; while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPPRIME_OFFSET) & XUSBPS_EP_ALL_MASK) && --Timeout) { /* NOP */ } XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPFLUSH_OFFSET, 0xFFFFFFFF); XUsbPs_Stop(InstancePtr); /* Write to CR register for controller reset */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET, XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) | XUSBPS_CMD_RST_MASK); /* Wait for reset to finish, hardware clears the reset bit once done */ Timeout = 1000000; while((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) & XUSBPS_CMD_RST_MASK) && --Timeout) { /* NOP */ } }
/** * * This function does a minimal DEVICE mode setup on the USB device and driver * as a design example. The purpose of this function is to illustrate how to * set up a USB flash disk emulation system. * * * @param IntcInstancePtr is a pointer to the instance of the INTC driver. * @param UsbInstancePtr is a pointer to the instance of USB driver. * @param UsbDeviceId is the Device ID of the USB Controller and is the * XPAR_<USB_instance>_DEVICE_ID value from xparameters.h. * @param UsbIntrId is the Interrupt Id and is typically * XPAR_<INTC_instance>_<USB_instance>_IP2INTC_IRPT_INTR value * from xparameters.h. * * @return * - XST_SUCCESS if successful * - XST_FAILURE on error * ******************************************************************************/ static int UsbIntrExample(XScuGic *IntcInstancePtr, XUsbPs *UsbInstancePtr, u16 UsbDeviceId, u16 UsbIntrId) { int Status; u8 *MemPtr = NULL; int ReturnStatus = XST_FAILURE; /* For this example we only configure 2 endpoints: * Endpoint 0 (default control endpoint) * Endpoint 1 (BULK data endpoint) */ const u8 NumEndpoints = 2; XUsbPs_Config *UsbConfigPtr; XUsbPs_DeviceConfig DeviceConfig; /* Initialize the USB driver so that it's ready to use, * specify the controller ID that is generated in xparameters.h */ UsbConfigPtr = XUsbPs_LookupConfig(UsbDeviceId); if (NULL == UsbConfigPtr) { goto out; } /* We are passing the physical base address as the third argument * because the physical and virtual base address are the same in our * example. For systems that support virtual memory, the third * argument needs to be the virtual base address. */ Status = XUsbPs_CfgInitialize(UsbInstancePtr, UsbConfigPtr, UsbConfigPtr->BaseAddress); if (XST_SUCCESS != Status) { goto out; } /* Set up the interrupt subsystem. */ Status = UsbSetupIntrSystem(IntcInstancePtr, UsbInstancePtr, UsbIntrId); if (XST_SUCCESS != Status) { goto out; } /* Configuration of the DEVICE side of the controller happens in * multiple stages. * * 1) The user configures the desired endpoint configuration using the * XUsbPs_DeviceConfig data structure. This includes the number of * endpoints, the number of Transfer Descriptors for each endpoint * (each endpoint can have a different number of Transfer Descriptors) * and the buffer size for the OUT (receive) endpoints. Each endpoint * can have different buffer sizes. * * 2) Request the required size of DMAable memory from the driver using * the XUsbPs_DeviceMemRequired() call. * * 3) Allocate the DMAable memory and set up the DMAMemVirt and * DMAMemPhys members in the XUsbPs_DeviceConfig data structure. * * 4) Configure the DEVICE side of the controller by calling the * XUsbPs_ConfigureDevice() function. */ /* * For this example we only configure Endpoint 0 and Endpoint 1. * * Bufsize = 0 indicates that there is no buffer allocated for OUT * (receive) endpoint 0. Endpoint 0 is a control endpoint and we only * receive control packets on that endpoint. Control packets are 8 * bytes in size and are received into the Queue Head's Setup Buffer. * Therefore, no additional buffer space is needed. */ DeviceConfig.EpCfg[0].Out.Type = XUSBPS_EP_TYPE_CONTROL; DeviceConfig.EpCfg[0].Out.NumBufs = 2; DeviceConfig.EpCfg[0].Out.BufSize = 64; DeviceConfig.EpCfg[0].Out.MaxPacketSize = 64; DeviceConfig.EpCfg[0].In.Type = XUSBPS_EP_TYPE_CONTROL; DeviceConfig.EpCfg[0].In.NumBufs = 2; DeviceConfig.EpCfg[0].In.MaxPacketSize = 64; DeviceConfig.EpCfg[1].Out.Type = XUSBPS_EP_TYPE_BULK; DeviceConfig.EpCfg[1].Out.NumBufs = 16; DeviceConfig.EpCfg[1].Out.BufSize = 512; DeviceConfig.EpCfg[1].Out.MaxPacketSize = 512; DeviceConfig.EpCfg[1].In.Type = XUSBPS_EP_TYPE_BULK; DeviceConfig.EpCfg[1].In.NumBufs = 16; DeviceConfig.EpCfg[1].In.MaxPacketSize = 512; DeviceConfig.NumEndpoints = NumEndpoints; MemPtr = (u8 *)&Buffer[0]; memset(MemPtr,0,MEMORY_SIZE); Xil_DCacheFlushRange((unsigned int)MemPtr, MEMORY_SIZE); /* Finish the configuration of the DeviceConfig structure and configure * the DEVICE side of the controller. */ DeviceConfig.DMAMemPhys = (u32) MemPtr; Status = XUsbPs_ConfigureDevice(UsbInstancePtr, &DeviceConfig); if (XST_SUCCESS != Status) { goto out; } /* Set the handler for receiving frames. */ Status = XUsbPs_IntrSetHandler(UsbInstancePtr, UsbIntrHandler, NULL, XUSBPS_IXR_UE_MASK); if (XST_SUCCESS != Status) { goto out; } /* Set the handler for handling endpoint 0 events. This is where we * will receive and handle the Setup packet from the host. */ Status = XUsbPs_EpSetHandler(UsbInstancePtr, 0, XUSBPS_EP_DIRECTION_OUT, XUsbPs_Ep0EventHandler, UsbInstancePtr); /* Set the handler for handling endpoint 1 events. * * Note that for this example we do not need to register a handler for * TX complete events as we only send data using static data buffers * that do not need to be free()d or returned to the OS after they have * been sent. */ Status = XUsbPs_EpSetHandler(UsbInstancePtr, 1, XUSBPS_EP_DIRECTION_OUT, XUsbPs_Ep1EventHandler, UsbInstancePtr); /* Enable the interrupts. */ XUsbPs_IntrEnable(UsbInstancePtr, XUSBPS_IXR_UR_MASK | XUSBPS_IXR_UI_MASK); /* Start the USB engine */ XUsbPs_Start(UsbInstancePtr); /* At this point we wait for the user to plug in the usb plug. This * will cause the host to send USB packets. Once we received something, * we clean up and stop the controller. * * This will not really work if we want to use the USB storage * example. What can we do instead? */ while (NumReceivedFrames < 1) { /* NOP */ } /* Set return code to indicate success and fall through to clean-up * code. */ ReturnStatus = XST_SUCCESS; out: /* Clean up. It's always safe to disable interrupts and clear the * handlers, even if they have not been enabled/set. The same is true * for disabling the interrupt subsystem. */ XUsbPs_Stop(UsbInstancePtr); XUsbPs_IntrDisable(UsbInstancePtr, XUSBPS_IXR_ALL); (int) XUsbPs_IntrSetHandler(UsbInstancePtr, NULL, NULL, 0); UsbDisableIntrSystem(IntcInstancePtr, UsbIntrId); /* Free allocated memory. */ if (NULL != UsbInstancePtr->UserDataPtr) { free(UsbInstancePtr->UserDataPtr); } return ReturnStatus; }