⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbdriver.c

📁 基于ADSP-BF535 USB驱动应用程序
💻 C
📖 第 1 页 / 共 3 页
字号:
*		direction - direction for the transfer (EP_IN or EP_OUT)
*
*	Globals Used:
*		gActiveEndpointStates
*
*	Description:
*		Sets the DMA address/length for an endpoint, and arms it, alongwith providing
*		the appropriate config. information for the endpoint.
*
*	Returns:
*		Nothing
*
*------------------------------------------------------------*/
void ArmEndpoint (UCHAR endpointNumber, UCHAR direction)
	{
		USHORT cfgReg;
		//USHORT len = gActiveEndpointStates[endpointNumber].dmaBufferSize;

		cfgReg = (USHORT)((USBD_EPCFG_ARM) | (direction << 1) | (gActiveEndpointStates[endpointNumber].endpointType << 2));
		SET_USBD_MAX(cfgReg, GetMaxPacketSizeCode (gActiveEndpointStates[endpointNumber].maxPacketSize));

		(*(PVUS)((UINT)USBD_EPCFG0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) = cfgReg;
		//Dprintf ("CFG Reg = %08x", cfgReg);

		(*(PVUS)((UINT)USBD_EPADR0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) = 
			(USHORT)((ULONG)gActiveEndpointStates[endpointNumber].dmaBuffer & USBD_OFFSET_SGMSK);
		//Dprintf ("ADR Reg = %08x", (USHORT)((ULONG)gActiveEndpointStates[endpointNumber].dmaBuffer & USBD_OFFSET_SGMSK));

		(*(PVUS)((UINT)USBD_EPLEN0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) = 
			(USHORT)gActiveEndpointStates[endpointNumber].dmaBufferSize;

		//Dprintf ("LEN Reg: %08x", (USHORT)gActiveEndpointStates[endpointNumber].dmaBufferSize);

		asm("ssync;");

	}


/*------------------------------------------------------------
*	DisarmEndpoint
*
*	Parameters:  
*		endpointNumber - endpoint to arm.
*		direction - direction for the transfer (EP_IN or EP_OUT)
*
*	Globals Used:
*		gActiveEndpointStates
*
*	Description:
*		Disarms the given endpoint. In the process, it also toggles the
*		direction bit - as recommended by Errata (Item 27):
*		Blackfin ADSP-21535 Anomaly list
*		for Revision(s) ADSP-21535-0.2, ADSP-21535-1.0, ADSP-21535-1.1
*		Created Tue Sep 10 15:37:16 2002 (IM)
*
*	Returns:
*		Nothing
*
*------------------------------------------------------------*/
void DisarmEndpoint (UCHAR endpointNumber, UCHAR direction)
	{
		USHORT cfgReg;

		//Need to toggle the direction bit.
		cfgReg = (USHORT)((((direction) ? 0 : 1) << 1) | (gActiveEndpointStates[endpointNumber].endpointType << 2));
		SET_USBD_MAX(cfgReg, GetMaxPacketSizeCode (gActiveEndpointStates[endpointNumber].maxPacketSize));

		(*(PVUS)((UINT)USBD_EPCFG0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) = cfgReg;
		asm("ssync;");
		//Dprintf ("CFG Reg = %08x", cfgReg);

		
		cfgReg = (USHORT)((direction << 1) | (gActiveEndpointStates[endpointNumber].endpointType << 2));
		SET_USBD_MAX(cfgReg, GetMaxPacketSizeCode (gActiveEndpointStates[endpointNumber].maxPacketSize));

		(*(PVUS)((UINT)USBD_EPCFG0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) = cfgReg;
		//Dprintf ("CFG Reg = %08x", cfgReg);

		(*(PVUS)((UINT)USBD_EPLEN0 + (USBD_EPCFG1 - USBD_EPCFG0) * endpointNumber)) = 0;

		asm("ssync;");

	}


/*------------------------------------------------------------
*	USBDriver_ISR
*
*	Parameters:  
*		r0x, r1x, r2x
*
*	Globals Used:
*		
*
*	Description:
*		The ISR to handle USBD interrupts. 
*
*	Returns:
*		Nothing
*
*
*------------------------------------------------------------*/
//EX_REENTRANT_HANDLER  (USBDriver_ISR)
void USBDriver_ISR ( int _r0x, int _r1x, int _r2x )
	{
		int	i, currentEndpoint;
		USHORT		usbd_gintr;
		USHORT		usbd_status;
		static USHORT    usbd_epintr[MAX_PHY_EP];
		bool shouldStall, shouldRecycle;

		// clear the interrupt last!
		usbd_gintr = (USHORT)USBD_GINTR_REG;

		usbd_epintr[0]= (USHORT)USBD_INTR0_REG;
		USBD_INTR0_REG = usbd_epintr[0];
		usbd_epintr[1]= (USHORT)USBD_INTR1_REG;
		USBD_INTR1_REG = usbd_epintr[1];
		usbd_epintr[2]= (USHORT)USBD_INTR2_REG;
		USBD_INTR2_REG = usbd_epintr[2];
		usbd_epintr[3]= (USHORT)USBD_INTR3_REG;
		USBD_INTR3_REG = usbd_epintr[3];
		usbd_epintr[4]= (USHORT)USBD_INTR4_REG;
		USBD_INTR4_REG = usbd_epintr[4];
		usbd_epintr[5]= (USHORT)USBD_INTR5_REG;
		USBD_INTR5_REG = usbd_epintr[5];
		usbd_epintr[6]= (USHORT)USBD_INTR6_REG;
		USBD_INTR6_REG = usbd_epintr[6];
		usbd_epintr[7]= (USHORT)USBD_INTR7_REG;
		USBD_INTR7_REG = usbd_epintr[7];

		usbd_status = (USHORT)USBD_STAT_REG;
		asm("ssync;");

		//Dprintf1 ("usbd_gintr = %08x", usbd_gintr);
		//Dprintf1 ("epint0 = %08x", usbd_epintr[0]);

		if (usbd_gintr & USBD_GINTR_CFG)
			{
				if (gpOnConfigurationChange)
					{
						//Dprintf1 ("usbd_status = %08x", usbd_status);
						//Call the client to do whatever it needs to do on config change
						(*gpOnConfigurationChange)(GET_USBD_CONFIG(usbd_status), 
							GET_USBD_INTERFACE(usbd_status), 
							GET_USBD_ALTSETTING(usbd_status));
					}
			}

		if (usbd_gintr & USBD_GINTR_SUSP)
			{
				//We should reset the states of all our endpoints
				for (currentEndpoint = (MAX_PHY_EP-1); currentEndpoint >= EP0 ; currentEndpoint--)
					{
						gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
						gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;
						gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_IDLE;
					}

				//and free the DMA buffers
				InitDMA ();

				//let the client know about this!
				if (gpOnSuspend)
					(gpOnSuspend)();
			}


		if (usbd_gintr & USBD_GINTR_RESUME)
			{
				//Prepare control EP for receiving a setup packet!
				GetControlEndpointReady (EP0);

				//let the client know about this!
				if (gpOnResume)
					(gpOnResume)();
			}

		if (usbd_gintr & USBD_GINTR_RST)
			{
				//We should reset the states of all our endpoints
				for (currentEndpoint = (MAX_PHY_EP-1); currentEndpoint >= EP0 ; currentEndpoint--)
					{
						gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
						gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;
						gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_IDLE;
					}

				//and free the DMA buffers
				InitDMA ();

				//Prepare control EP for receiving a setup packet!
				GetControlEndpointReady (EP0);
				if (gpOnReset)
					(gpOnReset)();
			}


		if ((usbd_gintr & USBD_GINTR_SOF) && (gpOnSOF))
			(gpOnSOF)();

		for (currentEndpoint = EP0; currentEndpoint < MAX_PHY_EP; currentEndpoint++)
			{
				if ((gActiveEndpointStates[currentEndpoint].currentState == EP_STATE_WAITING_FOR_SETUP) &&
					((usbd_epintr[currentEndpoint] & USBD_INTR_SETUP)))
					{
						//Save a copy of the setup request
						CopyDMABufferToSETUPStruct (&gActiveEndpointStates[currentEndpoint].setupData,
							gActiveEndpointStates[currentEndpoint].dmaBuffer);

						//Dprintf ("Received Setup Request");

						//Don't need this buffer any more
						FreeDMABlock (gActiveEndpointStates[currentEndpoint].dmaBuffer);
						gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
						gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;

						//If there's no data-phase to this
						if (gActiveEndpointStates[currentEndpoint].setupData.wLength == 0)
							{
								//Dprintf ("Entering Status Phase");
								HandleNoDataControlRequest (currentEndpoint);
							}
						else
							{
								//We come here when wLength is non-zero
								//If direction of accompanying data is OUT, we need to have a DMA buffer
								//to recive it, and ARM our endpoint accordingly
								if (USB_CONTROL_REQUEST_GET_DIRECTION (gActiveEndpointStates[currentEndpoint].setupData.bmRequestType) 
									== USB_CONTROL_REQUEST_TYPE_OUT)
									{
										//Dprintf ("Entering Data Out Phase");
										HandleDataOutControlRequest (currentEndpoint);
									}
								else
									{
										//Dprintf ("Entering Data In Phase");
										HandleDataInControlRequest (currentEndpoint);
									}
							}
					}
				else if (usbd_epintr[currentEndpoint] & USBD_INTR_TC)
					{
						switch (gActiveEndpointStates[currentEndpoint].currentState)
							{
								case EP_STATE_WAITING_FOR_IN_TC:
									//Free the DMA buffer
									FreeDMABlock (gActiveEndpointStates[currentEndpoint].dmaBuffer);
									gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
									gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;
									gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_IDLE;

									//Let the client know that a xfer has completed
									if (gpOnInTC)
										(gpOnInTC)(currentEndpoint);
									
									break;

								case EP_STATE_WAITING_FOR_OUT_TC:
									gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_IDLE;
									shouldRecycle = false;
									//Let the client know that a xfer has completed
									if (gpOnOutTC)
										{
											shouldRecycle = (gpOnOutTC)(currentEndpoint, gActiveEndpointStates[currentEndpoint].dmaBuffer,
												gActiveEndpointStates[currentEndpoint].dmaBufferSize - 
												(*(PVUS)((UINT)USBD_EPLEN0 + (USBD_EPCFG1 - USBD_EPCFG0) * currentEndpoint)),
												usbd_epintr[currentEndpoint] & USBD_INTR_PC);
										}

									if (shouldRecycle)
										{
											gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_WAITING_FOR_OUT_TC;
											ArmEndpoint (currentEndpoint, EP_OUT);
										}
									else
										{
											DisarmEndpoint (currentEndpoint, EP_OUT);
											//Free the DMA buffer
											gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;
											FreeDMABlock (gActiveEndpointStates[currentEndpoint].dmaBuffer);
											gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
										}

									
									break;

								case EP_STATE_STATUS_PHASE:
									//Dprintf ("Completed Status Phase");
									//Nothing more to do, let's get the endpoint ready for more requests
									GetControlEndpointReady (currentEndpoint);
									break;
								case EP_STATE_DATA_OUT_PHASE:
									//We've recevied all the data, let's provide this to client
									//Dprintf ("Entering Status Phase from Data Out");
									shouldStall = true;
									if (gpOnSetupReq)
										{
											shouldStall = (!(gpOnSetupReq) (currentEndpoint, &gActiveEndpointStates[currentEndpoint].setupData,
												gActiveEndpointStates[currentEndpoint].dmaBuffer, &gActiveEndpointStates[currentEndpoint].dmaBufferSize));
										}

									//Free the DMA buffer
									FreeDMABlock (gActiveEndpointStates[currentEndpoint].dmaBuffer);
									gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
									gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;

									if (shouldStall)
										{
											StallEndpoint (currentEndpoint);
											GetControlEndpointReady (currentEndpoint);
										}
									else
										{
											gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_STATUS_PHASE;
											ArmEndpoint (currentEndpoint, EP_IN);
										}

									break;
								case EP_STATE_DATA_IN_PHASE:
									//The host has read the data we provided, let's enter the status phase
									//Free the DMA buffer

									//Let's not be too sure! Check to make sure this is indeed the case!
									if (gActiveEndpointStates[currentEndpoint].maxPacketSize >= 
										(*(PVUS)((UINT)USBD_EPLEN0 + (USBD_EPCFG1 - USBD_EPCFG0) * currentEndpoint)))
										{
											//Dprintf ("Entering Status Phase from Data In");
											FreeDMABlock (gActiveEndpointStates[currentEndpoint].dmaBuffer);
											gActiveEndpointStates[currentEndpoint].dmaBuffer = nil;
											gActiveEndpointStates[currentEndpoint].dmaBufferSize = 0;

											gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_STATUS_PHASE;
											ArmEndpoint (currentEndpoint, EP_OUT);
										}
									break;
								default:
									//ToDo: For non-control endpoints, we need to do our client notification
									//Etc. here
									break;
							} //(gActiveEndpointStates[currentEndpoint].currentState)
						
					} //if (usbd_epintr[currentEndpoint] & USBD_INTR_TC)

				if (usbd_epintr[currentEndpoint] & USBD_INTR_MERR)
					{
						if (gpOnMERR)
							(gpOnMERR)(currentEndpoint);
					}// (usbd_epintr[currentEndpoint] & USBD_INTR_MERR)

				
			} //(currentEndpoint = EP0; currentEndpoint < MAX_PHY_EP; currentEndpoint++)

		//ToDo: Add code to do whatever is necessary to handle other interrupts
		USBD_GINTR_REG = (USHORT)usbd_gintr;
		asm("ssync;");

	}



/*------------------------------------------------------------
*	HandleNoDataControlRequest
*
*	Parameters:  
*		currentEndpoint - endpoint on which to handle the request.
*
*	Globals Used:
*		gpOnSetupReq, gActiveEndpointStates
*
*	Description:
*		This routine is called to handle a Control Request(SETUP) with
*		no data. If the client has setup a callback, this routine calls
*		the client, with the setup data. And based on the client's reply
*		it either transitions the transfer to status phase, or stalls the
*		endpoint.
*
*	Returns:
*		Nothing.
*
*------------------------------------------------------------*/
void HandleNoDataControlRequest (UCHAR currentEndpoint)
	{
		//Call the client to let them know!
		if (gpOnSetupReq)
			{
				if ((gpOnSetupReq) (currentEndpoint, &gActiveEndpointStates[currentEndpoint].setupData,
					nil, nil))
					{
						//Success, meaning we are ready to get into the status phase,
						//Which simply involves receiving a zero length DATA OUT packet.
						gActiveEndpointStates[currentEndpoint].currentState = EP_STATE_STATUS_PHASE;
						ArmEndpoint (currentEndpoint, EP_OUT);
					}
				else
					{
						//stall!
						StallEndpoint (currentEndpoint);
						GetControlEndpointReady (currentEndpoint);
					}
			}
		else
			{
				//stall!
				StallEndpoint (currentEndpoint);
				GetControlEndpointReady (currentEndpoint);
			}
	}




/*------------------------------------------------------------
*	HandleDataOutControlRequest
*
*	Parameters:  
*		currentEndpoint - endpoint on which to handle the request.
*
*	Globals Used:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -