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

📄 usb.c

📁 coldfire的mcf5329的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * File:        usb.c
 * Purpose:     Provide common USB routines
 *
 * Notes:       
 *              
 */

#include "usb.h"

/********************************************************************/
/*
 * Initialize the USB host for operation. This initialization sets
 * up the USB host to detect when a device is connected.
 *
 * Parameters:
 *  port      USB module to initialize
 */
void 
usb_host_init(int port)
{
	/* Initialize the clock divider for the USB */
	MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBDIV;
	
	/* --- Start HOST controller --- */
    #ifdef DEBUG_PRINT
		printf("Set host mode.\n");	
	#endif		
	MCF_USB_USBMODE(port) = (MCF_USB_USBMODE_ES | MCF_USB_USBMODE_CM_HOST);

	MCF_USB_USBCMD(port) = ( 0
							| MCF_USB_USBCMD_ASP(3)
							| MCF_USB_USBCMD_ITC(0) );
    #ifdef DEBUG_PRINT
		printf("Set RUN bit.\n");	
	#endif
	MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_RS;
	
	/* Apply port power. This does not initialize the transceiver.
	 * If ULPI is being used it should be initialized before this point. */
	MCF_USB_PORTSC(port) = ( MCF_USB_PORTSC(port)	
							| MCF_USB_PORTSC_PP );
    #ifdef DEBUG_PRINT			
		printf("USB host initialized. Waiting for device connect.\n\n");							
	#endif							
}
/********************************************************************/
/*
 * Initialize the USB device for operation. This initialization performs
 * basic configuration to prepare the device for connection to a host.
 * Since currently only one USB port supports device operation, the port
 * for the device init is set at the beginning of this function. If future 
 * devices implement more than one USB device port then this can be changed
 * to a passed in parameter.
 *
 * Parameters:
 */
uint32 
usb_device_init(void)
{
	uint32 ep_list_addr;

	int port = USB_OTG;
	/* Initialize the clock divider for the USB */
	MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBDIV;
			
  	//--- Set Device Mode ---//
    #ifdef DEBUG_PRINT
		printf("Set device mode.\n");	
	#endif		
	MCF_USB_USBMODE(port) = (MCF_USB_USBMODE_ES | MCF_USB_USBMODE_CM_DEVICE);

  	/*--- Intial Configuration ---*/
  	MCF_USB_USBCMD(port) &= ~( MCF_USB_USBCMD_ITC(0xFF));	// Set interrupt threshold control = 0

    MCF_USB_USBMODE(port) |= MCF_USB_USBMODE_SLOM;	// Setup Lockouts Off
    
  	/* Initialize EP0 to handle enumeration. This function will also allocate
  	 * memory to be used for the device endpoint list. */
  	ep_list_addr = usb_device_ep0_init();

	/* Initialize queue head for EP0 IN (device to host)  */
	usb_ep_qh_init(ep_list_addr, EP_QH0_IN, 0, 0x40, 0, 1); 
	
	/* Initialize queue head for EP0 OUT (host to device)  */
	usb_ep_qh_init(ep_list_addr, EP_QH0_OUT, 0, 0x40, 0, 1); 

	MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_RS;	// RUN controller

	/* Enable  a valid B session to allow device to connect to a host. */
	MCF_CCM_UOCSR = ( 0
						| MCF_CCM_UOCSR_BVLD );

    #ifdef DEBUG_PRINT			
		printf("USB device initialized.\n");							
	#endif
	
	return ep_list_addr;							

}
/********************************************************************/
/*
 * This function allocates memory in the heap to use as the device
 * endpoint list. Then the function will initialize endpoint 0 so that
 * it is ready to respond to the host for enumeration. 
 * Since currently only one USB port supports device operation, the port
 * for the device init is set at the beginning of this function. If future 
 * devices implement more than one USB device port then this can be changed
 * to a passed in parameter.
 *
 * Parameters:
 *  eplistaddr      return a pointer to the device endpoint list
 */
