From f6e3d48476290fbd4309004ebb2d55a816f36aff Mon Sep 17 00:00:00 2001 From: Epagris Date: Wed, 1 May 2024 18:33:22 +0200 Subject: [PATCH] - auto ZLP reconsidered and removed, ZLP is always appended to transfers featuring a size divisible by max packet size - EEM tweaked --- class/eem.c | 34 +++++--- class/eem.h | 5 +- usb.c | 3 - usb_callback_event.h | 1 - usb_driver.c | 182 +------------------------------------------ usb_driver.h | 3 - 6 files changed, 28 insertions(+), 200 deletions(-) diff --git a/class/eem.c b/class/eem.c index 1b524da..03af74c 100644 --- a/class/eem.c +++ b/class/eem.c @@ -14,16 +14,14 @@ static USB_EemState eems = {0}; -static uint8_t netbBuf[USB_EEM_FIFO_SIZE]; // Network bound FIFO memory +// static uint8_t netbBuf[USB_EEM_FIFO_SIZE]; // Network bound FIFO memory static uint8_t hostbBuf[USB_EEM_FIFO_SIZE]; // Host bound FIFO memory #define EEM_EVENT_QUEUE_LENGTH (16) -#define EEM_FRAME_QUEUE_LENGTH (24) +#define EEM_FRAME_QUEUE_LENGTH (8) #define EEM_PCKT_SIZE (64) #define EEM_TRANSFER_UNIT (128) -static uint8_t transferBuffer[EEM_TRANSFER_UNIT]; // transfer buffer - void usb_eem_thread(void *); void usb_eem_init(uint8_t data_ep) { @@ -37,7 +35,7 @@ void usb_eem_init(uint8_t data_ep) { eems.eventQueue = osMessageQueueNew(EEM_EVENT_QUEUE_LENGTH, sizeof(uint8_t), NULL); // create network bound and host bound FIFOs - bfifo_create(&(eems.hostbFifo), netbBuf, USB_EEM_FIFO_SIZE); + // bfifo_create(&(eems.hostbFifo), netbBuf, USB_EEM_FIFO_SIZE); bfifo_create(&(eems.netbFifo), hostbBuf, USB_EEM_FIFO_SIZE); // create queue for hostbound frames @@ -47,6 +45,9 @@ void usb_eem_init(uint8_t data_ep) { eems.hostbState = EEM_IDLE; eems.netbState = EEM_IDLE; + // turn network bound autoarm on + eems.netbAutoArm = true; + // no EchoResponse is queued eems.echoRespQueued = false; @@ -81,6 +82,11 @@ int usb_eem_process_and_return(USB_CallbackEvent *cbevt) { if ((cbevt->ep == eems.data_ep)) { // verify endpoint bfifo_push(&(eems.netbFifo), cbevt->data, cbevt->size); // store portion of netbound packet usb_eem_push_event(EEM_EVT_NETBOUND_PCKT_RECEIVED); // push notification + + if (bfifo_get_free(&eems.netbFifo) < EEM_PCKT_SIZE) { // don't autoarm if OUT no more packets can be stored + eems.netbAutoArm = false; + cbevt->arm_out_endpoint = false; + } } break; @@ -101,7 +107,7 @@ int usb_eem_process_and_return(USB_CallbackEvent *cbevt) { // MSG("---\n"); // } } else { // no data is waiting for transmission - usbcore_schedule_transmission(eems.data_ep, NULL, 0); // send ZLP + //usbcore_schedule_transmission(eems.data_ep, NULL, 0); // send ZLP } // if FIFO is empty or flushed, then send notification @@ -208,6 +214,12 @@ void usb_eem_process_networkbound() { // pop data from the packet bfifo_pop(bf, eems.netbFrameSize, 0); + // if free size is greater then the size of a single USB packet, then arm the endpoint + if ((eems.netbAutoArm == false) && (bfifo_get_free(bf) > EEM_PCKT_SIZE)) { + eems.netbAutoArm = true; + usbcore_schedule_reception(eems.data_ep, EEM_PCKT_SIZE); + } + // MSG("PKT OK! %u\n", eems.netbFrameSize); eems.netbState = EEM_IDLE; @@ -217,11 +229,6 @@ void usb_eem_process_networkbound() { } void usb_eem_process_hostbound() { - // see if there are some packets waiting for transmission - if (osMessageQueueGetCount(eems.hostbFrameQ) == 0) { - return; // no packets - } - /*// check that forward buffer is indeed empty BFifo * bf = &eems.hostbFifo; if (bfifo_get_used(bf) > 0) { @@ -240,6 +247,11 @@ void usb_eem_process_hostbound() { // release frame dynmem_free(oldEemFrame); + // see if there are some packets waiting for transmission + if (osMessageQueueGetCount(eems.hostbFrameQ) == 0) { + return; // no packets + } + // at this point, we can safely pop from the frame queue, popping will not block, // and the forward queue is certainly empty diff --git a/class/eem.h b/class/eem.h index 6d039c3..5377fda 100644 --- a/class/eem.h +++ b/class/eem.h @@ -9,7 +9,7 @@ #include -#define USB_EEM_FIFO_SIZE (2048) +#define USB_EEM_FIFO_SIZE (8192) typedef enum { EEM_ECHO = 0, // Echo @@ -44,11 +44,12 @@ typedef struct { EthInterface * intf; // interface for packet interception and injection uint8_t data_ep; // bulk data in and out endpoint pair osMessageQueueId_t eventQueue; // event queue - BFifo hostbFifo; // Hostbound FIFO + // BFifo hostbFifo; // Hostbound FIFO BFifo netbFifo; // Network bound FIFO USB_EemFsmState netbState; // state of host bound operations uint16_t netbFrameSize; // size of network bound packet uint16_t netbSizeLeft; // number of bytes expected from the host sending into current network bound packet + bool netbAutoArm; // signal, that the netbound endpoint should be autoarmed or not USB_EemFsmState hostbState; // state of network bound operations osMessageQueueId_t hostbFrameQ; // queue for hostbound message pointers USB_EemFrame * hostbFrame; // hostbound frame diff --git a/usb.c b/usb.c index 40d7a63..46d5716 100644 --- a/usb.c +++ b/usb.c @@ -215,7 +215,6 @@ void usbcore_process_nonsetup_event(USBDRV_CallbackCompound *cbcpd) { cbevt.subtype = USB_CBEVST_IN_REQ; } cbevt.dir = USB_IN; - cbevt.enable_autozlp = true; // by default, enable auto ZLP break; } @@ -233,8 +232,6 @@ void usbcore_process_nonsetup_event(USBDRV_CallbackCompound *cbcpd) { if (cbevt.arm_out_endpoint) { usbdrv_autoarm_OUT_endpoint(cbcpd->ep); } - } else if (cbevt.dir == USB_IN) { - usbdrv_enable_autozlp(cbcpd->ep, cbevt.enable_autozlp); // handle auto ZLP setting } } } diff --git a/usb_callback_event.h b/usb_callback_event.h index e977eaf..81b6b48 100644 --- a/usb_callback_event.h +++ b/usb_callback_event.h @@ -29,7 +29,6 @@ typedef struct { const uint8_t * reply_data; // reply data uint8_t reply_size; // reply size bool arm_out_endpoint; // automatically arm OUT endpoint at the end of the current transmission - bool enable_autozlp; // enable automatic ZLP transmission based on transfer size } USB_CallbackEvent; #endif /* CORE_USB_USB_CALLBACK_EVENT */ diff --git a/usb_driver.c b/usb_driver.c index 0a6c440..bdafcec 100644 --- a/usb_driver.c +++ b/usb_driver.c @@ -284,7 +284,6 @@ void usbdrv_build_fifo() { if (cfg->is_configured) { cfg->fifo_size = CEIL4(MAX(USB_MIN_GROSS_TX_FIFO_SIZE, 2 * cfg->max_packet_size)); // correct FIFO size if necessary cfg->fifo_address = next_fifo_addr; // store FIFO address - cfg->auto_zlp = true; // turn on automatic ZLP appending cfg->zlp_next = false; // cfg->txp = false; // no transfer is in progress next_fifo_addr += cfg->fifo_size; // advance next address @@ -488,14 +487,8 @@ void usbdrv_fetch_received_data(uint8_t ep, uint16_t len) { // write data to specific endpoint FIFO uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) { - /*WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_XFRSIZ, len); - WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_PKTCNT, 1);*/ - // determine if a transmission is in progress or not bool txp = READ_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA); - /*if (txp) { - return 0; - }*/ uint16_t mps = gs.ep_IN[ep].max_packet_size; // fetch maximum packet size @@ -600,10 +593,6 @@ void usbdrv_autoarm_OUT_endpoint(uint8_t ep) { gs.ep_OUT[ep].autoarm = true; } -void usbdrv_enable_autozlp(uint8_t ep, bool en) { - gs.ep_IN[ep].auto_zlp = en; -} - // ---------------- void usbdrv_set_address(uint8_t addr) { @@ -774,7 +763,7 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) { // gs.ep_IN[ep].txp = false; // see if a ZLP transmission was queued - if (/*gs.ep_IN[ep].auto_zlp && */ gs.ep_IN[ep].zlp_next) { + if (gs.ep_IN[ep].zlp_next) { usbdrv_arm_IN_endpoint(ep, NULL, 0); // send ZLP } else { // no ZLP USBMSG("IN [%d]\n", ep); @@ -888,171 +877,4 @@ void OTG_FS_IRQHandler() { } return; -} - -// --------------- - -// uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) { -// /*WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_XFRSIZ, len); -// WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_PKTCNT, 1);*/ - -// // determine if a transmission is in progress or not -// if (gs.ep_IN[ep].txp) { -// return 0; -// } - -// // determine if a transmission is in progress or not -// // bool txp = READ_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA); // transmission in progress - -// // transmission may only be commenced if last transmission has concluded -// /*if (READ_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA)) { -// return 0; -// }*/ - -// uint16_t mps = gs.ep_IN[ep].max_packet_size; // fetch maximum packet size - -// // determine final write size -// uint32_t freeSize = 0; - -// // if (len > 0) { // only poll DTXFSTS if (len > 0) (see datasheet) -// freeSize = USBINEP[ep].DTXFSTS * sizeof(uint32_t); // get free transmit buffer size -// //} - -// // if (gs.ep_IN[ep].txp && (freeSize == 0)) { -// // return 0; -// // } - -// uint16_t writeSize = MIN(freeSize, len); // limit transmit size to free size - -// // if transmission is in progress, then remaining transmission bytes also limits transmission size -// if (gs.ep_IN[ep].txp) { -// uint16_t bytesLeft = USBINEP[ep].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ; -// writeSize = MIN(writeSize, bytesLeft); - -// // if this was the last write, then disable Tx empty interrupt -// if (bytesLeft <= mps) { -// USBD->DIEPEMPMSK &= ~((uint32_t)(1 << ep)); -// } else { // if not, turn it back on -// USBD->DIEPEMPMSK |= ((uint32_t)(1 << ep)); -// } - -// } else { // if no transmission was in progress, then setup endpoint for transmission -// // calculate packet count based on max packet size -// uint16_t packet_count = 1; // for ZLPs -// if (writeSize > 0) { // if length is nonzero -// packet_count = len / mps + (((len % mps) > 0) ? 1 : 0); // a transfer may contain multiple packets -// } - -// // set zlp_next if transfer size is integer multiple of max packet size and auto ZLP is on -// gs.ep_IN[ep].zlp_next = gs.ep_IN[ep].auto_zlp && (len > 0) && ((len % mps) == 0); - -// // program DIEPTSIZ with transfer length -// USBINEP[ep].DIEPTSIZ = /*(packet_count << USB_OTG_DIEPTSIZ_MULCNT_Pos) |*/ (packet_count << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | len; - -// // enable endpoint and cancel responding NAK -// SET_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK); - -// // enable FIFO empty interrupt, only if further write operations will follow -// // DO NOT enable this interrupt source when dealing with EP0! -// if ((ep != 0) && (writeSize < len)) { -// USBD->DIEPEMPMSK |= (1 << ep); -// } - -// // set transfer in progress -// gs.ep_IN[ep].txp = true; -// } - -// // disable ALL USB interrupts to prevent access to specific registers (see errata) -// CLEAR_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT); - -// // push full dwords -// volatile uint32_t *p = (uint32_t *)USBFIFO(ep); -// uint32_t floorlen_dwords = writeSize >> 2; -// for (uint16_t i = 0; i < floorlen_dwords; i++) { -// uint16_t i0 = 4 * i; -// uint32_t dword = data[i0] | (data[i0 + 1] << 8) | (data[i0 + 2] << 16) | (data[i0 + 3] << 24); -// p[i] = dword; -// } - -// // push the remaining partial dword -// uint8_t rem_bytes = writeSize & 0b11; -// if (rem_bytes > 0) { -// uint32_t rem_dword = 0; -// uint16_t rem_start = writeSize - rem_bytes; -// for (int16_t i = writeSize - 1; i >= rem_start; i--) { -// rem_dword = (rem_dword << 8) | data[i]; -// } -// *p = rem_dword; -// } - -// // unmask USB interrupts -// SET_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT); - -// // return with written size -// return writeSize; -// } - -// EZ MŰKÖDIK, DE CSAK RÖVID TRANSFEREKRE -// uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) { -// /*WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_XFRSIZ, len); -// WRITE_FIELD(USBINEP[ep].DIEPTSIZ, USB_OTG_DIEPTSIZ_PKTCNT, 1);*/ - -// // determine if a transmission is in progress or not -// bool txp = READ_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA); -// if (txp) { -// return 0; -// } - -// uint16_t mps = gs.ep_IN[ep].max_packet_size; // fetch maximum packet size - -// // determine final write size -// uint32_t freeSize = USBINEP[ep].DTXFSTS * sizeof(uint32_t); // get free transmit buffer size -// uint16_t writeSize = MIN(freeSize, len); // limit transmit size to free size - -// // calculate packet count based on max packet size -// uint16_t packet_count = 1; // for ZLPs -// if (writeSize > 0) { // if length is nonzero -// packet_count = writeSize / mps + (((writeSize % mps) > 0) ? 1 : 0); // a transfer may contain multiple packets -// } - -// // set zlp_next if transfer size is integer multiple of max packet size and auto ZLP is on -// gs.ep_IN[ep].zlp_next = gs.ep_IN[ep].auto_zlp && (writeSize > 0) && ((writeSize % mps) == 0); - -// // program DIEPTSIZ with transfer length -// USBINEP[ep].DIEPTSIZ = /*(packet_count << USB_OTG_DIEPTSIZ_MULCNT_Pos) |*/ (packet_count << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | writeSize; - -// // enable endpoint and cancel responding NAK -// SET_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK); - -// // set transfer in progress -// //gs.ep_IN[ep].txp = true; - -// // disable ALL USB interrupts to prevent access to specific registers (see errata) -// CLEAR_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT); - -// // push full dwords -// volatile uint32_t *p = (uint32_t *)USBFIFO(ep); -// uint32_t floorlen_dwords = writeSize >> 2; -// for (uint16_t i = 0; i < floorlen_dwords; i++) { -// uint16_t i0 = 4 * i; -// uint32_t dword = data[i0] | (data[i0 + 1] << 8) | (data[i0 + 2] << 16) | (data[i0 + 3] << 24); -// p[i] = dword; -// } - -// // push the remaining partial dword -// uint8_t rem_bytes = writeSize & 0b11; -// if (rem_bytes > 0) { -// uint32_t rem_dword = 0; -// uint16_t rem_start = writeSize - rem_bytes; -// for (int16_t i = writeSize - 1; i >= rem_start; i--) { -// rem_dword = (rem_dword << 8) | data[i]; -// } -// *p = rem_dword; -// } - -// // unmask USB interrupts -// SET_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT); - -// // return with written size -// return writeSize; -// } \ No newline at end of file +} \ No newline at end of file diff --git a/usb_driver.h b/usb_driver.h index 77baa56..58db2e9 100644 --- a/usb_driver.h +++ b/usb_driver.h @@ -35,10 +35,8 @@ typedef struct { uint8_t is_configured; // the endpoint is in use uint16_t fifo_address; // address in the FIFO uint16_t fifo_size; // FIFO size - bool8_t auto_zlp; // automatically insert ZLP packets bool8_t zlp_next; // indicates, that ZLP should be transmitted at the end of the current transfer (for IN endpoints) bool8_t autoarm; // automatically arm endpoint (for OUT endpoints) - //bool8_t txp; // transfer in progress } USBDRV_EpConfig; typedef enum { @@ -155,7 +153,6 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len); #define USBDRV_ARM_IN_ZLP(ep) usbdrv_arm_IN_endpoint((ep), NULL, 0) uint32_t usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size); // arm OUT endpoint, returned with the actual armed size (capped by the max packet size on that endpoint) void usbdrv_autoarm_OUT_endpoint(uint8_t ep); // automatically re-arm OUT endpoint at the and of the current OUT transfer -void usbdrv_enable_autozlp(uint8_t ep, bool en); // enable or disable automatic ZLP appending to the transaction bool usbdrv_get_endpoint_interrupt_flag(uint8_t ep, uint8_t dir); // get endpoint interrupt flag