📄 usb.c
字号:
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 + -