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

📄 usb.c

📁 该程序为UClinux下面的USB接口通讯程序,采用C语言编写,包含了makefile文件,使用的开发环境为华恒公司的嵌入式开发套件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************
 *
 * Copyright:
 *	MOTOROLA, INC. All Rights Reserved.  
 *  You are hereby granted a copyright license to use, modify, and
 *  distribute the SOFTWARE so long as this entire notice is
 *  retained without alteration in any modified and/or redistributed
 *  versions, and that such modified versions are clearly identified
 *  as such. No licenses are granted by implication, estoppel or
 *  otherwise under any patents or trademarks of Motorola, Inc. This 
 *  software is provided on an "AS IS" basis and without warranty.
 *
 *  To the maximum extent permitted by applicable law, MOTOROLA 
 *  DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING 
 *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
 *  PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH REGARD TO THE 
 *  SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) AND ANY 
 *  ACCOMPANYING WRITTEN MATERIALS.
 * 
 *  To the maximum extent permitted by applicable law, IN NO EVENT
 *  SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING 
 *  WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS 
 *  INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
 *  LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.   
 * 
 *  Motorola assumes no responsibility for the maintenance and support
 *  of this software
 ********************************************************************/

/*
 * File:		usb.c
 * Purpose:		Device Driver for the USB module of the MCF5272
 */

#include "mcf5272.h"
#include "init.h"

/********************************************************************/

/* Global Endpoint Status Structures */
USB_EP_STATE ep[NUM_ENDPOINTS];

/* Global Remote Wakeup Flag */
volatile int fRemoteWakeup = 0;

/* Global USB Descriptor Data (application specific) */
extern USB_DEVICE_DESC Descriptors;

/********************************************************************/
void 
usb_init(void)
{
	uint32 i, DescSize;
	uint32 *pConfigRam;
	uint32 *pDevDesc;
	MCF5272_IMM *imm = mcf5272_get_immp();

	/* Initialize Descriptor pointers and variables */
	pConfigRam = (uint32 *)((uint32)imm + MCF5272_USB_CFG_RAM);
	pDevDesc = (uint32 *)usb_get_desc(-1, -1, -1, -1);
	DescSize = usb_get_desc_size() + 3;

	/* Initialize Endpoint status structures */
	ep[0].ttype = CONTROL;
	ep[0].packet_size = ((USB_DEVICE_DESC *)pDevDesc)->bMaxPacketSize0;
	ep[0].fifo_length = (uint16)(ep[0].packet_size * FIFO_DEPTH);
	ep[0].buffer.start = 0;
	ep[0].buffer.free = 0;

	/* Set the EP0 IN-BUSY bit -- This is only required on
	   pre-2K75N masks. This bit is set by HW beginning with
	   the 2K75N silicon. */
	MCF5272_WR_USB_EP0CTL(imm, MCF5272_RD_USB_EP0CTL(imm) 
		| MCF5272_USB_EP0CTL_IN_BUSY);
	
	for (i = 1; i < NUM_ENDPOINTS; i++)
		ep[i].ttype = DISABLED;

	/* Invalidate Configuration RAM and disable Endpoint 0 */
	MCF5272_WR_USB_EP0CTL(imm, 0);

	/* Load the Configuration RAM with the descriptors */
	for (i = 0; i < (DescSize/4); i++)
		pConfigRam[i] = pDevDesc[i];

	/* Initialize FIFOs */
	usb_fifo_init();

	/* Initialize the Interrupts */
	usb_isr_init();

	/* Enable USB controller, Config RAM, EXT AFE */
#if (DEBUG)
	MCF5272_WR_USB_EP0CTL(imm, 0
		| MCF5272_USB_EP0CTL_DEBUG
	/*	| MCF5272_USB_EP0CTL_AFE_EN	*/
		| MCF5272_USB_EP0CTL_USB_EN
		| MCF5272_USB_EP0CTL_CFG_RAM_VAL);
#else
	MCF5272_WR_USB_EP0CTL(imm, 0
	/*	| MCF5272_USB_EP0CTL_AFE_EN	*/
		| MCF5272_USB_EP0CTL_USB_EN
		| MCF5272_USB_EP0CTL_CFG_RAM_VAL);
#endif
	
	/* Enable desired interrupts on EP0 */
	MCF5272_WR_USB_EP0IMR(imm, 0
		| MCF5272_USB_EP0IMR_DEV_CFG_EN
		| MCF5272_USB_EP0IMR_VEND_REQ_EN
		| MCF5272_USB_EP0IMR_WAKE_CHG_EN
		| MCF5272_USB_EP0IMR_RESUME_EN
		| MCF5272_USB_EP0IMR_SUSPEND_EN
		| MCF5272_USB_EP0IMR_RESET_EN
		| MCF5272_USB_EP0IMR_OUT_EOT_EN
		| MCF5272_USB_EP0IMR_OUT_EOP_EN
		| MCF5272_USB_EP0IMR_IN_EOT_EN
		| MCF5272_USB_EP0IMR_IN_EOP_EN
		| MCF5272_USB_EP0IMR_UNHALT_EN
		| MCF5272_USB_EP0IMR_HALT_EN);
}

