riscv-blink: fix usb stack

This appears to work now.

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2019-08-28 07:29:50 +08:00
parent a0d1e62ba2
commit 059e44a04b
3 changed files with 58 additions and 30 deletions

View File

@ -15,6 +15,7 @@ void usb_connect(void);
void usb_idle(void); void usb_idle(void);
void usb_disconnect(void); void usb_disconnect(void);
void usb_setup(const struct usb_setup_request *setup, uint32_t size); 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_in(void);
void usb_ack_out(void); void usb_ack_out(void);
@ -25,4 +26,4 @@ void usb_send(const void *data, int total_count);
} }
#endif #endif
#endif #endif

View File

@ -1,5 +1,6 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <string.h>
#include <usb.h> #include <usb.h>
struct usb_setup_request { struct usb_setup_request {
@ -28,19 +29,18 @@ static const uint8_t usb_config_descriptor[] = {
}; };
static const uint8_t usb_string0_descriptor[] = { static const uint8_t usb_string0_descriptor[] = {
0x04, 0x03, 0x09, 0x04, 0x04, 0x03, 0x09, 0x04
}; };
static const uint8_t usb_string1_descriptor[] = { static const uint8_t usb_string1_descriptor[] = {
0x0e, 0x03, 0x46, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x0c, 0x03, 0x46, 0x00, 0x6f, 0x00, 0x6f, 0x00,
0x73, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x73, 0x00, 0x6e, 0x00
}; };
static const uint8_t usb_string2_descriptor[] = { static const uint8_t usb_string2_descriptor[] = {
0x1a, 0x03, 0x46, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x16, 0x03, 0x46, 0x00, 0x6f, 0x00, 0x6d, 0x00,
0x75, 0x00, 0x20, 0x00, 0x55, 0x00, 0x70, 0x00, 0x75, 0x00, 0x20, 0x00, 0x42, 0x00, 0x6c, 0x00,
0x64, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x6b, 0x00
0x72, 0x00,
}; };
static const uint8_t usb_bos_descriptor[] = { 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 reply_buffer[8];
static uint8_t usb_configuration = 0; 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) void usb_setup(const struct usb_setup_request *setup, uint32_t size)
{ {
const uint8_t *data = NULL; const uint8_t *data = NULL;
@ -77,6 +79,9 @@ void usb_setup(const struct usb_setup_request *setup, uint32_t size)
switch (setup->wRequestAndType) switch (setup->wRequestAndType)
{ {
case 0x0500: // SET_ADDRESS case 0x0500: // SET_ADDRESS
usb_set_address(setup->wValue);
break;
case 0x0b01: // SET_INTERFACE case 0x0b01: // SET_INTERFACE
break; break;
@ -178,7 +183,10 @@ send:
if (data && datalen) { if (data && datalen) {
if (datalen > setup->wLength) if (datalen > setup->wLength)
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 else
usb_ack_in(); usb_ack_in();

View File

@ -6,21 +6,24 @@
// #ifdef CSR_USB_EP_0_OUT_EV_PENDING_ADDR // #ifdef CSR_USB_EP_0_OUT_EV_PENDING_ADDR
#if 1 #if 1
#define EP0OUT_BUFFERS 8 #define EP0OUT_BUFFERS 1
__attribute__((aligned(4))) __attribute__((aligned(4)))
static uint8_t volatile usb_ep0out_buffer_len[EP0OUT_BUFFERS]; static uint8_t usb_ep0out_buffer_len[EP0OUT_BUFFERS];
static uint8_t volatile usb_ep0out_buffer[EP0OUT_BUFFERS][128]; static uint8_t usb_ep0out_buffer[EP0OUT_BUFFERS][128];
static uint8_t volatile usb_ep0out_last_tok[EP0OUT_BUFFERS]; static uint8_t usb_ep0out_last_tok[EP0OUT_BUFFERS];
static volatile uint8_t usb_ep0out_wr_ptr; static uint8_t usb_ep0out_wr_ptr;
static volatile uint8_t usb_ep0out_rd_ptr; static uint8_t usb_ep0out_rd_ptr;
static const int max_byte_length = 64; static const int max_byte_length = 64;
static const uint8_t * volatile current_data; static const uint8_t * current_data;
static volatile int current_length; static int current_length;
static volatile int data_offset; static int data_offset;
static volatile int data_to_send; static int data_to_send;
static int next_packet_is_empty; 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, // Note that our PIDs are only bits 2 and 3 of the token,
// since all other bits are effectively redundant at this point. // since all other bits are effectively redundant at this point.
enum USB_PID { enum USB_PID {
@ -40,6 +43,15 @@ enum epfifo_response {
#define USB_EV_ERROR 1 #define USB_EV_ERROR 1
#define USB_EV_PACKET 2 #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) { void usb_idle(void) {
usb_ep_0_out_ev_enable_write(0); usb_ep_0_out_ev_enable_write(0);
usb_ep_0_in_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); usb_ep_0_in_ev_enable_write(0);
irq_setmask(irq_getmask() & ~(1 << USB_INTERRUPT)); irq_setmask(irq_getmask() & ~(1 << USB_INTERRUPT));
usb_pullup_out_write(0); usb_pullup_out_write(0);
usb_set_address_wrapper(0);
} }
void usb_connect(void) { void usb_connect(void) {
@ -75,13 +88,13 @@ void usb_connect(void) {
usb_pullup_out_write(1); usb_pullup_out_write(1);
irq_setmask(irq_getmask() | (1 << USB_INTERRUPT)); irq_setmask(irq_getmask() | (1 << USB_INTERRUPT));
} }
void usb_init(void) { void usb_init(void) {
usb_disconnect();
usb_ep0out_wr_ptr = 0; usb_ep0out_wr_ptr = 0;
usb_ep0out_rd_ptr = 0; usb_ep0out_rd_ptr = 0;
usb_pullup_out_write(0);
} }
static void process_tx(void) { static void process_tx(void) {
@ -136,8 +149,8 @@ static void process_tx(void) {
void usb_send(const void *data, int total_count) { 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_data = (uint8_t *)data;
current_length = total_count; current_length = total_count;
data_offset = 0; data_offset = 0;
@ -147,14 +160,16 @@ void usb_send(const void *data, int total_count) {
void usb_wait_for_send_done(void) { void usb_wait_for_send_done(void) {
while (current_data && current_length) while (current_data && current_length)
; process_tx();
while ((usb_ep_0_in_dtb_read() & 1) == 1) while ((usb_ep_0_in_dtb_read() & 1) == 1)
; ;
} }
void usb_isr(void) { void usb_isr(void) {
uint8_t ep0o_pending = usb_ep_0_out_ev_pending_read(); 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(); 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 // We got an OUT or a SETUP packet. Copy it to usb_ep0out_buffer
// and clear the "pending" bit. // and clear the "pending" bit.
@ -180,28 +195,27 @@ void usb_isr(void) {
usb_setup((const void *)obuf, obuf_len); usb_setup((const void *)obuf, obuf_len);
} }
usb_ep_0_out_ev_pending_write(ep0o_pending);
usb_ep_0_out_respond_write(EPF_ACK); usb_ep_0_out_respond_write(EPF_ACK);
} }
// We just got an "IN" token. Send data if we have it. // We just got an "IN" token. Send data if we have it.
if (ep0i_pending) { if (ep0i_pending) {
usb_ep_0_in_respond_write(EPF_NAK); 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; return;
} }
void usb_ack_in(void) { void usb_ack_in(void) {
while (usb_ep_0_in_respond_read() == EPF_ACK)
;
usb_ep_0_in_respond_write(EPF_ACK); usb_ep_0_in_respond_write(EPF_ACK);
} }
void usb_ack_out(void) { void usb_ack_out(void) {
while (usb_ep_0_out_respond_read() == EPF_ACK)
;
usb_ep_0_out_respond_write(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; 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 */ #endif /* CSR_USB_EP_0_OUT_EV_PENDING_ADDR */