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

📄 usb.c

📁 Freescale MCF5445evb 参考测试代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 & 0x1));//MCF_USB_PORTSC_CCS));    /* Determine the speed we are connected at. */    speed = (MCF_USB_PORTSC & 0x0C000000);//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;            case MCF_USB_PORTSC_PSPD_HIGH:                printf("Connected at high-speed\n");                break;            default:                printf("Invalid port speed\n");                break;        }        printf("PORTSC = 0x%08x\n",MCF_USB_PORTSC);         #endif    return speed;    }/********************************************************************//* * Disable the asynchronous and periodic lists. * * Parameters: *  port      USB module to send reset */void disable_async_per_schedules(int port){    /* Disable the asynchronous schedule */     MCF_USB_USBCMD &= ~MCF_USB_USBCMD_ASE;        /* Wait for asynchronous enable bit to clear */    while (MCF_USB_USBCMD & MCF_USB_USBCMD_ASE);    /* Disable the periodic schedule schedule */        MCF_USB_USBCMD &= ~MCF_USB_USBCMD_PSE;        /* Wait for periodic schedule enable bit to clear */    while (MCF_USB_USBCMD & MCF_USB_USBCMD_PSE);}/********************************************************************//* * Function to send an IN packet to the host while in USB device mode. * * Parameters: *  eplistaddr  pointer to the device endpoint list *  epnum       endpoint number to use *  buf         data to be sent to host *  size        amount of data to be transferred in bytes */void usb_device_send_control_packet(uint32 eplistaddr, uint32 epnum, uint8* buf, uint32 size){    int port = USB_OTG;    USB_DTD * usb_dtd1, * usb_dtd2;    uint8 * recv_buf[MAX_USB_DESC_SIZE];    /* Initialize dTD to send device descriptor */    usb_dtd1 = usb_dtd_init(size, 0, 0, (uint32*) buf);     /* Point the endpoint IN QH to the dTD */    ((USB_EP_QH*)(eplistaddr + EP_QH_IN(epnum)))->next_dtd = (uint32)usb_dtd1;        /* Prime Tx buffer for control endpoint */    MCF_USB_EPPRIME |= MCF_USB_EPPRIME_PETB(1<<epnum);        /* Wait for prime to complete *///    while (MCF_USB_EPPRIME & MCF_USB_EPPRIME_PETB(1<<epnum));        /* Initialize dTD for receive. The host won't actually send anything,       but a dTD needs to be setup to correctly deal with the 0 byte OUT       packet the host sends after receiving the IN data. */    usb_dtd2 = usb_dtd_init(0x40, 1, 0, (uint32*) recv_buf);        /* Point the endpoint OUT QH to the dTD */    ((USB_EP_QH*)(eplistaddr + EP_QH_OUT(epnum)))->next_dtd = (uint32)usb_dtd2;    /* Prime Rx buffer for control endpoint */    MCF_USB_EPPRIME |= MCF_USB_EPPRIME_PERB(1<<epnum);        /* Wait for prime to complete *///    while (MCF_USB_EPPRIME & MCF_USB_EPPRIME_PERB(1<<epnum));        /* Wait for OUT to complete */    while (!(MCF_USB_USBSTS & MCF_USB_USBSTS_UI ));    /* Clear interrupt */    MCF_USB_USBSTS |= MCF_USB_USBSTS_UI;           /* Return memory for dTDs to heap */    free((void *)usb_dtd1->malloc_ptr);    free((void *)usb_dtd2->malloc_ptr);     }/********************************************************************//* * Function to send an zero length IN packet to the host while in USB device mode. * * Parameters: *  eplistaddr  pointer to the device endpoint list *  epnum       endpoint number to use */void usb_device_send_zero_len_packet(uint32 eplistaddr, uint32 epnum){    int port = USB_OTG;    USB_DTD * usb_dtd1;    uint8 * empty_buf[1];    /* Set up dTD for zero length packet */        /* Initialize dTD */    usb_dtd1 = usb_dtd_init(0, 1, 0, (uint32*) empty_buf);      /* Point the endpoint IN QH to the dTD */    ((USB_EP_QH*)(eplistaddr + EP_QH_IN(epnum)))->next_dtd = (uint32)usb_dtd1;    /* Prime Tx buffer for control endpoint */    MCF_USB_EPPRIME |= MCF_USB_EPPRIME_PETB(1<<epnum);        /* Wait for prime to complete */    while (MCF_USB_EPPRIME & MCF_USB_EPPRIME_PETB(1<<epnum));    /* Wait for IN to complete */    while (!(MCF_USB_USBSTS & MCF_USB_USBSTS_UI ));    /* Clear interrupt */    MCF_USB_USBSTS |= MCF_USB_USBSTS_UI;        /* Return memory for dTDs to heap */    free((void *)usb_dtd1->malloc_ptr);}/********************************************************************//* * Allocate memory for a qTD and initialize the qTD. * This function assumes the qTD is the last in the list so  * the next qTD pointer is not initialized.  * * Parameters: *  trans_sz        number of bytes to be transferred *  ioc             interrupt on complete flag *  pid             PID code for the transfer ( *  buffer_ptr      pointer to the data buffer  */USB_QTD *usb_qtd_init(uint32 trans_sz, uint32 ioc, uint32 pid, uint32 * buffer_ptr){    USB_QTD *usb_qtd;    uint32 token;    uint32 malloc_addr;   /*    * The USB requires qTDs to be aligned on a 32 byte boundary.     * In order to accomplish this, the data is over-allocated and     * adjusted.     */    malloc_addr = (uint32)malloc(sizeof(USB_QTD)+32);    usb_qtd = (USB_QTD *)((malloc_addr + 31) & 0xFFFFFFE0);    usb_qtd->next_qtd = 0xDEAD0001;    usb_qtd->alt_qtd = 0x1;        switch (pid)    {        case SETUP_PID:            token = USB_QTD_TOKEN_PID_SETUP;            break;        case OUT_PID:            token = (USB_QTD_TOKEN_DT | USB_QTD_TOKEN_PID_OUT);            break;        case IN_PID:            token = (USB_QTD_TOKEN_DT | USB_QTD_TOKEN_PID_IN);            break;        default:            #ifdef DEBUG_PRINT                printf("ERR!! Invalid PID\n");            #endif            break;    }        if (trans_sz > MAX_QTD_TRANS_SIZE)        #ifdef DEBUG_PRINT            printf("ERR!! Invalid transfer size.\n");        #endif        if (ioc)        token |= USB_QTD_TOKEN_IOC;      usb_qtd->qtd_token = (token                            | USB_QTD_TOKEN_TRANS_SIZE(trans_sz)                            | USB_QTD_TOKEN_CERR(0x3)                            | USB_QTD_TOKEN_STAT_ACTIVE );                                usb_qtd->qtd_buf0 = (uint32) buffer_ptr;    usb_qtd->qtd_buf1 = 0;    usb_qtd->qtd_buf2 = 0;    usb_qtd->qtd_buf3 = 0;    usb_qtd->qtd_buf4 = 0;    usb_qtd->malloc_ptr = malloc_addr;    return usb_qtd;}/********************************************************************//* * Allocate memory for a QH and initialize the QH. * This function assumes the QH is the only one in the horizontoal list so  * the horizontal link pointer points to the queue head. This function * doesn't initialize the qTD pointer either. This must be done later.  * * Parameters: *  max_packet      maximum packet length for the endpoint *  head            used to mark the QH as the first in the linked list (not used for interrupt QHs)             *  eps             end point speed *  epnum           end pont number              *  dev_addr        device address *  smask           interrupt schedule mask (only used for periodic schedule QHs) */USB_QH *usb_qh_init(uint32 max_packet, uint32 head, uint32 eps, uint32 epnum,             uint32 dev_addr, uint32 smask){    USB_QH *usb_qh;    uint32 token;    uint32 malloc_addr;   /*    * The USB requires queue heads to be aligned on a 64 byte boundary.     * In order to accomplish this, the data is over-allocated and     * adjusted.      */    malloc_addr = (uint32)malloc(sizeof(USB_QH)*2);    usb_qh = (USB_QH *)((malloc_addr + 32) & 0xFFFFFFE0);        usb_qh->qh_link_ptr = (((uint32) usb_qh)                                 | USB_QH_LINK_PTR_TYP_QH );    if (max_packet > MAX_QH_PACKET_SIZE )        #ifdef DEBUG_PRINT            printf("ERR!! Invalid packet size.\n");        #endif    switch (eps)    {        case EPS_FULL:            token = USB_QH_EP_CHAR_EPS_FULL;            break;        case EPS_LOW:            token = USB_QH_EP_CHAR_EPS_LOW;            break;        case EPS_HIGH:            token = USB_QH_EP_CHAR_EPS_HIGH;            break;        default:            #ifdef DEBUG_PRINT                printf("ERR!! Invalid EPS\n");            #endif            break;    }        if (head)        token |= USB_QH_EP_CHAR_H;                        usb_qh->ep_char = ( token                         | USB_QH_EP_CHAR_MAX_PACKET(max_packet)                         | USB_QH_EP_CHAR_DTC                         | USB_QH_EP_CHAR_EP(epnum)                         | USB_QH_EP_CHAR_DEV_ADDR(dev_addr) );            /* Set interrupt to occur every 8ms */    usb_qh->ep_cap = (USB_QH_EP_CAP_MULT_ONE                        | USB_QH_EP_CAP_UFRAME_SMASK(smask));                usb_qh->curr_qtd = 0;    usb_qh->next_qtd = 1;    usb_qh->alt_qtd = 0;    usb_qh->qtd_token = 0;    usb_qh->qtd_buf0 = 0;    usb_qh->qtd_buf1 = 0;    usb_qh->qtd_buf2 = 0;    usb_qh->qtd_buf3 = 0;    usb_qh->qtd_buf4 = 0;        usb_qh->malloc_ptr = malloc_addr;    return usb_qh;}/********************************************************************//* * Initialize an endpoint QH. The space for the endpoint queue heads is  * allocated when the endpoint list is created, so this function does not * call malloc.  * * Parameters: *  eplistaddr      location of the endpoint list *  offset          offset within the endpoint list for the EP_QH (there are macros for this) *  mult            number of packets per transcation, should be 0 for non-ISO endpoints *  max_packet      maximum packet length for the endpoint           *  ios             flag to enable interrupts on incoming setup packets *  next_dtd        ponter to the first dtd for the ep_qh */void usb_ep_qh_init(uint32 eplistaddr, uint32 offset, uint32 mult, uint32 max_packet,                     uint32 ios, uint32 next_dtd){    USB_EP_QH* usb_ep_qh;    uint32 token;        /* Create a pointer to the endpoint queue head being initialized */    usb_ep_qh = (USB_EP_QH*) (eplistaddr + offset);        if (max_packet > MAX_QH_PACKET_SIZE )        #ifdef DEBUG_PRINT            printf("ERR!! Invalid packet size.\n");        #endif    if (ios)        token = USB_EP_QH_EP_CHAR_IOS;    else        token = 0;                        usb_ep_qh->ep_char = ( token                            | USB_EP_QH_EP_CHAR_MULT(mult)                                                          | USB_EP_QH_EP_CHAR_MAX_PACKET(max_packet));                usb_ep_qh->curr_dtd = 0;    usb_ep_qh->next_dtd = next_dtd;    usb_ep_qh->dtd_token = 0;    usb_ep_qh->dtd_buf0 = 0;    usb_ep_qh->dtd_buf1 = 0;    usb_ep_qh->dtd_buf2 = 0;    usb_ep_qh->dtd_buf3 = 0;    usb_ep_qh->dtd_buf4 = 0;}/********************************************************************//* * Allocate memory for a device transfer descriptor (dTD) and initialize * the dTD. This function assumes the dTD is the last in the list so  * the next dTD pointer is marked as invalid.  * * Parameters: *  trans_sz        number of bytes to be transferred *  ioc             interrupt on complete flag *  pid             PID code for the transfer ( *  buffer_ptr      pointer to the data buffer  */USB_DTD *usb_dtd_init(uint32 trans_sz, uint32 ioc, uint32 multo, uint32 * buffer_ptr){    USB_DTD *usb_dtd;    uint32 token;    uint32 malloc_addr;   /*    * The USB requires dTDs to be aligned on a 64 byte boundary.     * In order to accomplish this, the data is over-allocated and     * adjusted.     */    malloc_addr = (uint32)malloc(sizeof(USB_DTD)*2);    usb_dtd = (USB_DTD *)((malloc_addr + 32) & 0xFFFFFFE0);    usb_dtd->next_dtd = 0xDEAD0001;            if (trans_sz > MAX_DTD_TRANS_SIZE)        #ifdef DEBUG_PRINT            printf("ERR!! Invalid transfer size.\n");        #endif        if (ioc)        token = USB_DTD_TOKEN_IOC;    else        token = 0;      usb_dtd->dtd_token = (token                            | USB_DTD_TOKEN_TOTAL_BYTES(trans_sz)                            | USB_DTD_TOKEN_MULTO(multo)                            | USB_DTD_TOKEN_STAT_ACTIVE );                                usb_dtd->dtd_buf0 = (uint32) buffer_ptr;    usb_dtd->dtd_buf1 = 0;    usb_dtd->dtd_buf2 = 0;    usb_dtd->dtd_buf3 = 0;    usb_dtd->dtd_buf4 = 0;    usb_dtd->malloc_ptr = malloc_addr;    return usb_dtd;}/********************************************************************/

⌨️ 快捷键说明

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