diff --git a/riscv-blink/include/usb.h b/riscv-blink/include/usb.h index 632823d..19fbb68 100644 --- a/riscv-blink/include/usb.h +++ b/riscv-blink/include/usb.h @@ -15,6 +15,7 @@ void usb_connect(void); void usb_idle(void); void usb_disconnect(void); void usb_setup(const struct usb_setup_request *setup, uint32_t size); +void usb_set_address(uint8_t address); void usb_ack_in(void); void usb_ack_out(void); @@ -25,4 +26,4 @@ void usb_send(const void *data, int total_count); } #endif -#endif \ No newline at end of file +#endif diff --git a/riscv-blink/src/usb-dev.c b/riscv-blink/src/usb-dev.c index dcab322..32faf6c 100644 --- a/riscv-blink/src/usb-dev.c +++ b/riscv-blink/src/usb-dev.c @@ -1,5 +1,6 @@ #include #include +#include #include struct usb_setup_request { @@ -28,19 +29,18 @@ static const uint8_t usb_config_descriptor[] = { }; static const uint8_t usb_string0_descriptor[] = { - 0x04, 0x03, 0x09, 0x04, + 0x04, 0x03, 0x09, 0x04 }; static const uint8_t usb_string1_descriptor[] = { - 0x0e, 0x03, 0x46, 0x00, 0x6f, 0x00, 0x6f, 0x00, - 0x73, 0x00, 0x6e, 0x00, 0x00, 0x00, + 0x0c, 0x03, 0x46, 0x00, 0x6f, 0x00, 0x6f, 0x00, + 0x73, 0x00, 0x6e, 0x00 }; static const uint8_t usb_string2_descriptor[] = { - 0x1a, 0x03, 0x46, 0x00, 0x6f, 0x00, 0x6d, 0x00, - 0x75, 0x00, 0x20, 0x00, 0x55, 0x00, 0x70, 0x00, - 0x64, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, - 0x72, 0x00, + 0x16, 0x03, 0x46, 0x00, 0x6f, 0x00, 0x6d, 0x00, + 0x75, 0x00, 0x20, 0x00, 0x42, 0x00, 0x6c, 0x00, + 0x69, 0x00, 0x6e, 0x00, 0x6b, 0x00 }; static const uint8_t usb_bos_descriptor[] = { @@ -67,7 +67,9 @@ static const uint8_t usb_string_microsoft[18] = { static uint8_t reply_buffer[8]; static uint8_t usb_configuration = 0; +static uint8_t data_buffer[64]; +__attribute__((section(".ramtext"))) void usb_setup(const struct usb_setup_request *setup, uint32_t size) { const uint8_t *data = NULL; @@ -77,6 +79,9 @@ void usb_setup(const struct usb_setup_request *setup, uint32_t size) switch (setup->wRequestAndType) { case 0x0500: // SET_ADDRESS + usb_set_address(setup->wValue); + break; + case 0x0b01: // SET_INTERFACE break; @@ -178,7 +183,10 @@ send: if (data && datalen) { if (datalen > setup->wLength) datalen = setup->wLength; - usb_send(data, datalen); + if (datalen > sizeof(data_buffer)) + datalen = sizeof(data_buffer); + memcpy(data_buffer, data, datalen); + usb_send(data_buffer, datalen); } else usb_ack_in(); diff --git a/riscv-blink/src/usb-epfifo.c b/riscv-blink/src/usb-epfifo.c index b930201..1d6dc32 100644 --- a/riscv-blink/src/usb-epfifo.c +++ b/riscv-blink/src/usb-epfifo.c @@ -6,21 +6,24 @@ // #ifdef CSR_USB_EP_0_OUT_EV_PENDING_ADDR #if 1 -#define EP0OUT_BUFFERS 8 +#define EP0OUT_BUFFERS 1 __attribute__((aligned(4))) -static uint8_t volatile usb_ep0out_buffer_len[EP0OUT_BUFFERS]; -static uint8_t volatile usb_ep0out_buffer[EP0OUT_BUFFERS][128]; -static uint8_t volatile usb_ep0out_last_tok[EP0OUT_BUFFERS]; -static volatile uint8_t usb_ep0out_wr_ptr; -static volatile uint8_t usb_ep0out_rd_ptr; +static uint8_t usb_ep0out_buffer_len[EP0OUT_BUFFERS]; +static uint8_t usb_ep0out_buffer[EP0OUT_BUFFERS][128]; +static uint8_t usb_ep0out_last_tok[EP0OUT_BUFFERS]; +static uint8_t usb_ep0out_wr_ptr; +static uint8_t usb_ep0out_rd_ptr; static const int max_byte_length = 64; -static const uint8_t * volatile current_data; -static volatile int current_length; -static volatile int data_offset; -static volatile int data_to_send; +static const uint8_t * current_data; +static int current_length; +static int data_offset; +static int data_to_send; static int next_packet_is_empty; +static uint8_t new_address; +static int have_new_address; + // Note that our PIDs are only bits 2 and 3 of the token, // since all other bits are effectively redundant at this point. enum USB_PID { @@ -40,6 +43,15 @@ enum epfifo_response { #define USB_EV_ERROR 1 #define USB_EV_PACKET 2 +// Firmware versions < 1.9 didn't have usb_address_write() +static void usb_set_address_wrapper(uint8_t address) { + if (version_major_read() < 1) + return; + if (version_minor_read() < 9) + return; + usb_address_write(address); +} + void usb_idle(void) { usb_ep_0_out_ev_enable_write(0); usb_ep_0_in_ev_enable_write(0); @@ -58,6 +70,7 @@ void usb_disconnect(void) { usb_ep_0_in_ev_enable_write(0); irq_setmask(irq_getmask() & ~(1 << USB_INTERRUPT)); usb_pullup_out_write(0); + usb_set_address_wrapper(0); } void usb_connect(void) { @@ -75,13 +88,13 @@ void usb_connect(void) { usb_pullup_out_write(1); - irq_setmask(irq_getmask() | (1 << USB_INTERRUPT)); + irq_setmask(irq_getmask() | (1 << USB_INTERRUPT)); } void usb_init(void) { + usb_disconnect(); usb_ep0out_wr_ptr = 0; usb_ep0out_rd_ptr = 0; - usb_pullup_out_write(0); } static void process_tx(void) { @@ -136,8 +149,8 @@ static void process_tx(void) { void usb_send(const void *data, int total_count) { - while ((current_length || current_data))// && usb_ep_0_in_respond_read() != EPF_NAK) - ; + while ((current_length || current_data) && usb_ep_0_in_respond_read() != EPF_NAK) + process_tx(); current_data = (uint8_t *)data; current_length = total_count; data_offset = 0; @@ -147,14 +160,16 @@ void usb_send(const void *data, int total_count) { void usb_wait_for_send_done(void) { while (current_data && current_length) - ; + process_tx(); while ((usb_ep_0_in_dtb_read() & 1) == 1) ; } void usb_isr(void) { uint8_t ep0o_pending = usb_ep_0_out_ev_pending_read(); + usb_ep_0_out_ev_pending_write(ep0o_pending); uint8_t ep0i_pending = usb_ep_0_in_ev_pending_read(); + usb_ep_0_in_ev_pending_write(ep0i_pending); // We got an OUT or a SETUP packet. Copy it to usb_ep0out_buffer // and clear the "pending" bit. @@ -180,28 +195,27 @@ void usb_isr(void) { usb_setup((const void *)obuf, obuf_len); } - usb_ep_0_out_ev_pending_write(ep0o_pending); usb_ep_0_out_respond_write(EPF_ACK); } // We just got an "IN" token. Send data if we have it. if (ep0i_pending) { usb_ep_0_in_respond_write(EPF_NAK); - usb_ep_0_in_ev_pending_write(ep0i_pending); + if (have_new_address) { + have_new_address = 0; + usb_set_address_wrapper(new_address); + } } + process_tx(); return; } void usb_ack_in(void) { - while (usb_ep_0_in_respond_read() == EPF_ACK) - ; usb_ep_0_in_respond_write(EPF_ACK); } void usb_ack_out(void) { - while (usb_ep_0_out_respond_read() == EPF_ACK) - ; usb_ep_0_out_respond_write(EPF_ACK); } @@ -234,4 +248,9 @@ int usb_recv(void *buffer, unsigned int buffer_len) { return 0; } +void usb_set_address(uint8_t _new_address) { + new_address = _new_address; + have_new_address = 1; +} + #endif /* CSR_USB_EP_0_OUT_EV_PENDING_ADDR */