void usb_init(void) { // Setup state information usb_state = DEFAULT; usb_bm_state = 0; // Setconfig configuration information usb_current_config = 0; usb_current_alt_interface = 0; // Disconnect from USB-bus since we are in this routine from a power on and not a soft reset: usbcs |= 0x08; delay_ms(50); usbcs &= ~0x08; /*intterrupt enable uresie,suspie,sutokie,sudavie */ usbien = 0x1d; /*Endpoint 0 to 5 IN interrupt enables (in_ien)*/ in_ien = 0x01; /*Endpoints 0 to 5 IN interrupt request register (in_irq) - clear interrupt*/ in_irq = 0x1f; /*Endpoint 0 to 5 OUT interrupt enables (out_ien)*/ out_ien = 0x01; /*Endpoints 0 to 5 OUT interrupt request register (out_irq) - clear in interrupt*/ out_irq = 0x1f; // Setup the USB RAM with some OK default values: bout1addr = MAX_PACKET_SIZE_EP0/2; bout2addr = MAX_PACKET_SIZE_EP0/2 + USB_EP1_SIZE/2; bout3addr = MAX_PACKET_SIZE_EP0/2 + 2*USB_EP1_SIZE/2; bout4addr = MAX_PACKET_SIZE_EP0/2 + 3*USB_EP1_SIZE/2; bout5addr = MAX_PACKET_SIZE_EP0/2 + 4*USB_EP1_SIZE/2; binstaddr = 0xc0; bin1addr = MAX_PACKET_SIZE_EP0/2; bin2addr = MAX_PACKET_SIZE_EP0/2 + USB_EP1_SIZE/2; bin3addr = MAX_PACKET_SIZE_EP0/2 + 2*USB_EP1_SIZE/2; bin4addr = MAX_PACKET_SIZE_EP0/2 + 3*USB_EP1_SIZE/2; bin5addr = MAX_PACKET_SIZE_EP0/2 + 4*USB_EP1_SIZE/2; // Set all endpoints to not valid (except EP0IN and EP0OUT) /*Endpoints 0 to 5 IN valid bits (Inbulkval)*/ inbulkval = 0x01; /*Endpoints 0 to 5 OUT valid bits (outbulkval)*/ outbulkval = 0x01; /*Isochronous IN endpoint valid bits (inisoval)*/ inisoval = 0x00; /*Isochronous OUT endpoint valid bits (outisoval)*/ outisoval = 0x00; /* Switch ON Endpoint 1 */ /*Endpoint 0 to 5 OUT interrupt enables (out_ien)* - out1ien */ in_ien |= 0x02; /*Endpoints 0 to 5 OUT valid bits (outbulkval)*/ inbulkval |= 0x02; /*Endpoint 0 to 5 OUT interrupt enables (out_ien)*/ out_ien |= 0x02; /*Endpoints 0 to 5 OUT valid bits (outbulkval)*/ outbulkval |= 0x02; /* Endpoint 0 to 5 OUT byte count registers (outxbc) ?Maybe 0xff is register clear*/ out1bc = 0xff; /* Switch ON Endpoint 2 */ /*Endpoint 0 to 5 OUT interrupt enables (out_ien)* - out1ien */ in_ien |= 0x04; /*Endpoints 0 to 5 OUT valid bits (outbulkval)*/ inbulkval |= 0x04; /*Endpoint 0 to 5 OUT interrupt enables (out_ien)*/ out_ien |= 0x04; /*Endpoints 0 to 5 OUT valid bits (outbulkval)*/ outbulkval |= 0x04; /* Endpoint 0 to 5 OUT byte count registers (outxbc) ?Maybe 0xff is register clear*/ out2bc = 0xff; /* Switch ON Endpoint 3 */ /*Endpoint 0 to 5 OUT interrupt enables (out_ien)* - out1ien */ in_ien |= 0x08; /*Endpoints 0 to 5 OUT valid bits (outbulkval)*/ inbulkval |= 0x08; /*Endpoint 0 to 5 OUT interrupt enables (out_ien)*/ out_ien |= 0x08; /*Endpoints 0 to 5 OUT valid bits (outbulkval)*/ outbulkval |= 0x08; /* Endpoint 0 to 5 OUT byte count registers (outxbc) ?Maybe 0xff is register clear*/ out3bc = 0xff; }
USB = 1; // USBIRQ is mapped to IEN1.4 EA = 1; // enable global interrupt
/* USB interrupt request */ void usb_irq_handler(void) interrupt INTERRUPT_USB_INT { usb_irq(); }
void usb_irq(void) { uint8_t i; uint8_t temp_irq; if (ivec == INT_USBRESET) { /*The USB interrupt request register (usbirq) - clear USB reset interrupt request*/ usbirq = 0x10; usb_state = DEFAULT; usb_current_config = 0; usb_current_alt_interface = 0; usb_bm_state = 0; } else { switch(ivec) { case INT_SUDAV: /*Setup data valid interrupt*/ usbirq = 0x01; isr_sudav(); break; case INT_SOF: /*Start of frame interrupt (sofir)*/ usbirq = 0x02; break; case INT_SUTOK: /*Setup token interrupt*/ usbirq = 0x04; packetizer_data_ptr = NULL; packetizer_data_size = 0; packetizer_pkt_size = 0; break; case INT_SUSPEND: /*Suspend interrupt (suspir)*/ usbirq = 0x08; break; case INT_EP0IN: in_irq = 0x01; packetizer_isr_ep0_in(); break; case INT_EP0OUT: out_irq = 0x01; packetizer_data_size = 0; USB_EP0_HSNAK(); break; case INT_EP1IN: in_irq = 0x02; int_ep1in_handler(); break; case INT_EP1OUT: out_irq = 0x02; out1bc = 0xff; break; case INT_EP2IN: in_irq = 0x04; break; default: break; } } }
Enumeration is the process of determining the fact that a device is actually connected to the USB bus and what parameters it requires - power consumption,
the number and type of the end point (or points), the device class, etc. In the enumeration process, the host assigns an address to the device and allows configuration,
allowing the device to transfer data over the bus. [...]
The general enumeration process under the Windows operating system includes the following steps:
')
1. The host or hub detects the connection of a new device using pull-up resistors, which the device connects to a pair of data signal wires (D + and D-). The host makes a delay of at least 100 ms, which allows you to insert the connector completely and stabilize the device power supply.
2. The host issues a reset to the bus, which puts the device in the default state. The device can now respond to the default zero address.
3. The MS Windows host requests the first 64 bytes of the device descriptor (Device Descriptor).
4. After receiving the first 8 bytes of the device descriptor, the host immediately issues a new bus reset.
5. Now the host issues the Set Address command, which puts the device into addressable state.
6. The host requests all 18 bytes of the device descriptor.
7. It then requests 9 bytes of the Configuration Descriptor to determine its full size.
8. The host requests 255 bytes of the configuration descriptor.
9. The host requests all string descriptors (String Descriptors), if any.
static void isr_sudav() { bmRequestType = setupbuf[0]; /* Host-to-device standart request */ if((bmRequestType & 0x60 ) == 0x00) { switch(setupbuf[1]) { case USB_REQ_GET_DESCRIPTOR: usb_process_get_descriptor(); break; case USB_REQ_GET_STATUS: usb_process_get_status(); break; case USB_REQ_SET_ADDRESS: usb_state = ADDRESSED; usb_current_config = 0x00; break; case USB_REQ_GET_CONFIGURATION: switch(usb_state) { case ADDRESSED: in0buf[0] = 0x00; in0bc = 0x01; break; case CONFIGURED: in0buf[0] = usb_current_config; in0bc = 0x01; break; case ATTACHED: case POWERED: case SUSPENDED: case DEFAULT: default: USB_EP0_STALL(); break; } break; case USB_REQ_SET_CONFIGURATION: switch(setupbuf[2]) { case 0x00: usb_state = ADDRESSED; usb_current_config = 0x00; USB_EP0_HSNAK(); break; case 0x01: usb_state = CONFIGURED; usb_bm_state |= USB_BM_STATE_CONFIGURED; usb_current_config = 0x01; USB_EP0_HSNAK(); break; default: USB_EP0_STALL(); break; } break; case USB_REQ_GET_INTERFACE: // GET_INTERFACE in0buf[0] = usb_current_alt_interface; in0bc = 0x01; break; case USB_REQ_SET_DESCRIPTOR: case USB_REQ_SET_INTERFACE: // SET_INTERFACE case USB_REQ_SYNCH_FRAME: // SYNCH_FRAME default: USB_EP0_STALL(); break; } } // bmRequestType = 0 01 xxxxx : Data transfer direction: Host-to-device, Type: Class else if((bmRequestType & 0x60 ) == 0x20) // Class request { if(setupbuf[6] != 0 && ((bmRequestType & 0x80) == 0x00)) { // If there is a OUT-transaction associated with the Control-Transfer-Write we call the callback // when the OUT-transaction is finished. Note that this function do not handle several out transactions. out0bc = 0xff; } else { USB_EP0_HSNAK(); } } /* Extended Compat ID OS Descriptor setupbuf[1] (bRequest) is equal to MS_VendorCode (0xAA is current program)*/ else if(bmRequestType == 0xC0 && setupbuf[1] == MS_VENDORCODE) { packetizer_pkt_size = MAX_PACKET_SIZE_EP0; //xprintf("Extended Compat ID\r"); packetizer_data_ptr = g_usb_extended_compat_id; packetizer_data_size = MIN(setupbuf[6], packetizer_data_ptr[0]); packetizer_isr_ep0_in(); } /* Extended Properties OS Descriptor */ else if(bmRequestType == 0xC1 && setupbuf[1] == MS_VENDORCODE) { packetizer_pkt_size = MAX_PACKET_SIZE_EP0; //xprintf("Extended Properties ID\r"); packetizer_data_ptr = g_usb_extended_proper_os; packetizer_data_size = MIN(setupbuf[6], packetizer_data_ptr[0]); packetizer_isr_ep0_in(); } else // Unknown request type { USB_EP0_STALL(); } }
void int_ep1in_handler(void) { uint8_t i; for(i=0;i<64;i++){ in1buf[i]=i; } in1bc = 64; }
void int_ep1out_handler(void) { do_anything(out1buf,in1bc); in1bc = 0xFF; //dummy write }
while(1) { while(in2cs != 0); if(i%2){ //first buffer for(i=0;i<64;i++) in2buf[i]=0xAA; in2bc = 64; } else { //second buffer for(i=0;i<64;i++) in3buf[i]=0xBB; in2bc = 64; } i++; }
Data transfer to host in single buffer | 360 kb / s |
Data transfer to host in double buffer | 510 kb / s |
Receive data from single buffer host | 230 kb / s |
Receive data from host double buffer | not tested |
Source: https://habr.com/ru/post/367955/
All Articles