From 241e20059313285b3c69d72d5360f27dbcee7573 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sat, 21 Dec 2024 21:31:47 +0100 Subject: [PATCH] feat: allow reading larger packets without data loss --- firmware/include/usb_device.h | 2 +- firmware/include/usb_device_cdc.h | 4 +++ firmware/src/main.c | 25 ++++++++++++------ firmware/src/usb_device_cdc.c | 43 +++++++++++++++++++------------ 4 files changed, 49 insertions(+), 25 deletions(-) diff --git a/firmware/include/usb_device.h b/firmware/include/usb_device.h index 6ae4873..79f723b 100644 --- a/firmware/include/usb_device.h +++ b/firmware/include/usb_device.h @@ -58,7 +58,7 @@ typedef enum { typedef struct { packet_status_t packet_status; packet_dpid_t dpid; - uint8_t byte_count; + uint16_t byte_count; uint8_t endpoint_num; uint8_t status_phase_start; } packet_info_t; diff --git a/firmware/include/usb_device_cdc.h b/firmware/include/usb_device_cdc.h index 3d63c79..4414f3a 100644 --- a/firmware/include/usb_device_cdc.h +++ b/firmware/include/usb_device_cdc.h @@ -124,6 +124,10 @@ typedef struct { cdc_tx_state_t tx_state; uint8_t got_setup; + + bool endpoint_nak; + uint32_t lost_data; + bool reenabled_endpoint; } usb_device_cdc_t; /** diff --git a/firmware/src/main.c b/firmware/src/main.c index bc843d5..a6c23ff 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -239,7 +239,7 @@ usb_device_t* init_usb() void *usb_dev = usb_device_init(USB_OTG_HS1, &USB_CLASS_CDC_ACM, 0x1234, 0x1111, u"Frantisek Bohacek", u"Display", 1, NULL); - cdc_acm_configure(usb_dev, 512 * 4); // 4 full packets maximum + cdc_acm_configure(usb_dev, 512 * 8); // 8 full packets maximum usb_device_setup(usb_dev); return usb_dev; @@ -337,8 +337,8 @@ void init_clock(void) { /* clocks_system_clock_source(CLOCK_SOURCE_PLL_1_P_CK, 1, 1, 1, 300); */ } -#define DISPLAY_WIDTH 800 -#define DISPLAY_HEIGHT 800 +#define DISPLAY_WIDTH 800UL +#define DISPLAY_HEIGHT 480UL typedef struct { uint8_t b; @@ -492,16 +492,19 @@ void main() void app_loop(usb_device_t* usb_dev, display_t* display, pixel_rgb888_t* framebuffer) { - uint8_t data[64]; + uint8_t data[1024]; bool handling_cmd = false; uint8_t cmd; uint32_t pos = 0; + uint32_t max_size = 1; display_refresh(display); while (1) { - uint16_t received = cdc_data_receive(usb_dev, data, 1); + uint16_t received = cdc_data_receive(usb_dev, data, max_size); + + max_size = 1; if (received == 0) { continue; @@ -562,13 +565,19 @@ void app_loop(usb_device_t* usb_dev, display_t* display, pixel_rgb888_t* framebu break; case 'i': handling_cmd = true; - ((uint8_t *)framebuffer)[pos] = data[0]; + max_size = 1024; - pos++; + for (uint16_t i = 0; i < received; i++) { + if (pos > 0) { + ((uint8_t *)framebuffer)[pos - 1] = data[i]; + } + pos++; + } - if (pos == DISPLAY_WIDTH * DISPLAY_HEIGHT * 3) { + if (pos >= DISPLAY_WIDTH * DISPLAY_HEIGHT * 3) { handling_cmd = false; display_refresh(display); + max_size = 1; } break; } diff --git a/firmware/src/usb_device_cdc.c b/firmware/src/usb_device_cdc.c index 7001655..7361157 100644 --- a/firmware/src/usb_device_cdc.c +++ b/firmware/src/usb_device_cdc.c @@ -118,6 +118,9 @@ void cdc_acm_configure(usb_device_t* device, uint16_t rx_queue_size) { usb_device_cdc_t* cdc = (usb_device_cdc_t*)device->class; usb_class_header_t* header = &cdc->header; + cdc->endpoint_nak = false; + cdc->lost_data = 0; + queue_t* rx_queue = queue_malloc(1, rx_queue_size); cdc->rx_buffer = rx_queue; queue_init(rx_queue, 1, rx_queue_size); @@ -571,6 +574,15 @@ void usb_device_cdc_tx_done_callback(usb_device_t *device, cdc_process_tx(device, CDC_TX_DONE); } +void usb_device_cdc_enable_endpoint_maybe(usb_device_t* device, usb_device_cdc_t *cdc) { + if (queue_space(cdc->rx_buffer) >= MAX_PACKET_SIZE) { + reg_write_bits_pos(&device->out[DATA_ENDPOINT].DOEPTSIZ, MAX_PACKET_SIZE, USB_OTG_DOEPTSIZ_XFRSIZ_Pos, 0xFFFF); + reg_write_bits_pos(&device->out[DATA_ENDPOINT].DOEPTSIZ, 1, USB_OTG_DOEPTSIZ_PKTCNT_Pos, 0x3FF); + device->out[DATA_ENDPOINT].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + cdc->endpoint_nak = false; + } +} + void usb_device_cdc_received_data_callback(usb_device_t *device, packet_info_t *packet) { usb_device_cdc_t* cdc = (usb_device_cdc_t*)device->class; uint8_t data[4*MAX_PACKET_SIZE]; @@ -581,22 +593,17 @@ void usb_device_cdc_received_data_callback(usb_device_t *device, packet_info_t * if (packet->packet_status == PACKET_OUT_DATA_PACKET_RCVD) { // TODO: could be optimized until pointer has to wrap usb_generic_read(data, len, fifo); - - for (uint16_t i = 0; i < len; i++) { - queue_enqueue(cdc->rx_buffer, (void*)&data[i]); + if (queue_space(cdc->rx_buffer) < len) { + cdc->lost_data += len - queue_space(cdc->rx_buffer); } - if (queue_space(cdc->rx_buffer) >= MAX_PACKET_SIZE) { - reg_write_bits_pos(&device->out[2].DOEPTSIZ, MAX_PACKET_SIZE, USB_OTG_DOEPTSIZ_XFRSIZ_Pos, 0xFFFF); - reg_write_bits_pos(&device->out[2].DOEPTSIZ, 1, USB_OTG_DOEPTSIZ_PKTCNT_Pos, 0x3FF); - device->out[DATA_ENDPOINT].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + for (uint16_t i = 0; i < len; i++) { + queue_enqueue(cdc->rx_buffer, (void*)&data[i]); } } else if(packet->packet_status == PACKET_OUT_TRANSFER_COMPLETED) { - if (queue_space(cdc->rx_buffer) >= MAX_PACKET_SIZE) { - reg_write_bits_pos(&device->out[2].DOEPTSIZ, MAX_PACKET_SIZE, USB_OTG_DOEPTSIZ_XFRSIZ_Pos, 0xFFFF); - reg_write_bits_pos(&device->out[2].DOEPTSIZ, 1, USB_OTG_DOEPTSIZ_PKTCNT_Pos, 0x3FF); - device->out[DATA_ENDPOINT].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; - } + if (!(device->out[DATA_ENDPOINT].DOEPINT & USB_OTG_DOEPINT_NAK)) { + usb_device_cdc_enable_endpoint_maybe(device, cdc); + } } else { usb_generic_read(data, packet->byte_count, fifo); } @@ -604,10 +611,10 @@ void usb_device_cdc_received_data_callback(usb_device_t *device, packet_info_t * void usb_device_cdc_nak_callback(usb_device_t *device, uint8_t endpoint) { usb_device_cdc_t* cdc = (usb_device_cdc_t*)device->class; - if (queue_space(cdc->rx_buffer) >= MAX_PACKET_SIZE) { - reg_write_bits_pos(&device->out[2].DOEPTSIZ, MAX_PACKET_SIZE, USB_OTG_DOEPTSIZ_XFRSIZ_Pos, 0xFFFF); - reg_write_bits_pos(&device->out[2].DOEPTSIZ, 1, USB_OTG_DOEPTSIZ_PKTCNT_Pos, 0x3FF); - device->out[DATA_ENDPOINT].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + if (queue_space(cdc->rx_buffer) > MAX_PACKET_SIZE) { + usb_device_cdc_enable_endpoint_maybe(device, cdc); + } else { + cdc->endpoint_nak = true; } } void usb_device_cdc_nyet_callback(usb_device_t *device, uint8_t endpoint) { @@ -671,6 +678,10 @@ uint16_t cdc_data_receive(usb_device_t *device, uint8_t* buffer, } } + if (cdc->endpoint_nak) { + usb_device_cdc_enable_endpoint_maybe(device, cdc); + } + return size; } -- 2.48.1