aboutsummaryrefslogtreecommitdiffstats
path: root/core/usb
diff options
context:
space:
mode:
Diffstat (limited to 'core/usb')
-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