mirror of
https://github.com/im-tomu/fomu-workshop.git
synced 2024-09-20 11:20:11 +00:00
riscv-blink: fix usb stack
This appears to work now. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
a0d1e62ba2
commit
059e44a04b
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user