uint32 
usb_device_ep0_init(void)
{
	int i, port = USB_OTG;
	uint32 eplistaddr;
	/* Allocate space for the device endpoint list*/
   /*
	* The USB requires the endpoint listb to be aligned on a 2kbyte boundary. 
	* In order to accomplish this, the data is over-allocated and 
	* adjusted. 
 	*/
	eplistaddr = (uint32)malloc(sizeof(2048)*2);
    eplistaddr = (eplistaddr + 2048) & 0xFFFFF800;

	/* Set the device endpoint list address */
  	MCF_USB_EPLISTADDR(port) = eplistaddr;
  	
  	/* Clear the entire ep list */
  	for ( i =0; i < 0x10; i++)
		*((uint32 *)(eplistaddr + (i*4))) = 0;  			 

  	/* Configure EP0. Only the required EP0 for control traffic is initialized at this time. */
  	MCF_USB_EPCR0(port) |= (MCF_USB_EPCR_TXE | MCF_USB_EPCR_RXE);	// Enable TX/RX of EP0

	return eplistaddr;

}
/********************************************************************/
/*
 * Initialize the periodic schedule. This function creates an empty
 * frame list for the periodic schedule, points the periodic base
 * address to the empty frame list, and enables the periodic schedule.
 *
 * Parameters:
 *  port      			USB module to initialize
 *  frame_list_size		size of the frame list for the periodic schedule
 *  periodic_base		pointer to the start of the allocated frame list
 */
uint32 
periodic_schedule_init(int port, uint32 frame_list_size)
{
	uint32 i;
	uint32 periodic_base;
 	uint32 malloc_addr;

    /* Disable the asynchronous schedule */
//    MCF_USB_USBCMD(port) &= ~MCF_USB_USBCMD_ASE;

	/* Initialize the USBCMD register for the desired size of the frame list */
	switch (frame_list_size)
	{ case 1024:
		MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_FS_1024;
	   	break;
	  case 512:
		MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_FS_512;
	   	break;
	  case 256:
		MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_FS_256;
	   	break;
	  case 128:
		MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_FS_128;
	   	break;
	  case 64:
		MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_FS_64;
	   	break;
	  case 32:
		MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_FS_32;
	   	break;
	  case 16:
		MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_FS_16;
	   	break;
	  case 8:
		MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_FS_8;
	   	break;
  	default:
  		printf("ERR!! Invalid frame list size\n");
		MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_FS_1024; /* Use the max size by default */  		
	    break;
	}
	
   /*
	* The USB requires the frame list to be aligned on an 8Kbyte boundary. 
	* In order to accomplish this, the data is over-allocated according to 
	* the largest possible frame list size and adjusted.  
 	*/
	/* Allocate memory for the frame list */
	malloc_addr = (uint32)malloc(1024*4);

    periodic_base = (uint32)((malloc_addr + 0x1000) & 0xFFFFF000);
	
	
	/* Fill the frame list with link pointers marked as invalid
	 * since we don't have any traffic to send yet.
	 */
    for ( i=0; i<(frame_list_size*4); i=i+4)
		*(uint32 *)(periodic_base+i) = 1;
		
	/* Initialize the Periodic base address register */
	MCF_USB_PERIODICLISTBASE(port) = periodic_base;	

	/* Enable the periodic schedule */
	MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_PSE;
	
	/* Wait for periodic schedule to enable */
	while (!(MCF_USB_USBSTS(port) & MCF_USB_USBSTS_PS));
    
    #ifdef DEBUG_PRINT			
	   	printf("Periodic schedule is enabled.\n");
    #endif
    
    return periodic_base;
}
/********************************************************************/
/*
 * Issue a USB reset to the specified port.
 *
 * Parameters:
 *  port      USB module to send reset
 */
void 
send_usb_reset(int port)
{
	MCF_USB_PORTSC(port) |= MCF_USB_PORTSC_PR;  // Set Port Reset
	#ifdef DEBUG_PRINT
		printf("Start reset.\n");
    	printf("PORTSC = 0x%08x\n",MCF_USB_PORTSC(port));		
    #endif
    
	/* Wait for reset to finish */
	while (MCF_USB_PORTSC(port) & MCF_USB_PORTSC_PR);
    #ifdef DEBUG_PRINT			
		printf("USB reset complete.\n\n");							
	#endif							

}
/********************************************************************/
/*
 * USB device response to a USB bus reset.
 *
 * Parameters:
 */
