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

📄 usb.c

📁 Freescale MCF5445evb 参考测试代码
💻 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: *  xcvr    USB_PHY_ULPI or USB_PHY_FSLS */void usb_host_init(int xcvr){    /* Initialize the clock divider for the USB */    //MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBDIV;        /* Use external clock source if PLL isn't a multiple of 60MHz */    if (FSYS_MHZ % 60)        MCF_CCM_MISCCR &= ~MCF_CCM_MISCCR_USBSRC;        /* --- Start HOST controller --- */    #ifdef DEBUG_PRINT        printf("Set host mode.\n");     #endif          MCF_USB_USBMODE = 0        | MCF_USB_USBMODE_ES         | MCF_USB_USBMODE_CM_HOST;    MCF_USB_USBCMD = 0        | MCF_USB_USBCMD_ASP(3)        | MCF_USB_USBCMD_ITC(0);            #ifdef DEBUG_PRINT        printf("Set RUN bit.\n");       #endif    MCF_USB_USBCMD |= MCF_USB_USBCMD_RS;        ASSERT(xcvr == USB_PHY_ULPI || xcvr == USB_PHY_FSLS);    if (xcvr == USB_PHY_ULPI)    {        /* Enable the required ULPI signals */        MCF_GPIO_PAR_DMA = MCF_GPIO_PAR_DMA            & MCF_GPIO_PAR_DMA_DACK1_MASK            | MCF_GPIO_PAR_DMA_DACK1_ULPI_DIR;        MCF_GPIO_PAR_USB = 0            | MCF_GPIO_PAR_USB_VBUSEN_ULPI_NXT            | MCF_GPIO_PAR_USB_VBUSOC_ULPI_STP;        MCF_GPIO_PAR_FEC = MCF_GPIO_PAR_FEC             & MCF_GPIO_PAR_FEC_FEC0_MASK            | MCF_GPIO_PAR_FEC_FEC0_RMII_ULPI;                /* Turn on the port */        MCF_USB_PORTSC = 0            | MCF_USB_PORTSC_PTS_ULPI   /* external ULPI transceiver */            | MCF_USB_PORTSC_PP;    }    else /* (xcvr == USB_PHY_FSLS) */    {        /* Enable VBUS_EN and VBUS_OC signals */        MCF_GPIO_PAR_USB = 0            | MCF_GPIO_PAR_USB_VBUSEN_VBUSEN            | MCF_GPIO_PAR_USB_VBUSOC_VBUSOC;                    /* Setup USB_VBUS_OC signal to be active-low */        MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBOC;                /* Turn on the port */        MCF_USB_PORTSC = 0            | MCF_USB_PORTSC_PTS_FS_LS  /* on-chip FS/LS transceiver */            | 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: *  xcvr    USB_PHY_ULPI or USB_PHY_FSLS */uint32 usb_device_init(int xcvr){    uint32 ep_list_addr;//  int port = USB_OTG;    /* Initialize the clock divider for the USB */    //MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBDIV;        /* Use external clock source if PLL isn't a multiple of 60MHz */    if (FSYS_MHZ % 60)        MCF_CCM_MISCCR &= ~MCF_CCM_MISCCR_USBSRC;    //else     //    MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBSRC;                    /* Enable the correct transceiver */    ASSERT(xcvr == USB_PHY_ULPI || xcvr == USB_PHY_FSLS);    if (xcvr == USB_PHY_ULPI)    {        /* Enable the required ULPI signals */        MCF_GPIO_PAR_DMA = MCF_GPIO_PAR_DMA            & MCF_GPIO_PAR_DMA_DACK1_MASK            | MCF_GPIO_PAR_DMA_DACK1_ULPI_DIR;        MCF_GPIO_PAR_USB = 0            | MCF_GPIO_PAR_USB_VBUSEN_ULPI_NXT            | MCF_GPIO_PAR_USB_VBUSOC_ULPI_STP;        MCF_GPIO_PAR_FEC = MCF_GPIO_PAR_FEC             & MCF_GPIO_PAR_FEC_FEC0_MASK            | MCF_GPIO_PAR_FEC_FEC0_RMII_ULPI;                /* Turn on the port */        MCF_USB_PORTSC = 0            | MCF_USB_PORTSC_PTS_ULPI;   /* external ULPI transceiver */    }    else /* (xcvr == USB_PHY_FSLS) */    {        /* Insure that the MIC2026 ENB signal isn't asserted */        /*MCF_GPIO_PAR_USB = 0            | MCF_GPIO_PAR_USB_VBUSEN_GPIO            | MCF_GPIO_PAR_USB_VBUSOC_GPIO;        MCF_GPIO_PODR_USB = 0;        MCF_GPIO_PDDR_USB = MCF_GPIO_PDDR_USB_PDDR1;        */        /* Enable USB controller to control FSLS PHY internal D+ pull-up */        //MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBPUE;        /* Turn on the port */        MCF_USB_PORTSC |= MCF_USB_PORTSC_PTS_FS_LS;  /* on-chip FS/LS transceiver */    }    //--- Set Device Mode ---//    #ifdef DEBUG_PRINT        printf("Set device mode.\n");       #endif          MCF_USB_USBMODE = (MCF_USB_USBMODE_ES | MCF_USB_USBMODE_CM_DEVICE);    /*--- Intial Configuration ---*/    MCF_USB_USBCMD &= ~( MCF_USB_USBCMD_ITC(0xFF)); // Set interrupt threshold control = 0    MCF_USB_USBMODE |= 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 |= MCF_USB_USBCMD_RS;    // RUN controller    /* Enable a valid B session to allow device to connect to a host. */    MCF_CCM_UOCSR = 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(2048*2);    eplistaddr = (eplistaddr + 2048) & 0xFFFFF800;    /* Set the device endpoint list address */    MCF_USB_EPLISTADDR = 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 |= (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 &= ~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 |= MCF_USB_USBCMD_FS_1024;        break;      case 512:        MCF_USB_USBCMD |= MCF_USB_USBCMD_FS_512;        break;      case 256:        MCF_USB_USBCMD |= MCF_USB_USBCMD_FS_256;        break;      case 128:        MCF_USB_USBCMD |= MCF_USB_USBCMD_FS_128;        break;      case 64:        MCF_USB_USBCMD |= MCF_USB_USBCMD_FS_64;        break;      case 32:        MCF_USB_USBCMD |= MCF_USB_USBCMD_FS_32;        break;      case 16:        MCF_USB_USBCMD |= MCF_USB_USBCMD_FS_16;        break;      case 8:        MCF_USB_USBCMD |= MCF_USB_USBCMD_FS_8;        break;    default:        printf("ERR!! Invalid frame list size\n");        MCF_USB_USBCMD |= 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 = periodic_base;       /* Enable the periodic schedule */    MCF_USB_USBCMD |= MCF_USB_USBCMD_PSE;        /* Wait for periodic schedule to enable */    while (!(MCF_USB_USBSTS & 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 |= MCF_USB_PORTSC_PR;  // Set Port Reset    #ifdef DEBUG_PRINT        printf("Start reset.\n");        printf("PORTSC = 0x%08x\n",MCF_USB_PORTSC);         #endif        /* Wait for reset to finish */    while (MCF_USB_PORTSC & 0x100);//MCF_USB_PORTSC_PR);    #ifdef DEBUG_PRINT                  printf("PORTSC = 0x%08x\n",MCF_USB_PORTSC);             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);         /* Clear all setup token semaphores */    temp = MCF_USB_EPSETUPSR;    MCF_USB_EPSETUPSR = temp;    #ifdef DEBUG_PRINT        printf("EPSETUPSR = 0x%08x\n",MCF_USB_EPSETUPSR);    #endif        /* Clear all complete status bits */    temp = MCF_USB_EPCOMPLETE;    MCF_USB_EPCOMPLETE = temp;    #ifdef DEBUG_PRINT                  printf("EPCOMPLETE = 0x%08x\n",MCF_USB_EPCOMPLETE);    #endif        /* Wait for all primed status to clear */    while (MCF_USB_EPPRIME);    #ifdef DEBUG_PRINT        printf("EPPRIME = 0x%08x\n",MCF_USB_EPPRIME);    #endif    /* Flush all endpoints */    MCF_USB_EPFLUSH = 0xFFFFFFFF;        /* Wait for host to stop signalling reset */    while (MCF_USB_PORTSC & 0x100);//MCF_USB_PORTSC_PR);        /* Clear reset status bit */    MCF_USB_USBSTS |= 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);         #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 & MCF_USB_USBSTS_UI ));    while(!(MCF_USB_EPSETUPSR & MCF_USB_EPSETUPSR_EPSETUPSTAT(1)));            /* Verify that transaction is a SETUP on EP0 *///  if (MCF_USB_EPSETUPSR != 1)//      printf("\nERR!!! Expected SETUP on EP0 not received!\n");        /* Clear setup identification */    MCF_USB_EPSETUPSR |= MCF_USB_EPSETUPSR_EPSETUPSTAT(1);        /* Set setup tripwire */    MCF_USB_USBCMD |= 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 & MCF_USB_USBCMD_SUTW));        /* Clear SUTW bit */    MCF_USB_USBCMD &= ~MCF_USB_USBCMD_SUTW;        /* Wait for EPSETUP to clear */    while (MCF_USB_EPSETUPSR & MCF_USB_EPSETUPSR_EPSETUPSTAT(1));}/********************************************************************/int swap32(int data){

⌨️ 快捷键说明

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