/********************************************************************/
void 
usb_isr_init(void)
{
	MCF5272_IMM *imm = mcf5272_get_immp();

	/* Clear any pending interrupts in all Endpoints */
	MCF5272_WR_USB_EP0ISR(imm, 0x0001FFFF);
	MCF5272_WR_USB_EP1ISR(imm, 0x001F);
	MCF5272_WR_USB_EP2ISR(imm, 0x001F);
	MCF5272_WR_USB_EP3ISR(imm, 0x001F);
	MCF5272_WR_USB_EP4ISR(imm, 0x001F);
	MCF5272_WR_USB_EP5ISR(imm, 0x001F);
	MCF5272_WR_USB_EP6ISR(imm, 0x001F);
	MCF5272_WR_USB_EP7ISR(imm, 0x001F);

	/* Enable all interrupts on all Endpoints */
	/* These will be altered on configuration/interface changes */
	MCF5272_WR_USB_EP0IMR(imm, 0x0001FFFF);
	MCF5272_WR_USB_EP1IMR(imm, 0x001F);
	MCF5272_WR_USB_EP2IMR(imm, 0x001F);
	MCF5272_WR_USB_EP3IMR(imm, 0x001F);
	MCF5272_WR_USB_EP4IMR(imm, 0x001F);
	MCF5272_WR_USB_EP5IMR(imm, 0x001F);
	MCF5272_WR_USB_EP6IMR(imm, 0x001F);
	MCF5272_WR_USB_EP7IMR(imm, 0x001F);

	/* Initialize Interrupt Control Registers */
	MCF5272_WR_SIM_ICR2(imm, 0
		| (0x00008888)
		| (USB_EP0_LEVEL << 12) 
		| (USB_EP1_LEVEL << 8) 
		| (USB_EP2_LEVEL << 4) 
		| (USB_EP3_LEVEL << 0));
	MCF5272_WR_SIM_ICR3(imm, 0
		| (0x88880000)
		| (USB_EP4_LEVEL << 28) 
		| (USB_EP5_LEVEL << 24) 
		| (USB_EP6_LEVEL << 20) 
		| (USB_EP7_LEVEL << 16));
}

