diff options
author | Marti Bolivar <mbolivar@leaflabs.com> | 2012-07-31 14:36:31 -0400 |
---|---|---|
committer | Marti Bolivar <mbolivar@leaflabs.com> | 2012-07-31 15:04:49 -0400 |
commit | 925446023aa23c2141d711c6e42cd2f75ce70a93 (patch) | |
tree | a1b515b456a1c568f37c807d99a3b7e999a96c85 /libmaple | |
parent | 723ae6fd39fae696540c32643fabcb7e790b45b7 (diff) | |
download | librambutan-925446023aa23c2141d711c6e42cd2f75ce70a93.tar.gz librambutan-925446023aa23c2141d711c6e42cd2f75ce70a93.zip |
usb_cdcacm: Add usb_cdcacm_peek().
We need this so the bootloader reset signal detector can look ahead in
the byte stream without stealing bytes from the user when "1EAF" isn't
received.
While we're doing this, take the time to fix a bunch of RX-related
code (dead code removal, adding volatile, etc.)
Signed-off-by: Marti Bolivar <mbolivar@leaflabs.com>
Diffstat (limited to 'libmaple')
-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) { |