From fae65117cd13b96b839eab7bec42d108b19c6520 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Thu, 28 Feb 2019 10:48:25 +0800 Subject: [PATCH] usb: work-in-progress for USB development Signed-off-by: Sean Cross --- src/main.c | 73 ++++----- src/{usb.c => usb-epfifo.c} | 310 ++++++++++++++++++++++++++++++++---- src/usb-rawfifo.c | 116 ++++++++++++++ 3 files changed, 425 insertions(+), 74 deletions(-) rename src/{usb.c => usb-epfifo.c} (51%) create mode 100644 src/usb-rawfifo.c diff --git a/src/main.c b/src/main.c index 22fdfd7..a12b6e2 100644 --- a/src/main.c +++ b/src/main.c @@ -23,7 +23,12 @@ void isr(void) static void rv_putchar(void *ignored, char c) { (void)ignored; + if (c == '\n') + uart_write('\r'); + if (c == '\r') + return; uart_write(c); + // uart_sync(); } static void init(void) @@ -36,37 +41,21 @@ static void init(void) time_init(); } +static const char *usb_hw_api(void) { #ifdef CSR_USB_EP_0_OUT_EV_PENDING_ADDR + return "epfifo"; #else -static void get_print_status(void) -{ - static int loops; - uint32_t obe = usb_obuf_empty_read(); - uint8_t obufbuf[128]; - int obufbuf_cnt = 0; - loops++; - - while (!usb_obuf_empty_read()) { - uint32_t obh = usb_obuf_head_read(); - obufbuf[obufbuf_cnt++] = obh; - usb_obuf_head_write(1); - } - if (obufbuf_cnt) { - int i; - printf("i: %d b: %d --", loops, obufbuf_cnt);//obe: %d obh: %02x\n", i, obe, obh); - for (i = 0; i < obufbuf_cnt; i++) { - printf(" %02x", obufbuf[i]); - } - printf("\n"); - } - // if (!obe) { - // uint32_t obh = usb_obuf_head_read(); - // usb_obuf_head_write(1); - // if (i < 300) - // printf("i: %8d obe: %d obh: %02x\n", i, obe, obh); - // } +#ifdef CSR_USB_OBUF_EMPTY_ADDR + return "rawfifo"; +#else +#ifdef CSR_USB_WHATEVER + return "whatever"; +#else + return "unrecognized hw api"; +#endif /* CSR_USB_WHATEVER */ +#endif /* CSR_USB_OBUF_EMPTY_ADDR */ +#endif /* CSR_USB_EP_0_OUT_EV_PENDING_ADDR */ } -#endif int main(int argc, char **argv) { @@ -74,20 +63,26 @@ int main(int argc, char **argv) (void)argv; init(); - usb_pullup_out_write(1); - usb_ep_0_out_ev_pending_write((1 << 1)); - if (usb_ep_0_out_ev_pending_read() & (1 << 1)) - usb_isr(); - - printf("Hello, world!\n"); + printf("\n\nUSB API: %s\n", usb_hw_api()); + // printf("Press any key to enable USB...\n"); + + usb_print_status(); + // uart_read(); + printf("Enabling USB\n"); + usb_connect(); + printf("USB enabled, waiting for packet...\n"); + // usb_wait(); + usb_print_status(); + int last = 0; while (1) { - if (usb_ep_0_out_ev_pending_read() & (1 << 1)) - usb_isr(); - // elapsed(&last_event, 1000); - - // get_print_status(); + if (usb_irq_happened() != last) { + last = usb_irq_happened(); + printf("USB %d IRQ happened\n", last); + } + // printf("x"); + usb_print_status(); } return 0; } \ No newline at end of file diff --git a/src/usb.c b/src/usb-epfifo.c similarity index 51% rename from src/usb.c rename to src/usb-epfifo.c index 8ee1750..abd22c1 100644 --- a/src/usb.c +++ b/src/usb-epfifo.c @@ -1,30 +1,19 @@ #include #include +#include #include #include #include +#include + +#ifdef CSR_USB_EP_0_OUT_EV_PENDING_ADDR #define NUM_BUFFERS 4 #define BUFFER_SIZE 64 #define EP_INTERVAL_MS 6 -static struct GrainuumUSB usb; -static uint8_t usb_buf[67]; - -static uint32_t rx_buffer[NUM_BUFFERS][BUFFER_SIZE / sizeof(uint32_t)]; -static uint8_t rx_buffer_head; -static uint8_t rx_buffer_tail; - -static uint32_t rx_buffer_queries = 0; - - -static void set_usb_config_num(struct GrainuumUSB *usb, int configNum) -{ - (void)usb; - (void)configNum; - ; -} - +//static struct GrainuumUSB usb; +//static uint8_t usb_buf[67]; static const uint8_t hid_report_descriptor[] = { 0x06, 0x00, 0xFF, // (GLOBAL) USAGE_PAGE 0xFF00 Vendor-defined 0x09, 0x00, // (LOCAL) USAGE 0xFF000000 @@ -114,6 +103,255 @@ static const struct usb_configuration_descriptor configuration_descriptor = { }, }; +enum epfifo_response { + EPF_ACK = 0, + EPF_NAK = 1, + EPF_NONE = 2, + EPF_STALL = 3, +}; + +#define USB_EV_ERROR 1 +#define USB_EV_PACKET 2 + +void usb_connect(void) { + usb_pullup_out_write(1); + + // By default, it wants to respond with NAK. + usb_ep_0_out_respond_write(EPF_ACK); + usb_ep_0_in_respond_write(EPF_NAK); + + usb_ep_0_out_ev_pending_write(usb_ep_0_out_ev_enable_read()); + usb_ep_0_in_ev_pending_write(usb_ep_0_in_ev_pending_read()); + usb_ep_0_out_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + usb_ep_0_in_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + + irq_setmask(irq_getmask() | (1 << USB_INTERRUPT)); +} + +void usb_init(void) { + return; +} + +volatile int irq_count = 0; + +#define EP0OUT_BUFFERS 64 +static uint8_t usb_ep0out_buffer[EP0OUT_BUFFERS][128]; +uint8_t usb_ep0out_wr_ptr; +uint8_t usb_ep0out_rd_ptr; +int descriptor_ptr; +int max_byte_length = 8; + +static const uint8_t *current_data; +static int current_length; +static int current_offset; +static int current_to_send; + +static int maybe_send_more_data(int epnum) { + (void)epnum; + // Don't allow requeueing + if (usb_ep_0_in_respond_read() != EPF_NAK) + return -1; + // if (!usb_ep_0_in_ibuf_empty_read()) + // return -2; + + int this_offset; + current_to_send = current_length - current_offset; + if (current_to_send > max_byte_length) + current_to_send = max_byte_length; + + for (this_offset = current_offset; this_offset < current_offset + current_to_send; this_offset++) { + usb_ep_0_in_ibuf_head_write(current_data[this_offset]); + } + usb_ep_0_in_respond_write(EPF_ACK); + return 0; +} + +static int send_data(int epnum, const void *data, int total_count) { + // Don't allow requeueing + if (usb_ep_0_in_respond_read() != EPF_NAK) + return -1; + current_data = (uint8_t *)data; + current_length = total_count; + current_offset = 0; + maybe_send_more_data(epnum); + return 0; +} + +void usb_isr(void) { + irq_count++; + + uint8_t ep0o_pending = usb_ep_0_out_ev_pending_read(); + uint8_t ep0i_pending = usb_ep_0_in_ev_pending_read(); + + if (ep0o_pending) { + int byte_count = 0; + uint8_t *obuf = usb_ep0out_buffer[usb_ep0out_wr_ptr]; + while (1) { + if (usb_ep_0_out_obuf_empty_read()) + break; + obuf[++byte_count] = usb_ep_0_out_obuf_head_read(); + usb_ep_0_out_obuf_head_write(0); + } + usb_ep_0_out_ev_pending_write(ep0o_pending); + + if (byte_count) { + obuf[0] = byte_count; + usb_ep0out_wr_ptr = (usb_ep0out_wr_ptr + 1) & (EP0OUT_BUFFERS-1); + + // usb_ep_0_in_dtb_write(1); + send_data(0, &device_descriptor, sizeof(device_descriptor)); + } + else { + usb_ep_0_out_respond_write(EPF_ACK); + } + } + + if (ep0i_pending) { + /* + uint8_t *descriptor = (uint8_t *)&device_descriptor; + if (descriptor_ptr < 0) { + usb_ep_0_in_respond_write(EPF_NAK); + } + else if (descriptor_ptr >= sizeof(device_descriptor)) { + descriptor_ptr = -1; + usb_ep_0_in_respond_write(EPF_ACK); + } + else { + usb_ep_0_in_respond_write(EPF_NAK); + for (descriptor_ptr; descriptor_ptr < sizeof(device_descriptor); descriptor_ptr++) { + usb_ep_0_in_ibuf_head_write(descriptor[descriptor_ptr]); + } + usb_ep_0_in_respond_write(EPF_ACK); + } + */ + usb_ep_0_in_respond_write(EPF_NAK); + current_offset += current_to_send; + maybe_send_more_data(0); + usb_ep_0_in_ev_pending_write(ep0i_pending); + } + + return; +} + +void usb_wait(void) { + while (!irq_count) + ; +} + +int usb_irq_happened(void) { + return irq_count; +} + +static const char hex[] = "0123456789abcdef"; +void usb_print_status(void) { + /* + printf("EP0_OUT Status: %02x\n", usb_ep_0_out_ev_status_read()); + printf("EP0_OUT Pending: %02x\n", usb_ep_0_out_ev_pending_read()); + printf("EP0_OUT Enable: %02x\n", usb_ep_0_out_ev_enable_read()); + printf("EP0_OUT Last Tok: %02x\n", usb_ep_0_out_last_tok_read()); + printf("EP0_OUT Respond: %02x\n", usb_ep_0_out_respond_read()); + printf("EP0_OUT DTB: %02x\n", usb_ep_0_out_dtb_read()); + printf("EP0_OUT OBUF Head: %02x\n", usb_ep_0_out_obuf_head_read()); + printf("EP0_OUT OBUF Empty: %02x\n", usb_ep_0_out_obuf_empty_read()); + printf("EP0_IN Status: %02x\n", usb_ep_0_in_ev_status_read()); + printf("EP0_IN Pending: %02x\n", usb_ep_0_in_ev_pending_read()); + printf("EP0_IN Enable: %02x\n", usb_ep_0_in_ev_enable_read()); + printf("EP0_IN Last Tok: %02x\n", usb_ep_0_in_last_tok_read()); + printf("EP0_IN Respond: %02x\n", usb_ep_0_in_respond_read()); + printf("EP0_IN DTB: %02x\n", usb_ep_0_in_dtb_read()); + printf("EP0_IN IBUF Head: %02x\n", usb_ep_0_in_ibuf_head_read()); + printf("EP0_IN IBUF Empty: %02x\n", usb_ep_0_in_ibuf_empty_read()); + */ + while (usb_ep0out_rd_ptr != usb_ep0out_wr_ptr) { + // printf("for (this_offset = current_offset; this_offset < this_offset + current_to_send; this_offset++) {\n"); + // printf("for (this_offset = %d; this_offset < %d; %d++) {\n", current_offset, this_offset, this_offset + current_to_send, this_offset); + printf("current_data: 0x%08x\n", current_data); + printf("current_length: %d\n", current_length); + printf("current_offset: %d\n", current_offset); + printf("current_to_send: %d\n", current_to_send); + uint8_t *obuf = usb_ep0out_buffer[usb_ep0out_rd_ptr]; + uint8_t cnt = obuf[0]; + unsigned int i; + if (cnt) { + for (i = 0; i < cnt; i++) { + uart_write(' '); + uart_write(hex[(obuf[i+1] >> 4) & 0xf]); + uart_write(hex[obuf[i+1] & (0xf)]); + // printf(" %02x", obufbuf[i]); + } + uart_write('\r'); + uart_write('\n'); + } + // printf("\n"); + usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1); + } +} + + +// static inline unsigned char usb_pullup_out_read(void); +// static inline void usb_pullup_out_write(unsigned char value); + + +// static inline unsigned char usb_ep_0_out_ev_status_read(void); +// static inline void usb_ep_0_out_ev_status_write(unsigned char value); + +// static inline unsigned char usb_ep_0_out_ev_pending_read(void); +// static inline void usb_ep_0_out_ev_pending_write(unsigned char value); + +// static inline unsigned char usb_ep_0_out_ev_enable_read(void); +// static inline void usb_ep_0_out_ev_enable_write(unsigned char value); + +// static inline unsigned char usb_ep_0_out_last_tok_read(void); + +// static inline unsigned char usb_ep_0_out_respond_read(void); +// static inline void usb_ep_0_out_respond_write(unsigned char value); + +// static inline unsigned char usb_ep_0_out_dtb_read(void); +// static inline void usb_ep_0_out_dtb_write(unsigned char value); + +// static inline unsigned char usb_ep_0_out_obuf_head_read(void); +// static inline void usb_ep_0_out_obuf_head_write(unsigned char value); + +// static inline unsigned char usb_ep_0_out_obuf_empty_read(void); + + +// static inline unsigned char usb_ep_0_in_ev_status_read(void); +// static inline void usb_ep_0_in_ev_status_write(unsigned char value); + +// static inline unsigned char usb_ep_0_in_ev_pending_read(void); +// static inline void usb_ep_0_in_ev_pending_write(unsigned char value); + +// static inline unsigned char usb_ep_0_in_ev_enable_read(void); +// static inline void usb_ep_0_in_ev_enable_write(unsigned char value); + +// static inline unsigned char usb_ep_0_in_last_tok_read(void); + +// static inline unsigned char usb_ep_0_in_respond_read(void); +// static inline void usb_ep_0_in_respond_write(unsigned char value); + +// static inline unsigned char usb_ep_0_in_dtb_read(void); +// static inline void usb_ep_0_in_dtb_write(unsigned char value); + +// static inline unsigned char usb_ep_0_in_ibuf_head_read(void); +// static inline void usb_ep_0_in_ibuf_head_write(unsigned char value); + +// static inline unsigned char usb_ep_0_in_ibuf_empty_read(void); + + +#if 0 +static uint32_t rx_buffer[NUM_BUFFERS][BUFFER_SIZE / sizeof(uint32_t)]; +static uint8_t rx_buffer_head; +static uint8_t rx_buffer_tail; + +static uint32_t rx_buffer_queries = 0; +static void set_usb_config_num(struct GrainuumUSB *usb, int configNum) +{ + (void)usb; + (void)configNum; + ; +} + + #define USB_STR_BUF_LEN 64 static uint32_t str_buf_storage[USB_STR_BUF_LEN / sizeof(uint32_t)]; @@ -307,30 +545,32 @@ static struct GrainuumConfig cfg = { .setConfigNum = set_usb_config_num, }; -void usb_isr(void) { - grainuumCaptureI(&usb, usb_buf); - return; -} +// void usb_isr(void) { +// // grainuumCaptureI(&usb, usb_buf); +// return; +// } -void usb_init(void) { - grainuumInit(&usb, &cfg); - grainuumConnect(&usb); - return; -} +// void usb_init(void) { +// // grainuumInit(&usb, &cfg); +// // grainuumConnect(&usb); +// return; +// } void usbPhyWriteI(const struct GrainuumUSB *usb, const void *buffer, uint32_t size) { - (void)usb; - const uint8_t *ubuffer = (const uint8_t *)buffer; - uint32_t i = 0; - while (i < size) - usb_obuf_head_write(ubuffer[i]); + // (void)usb; + // const uint8_t *ubuffer = (const uint8_t *)buffer; + // uint32_t i = 0; + // while (i < size) + // usb_obuf_head_write(ubuffer[i]); } int usbPhyReadI(const struct GrainuumUSB *usb, uint8_t *samples) { (void)usb; int count = 0; - while (!usb_ibuf_empty_read()) { - samples[count++] = usb_ibuf_head_read(); - } + // while (!usb_ibuf_empty_read()) { + // samples[count++] = usb_ibuf_head_read(); + // } return count; -} \ No newline at end of file +} +#endif +#endif /* CSR_USB_EP_0_OUT_EV_PENDING_ADDR */ \ No newline at end of file diff --git a/src/usb-rawfifo.c b/src/usb-rawfifo.c new file mode 100644 index 0000000..96393b8 --- /dev/null +++ b/src/usb-rawfifo.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include +#include + +#ifdef CSR_USB_OBUF_EMPTY_ADDR + +static inline unsigned char usb_obuf_head_read(void); +static inline void usb_obuf_head_write(unsigned char value); + +static inline unsigned char usb_obuf_empty_read(void); + +static inline unsigned char usb_arm_read(void); +static inline void usb_arm_write(unsigned char value); + +static inline unsigned char usb_ibuf_head_read(void); +static inline void usb_ibuf_head_write(unsigned char value); + +static inline unsigned char usb_ibuf_empty_read(void); + +static inline unsigned char usb_pullup_out_read(void); +static inline void usb_pullup_out_write(unsigned char value); + +static inline unsigned char usb_ev_status_read(void); +static inline void usb_ev_status_write(unsigned char value); + +static inline unsigned char usb_ev_pending_read(void); +static inline void usb_ev_pending_write(unsigned char value); + +static inline unsigned char usb_ev_enable_read(void); +static inline void usb_ev_enable_write(unsigned char value); + +static const char hex[] = "0123456789abcdef"; + +uint8_t usb_ep0out_wr_ptr; +uint8_t usb_ep0out_rd_ptr; +#define EP0OUT_BUFFERS 64 +static uint8_t usb_ep0out_buffer[EP0OUT_BUFFERS][128]; +void usb_print_status(void) +{ + static int loops; + loops++; + + while (usb_ep0out_rd_ptr != usb_ep0out_wr_ptr) { + uint8_t *obuf = usb_ep0out_buffer[usb_ep0out_rd_ptr]; + uint8_t cnt = obuf[0]; + unsigned int i; + if (cnt) { + for (i = 0; i < cnt; i++) { + uart_write(' '); + uart_write(hex[(obuf[i+1] >> 4) & 0xf]); + uart_write(hex[obuf[i+1] & (0xf)]); + // printf(" %02x", obufbuf[i]); + } + uart_write('\r'); + uart_write('\n'); + } + // printf("\n"); + usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1); + } + // if (!obe) { + // uint32_t obh = usb_obuf_head_read(); + // usb_obuf_head_write(1); + // if (i < 300) + // printf("i: %8d obe: %d obh: %02x\n", i, obe, obh); + // } +} + +int irq_happened; + +void usb_init(void) { + return; +} + +void usb_isr(void) { + uint8_t pending = usb_ev_pending_read(); + + // Advance the obuf head, which will reset the obuf_empty bit + if (pending & 1) { + int byte_count = 0; + uint8_t *obuf = usb_ep0out_buffer[usb_ep0out_wr_ptr]; + while (1) { + if (usb_obuf_empty_read()) + break; + obuf[++byte_count] = usb_obuf_head_read(); + usb_obuf_head_write(0); + } + usb_ev_pending_write(1); + obuf[0] = byte_count; + usb_ep0out_wr_ptr = (usb_ep0out_wr_ptr + 1) & (EP0OUT_BUFFERS-1); + } + + return; +} + +void usb_connect(void) { + usb_pullup_out_write(1); + + usb_ev_pending_write(usb_ev_pending_read()); + usb_ev_enable_write(0xff); + + irq_setmask(irq_getmask() | (1 << USB_INTERRUPT)); +} + +void usb_wait(void) { + while (!irq_happened) + ; +} + +int usb_irq_happened(void) { + return irq_happened; +} + +#endif /* CSR_USB_OBUF_EMPTY_ADDR */ \ No newline at end of file