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_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);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <usb.h>
|
||||
|
||||
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();
|
||||
|
@ -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) {
|
||||
@ -79,9 +92,9 @@ void usb_connect(void) {
|
||||
}
|
||||
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user