/********************************************************************/
void 
usb_endpoint0_isr(void)
{
	MCF5272_IMM *imm = mcf5272_get_immp();
	uint32 event;

	event = MCF5272_RD_USB_EP0ISR(imm) & MCF5272_RD_USB_EP0IMR(imm);

	if (event & MCF5272_USB_EP0ISR_DEV_CFG)
	{
		usb_devcfg_service();
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EP0ISR(imm, MCF5272_USB_EP0ISR_DEV_CFG);
	}
	if (event & MCF5272_USB_EP0ISR_VEND_REQ)
	{
		/* Is this a GET_DESCRIPTOR(String) request? */
		if ((MCF5272_RD_USB_DRR1(imm) & 0xFF00 >> 8) == GET_DESCRIPTOR)
		{
			/* To do: Return STRING Descriptor if it exists */
			printf("Host requested the String Descriptor\n");
			while (1) ;
		}
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EP0ISR(imm, MCF5272_USB_EP0ISR_VEND_REQ);
		usb_vendreq_service(
			(uint8)(MCF5272_RD_USB_DRR1(imm) & 0xFF),
			(uint8)(MCF5272_RD_USB_DRR1(imm) >> 8),
			(uint16)(MCF5272_RD_USB_DRR1(imm) >> 16),
			(uint16)(MCF5272_RD_USB_DRR2(imm) & 0xFFFF),
			(uint16)(MCF5272_RD_USB_DRR2(imm) >> 16));
	}
	if (event & MCF5272_USB_EP0ISR_FRM_MAT)
	{
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EP0ISR(imm, MCF5272_USB_EP0ISR_FRM_MAT);
	}
	if (event & MCF5272_USB_EP0ISR_ASOF)
	{
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EP0ISR(imm, MCF5272_USB_EP0ISR_ASOF);
	}
	if (event & MCF5272_USB_EP0ISR_SOF)
	{
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EP0ISR(imm, MCF5272_USB_EP0ISR_SOF);
	}
	if (event & MCF5272_USB_EP0ISR_WAKE_CHG)
	{
        if (MCF5272_RD_USB_EP0SR(imm) & MCF5272_USB_EP0SR_WAKE_ST)
        {
            /* Enable Wake-on-Ring */
            MCF5272_WR_USB_EP0CTL(imm,
                  MCF5272_RD_USB_EP0CTL(imm)
                | MCF5272_USB_EP0CTL_WOR_EN);
            /* Wake-on-Ring function is invoked when /INT1 pin is 0 */
            MCF5272_WR_USB_EP0CTL(imm,
                  MCF5272_RD_USB_EP0CTL(imm)
                & ~MCF5272_USB_EP0CTL_WOR_LVL);
 		    #if (DEBUG)
			    printf("Wake-on-Ring enabled.\n");
		    #endif
        }
        else
        {
			/* Disable Wake-on-Ring */
			MCF5272_WR_USB_EP0CTL(imm,
				   MCF5272_RD_USB_EP0CTL(imm)
				& ~MCF5272_USB_EP0CTL_WOR_EN);
			#if (DEBUG)
				printf("Wake-on-Ring disabled.\n");
			#endif
        }
        /* Clear this interrupt bit */
		MCF5272_WR_USB_EP0ISR(imm, MCF5272_USB_EP0ISR_WAKE_CHG);
	}
	if (event & MCF5272_USB_EP0ISR_RESUME)
	{
        usb_bus_state_chg_service(RESUME);
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EP0ISR(imm, MCF5272_USB_EP0ISR_RESUME);
	}
	if (event & MCF5272_USB_EP0ISR_SUSPEND)
	{
        if (MCF5272_RD_USB_EP0SR(imm) & MCF5272_USB_EP0SR_WAKE_ST)
            usb_bus_state_chg_service(SUSPEND | ENABLE_WAKEUP);
        else
            usb_bus_state_chg_service(SUSPEND);
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EP0ISR(imm, MCF5272_USB_EP0ISR_SUSPEND);
	}
	if (event & MCF5272_USB_EP0ISR_RESET)
	{
        usb_bus_state_chg_service(RESET);
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EP0ISR(imm, MCF5272_USB_EP0ISR_RESET);
	}
	if (event & ( MCF5272_USB_EP0ISR_OUT_EOT
				| MCF5272_USB_EP0ISR_OUT_EOP
				| MCF5272_USB_EP0ISR_OUT_LVL))
	{
		usb_out_service(0, event);
	}
	if (event & ( MCF5272_USB_EP0ISR_IN_EOT
				| MCF5272_USB_EP0ISR_IN_EOP
				| MCF5272_USB_EP0ISR_IN_LVL))
	{
		usb_in_service(0, event);
	}
	if (event & MCF5272_USB_EP0ISR_UNHALT)
	{
		#if (DEBUG)
			printf("Endpoint 0 has been UNHALTed\n");
		#endif
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EP0ISR(imm, MCF5272_USB_EP0ISR_UNHALT);
	}
	if (event & MCF5272_USB_EP0ISR_HALT)
	{
		#if (DEBUG)
			printf("Endpoint 0 has been HALTed\n");
		#endif
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EP0ISR(imm, MCF5272_USB_EP0ISR_HALT);
	}

}

