diff options
-rw-r--r-- | core/usb/descriptors.c | 6 | ||||
-rw-r--r-- | core/usb/descriptors.h | 6 | ||||
-rw-r--r-- | core/usb/usb.c | 89 | ||||
-rw-r--r-- | core/usb/usb.h | 5 | ||||
-rw-r--r-- | core/usb/usb_callbacks.c | 54 | ||||
-rw-r--r-- | core/usb/usb_callbacks.h | 8 | ||||
-rw-r--r-- | core/usb/usb_config.h | 2 | ||||
-rw-r--r-- | core/usb/usb_hardware.h | 2 |
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 |