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 | 
