diff --git a/class/cdc.h b/class/cdc.h index 03640cd..b919ed0 100644 --- a/class/cdc.h +++ b/class/cdc.h @@ -62,7 +62,7 @@ typedef struct { // ---------------- -#define USB_CDC_PCKT_BUFSIZE (120) +#define USB_CDC_PCKT_BUFSIZE (128) // ---------------- diff --git a/usb_driver.c b/usb_driver.c index 6e46d52..cd910be 100644 --- a/usb_driver.c +++ b/usb_driver.c @@ -178,11 +178,9 @@ void usbdrv_preload_endpoint_config(uint8_t ep, uint8_t dir, const USBDRV_EpConf if (dir == USB_OUT) { gs.ep_OUT[ep] = *cfg; gs.ep_OUT[ep].is_configured = true; - gs.ep_OUT[ep].task_commenced = USB_EPEVT_IDLE; } else { gs.ep_IN[ep] = *cfg; gs.ep_IN[ep].is_configured = true; - gs.ep_IN[ep].task_commenced = USB_EPEVT_IDLE; } } @@ -400,7 +398,7 @@ void usbdrv_set_rx_fifo_size(uint16_t size) { // stall endpoint void usbdrv_stall_endpoint(uint8_t ep, uint8_t dir, bool stall) { USB_OTG_INEndpointTypeDef *inep = USBINEP + ep; - USB_OTG_OUTEndpointTypeDef *outep = USBOUTEP + ep; + // USB_OTG_OUTEndpointTypeDef *outep = USBOUTEP + ep; if (stall) { if (dir == USB_IN) { @@ -418,10 +416,6 @@ void usbdrv_stall_endpoint(uint8_t ep, uint8_t dir, bool stall) { // flush trnasmit FIFO usbdrv_flush_tx_fifo(ep); - - // signal that the endpoint is stalled - gs.ep_IN[ep].task_commenced = USB_EPEVT_STALLED; - } else { if (dir == USB_IN) { if (ep != 0) { // special treatment for EP0 @@ -429,9 +423,6 @@ void usbdrv_stall_endpoint(uint8_t ep, uint8_t dir, bool stall) { } CLEAR_BIT(inep->DIEPCTL, USB_OTG_DIEPCTL_STALL); // clear endpoint stall } - - // signal that the endpoint stalling is over - gs.ep_IN[ep].task_commenced = USB_EPEVT_IDLE; } } @@ -476,24 +467,24 @@ 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);*/ - // endpoint is already armed - // if (gs.ep_IN[ep].task_commenced == USB_EPEVT_ARMED) { - // return; - // } - - // gs.ep_IN[ep].task_commenced = USB_EPEVT_ARMED; + // transmission may only be commenced if last transmission has concluded + if (READ_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA)) { + return 0; + } // 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 + uint16_t writeSize = MIN(freeSize, len); // limit transmit size to free size // calculate packet count based on max packet size uint16_t mps = gs.ep_IN[ep].max_packet_size; uint16_t packet_count = 1; // for ZLPs - if (writeSize > 0) { // if length is nonzero + if (writeSize > 0) { // if length is nonzero packet_count = writeSize / mps + (((writeSize % mps) > 0) ? 1 : 0); } - // TODO: ZLP ending + + // set zlp_next if transmission size is integer multiple of max packet size + gs.ep_IN[ep].zlp_next = (writeSize > 0) && ((writeSize % mps) == 0); // program DIEPTSIZ with transfer length (TODO: currently only a single transfer!) USBINEP[ep].DIEPTSIZ = (packet_count << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | writeSize; @@ -533,12 +524,8 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) { // arm OUT endpoint void usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size) { - // if (gs.ep_OUT[ep].task_commenced == USB_EPEVT_IDLE) { // only effective if endpointis not armed (no double arming!) - // gs.ep_OUT[ep].task_commenced = USB_EPEVT_ARMED; // step in armed state - USBOUTEP[ep].DOEPTSIZ |= USB_OTG_DOEPTSIZ_PKTCNT | size; // program DIEPTSIZ with maximum (expected) transfer length and set PCKTCNT to make ready for reception SET_BIT(USBOUTEP[ep].DOEPCTL, USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK); // enable endpoint and clear NAK - //} } // ---------------- @@ -618,11 +605,6 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) { case USB_FSM_SETUP_OPERATE: { // expect SETUP transactions first, then everything else as well switch (evt_code) { case USB_EVT_RECEPTION_DONE: { // reception done - - // for (uint32_t i = 0; i < 100000; i++) { - // __NOP(); - // } - USBDRV_EventData evt_data = {0}; usbdrv_process_rx_fifo_top(&evt_data); // process rx fifo top @@ -641,11 +623,6 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) { } else if (evt_data.rx.pckt_status == USB_PCKT_STATUS_OUT_TRANSFER_CPLT) { stage = UST_DATA; - // OUT transaction has fired - if (gs.ep_OUT[0].task_commenced == USB_EPEVT_ARMED) { - gs.ep_OUT[0].task_commenced = USB_EPEVT_IDLE; - } - USBMSG("--DATA\n"); } @@ -681,11 +658,6 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) { SET_BIT(USBOUTEP[ep].DOEPINT, USB_OTG_DOEPINT_XFRC); USBMSG("OUT\n"); - // reset commenced task state - if (gs.ep_OUT[ep].task_commenced == USB_EPEVT_ARMED) { - gs.ep_OUT[ep].task_commenced = USB_EPEVT_IDLE; - } - usbdrv_arm_OUT_endpoint(ep, gs.ep_OUT[ep].max_packet_size); } } @@ -707,32 +679,25 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) { if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC)) { // timeout done SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC); USBMSG("TO\n"); - - gs.ep_IN[ep].task_commenced = USB_EPEVT_IDLE; } if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_XFRC)) { // IN transaction done SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_XFRC); - // reset commenced task state - if (gs.ep_IN[ep].task_commenced == USB_EPEVT_ARMED) { - gs.ep_IN[ep].task_commenced = USB_EPEVT_IDLE; + // see if a ZLP transmission was queued + if (gs.ep_IN[ep].zlp_next) { + usbdrv_arm_IN_endpoint(ep, NULL, 0); // send ZLP + } else { // no ZLP + USBMSG("IN [%d]\n", ep); + + cbcpd.code = USB_CBC_IN_DONE; + usbcore_process_nonsetup_event(&cbcpd); } - - USBMSG("IN [%d]\n", ep); - - cbcpd.code = USB_CBC_IN_DONE; - usbcore_process_nonsetup_event(&cbcpd); } if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE)) { // IN endpoint IN token received with Tx FIFO empty interrupt SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE); - // reset stalled state - if (gs.ep_IN[ep].task_commenced == USB_EPEVT_STALLED) { - usbdrv_stall_endpoint(ep, USB_IN, false); - } - // USBMSG("IN FIFOEMPTY [%d]\n", ep); cbcpd.code = USB_CBC_IN_FIFOEMPTY; diff --git a/usb_driver.h b/usb_driver.h index 351d534..c9f2a30 100644 --- a/usb_driver.h +++ b/usb_driver.h @@ -26,9 +26,7 @@ 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 - - // management variables - uint8_t task_commenced; // task commenced on endpoint + bool8_t zlp_next; // indicates, that ZLP should be transmitted at the end of the current transfer } USBDRV_EpConfig; typedef enum { diff --git a/utils/gen_queue.c b/utils/gen_queue.c deleted file mode 100644 index d697bcf..0000000 --- a/utils/gen_queue.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "gen_queue.h" - -#include -#include - -Queue *q_create(uint32_t length, uint32_t elemSize, uint8_t *mem) { - Queue *q = (Queue *)mem; - q->length = length; - q->elemSize = elemSize; - q->readIdx = 0; - q->writeIdx = 0; - memset(q->elements, 0, length * elemSize); - - return q; -} - -void q_clear(Queue *q) { - q->readIdx = 0; - q->writeIdx = 0; - memset(q->elements, 0, q->length * q->elemSize); -} - -uint32_t q_avail(const Queue *q) { - return q->writeIdx - q->readIdx; -} - -#define MQ_NEXT(size, current) (((current) + 1) % (size)) - -bool q_push(Queue *q, const void *src) { - if (MQ_NEXT(q->length, q->writeIdx) == q->readIdx) { // cannot push, queue is full - return false; - } - - // can push - memcpy(q->elements + q->writeIdx * q->elemSize, src, q->elemSize); - - // advance write pointer - q->writeIdx = MQ_NEXT(q->length, q->writeIdx); - - return true; -} - -void q_top(Queue *q, void *dest) { - memcpy(dest, q->elements + q->readIdx, q->elemSize); -} - -void q_pop(Queue *q) { - if (q_avail(q) > 0) { // if there's something to pop - q->readIdx = MQ_NEXT(q->length, q->readIdx); - } -} diff --git a/utils/gen_queue.h b/utils/gen_queue.h deleted file mode 100644 index 364f15f..0000000 --- a/utils/gen_queue.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef CORE_USB_UTILS_GE_QUEUE -#define CORE_USB_UTILS_GE_QUEUE - -#include -#include - -/** - * Generic Queue. - */ -typedef struct { - uint32_t writeIdx; ///< Next block to write - uint32_t readIdx; ///< Next block to read - uint32_t length; ///< Size of circular buffer - uint32_t elemSize; ///< Element size - uint8_t elements[]; ///< Array of packets -} Queue; - -/** - * Create Queue. - * @param length length of circular buffer - * @param elemSize element size - * @param mem backing memory, should be DWORD-aligned! - * @return pointer to Queue instance OR NULL on failure - */ -Queue *q_create(uint32_t length, uint32_t elemSize, uint8_t *mem); - -/** - * Create Queue based on storage type. - */ -#define Q_CREATE_T(length, T, mem) q_create((length), sizeof(T), (mem)) - -/** - * @brief Calculate required memory size for allocating a new queue fitting - * length elements of type T. - */ -#define Q_REQ_MEM_SIZE_T(length, T) (sizeof(Queue) + (length * sizeof(T))) - -/** - * Clear circular buffer. - * @param q pointer to Queue - */ -void q_clear(Queue *q); - -/** - * Get number of available elements. - * @param q pointer to Queue - * @return number of available elements - */ -uint32_t q_avail(const Queue *q); - -/** - * Push element to the Queue. - * @param q pointer to Queue - * @param raw pointer to raw packet - * @return true on success, false on failure (e.g.: queue full) - */ -bool q_push(Queue *q, const void *src); - -/** - * Get top element. - * @param q pointer to Queue - * @return top element (COPY, NOT POINTER!) - */ -void q_top(Queue *q, void *dest); - -/** - * Pop top element. - * @param q pointer to Queue - */ -void q_pop(Queue *q); - -#endif /* CORE_USB_UTILS_GE_QUEUE */