/********************************************************************/
void 
usb_endpoint_isr(uint32 epnum)
{
	int event;
	MCF5272_IMM *imm = mcf5272_get_immp();

	#if (DEBUG)
		printf("Received interrupt for Endpoint %d\n",epnum);
	#endif

	event = MCF5272_RD_USB_EPISR(imm, epnum) 
		  & MCF5272_RD_USB_EPIMR(imm, epnum);

	if (event & ( MCF5272_USB_EPNISR_EOT	
				| MCF5272_USB_EPNISR_EOP
				| MCF5272_USB_EPNISR_FIFO_LVL))
	{
		/* IN Endpoint */
		if (MCF5272_RD_USB_EPISR(imm, epnum) & MCF5272_USB_EPNISR_DIR)
			usb_in_service(epnum, event);
		/* OUT Endpoint */
		else
			usb_out_service(epnum,event);
	}
	if (event & MCF5272_USB_EPNISR_HALT)
	{
		/* Call Project specific routine */
		usb_ep_halt(epnum);
		MCF5272_WR_USB_EPISR(imm, epnum, MCF5272_USB_EPNISR_HALT);
	}
	if (event & MCF5272_USB_EPNISR_UNHALT)
	{
		/* Call Project specific routine */
		usb_ep_unhalt(epnum);
		MCF5272_WR_USB_EPISR(imm, epnum, MCF5272_USB_EPNISR_UNHALT);
	}

}

/********************************************************************/
void 
usb_in_service(uint32 epnum, uint32 event)
{
	MCF5272_IMM *imm = mcf5272_get_immp();
	uint16 i;
	uint32 free_space;

	#if (DEBUG)
		if (event & MCF5272_USB_EP0ISR_IN_EOT)
			printf("Received IN_EOT for EP #%d\n",epnum);
		if (event & MCF5272_USB_EP0ISR_IN_EOP)
			printf("Received IN_EOP for EP #%d\n",epnum);
		if (event & MCF5272_USB_EP0ISR_IN_LVL)
			printf("Received IN_LVL for EP #%d\n",epnum);
	#endif

	/* Clear the FIFO Level interrupt now */
	if (event & MCF5272_USB_EPNISR_FIFO_LVL)
		MCF5272_WR_USB_EPISR(imm, epnum, MCF5272_USB_EPNISR_FIFO_LVL);

	if (event & (MCF5272_USB_EPNISR_EOP | MCF5272_USB_EPNISR_FIFO_LVL))
	{	
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EPISR(imm, epnum, MCF5272_USB_EPNISR_EOP);

		if (ep[epnum].buffer.position < ep[epnum].buffer.length)
		{
			/* USBEPDP0 only monitors the OUT FIFO */
			if (epnum == 0)
				free_space = ep[0].packet_size;
			else
				free_space = (uint16)(ep[epnum].fifo_length \
								- MCF5272_RD_USB_EPDPR(imm, epnum));
	
			for (i = ep[epnum].buffer.position; \
				 i < ep[epnum].buffer.position + free_space; )
			{
				/* Write from the buffer to the FIFO */
				if ((((ep[epnum].buffer.position + free_space) - i) > 3) 
					&& ((i + 4) < ep[epnum].buffer.length))
				{
					MCF5272_WR_USB_EPDR(imm, epnum, 32,
						*(uint32 *)(&ep[epnum].buffer.start[i]));
					i += 4;
				}
				else
				{
					MCF5272_WR_USB_EPDR(imm,epnum,8,ep[epnum].buffer.start[i]);
					i++;
				}
				if ( i >= ep[epnum].buffer.length )
				{
					/* All done -> Clear the IN-BUSY bit */
					MCF5272_WR_USB_EPCTL(imm, epnum, 
						MCF5272_RD_USB_EPCTL(imm, epnum)
						& ~MCF5272_USB_EPNCTL_IN_BUSY);
					break;
				}
			}
			ep[epnum].buffer.position = i;
		}
	}
	if ((event & MCF5272_USB_EPNISR_FIFO_LVL) && 
		(ep[epnum].ttype == ISOCHRONOUS))
	{
		/* Clear this interrupt bit */
		MCF5272_WR_USB_EPISR(imm, epnum, 0
			| MCF5272_USB_EPNISR_FIFO_LVL );
		if (ep[epnum].buffer.start && 
			 (ep[epnum].buffer.length == ep[epnum].buffer.position))
		{
			usb_ep_tx_done(epnum);
			ep[epnum].buffer.start = 0;
			ep[epnum].buffer.length = 0;
			ep[epnum].buffer.position = 0;
			ep[epnum].buffer.free = 0;

		}
	}
	if (event & MCF5272_USB_EPNISR_EOT)
	{
		MCF5272_WR_USB_EPISR(imm, epnum, 0
			| MCF5272_USB_EPNISR_EOT);
		if (ep[epnum].buffer.start)
		{
			if (ep[epnum].buffer.free)
				free(ep[epnum].buffer.start);

			/* Call the Tx Handler */
			usb_ep_tx_done(epnum);
		}
		ep[epnum].buffer.start = 0;
		ep[epnum].buffer.length = 0;
		ep[epnum].buffer.position = 0;
		ep[epnum].buffer.free = 0;

		/* Set the IN-BUSY bit
		   This is only required on pre-2K75N masks. This bit is set by 
		   HW beginning with the 2K75N silicon. */
		MCF5272_WR_USB_EPCTL(imm, epnum, MCF5272_RD_USB_EPCTL(imm, epnum) 
			| MCF5272_USB_EPNCTL_IN_BUSY);
	}
}