void usb_bus_reset(void)
{
	int port = USB_OTG;
	uint32 temp;
	
//	printf("USBSTS = 0x%08x\n",MCF_USB_USBSTS(port));		

    /* Clear all setup token semaphores */
    temp = MCF_USB_EPSETUPSR(port);
    MCF_USB_EPSETUPSR(port) = temp;
    #ifdef DEBUG_PRINT
	    printf("EPSETUPSR = 0x%08x\n",MCF_USB_EPSETUPSR(port));
    #endif
    
    /* Clear all complete status bits */
    temp = MCF_USB_EPCOMPLETE(port);
    MCF_USB_EPCOMPLETE(port) = temp;
    #ifdef DEBUG_PRINT    		
	    printf("EPCOMPLETE = 0x%08x\n",MCF_USB_EPCOMPLETE(port));
    #endif
    
	/* Wait for all primed status to clear */
	while (MCF_USB_EPPRIME(port));
    #ifdef DEBUG_PRINT
		printf("EPPRIME = 0x%08x\n",MCF_USB_EPPRIME(port));
	#endif

    /* Flush all endpoints */
    MCF_USB_EPFLUSH(port) = 0xFFFFFFFF;    

   	/* Wait for host to stop signalling reset */
	while (MCF_USB_PORTSC(port) & MCF_USB_PORTSC_PR);
	
	/* Clear reset status bit */
	MCF_USB_USBSTS(port) |= MCF_USB_USBSTS_URI | MCF_USB_USBSTS_UI;
	
    #ifdef DEBUG_PRINT
	    printf("\n\nUSB Bus Reset Complete!!!\n");
		printf("USBSTS = 0x%08x\n",MCF_USB_USBSTS(port));		
	#endif
}
/********************************************************************/
/*
 * USB device function to return the data from a setup packet.
 *
 * Parameters:
 * ep_list_addr	pointer to the device endpoint list address
 * setup03		bytes 0-3 of the setup packet
 * setup47 		bytes 4-7 of the setup packet
 */
void get_setup_packet(uint32 ep_list_addr, uint32* setup03, uint32* setup47)
{
	int port = USB_OTG;

    /* Wait for setup */
//    while (!(MCF_USB_USBSTS(port) & MCF_USB_USBSTS_UI ));
	while(!(MCF_USB_EPSETUPSR(port) & MCF_USB_EPSETUPSR_EPSETUPSTAT(1)));
		
	/* Verify that transaction is a SETUP on EP0 */
//	if (MCF_USB_EPSETUPSR(port) != 1)
//	    printf("\nERR!!! Expected SETUP on EP0 not received!\n");
    
    /* Clear setup identification */
    MCF_USB_EPSETUPSR(port) |= MCF_USB_EPSETUPSR_EPSETUPSTAT(1);
    
    /* Set setup tripwire */
    MCF_USB_USBCMD(port) |= MCF_USB_USBCMD_SUTW;
    
	/* Get the actual setup data. The data is returned little endian
	 * so it needs to be byte swapped.
	 */
	*(uint32 *)setup03 = swap32(*(uint32 *)(ep_list_addr+0x28));
	*(uint32 *)setup47 = swap32(*(uint32 *)(ep_list_addr+0x2C));
    
    /* Wait for SUTW bit to set */
    while ( !(MCF_USB_USBCMD(port) & MCF_USB_USBCMD_SUTW));
    
    /* Clear SUTW bit */
    MCF_USB_USBCMD(port) &= ~MCF_USB_USBCMD_SUTW;
    
    /* Wait for EPSETUP to clear */
    while (MCF_USB_EPSETUPSR(port) & MCF_USB_EPSETUPSR_EPSETUPSTAT(1));

}
/********************************************************************/
int swap32(int data)
{
    uint32 swapped = 0;

    swapped |= data & 0x000000ff;
    swapped <<= 8;
    data >>= 8;
    swapped |= data & 0x000000ff;
    swapped <<= 8;
    data >>= 8;
    swapped |= data & 0x000000ff;
    swapped <<= 8;
    data >>= 8;
    swapped |= data & 0x000000ff;

    return(swapped);
}

/********************************************************************/
/*
 * Return the speed of the USB port.
 *
 * Parameters:
 *  port      USB module to send reset
 */
int 
get_port_speed(int port)
{
	int speed;
	
	/* Wait for connect */
	while(!( MCF_USB_PORTSC(port) & MCF_USB_PORTSC_CCS));

	/* Determine the speed we are connected at. */
	speed = (MCF_USB_PORTSC(port) & MCF_USB_PORTSC_PSPD(0x3));
	#ifdef DEBUG_PRINT
		switch (speed)
		{ case MCF_USB_PORTSC_PSPD_FULL:
			printf("Connected at full-speed\n");
    		break;
  		case MCF_USB_PORTSC_PSPD_LOW:
	  		printf("Connected at low-speed\n");
    		break;

⌨️ 快捷键说明

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