aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAJM <poslathian@poslathian.(none)>2010-04-24 22:23:50 -0400
committerbnewbold <bnewbold@robocracy.org>2010-05-20 22:09:15 -0400
commit6ad3acd15e9859ac9bc77c1eb04d67108dcc5a03 (patch)
tree689a264bfd8535205a9a905afc03e38cf762520b
parenta86ec7c81d7ad2037e900899a0b32c5592cae7c0 (diff)
downloadlibrambutan-6ad3acd15e9859ac9bc77c1eb04d67108dcc5a03.tar.gz
librambutan-6ad3acd15e9859ac9bc77c1eb04d67108dcc5a03.zip
finally got TX working without any delay, there is some weird timing involved in what happens when the line state is toggled (host port disconnected) and theres still data waiting to go out, this will hang any while(txCount != 0) calls. similarly, sending data without checking txCount != 0 will hard fault the chip. This is all handled now by usbSendBytes, which returns -1 for unconnected, and 0 for simply 'waiting to send'
-rw-r--r--core/usb/descriptors.c6
-rw-r--r--core/usb/descriptors.h6
-rw-r--r--core/usb/usb.c89
-rw-r--r--core/usb/usb.h5
-rw-r--r--core/usb/usb_callbacks.c54
-rw-r--r--core/usb/usb_callbacks.h8
-rw-r--r--core/usb/usb_config.h2
-rw-r--r--core/usb/usb_hardware.h2
8 files changed, 149 insertions, 23 deletions
diff --git a/core/usb/descriptors.c b/core/usb/descriptors.c
index 7ff26a2..5038709 100644
--- a/core/usb/descriptors.c
+++ b/core/usb/descriptors.c
@@ -143,7 +143,7 @@ const USB_Descriptor_Config usbVcomDescriptor_Config = {
which is 0x0409 for US English
*/
-uint8 usbVcomDescriptor_LangID[USB_DESCRIPTOR_STRING_LEN(1)] =
+const uint8 usbVcomDescriptor_LangID[USB_DESCRIPTOR_STRING_LEN(1)] =
{
USB_DESCRIPTOR_STRING_LEN(1),
USB_DESCRIPTOR_TYPE_STRING,
@@ -151,7 +151,7 @@ uint8 usbVcomDescriptor_LangID[USB_DESCRIPTOR_STRING_LEN(1)] =
0x04
};
-uint8 usbVcomDescriptor_iManufacturer[USB_DESCRIPTOR_STRING_LEN(8)] =
+const uint8 usbVcomDescriptor_iManufacturer[USB_DESCRIPTOR_STRING_LEN(8)] =
{
USB_DESCRIPTOR_STRING_LEN(8),
USB_DESCRIPTOR_TYPE_STRING,
@@ -159,7 +159,7 @@ uint8 usbVcomDescriptor_iManufacturer[USB_DESCRIPTOR_STRING_LEN(8)] =
'L', 0, 'a', 0, 'b', 0, 's', 0
};
-uint8 usbVcomDescriptor_iProduct[USB_DESCRIPTOR_STRING_LEN(8)] =
+const uint8 usbVcomDescriptor_iProduct[USB_DESCRIPTOR_STRING_LEN(8)] =
{
USB_DESCRIPTOR_STRING_LEN(8),
USB_DESCRIPTOR_TYPE_STRING,
diff --git a/core/usb/descriptors.h b/core/usb/descriptors.h
index f15221a..6e96024 100644
--- a/core/usb/descriptors.h
+++ b/core/usb/descriptors.h
@@ -191,9 +191,9 @@ typedef struct {
extern const USB_Descriptor_Device usbVcomDescriptor_Device;
extern const USB_Descriptor_Config usbVcomDescriptor_Config;
-extern uint8 usbVcomDescriptor_LangID[USB_DESCRIPTOR_STRING_LEN(1)];
-extern uint8 usbVcomDescriptor_iManufacturer[USB_DESCRIPTOR_STRING_LEN(8)];
-extern uint8 usbVcomDescriptor_iProduct[USB_DESCRIPTOR_STRING_LEN(8)];
+extern const uint8 usbVcomDescriptor_LangID[USB_DESCRIPTOR_STRING_LEN(1)];
+extern const uint8 usbVcomDescriptor_iManufacturer[USB_DESCRIPTOR_STRING_LEN(8)];
+extern const uint8 usbVcomDescriptor_iProduct[USB_DESCRIPTOR_STRING_LEN(8)];
#if defined(__cplusplus)
}
diff --git a/core/usb/usb.c b/core/usb/usb.c
index 8ef8697..c8a27c2 100644
--- a/core/usb/usb.c
+++ b/core/usb/usb.c
@@ -334,10 +334,89 @@ if (wIstr & ISTR_CTR & wInterrupt_Mask)
#endif
}
+/* copies data out of sendBuf into the packet memory for
+ usb, but waits until any previous usb transmissions have
+ completed before doing this. It returns without waiting
+ for its data to be sent. most efficient when 64 bytes are copied
+ at a time. users responsible for not overflowing sendbuf
+ with len! if > 64 bytes are being sent, then the function
+ will block at every 64 byte packet
+*/
+int16 usbSendBytes(uint8* sendBuf, uint16 len) {
+/* while (countTx != 0) { */
+/* if (reset_state == NDTR_NRTS) { */
+/* return 0; */
+/* } */
+/* }/\* wait for pipe to be clear *\/ */
+
+ if (reset_state == NDTR_NRTS) {
+ return -1; /* indicates to caller to stop trying, were not connected */
+ }
+
+ /* ideally we should wait here, but it gets stuck
+ for some reason. countTx wont decrement when
+ theres no host side port reading the data, this is
+ known, but even if we add the check for NDTR_NRTS it
+ still gets stuck...*/
+ if (countTx != 0) {
+ return 0; /* indicated to caller to keep trying, were just busy */
+ }
+
+ uint16 sent = len;
+
+ while (len > VCOM_TX_EPSIZE) {
+ countTx = VCOM_TX_EPSIZE;
+
+ UserToPMABufferCopy(sendBuf,VCOM_TX_ADDR,VCOM_TX_EPSIZE);
+ _SetEPTxCount(VCOM_TX_ENDP,VCOM_TX_EPSIZE);
+ _SetEPTxValid(VCOM_TX_ENDP);
+
+ while(countTx != 0);
+ len -= VCOM_TX_EPSIZE;
+ sendBuf += VCOM_TX_EPSIZE;
+ }
+
+ if (len != 0) {
+ countTx = len;
+ UserToPMABufferCopy(sendBuf,VCOM_TX_ADDR,len);
+ _SetEPTxCount(VCOM_TX_ENDP,len);
+ _SetEPTxValid(VCOM_TX_ENDP);
+ }
+
+ return sent;
+}
+
+/* returns the number of available bytes are in the recv FIFO */
+uint8 usbBytesAvailable(void) {
+ return VCOM_RX_EPSIZE - maxNewBytes;
+}
+
+/* copies len bytes from the local recieve FIFO (not
+ 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) {
+ uint8 bytesCopied;
+
+ if (len > VCOM_RX_EPSIZE - maxNewBytes) {
+ len = VCOM_RX_EPSIZE - maxNewBytes;
+ }
+
+ int i;
+ for (i=0;i<len;i++) {
+ *recvBuf++ = vcomBufferRx[(recvBufOut++)%VCOM_RX_EPSIZE];
+ }
+
+ maxNewBytes += bytesCopied;
+ return bytesCopied;
+}
+
void usbSendHello(void) {
- char* myStr = "HELLO!";
- char myCh = 'a';
- UserToPMABufferCopy((uint8*)myStr,VCOM_TX_ADDR,6);
- _SetEPTxCount(VCOM_TX_ENDP,6);
- _SetEPTxValid(VCOM_TX_ENDP);
+ char* myStr = "hello!";
+
+ uint8 thisVal = 48 + usbBytesAvailable();
+ char *line = "\n";
+ while(usbSendBytes(&thisVal,1) == 0);
+ while(usbSendBytes((uint8*)line,1) == 0);
+ GetEPTxCount(1);
}
diff --git a/core/usb/usb.h b/core/usb/usb.h
index 087ca72..c6377ab 100644
--- a/core/usb/usb.h
+++ b/core/usb/usb.h
@@ -49,6 +49,11 @@ typedef enum
/* overloaded ISR routine, this is the main usb ISR */
void usb_lpIRQHandler(void);
+ /* blocking functions for send/receive */
+ int16 usbSendBytes(uint8* sendBuf,uint16 len);
+ uint8 usbBytesAvailable(void);
+ uint8 usbReceiveBytes(uint8* recvBuf, uint8 len);
+
void usbSendHello(void);
#ifdef __cplusplus
diff --git a/core/usb/usb_callbacks.c b/core/usb/usb_callbacks.c
index 83b39c7..402e8f5 100644
--- a/core/usb/usb_callbacks.c
+++ b/core/usb/usb_callbacks.c
@@ -31,28 +31,54 @@ USB_Line_Coding line_coding = {
datatype: 0x08
};
-uint8 vcomBufferTx[VCOM_TX_EPSIZE];
uint8 vcomBufferRx[VCOM_RX_EPSIZE];
-uint8 countTx = 0;
-uint8 countRx = 0;
+uint8 countTx = 0;
+uint8 recvBufIn = 0;
+uint8 recvBufOut = 0;
+uint8 maxNewBytes = VCOM_RX_EPSIZE;
RESET_STATE reset_state = START;
void vcomDataTxCb(void) {
/* do whatever after data has been sent to host */
+
+ /* allows usbSendBytes to stop blocking */
+
+
countTx = 0;
}
+/* we could get arbitrarily complicated here for speed purposes
+ however, the simple scheme here is to implement a receive fifo
+ and always set the maximum to new bytes to the space remaining
+ in the fifo. this number will be reincremented after calls
+ to usbReceiveBytes */
void vcomDataRxCb(void) {
/* do whatever after data has been received from host */
- /* countRx = GetEPRxCount(VCOM_RX_ENDP); */
-/* PMAToUserBufferCopy(vcomBufferRx,VCOM_RX_ADDR,countRx); */
-/* SetEPRxValid(VCOM_RX_ENDP); */
-/* countTx = countRx; */
-/* UserToPMABufferCopy(vcomBufferRx,VCOM_TX_ADDR,countTx); */
-/* SetEPTxCount(VCOM_TX_ENDP,countTx); */
-/* SetEPTxValid(VCOM_TX_ENDP); */
+ /* setEPRxCount on the previous cycle should garuntee
+ we havnt received more bytes than we can fit */
+ uint8 newBytes = _GetEPRxCount(VCOM_RX_ENDP);
+ /* assert (newBytes <= maxNewBytes); */
+
+ if (recvBufIn + newBytes < VCOM_RX_EPSIZE) {
+ 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 remaining = newBytes - tailBytes;
+
+ PMAToUserBufferCopy(&vcomBufferRx[recvBufIn],VCOM_RX_ADDR,tailBytes);
+ PMAToUserBufferCopy(&vcomBufferRx[0], VCOM_RX_ADDR,remaining);
+
+ recvBufIn += (newBytes % VCOM_RX_EPSIZE);
+ }
+
+ maxNewBytes -= newBytes;
+ SetEPRxCount(VCOM_RX_ENDP,maxNewBytes);
+ SetEPRxValid(VCOM_RX_ENDP);
}
void vcomManagementCb(void) {
@@ -115,12 +141,18 @@ void usbReset(void) {
/* setup data endpoint IN (tx) */
SetEPType (VCOM_TX_ENDP, EP_BULK);
- SetEPRxAddr (VCOM_TX_ENDP, VCOM_TX_ADDR);
+ SetEPTxAddr (VCOM_TX_ENDP, VCOM_TX_ADDR);
SetEPTxStatus (VCOM_TX_ENDP, EP_TX_NAK);
SetEPRxStatus (VCOM_TX_ENDP, EP_RX_DIS);
bDeviceState = ATTACHED;
SetDeviceAddress(0);
+
+ /* reset the rx fifo */
+ recvBufIn = 0;
+ recvBufOut = 0;
+ maxNewBytes = VCOM_RX_EPSIZE;
+ countTx = 0;
}
diff --git a/core/usb/usb_callbacks.h b/core/usb/usb_callbacks.h
index 53857ae..b95ea15 100644
--- a/core/usb/usb_callbacks.h
+++ b/core/usb/usb_callbacks.h
@@ -5,6 +5,7 @@
#include "libmaple.h"
#include "usb_lib.h"
+#include "usb_config.h"
#define SET_LINE_CODING 0x20
#define GET_LINE_CODING 0x21
@@ -30,6 +31,13 @@ typedef enum {
DTR_NRTS
} RESET_STATE;
+extern RESET_STATE reset_state; /* tracks DTR/RTS */
+extern uint8 countTx;
+extern uint8 vcomBufferRx[VCOM_RX_EPSIZE]; /* no reason this has to be VCOM_RX_EPSIZE, could be bigger */
+extern uint8 recvBufIn; /* the FIFO in index to the recvbuffer */
+extern uint8 recvBufOut; /* the FIFO out index to the recvbuffer */
+extern uint8 maxNewBytes;
+
void vcomDataTxCb(void);
void vcomDataRxCb(void);
void vcomManagementCb(void);
diff --git a/core/usb/usb_config.h b/core/usb/usb_config.h
index 3ff24f8..12d21c8 100644
--- a/core/usb/usb_config.h
+++ b/core/usb/usb_config.h
@@ -29,7 +29,7 @@
#define VCOM_RX_ENDP ENDP3
#define VCOM_RX_EPNUM 0x03
-#define VCOM_RX_ADDR 0x140
+#define VCOM_RX_ADDR 0x110
#define VCOM_RX_EPSIZE 0x40
#define bMaxPacketSize 0x40 /* 64B, maximum for USB FS Devices */
diff --git a/core/usb/usb_hardware.h b/core/usb/usb_hardware.h
index d7e4ff0..8258da9 100644
--- a/core/usb/usb_hardware.h
+++ b/core/usb/usb_hardware.h
@@ -33,6 +33,8 @@
#define GPIOA ((u32)0x40010800)
#define GPIOC ((u32)0x40011000)
+#define USB_PACKET_BUFFER ((u32)0x40006000)
+
#define RCC_CR RCC
#define RCC_CFGR RCC + 0x04
#define RCC_CIR RCC + 0x08