/********************************************************************/
void 
usb_out_service(uint32 epnum, uint32 event)
{
	MCF5272_IMM *imm = mcf5272_get_immp();
	uint32 i;
	uint16 fifo_data;

	#if (DEBUG)
		if (event & (MCF5272_USB_EP0ISR_OUT_EOT | MCF5272_USB_EPNISR_EOT))
			printf("Received OUT_EOT on EP%d\n",epnum);
		if (event & (MCF5272_USB_EP0ISR_OUT_EOP | MCF5272_USB_EPNISR_EOP))
			printf("Received OUT_EOP on EP%d\n",epnum);
		if (event & (MCF5272_USB_EP0ISR_OUT_LVL | MCF5272_USB_EPNISR_FIFO_LVL))
			printf("Received OUT_LVL on EP%d\n",epnum);
	#endif
	
	if (event & (MCF5272_USB_EP0ISR_OUT_LVL | MCF5272_USB_EPNISR_FIFO_LVL))
	{
		/* Clear the FIFO Level Interrupt bits now */
		MCF5272_WR_USB_EPISR(imm, epnum, 0
			| MCF5272_USB_EP0ISR_OUT_LVL
			| MCF5272_USB_EPNISR_FIFO_LVL);
	}
	if (event & ( MCF5272_USB_EP0ISR_OUT_LVL 
				| MCF5272_USB_EPNISR_FIFO_LVL
				| MCF5272_USB_EP0ISR_OUT_EOP
				| MCF5272_USB_EPNISR_EOP))
	{
		/* Clear the EOP interrupt bits */
		MCF5272_WR_USB_EPISR(imm, epnum, 0 
			| MCF5272_USB_EP0ISR_OUT_EOP
			| MCF5272_USB_EPNISR_EOP);

		/* Read the Data Present register */
		fifo_data = MCF5272_RD_USB_EPDPR(imm, epnum);

		if (ep[epnum].buffer.start &&
		   (ep[epnum].buffer.position + fifo_data > ep[epnum].buffer.length))
		{
			/* Buffer is going to overflow! */
			/* To do: realloc() to avoid this problem */
			usb_ep_rx_done(epnum,OVERFLOW_ERROR);
			ep[epnum].buffer.start = 0;
		}
		if (ep[epnum].buffer.start == 0)
		{
			/* No Buffer allocated! */
			ep[epnum].buffer.start = (uint8 *) malloc(BUFFER_SIZE);
			if (!ep[epnum].buffer.start)
			{
				/* Could not allocate buffer */
				usb_ep_rx_done(epnum,MALLOC_ERROR);
				return;
			}
			ep[epnum].buffer.free = TRUE;
			ep[epnum].buffer.length = BUFFER_SIZE;
			ep[epnum].buffer.position = 0;
		}

		/* Read the data from the FIFO into the buffer */
		for (i = ep[epnum].buffer.position; \
			 i < ep[epnum].buffer.position + fifo_data;)
		{
			if (ep[epnum].buffer.position + fifo_data - i > 3)
			{
				*((uint32 *)(&ep[epnum].buffer.start[i])) = 
					MCF5272_RD_USB_EPDR(imm, epnum,32);
				i += 4;
			}
			else
			{
				ep[epnum].buffer.start[i] = 
					MCF5272_RD_USB_EPDR(imm, epnum,8);
				i++;
			}

⌨️ 快捷键说明

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