From 8b0cb9f1a6111f0fcb1cd16548efdc6046571846 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 13 Dec 2010 21:23:31 -0500 Subject: fixed horrible misleading comment in usb.h --- libmaple/usb/usb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmaple/usb/usb.h b/libmaple/usb/usb.h index ffba9ff..c0fcec0 100644 --- a/libmaple/usb/usb.h +++ b/libmaple/usb/usb.h @@ -72,7 +72,7 @@ void usbEnbISR(void); void usb_lpIRQHandler(void); void usbWaitReset(void); -/* blocking functions for send/receive */ +/* nonblocking functions for send/receive */ uint16 usbSendBytes(uint8* sendBuf,uint16 len); uint8 usbBytesAvailable(void); uint8 usbReceiveBytes(uint8* recvBuf, uint8 len); -- cgit v1.2.3 From 873356a31fae8cf4e8b6a5ab609125a5a501d1c4 Mon Sep 17 00:00:00 2001 From: AJM Date: Mon, 13 Dec 2010 22:03:14 -0500 Subject: candidate bugfix for serialusb receive bug changed USB driver to nak whenever it cant fill an entire endpoint (64B) worth of new data. The old scheme was to set receive valid as long as as the endpoint buffer wasnt full, the new scheme is to nak until it is completely empty. --- libmaple/usb/descriptors.h | 25 ++++++++++++++++++++++++- libmaple/usb/usb.c | 30 ++++++++++-------------------- libmaple/usb/usb.h | 6 +++--- libmaple/usb/usb_callbacks.c | 8 ++++++-- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/libmaple/usb/descriptors.h b/libmaple/usb/descriptors.h index 6652942..6f7d08b 100644 --- a/libmaple/usb/descriptors.h +++ b/libmaple/usb/descriptors.h @@ -1,4 +1,27 @@ -/* insert license */ +/* ***************************************************************************** + * The MIT License + * + * Copyright (c) 2010 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * ****************************************************************************/ + #ifndef __DESCRIPTORS_H #define __DESCRIPTORS_H diff --git a/libmaple/usb/usb.c b/libmaple/usb/usb.c index 923e54b..2b99132 100644 --- a/libmaple/usb/usb.c +++ b/libmaple/usb/usb.c @@ -332,23 +332,11 @@ void usbWaitReset(void) { * This function will quickly copy up to 64 bytes of data (out of an * arbitrarily large buffer) into the USB peripheral TX buffer and return the * number placed in that buffer. It is up to usercode to divide larger packets - * into 64-byte chunks to guarantee delivery. Use usbGetCountTx() to determine - * whether the bytes were ACTUALLY recieved by the host or just transfered to - * the buffer. + * into 64-byte chunks to guarantee delivery. * - * The function will return -1 if it doesn't think that the USB host is - * "connected", but it can't detect this state robustly. "Connected" in this - * context means that an actual program on the Host operating system is - * connected to the virtual COM/ttyACM device and is recieving the bytes; the - * Host operating system is almost always configured and keeping this endpoint - * alive, but the bytes never get read out of the endpoint buffer. - * - * The behavior of this function is subtle and frustrating; it has gone through - * many simpler and cleaner implementation that frustratingly don't work cross - * platform. - * - * */ -uint16 usbSendBytes(uint8* sendBuf, uint16 len) { + * + */ +uint32 usbSendBytes(uint8* sendBuf, uint16 len) { uint16 loaded = 0; @@ -384,7 +372,7 @@ uint16 usbSendBytes(uint8* sendBuf, uint16 len) { } /* returns the number of available bytes are in the recv FIFO */ -uint8 usbBytesAvailable(void) { +uint32 usbBytesAvailable(void) { return VCOM_RX_EPSIZE - maxNewBytes; } @@ -392,7 +380,7 @@ uint8 usbBytesAvailable(void) { usb packet buffer) into recvBuf and deq's the fifo. will only copy the minimum of len or the available bytes. returns the number of bytes copied */ -uint8 usbReceiveBytes(uint8* recvBuf, uint8 len) { +uint32 usbReceiveBytes(uint8* recvBuf, uint8 len) { if (len > VCOM_RX_EPSIZE - maxNewBytes) { len = VCOM_RX_EPSIZE - maxNewBytes; } @@ -403,11 +391,13 @@ uint8 usbReceiveBytes(uint8* recvBuf, uint8 len) { recvBufOut = (recvBufOut + 1) % VCOM_RX_EPSIZE; } - maxNewBytes += len; + maxNewBytes += len; /* is this the potential bug? */ + // assert(maxNewBytes < VCOM_RX_EPSIZE) /* re-enable the rx endpoint which we had set to receive 0 bytes */ - if (maxNewBytes - len == 0) { + if (maxNewBytes >= VCOM_RX_EPSIZE) { SetEPRxCount(VCOM_RX_ENDP,maxNewBytes); + SetEPRxStatus(VCOM_RX_ENDP,EP_RX_VALID); } return len; diff --git a/libmaple/usb/usb.h b/libmaple/usb/usb.h index ffba9ff..84390cb 100644 --- a/libmaple/usb/usb.h +++ b/libmaple/usb/usb.h @@ -73,9 +73,9 @@ void usb_lpIRQHandler(void); void usbWaitReset(void); /* blocking functions for send/receive */ -uint16 usbSendBytes(uint8* sendBuf,uint16 len); -uint8 usbBytesAvailable(void); -uint8 usbReceiveBytes(uint8* recvBuf, uint8 len); +uint32 usbSendBytes(uint8* sendBuf,uint16 len); +uint32 usbBytesAvailable(void); +uint32 usbReceiveBytes(uint8* recvBuf, uint8 len); uint8 usbGetDTR(void); uint8 usbGetRTS(void); uint8 usbIsConnected(void); diff --git a/libmaple/usb/usb_callbacks.c b/libmaple/usb/usb_callbacks.c index 4cdaf73..c30d650 100644 --- a/libmaple/usb/usb_callbacks.c +++ b/libmaple/usb/usb_callbacks.c @@ -132,8 +132,12 @@ void vcomDataRxCb(void) { } maxNewBytes -= newBytes; - SetEPRxCount(VCOM_RX_ENDP,maxNewBytes); - SetEPRxValid(VCOM_RX_ENDP); + + if (maxNewBytes > VCOM_RX_EPSIZE) { + SetEPRxCount(VCOM_RX_ENDP,0); + SetEPRxStatus(VCOM_RX_ENDP,EP_RX_NAK); /* nak until we clear the buffer */ + } + } void vcomManagementCb(void) { -- cgit v1.2.3 From a2ee93f95a128ede3a83c442eee6f6afe5c92c1e Mon Sep 17 00:00:00 2001 From: AJM Date: Mon, 13 Dec 2010 22:09:12 -0500 Subject: made SerialUSB.read blocking it should have been blocking before but wasnt. see bug #49 --- wirish/usb_serial.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/wirish/usb_serial.cpp b/wirish/usb_serial.cpp index 5c8a65f..d4a8148 100644 --- a/wirish/usb_serial.cpp +++ b/wirish/usb_serial.cpp @@ -101,17 +101,27 @@ uint32 USBSerial::available(void) { return usbBytesAvailable(); } +/* blocks forever until len_bytes is received */ uint32 USBSerial::read(void *buf, uint32 len) { if (!buf) { return 0; } - return usbReceiveBytes((uint8*)buf, len); + uint32 bytes_in = 0; + while (len > 0) { + uint32 new_bytes = usbReceiveBytes(&(uint8)buf[new_bytes], len); + len -= newBytes; + bytes_in += new_bytes; + } + + return len; } +/* blocks forever until 1 byte is received */ uint8 USBSerial::read(void) { uint8 ch; - usbReceiveBytes(&ch, 1); + + while (usbReceiveBytes(&ch, 1) == 0); return ch; } -- cgit v1.2.3 From ef3fcf8b3ed17540a4a931525afee8168852c48c Mon Sep 17 00:00:00 2001 From: AJM Date: Mon, 13 Dec 2010 22:33:22 -0500 Subject: fixed broken build from usb_serial.cpp oops --- wirish/usb_serial.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wirish/usb_serial.cpp b/wirish/usb_serial.cpp index d4a8148..e2cdee3 100644 --- a/wirish/usb_serial.cpp +++ b/wirish/usb_serial.cpp @@ -109,8 +109,8 @@ uint32 USBSerial::read(void *buf, uint32 len) { uint32 bytes_in = 0; while (len > 0) { - uint32 new_bytes = usbReceiveBytes(&(uint8)buf[new_bytes], len); - len -= newBytes; + uint32 new_bytes = usbReceiveBytes((uint8*)((uint8*)buf+bytes_in), len); + len -= new_bytes; bytes_in += new_bytes; } -- cgit v1.2.3 From 125cbc814bc032ba217e8c10e0ceb43981126ce3 Mon Sep 17 00:00:00 2001 From: AJM Date: Mon, 13 Dec 2010 23:46:36 -0500 Subject: enlarged rx buffer and nak when less than 64 bytes is left in packet buf --- libmaple/usb/usb.c | 4 ++-- libmaple/usb/usb.h | 4 ++-- libmaple/usb/usb_callbacks.c | 23 ++++++++++++----------- libmaple/usb/usb_callbacks.h | 10 +++++----- libmaple/usb/usb_config.h | 1 + 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/libmaple/usb/usb.c b/libmaple/usb/usb.c index 2b99132..396579f 100644 --- a/libmaple/usb/usb.c +++ b/libmaple/usb/usb.c @@ -336,7 +336,7 @@ void usbWaitReset(void) { * * */ -uint32 usbSendBytes(uint8* sendBuf, uint16 len) { +uint32 usbSendBytes(uint8* sendBuf, uint32 len) { uint16 loaded = 0; @@ -380,7 +380,7 @@ uint32 usbBytesAvailable(void) { usb packet buffer) into recvBuf and deq's the fifo. will only copy the minimum of len or the available bytes. returns the number of bytes copied */ -uint32 usbReceiveBytes(uint8* recvBuf, uint8 len) { +uint32 usbReceiveBytes(uint8* recvBuf, uint32 len) { if (len > VCOM_RX_EPSIZE - maxNewBytes) { len = VCOM_RX_EPSIZE - maxNewBytes; } diff --git a/libmaple/usb/usb.h b/libmaple/usb/usb.h index 84390cb..5bc31e1 100644 --- a/libmaple/usb/usb.h +++ b/libmaple/usb/usb.h @@ -73,9 +73,9 @@ void usb_lpIRQHandler(void); void usbWaitReset(void); /* blocking functions for send/receive */ -uint32 usbSendBytes(uint8* sendBuf,uint16 len); +uint32 usbSendBytes(uint8* sendBuf,uint32 len); uint32 usbBytesAvailable(void); -uint32 usbReceiveBytes(uint8* recvBuf, uint8 len); +uint32 usbReceiveBytes(uint8* recvBuf, uint32 len); uint8 usbGetDTR(void); uint8 usbGetRTS(void); uint8 usbIsConnected(void); diff --git a/libmaple/usb/usb_callbacks.c b/libmaple/usb/usb_callbacks.c index c30d650..d04f610 100644 --- a/libmaple/usb/usb_callbacks.c +++ b/libmaple/usb/usb_callbacks.c @@ -32,11 +32,11 @@ USB_Line_Coding line_coding = { datatype: 0x08 }; -uint8 vcomBufferRx[VCOM_RX_EPSIZE]; -volatile uint8 countTx = 0; -volatile uint8 recvBufIn = 0; -volatile uint8 recvBufOut = 0; -volatile uint8 maxNewBytes = VCOM_RX_EPSIZE; +uint8 vcomBufferRx[VCOM_RX_BUFLEN]; +volatile uint32 countTx = 0; +volatile uint32 recvBufIn = 0; +volatile uint32 recvBufOut = 0; +volatile uint32 maxNewBytes = VCOM_RX_BUFLEN; RESET_STATE reset_state = DTR_UNSET; uint8 line_dtr_rts = 0; @@ -61,6 +61,7 @@ void vcomDataRxCb(void) { /* setEPRxCount on the previous cycle should garuntee we havnt received more bytes than we can fit */ uint8 newBytes = GetEPRxCount(VCOM_RX_ENDP); + SetEPRxStatus(VCOM_RX_ENDP,EP_RX_NAK); /* assert (newBytes <= maxNewBytes); */ /* todo, not checking very carefully for edge cases. USUALLY, @@ -116,26 +117,26 @@ void vcomDataRxCb(void) { - if (recvBufIn + newBytes < VCOM_RX_EPSIZE) { + if (recvBufIn + newBytes < VCOM_RX_BUFLEN) { PMAToUserBufferCopy(&vcomBufferRx[recvBufIn],VCOM_RX_ADDR,newBytes); recvBufIn += newBytes; } else { /* we have to copy the data in two chunks because we roll over the edge of the circular buffer */ - uint8 tailBytes = VCOM_RX_EPSIZE - recvBufIn; + uint8 tailBytes = VCOM_RX_BUFLEN - recvBufIn; uint8 remaining = newBytes - tailBytes; PMAToUserBufferCopy(&vcomBufferRx[recvBufIn],VCOM_RX_ADDR,tailBytes); PMAToUserBufferCopy(&vcomBufferRx[0], VCOM_RX_ADDR,remaining); - recvBufIn = (recvBufIn + newBytes ) % VCOM_RX_EPSIZE; + recvBufIn = (recvBufIn + newBytes ) % VCOM_RX_BUFLEN; } maxNewBytes -= newBytes; - if (maxNewBytes > VCOM_RX_EPSIZE) { - SetEPRxCount(VCOM_RX_ENDP,0); - SetEPRxStatus(VCOM_RX_ENDP,EP_RX_NAK); /* nak until we clear the buffer */ + if (maxNewBytes >= VCOM_RX_EPSIZE) { + SetEPRxCount(VCOM_RX_ENDP,VCOM_RX_EPSIZE); + SetEPRxStatus(VCOM_RX_ENDP,EP_RX_VALID); } } diff --git a/libmaple/usb/usb_callbacks.h b/libmaple/usb/usb_callbacks.h index a94de11..21ceb77 100644 --- a/libmaple/usb/usb_callbacks.h +++ b/libmaple/usb/usb_callbacks.h @@ -34,11 +34,11 @@ typedef enum { extern RESET_STATE reset_state; /* tracks DTR/RTS */ extern uint8 line_dtr_rts; -extern volatile uint8 countTx; -extern uint8 vcomBufferRx[VCOM_RX_EPSIZE]; /* no reason this has to be VCOM_RX_EPSIZE, could be bigger */ -extern volatile uint8 recvBufIn; /* the FIFO in index to the recvbuffer */ -extern volatile uint8 recvBufOut; /* the FIFO out index to the recvbuffer */ -extern volatile uint8 maxNewBytes; +extern volatile uint32 countTx; +extern uint8 vcomBufferRx[VCOM_RX_BUFLEN]; /* no reason this has to be VCOM_RX_EPSIZE, could be bigger */ +extern volatile uint32 recvBufIn; /* the FIFO in index to the recvbuffer */ +extern volatile uint32 recvBufOut; /* the FIFO out index to the recvbuffer */ +extern volatile uint32 maxNewBytes; void vcomDataTxCb(void); void vcomDataRxCb(void); diff --git a/libmaple/usb/usb_config.h b/libmaple/usb/usb_config.h index ba05d42..e5f3979 100644 --- a/libmaple/usb/usb_config.h +++ b/libmaple/usb/usb_config.h @@ -26,6 +26,7 @@ #define VCOM_RX_EPNUM 0x03 #define VCOM_RX_ADDR 0x110 #define VCOM_RX_EPSIZE 0x40 +#define VCOM_RX_BUFLEN (VCOM_RX_EPSIZE*3) #define bMaxPacketSize 0x40 /* 64B, maximum for USB FS Devices */ -- cgit v1.2.3 From 40573207a2a5d17110c58a8d4051a4f2804b960a Mon Sep 17 00:00:00 2001 From: AJM Date: Tue, 14 Dec 2010 00:48:13 -0500 Subject: changed the serialusb to be simplest possible design no longer use a ring buffer. No longer double buffer a local rx buffer and the packet memory. Instead, we read out of packet memory and block it for all reads. This is going to be slower. but it tests OK (unlike the old one...). --- libmaple/usb/usb.c | 40 +++++++++++++++------------------------- libmaple/usb/usb_callbacks.c | 30 ++++-------------------------- libmaple/usb/usb_callbacks.h | 1 + 3 files changed, 20 insertions(+), 51 deletions(-) diff --git a/libmaple/usb/usb.c b/libmaple/usb/usb.c index 396579f..448c4ff 100644 --- a/libmaple/usb/usb.c +++ b/libmaple/usb/usb.c @@ -340,40 +340,32 @@ uint32 usbSendBytes(uint8* sendBuf, uint32 len) { uint16 loaded = 0; - if (bDeviceState != CONFIGURED || (!usbGetDTR() && !usbGetRTS())) { - // Indicates to caller to stop trying, were not configured/connected - // The DTR and RTS lines are handled differently on major platforms, so - // the above logic is unreliable - return 0; - } + /* any checks on connection (via dtr/rts) done upstream in wirish or by user */ - // Due to a variety of shit this is how we roll; all buffering etc is pushed - // upstream + /* last xmit hasnt finished, abort */ if (countTx) { return 0; } // We can only put VCOM_TX_EPSIZE bytes in the buffer if(len > VCOM_TX_EPSIZE) { - loaded = VCOM_TX_EPSIZE; - } else { - loaded = len; + len = VCOM_TX_EPSIZE; } // Try to load some bytes if we can - if (loaded) { - UserToPMABufferCopy(sendBuf,VCOM_TX_ADDR + countTx, loaded); - _SetEPTxCount(VCOM_TX_ENDP, countTx+loaded); + if (len) { + UserToPMABufferCopy(sendBuf,VCOM_TX_ADDR, len); + _SetEPTxCount(VCOM_TX_ENDP, len); _SetEPTxValid(VCOM_TX_ENDP); - countTx += loaded; + countTx += len; } - return loaded; + return len; } /* returns the number of available bytes are in the recv FIFO */ uint32 usbBytesAvailable(void) { - return VCOM_RX_EPSIZE - maxNewBytes; + return newBytes; } /* copies len bytes from the local recieve FIFO (not @@ -381,22 +373,20 @@ uint32 usbBytesAvailable(void) { will only copy the minimum of len or the available bytes. returns the number of bytes copied */ uint32 usbReceiveBytes(uint8* recvBuf, uint32 len) { - if (len > VCOM_RX_EPSIZE - maxNewBytes) { - len = VCOM_RX_EPSIZE - maxNewBytes; + if (len > newBytes) { + len = newBytes; } int i; for (i=0;i= VCOM_RX_EPSIZE) { - SetEPRxCount(VCOM_RX_ENDP,maxNewBytes); + if (newBytes == 0) { + SetEPRxCount(VCOM_RX_ENDP,VCOM_RX_EPSIZE); SetEPRxStatus(VCOM_RX_ENDP,EP_RX_VALID); } diff --git a/libmaple/usb/usb_callbacks.c b/libmaple/usb/usb_callbacks.c index d04f610..4d7e57a 100644 --- a/libmaple/usb/usb_callbacks.c +++ b/libmaple/usb/usb_callbacks.c @@ -37,7 +37,7 @@ volatile uint32 countTx = 0; volatile uint32 recvBufIn = 0; volatile uint32 recvBufOut = 0; volatile uint32 maxNewBytes = VCOM_RX_BUFLEN; - +volatile uint32 newBytes = 0; RESET_STATE reset_state = DTR_UNSET; uint8 line_dtr_rts = 0; @@ -47,7 +47,7 @@ void vcomDataTxCb(void) { /* allows usbSendBytes to stop blocking */ - countTx = 0; + countTx = 0; /* assumes tx transactions are atomic 64 bytes (nearly certain they are) */ } /* we could get arbitrarily complicated here for speed purposes @@ -60,9 +60,8 @@ void vcomDataRxCb(void) { /* setEPRxCount on the previous cycle should garuntee we havnt received more bytes than we can fit */ - uint8 newBytes = GetEPRxCount(VCOM_RX_ENDP); + newBytes = GetEPRxCount(VCOM_RX_ENDP); SetEPRxStatus(VCOM_RX_ENDP,EP_RX_NAK); - /* assert (newBytes <= maxNewBytes); */ /* todo, not checking very carefully for edge cases. USUALLY, if we emit the reset pulse and send 4 bytes, then newBytes @@ -117,28 +116,7 @@ void vcomDataRxCb(void) { - if (recvBufIn + newBytes < VCOM_RX_BUFLEN) { - PMAToUserBufferCopy(&vcomBufferRx[recvBufIn],VCOM_RX_ADDR,newBytes); - recvBufIn += newBytes; - } else { - /* we have to copy the data in two chunks because we roll over - the edge of the circular buffer */ - uint8 tailBytes = VCOM_RX_BUFLEN - recvBufIn; - uint8 remaining = newBytes - tailBytes; - - PMAToUserBufferCopy(&vcomBufferRx[recvBufIn],VCOM_RX_ADDR,tailBytes); - PMAToUserBufferCopy(&vcomBufferRx[0], VCOM_RX_ADDR,remaining); - - recvBufIn = (recvBufIn + newBytes ) % VCOM_RX_BUFLEN; - } - - maxNewBytes -= newBytes; - - if (maxNewBytes >= VCOM_RX_EPSIZE) { - SetEPRxCount(VCOM_RX_ENDP,VCOM_RX_EPSIZE); - SetEPRxStatus(VCOM_RX_ENDP,EP_RX_VALID); - } - + PMAToUserBufferCopy(&vcomBufferRx[0],VCOM_RX_ADDR,newBytes); } void vcomManagementCb(void) { diff --git a/libmaple/usb/usb_callbacks.h b/libmaple/usb/usb_callbacks.h index 21ceb77..20d2c13 100644 --- a/libmaple/usb/usb_callbacks.h +++ b/libmaple/usb/usb_callbacks.h @@ -39,6 +39,7 @@ extern uint8 vcomBufferRx[VCOM_RX_BUFLEN]; /* no reason this has to be VCOM_RX_ extern volatile uint32 recvBufIn; /* the FIFO in index to the recvbuffer */ extern volatile uint32 recvBufOut; /* the FIFO out index to the recvbuffer */ extern volatile uint32 maxNewBytes; +extern volatile uint32 newBytes; void vcomDataTxCb(void); void vcomDataRxCb(void); -- cgit v1.2.3 From 84fd2532a7f23d20354ff590790b3f892cb7e7d7 Mon Sep 17 00:00:00 2001 From: AJM Date: Tue, 14 Dec 2010 01:39:20 -0500 Subject: added a usbBlockingSendByte(char ch) this new function will only return AFTER the usb interrupt has been serviced and the byte is sent. Bytes should NOT fall on the floor ever with this function. (but they still do? pyserials problem?) --- libmaple/usb/usb.c | 15 ++++++++++----- libmaple/usb/usb.h | 1 + 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libmaple/usb/usb.c b/libmaple/usb/usb.c index 448c4ff..4e86ed0 100644 --- a/libmaple/usb/usb.c +++ b/libmaple/usb/usb.c @@ -336,10 +336,15 @@ void usbWaitReset(void) { * * */ +void usbBlockingSendByte(char ch) { + while (countTx); + UserToPMABufferCopy(&ch,VCOM_TX_ADDR,1); + _SetEPTxCount(VCOM_TX_ENDP,1); + _SetEPTxValid(VCOM_TX_ENDP); + countTx = 1; + while (countTx); +} uint32 usbSendBytes(uint8* sendBuf, uint32 len) { - - uint16 loaded = 0; - /* any checks on connection (via dtr/rts) done upstream in wirish or by user */ /* last xmit hasnt finished, abort */ @@ -348,8 +353,8 @@ uint32 usbSendBytes(uint8* sendBuf, uint32 len) { } // We can only put VCOM_TX_EPSIZE bytes in the buffer - if(len > VCOM_TX_EPSIZE) { - len = VCOM_TX_EPSIZE; + if(len > VCOM_TX_EPSIZE/2) { + len = VCOM_TX_EPSIZE/2; } // Try to load some bytes if we can diff --git a/libmaple/usb/usb.h b/libmaple/usb/usb.h index 5bc31e1..0ed02e5 100644 --- a/libmaple/usb/usb.h +++ b/libmaple/usb/usb.h @@ -73,6 +73,7 @@ void usb_lpIRQHandler(void); void usbWaitReset(void); /* blocking functions for send/receive */ +void usbBlockingSendByte(char ch); uint32 usbSendBytes(uint8* sendBuf,uint32 len); uint32 usbBytesAvailable(void); uint32 usbReceiveBytes(uint8* recvBuf, uint32 len); -- cgit v1.2.3 From 61b310c5124b27226f1a6ade5cd726128fed61aa Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 21 Dec 2010 10:31:01 -0500 Subject: readme and coding standard updates --- libmaple/usb/README | 84 ++++++++++++++++++++++++++--------------------- notes/coding_standard.txt | 32 ++++++++++++++---- 2 files changed, 71 insertions(+), 45 deletions(-) diff --git a/libmaple/usb/README b/libmaple/usb/README index f3970b6..540b1ea 100644 --- a/libmaple/usb/README +++ b/libmaple/usb/README @@ -5,16 +5,19 @@ The USB submodule of libmaple is responsible for: the USB isr, resetting the USB disc pin (used to tell the host were alive). Additionally, the USB submodule defines the virtual com port USB applications that is available to all user sketches - via Usb.print() and others. + via SerialUSB.print() and others. To use it: - Call Usb.init() to enable the IRQ channel, configure the clocks, - pull down usb_disc, and setup the vcom buffers - Usb.print/ln, available(), read(), write() implement the same + + [This section is out of date. Does SerialUSB.begin() do the same + thing as the old Usb.init()?] + + SerialUSB.print/ln, available(), read(), write() implement the same interface as Serial1/2/3 - - + + Current Status: + Currently, the USB submodule relies on the low level core library provided by ST to access the USB peripheral registers and implement the USB transfer protocol for control endpoint @@ -22,23 +25,27 @@ Current Status: unfortunately hard to untangle from this low level dependence, and when a new USB core library is written (to nix ST dependence) changes will likely have to be made to virtual com application - code. Ideally, the new core library should mimick the form of - MyUSB (LUFA), since this library (USB for AVR) is growing in - popularity and in example applications. Additionally, the USB lib - here relies on low level hardware functions that were just ripped - out of the bootloader code (for simplicity) but clearly this - should be replaced with direct accesses to functions provided - elsewhere in libmaple. - - The virtual com port serves two important purposes. 1) is allows - serial data transfers between user sketches an a host computer. 2) - is allows the host machine to issue a system reset by asserting - the DTR signal. After reset, Maple will run the DFU bootloader for - a few seconds, during which the user can begin a DFU download - operation ('downloads' application binary into RAM/FLASH). This - without this virtual com port, it would be necessary to find an - alternative means to reset the chip in order to enable the - bootloader. + code. Ideally, the new core library should mimic the form of MyUSB + (LUFA), since this library (USB for AVR) is growing in popularity + and in example applications. Additionally, the USB lib here relies + on low level hardware functions that were just ripped out of the + bootloader code (for simplicity) but clearly this should be + replaced with direct accesses to functions provided elsewhere in + libmaple. + + The virtual com port serves two important purposes. + + 1) It allows serial data transfers between user sketches an a + host computer. + + 2) It allows the host machine to issue a system reset by + asserting the DTR signal. + + After reset, Maple will run the DFU bootloader for a few seconds, + during which the user can begin a DFU upload operation (uploads + application binary into RAM/FLASH). Thus, without this virtual com + port, it would be necessary to find an alternative means to reset + the chip in order to enable the bootloader. If you would like to develop your own USB application for whatever reason (uses faster isochronous enpoints for streaming audio, or @@ -51,19 +58,19 @@ Current Status: It would be possible to build a compound USB device, that implements endpoints for both the virtual COM port as well as some - other components (mass sotrage etc.) however this turns out to be - a burden from the host driver side, as windows and *nix handle + other components (mass storage etc.). However, this turns out to + be a burden from the host driver side, as Windows and *nix handle compound USB devices quite differently. - Be mindful that running the USB application isnt "free." The + Be mindful that enabling the USB peripheral isnt "free." The device must respond to periodic bus activity (every few - milliseconds) by servicing an ISR. Therefore the USB application + milliseconds) by servicing an ISR. Therefore, the USB application should be disabled inside of timing critical applications. In order to disconnect the device from the host, the USB_DISC pin can - be asserted (on Maple v1,2,3 this is GPIOC,12). Alternatively, the - NVIC can be directly configured to disable the USB LP/HP IRQ's + be asserted (on Maple this is GPIO C12). Alternatively, the NVIC + can be directly configured to disable the USB LP/HP IRQ's. - This library should exposed through usb.h, do not include any + This library should exposed through usb.h; do not include any other files direcly in your application. The files inside of usb_lib were provided by ST and are subject to @@ -72,21 +79,22 @@ Current Status: Integration with libmaple: - The current USB lib is ported directly from the maple bootloader - code, adapted to be a virtual com rather than a DFU device. That - means several functions are redefined locally that could have been - pulled from elsewhere in libmaple. Thus, ths USB module depends - absolutely zero on libmaple, it even ensures that clocks are - configured correctly for its operation. + The current USB lib is ported from the Maple bootloader code, + adapted to be a virtual com rather than a DFU device. That means + several functions are redefined locally that could have been + pulled from elsewhere in libmaple. Thus, ths USB module doesn't + have too many dependencies on libmaple. It even ensures that + clocks are configured correctly for its operation. However, over + time, some libmaple dependencies have crept in. Todo: - write custom low level USB stack to strip out any remaining dependence on ST code - remove dependence on hardware.c, since any functions here really - should have their own analogues elsewhere inside libmaple + should have their own analogs elsewhere inside libmaple - add a high level USB application library that would allow users to make their own HID/Mass Storage/Audio/Video devices. - - implement a Usb.link(SerialX) that forces a passthrough + - implement a SerialUSB.link(SerialX) that forces a passthrough the host computer virtual com to SerialX, and utilizes the line_config commands correctly (sets baud etc) diff --git a/notes/coding_standard.txt b/notes/coding_standard.txt index bab1e38..c0e4e4e 100644 --- a/notes/coding_standard.txt +++ b/notes/coding_standard.txt @@ -50,7 +50,7 @@ Whitespace - Files end in exactly one newline. [The presence of a newline at EOF is already done by `c-require-final-newline' in recent versions of - emacs.] + Emacs.] - Exactly two newlines separate source paragraphs. @@ -71,7 +71,7 @@ Comments /* comment starts here * the comment can end on the same line */ -- Doxygen comments are newline comments that begin with /** instead. +- Doxygen comments begin with /** instead. - Single-line comments on the same line are // in c or c++. @@ -114,9 +114,8 @@ because It_Looks_Really_Ugly, ok? - Structs: pick a style from "Variables" or "Classes" depending on how you mean it (since it might be either a simple record type, in which case do like c variables, or you might be faking an object in c, in - which case do like classes). If it's in a typedef, should also - probably put _t at the end, but maybe you won't, and I don't really - feel too strongly about it. + which case do like classes). If it's in a typedef, don't feel + obliged to put "_t" at the end of the name; we don't. - Acronyms: The case of letters in an acronym is determined by the case of the first letter in the acronym. Examples: @@ -139,11 +138,26 @@ because It_Looks_Really_Ugly, ok? Documentation ------------- -- Document your code, bitches! +- Document your code. This should go without saying. - At least put a doxygen comment with a nonempty @brief for every source file you add. See the existing ones for examples. +- Doxygen comments generally just belong on types, functions, + etc. that are part of the public user-facing API. This generally + means that if there's ReST documentation for it under docs/source/, + it needs Doxygen comments, and that ReST should use Breathe to pull + that Doxygen comment out. (For more info on this, see docs/README). + + There are some exceptions to this rule since Breathe isn't totally + mature yet and Sphinx's C++ domain is still in flux. In these + cases, document the code "manually" in ReST. + + This should be avoided if at all possible, since it creates a + maintenance burden of documenting things in two places at once, and + provides an opportunity for bad documentation to slip in, when the + code comments fall out of sync with the ReST docs. + General Formatting ------------------ @@ -160,5 +174,9 @@ General Formatting Then put the file somewhere in your load-path, and (require 'lineker) - (dolist (hook programming-mode-hooks) + (dolist (hook '(c-mode-hook c++-mode-hook)) (add-hook hook (lambda () (lineker-mode 1)))) + + There are only a few exceptional situations. The most important one + is when specifying a lookup table like PIN_MAP where it'd be ugly to + split each entry over multiple lines. -- cgit v1.2.3