diff options
-rw-r--r-- | libmaple/include/libmaple/usb_cdcacm.h | 1 | ||||
-rw-r--r-- | libmaple/usb/stm32f1/usb_cdcacm.c | 65 |
2 files changed, 39 insertions, 27 deletions
diff --git a/libmaple/include/libmaple/usb_cdcacm.h b/libmaple/include/libmaple/usb_cdcacm.h index 3b15d48..1e2ed59 100644 --- a/libmaple/include/libmaple/usb_cdcacm.h +++ b/libmaple/include/libmaple/usb_cdcacm.h @@ -87,6 +87,7 @@ void usb_cdcacm_disable(gpio_dev*, uint8); void usb_cdcacm_putc(char ch); uint32 usb_cdcacm_tx(const uint8* buf, uint32 len); uint32 usb_cdcacm_rx(uint8* buf, uint32 len); +uint32 usb_cdcacm_peek(uint8* buf, uint32 len); uint32 usb_cdcacm_data_available(void); /* in RX buffer */ uint16 usb_cdcacm_get_pending(void); diff --git a/libmaple/usb/stm32f1/usb_cdcacm.c b/libmaple/usb/stm32f1/usb_cdcacm.c index 6998a25..44b2239 100644 --- a/libmaple/usb/stm32f1/usb_cdcacm.c +++ b/libmaple/usb/stm32f1/usb_cdcacm.c @@ -284,14 +284,14 @@ USB_Line_Coding line_coding = { .paritytype = 0x00, .datatype = 0x08 }; -uint8 vcomBufferRx[USB_CDCACM_RX_BUFLEN]; -volatile uint32 countTx = 0; -volatile uint32 recvBufIn = 0; -volatile uint32 recvBufOut = 0; -volatile uint32 maxNewBytes = USB_CDCACM_RX_BUFLEN; -volatile uint32 newBytes = 0; RESET_STATE reset_state = DTR_UNSET; -uint8 line_dtr_rts = 0; + +static volatile uint8 vcomBufferRx[USB_CDCACM_RX_BUFLEN]; +static volatile uint32 rx_offset = 0; +static volatile uint32 countTx = 0; +static volatile uint32 newBytes = 0; + +static volatile uint8 line_dtr_rts = 0; /* * Endpoint callbacks @@ -438,7 +438,28 @@ uint16 usb_cdcacm_get_pending() { * Copies up to len bytes from our private data buffer (*NOT* the PMA) * into buf and deq's the FIFO. */ uint32 usb_cdcacm_rx(uint8* buf, uint32 len) { - static int offset = 0; + /* Copy bytes to buffer. */ + uint32 n_copied = usb_cdcacm_peek(buf, len); + + /* Mark bytes as read. */ + newBytes -= n_copied; + rx_offset += n_copied; + + /* If all bytes have been read, re-enable the RX endpoint, which + * was set to NAK when the current batch of bytes was received. */ + if (newBytes == 0) { + usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE); + usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); + rx_offset = 0; + } + + return n_copied; +} + +/* Nonblocking byte lookahead. + * + * Looks at unread bytes without marking them as read. */ +uint32 usb_cdcacm_peek(uint8* buf, uint32 len) { int i; if (len > newBytes) { @@ -446,17 +467,7 @@ uint32 usb_cdcacm_rx(uint8* buf, uint32 len) { } for (i = 0; i < len; i++) { - buf[i] = vcomBufferRx[i + offset]; - } - - newBytes -= len; - offset += len; - - /* Re-enable the RX endpoint, which we had set to receive 0 bytes */ - if (newBytes == 0) { - usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE); - usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); - offset = 0; + buf[i] = vcomBufferRx[i + rx_offset]; } return len; @@ -486,8 +497,10 @@ static void vcomDataTxCb(void) { static void vcomDataRxCb(void) { /* FIXME this is mad buggy */ - /* setEPRxCount on the previous cycle should garuntee - we havnt received more bytes than we can fit */ + /* This following is safe since sizeof(vcomBufferRx) exceeds the + * largest possible USB_CDCACM_RX_EPSIZE, and we set to NAK after + * each data packet. Only when all bytes have been read is the RX + * endpoint set back to VALID. */ newBytes = usb_get_ep_rx_count(USB_CDCACM_RX_ENDP); usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_NAK); @@ -537,7 +550,7 @@ static void vcomDataRxCb(void) { } } - usb_copy_from_pma(vcomBufferRx, newBytes, USB_CDCACM_RX_ADDR); + usb_copy_from_pma((uint8*)vcomBufferRx, newBytes, USB_CDCACM_RX_ADDR); if (rx_hook) { rx_hook(USB_CDCACM_HOOK_RX, 0); @@ -615,11 +628,9 @@ static void usbReset(void) { USBLIB->state = USB_ATTACHED; SetDeviceAddress(0); - /* reset the rx fifo */ - recvBufIn = 0; - recvBufOut = 0; - maxNewBytes = USB_CDCACM_RX_EPSIZE; - countTx = 0; + /* Reset the RX/TX state */ + countTx = 0; + rx_offset = 0; } static RESULT usbDataSetup(uint8 request) { |