diff --git a/cores/arduino/Stream.h b/cores/arduino/Stream.h index bd5311b84a..db3dbe48d7 100644 --- a/cores/arduino/Stream.h +++ b/cores/arduino/Stream.h @@ -94,12 +94,12 @@ class Stream : public Print float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); // float version of parseInt - size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer + virtual size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } // terminates if length characters have been read or timeout (see setTimeout) // returns the number of characters placed in the buffer (0 means no valid data found) - size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character + virtual size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } // terminates if length characters have been read, timeout, or if the terminator character detected // returns the number of characters placed in the buffer (0 means no valid data found) diff --git a/cores/arduino/USBSerial.cpp b/cores/arduino/USBSerial.cpp index 7df1d48e42..571bdb4e78 100644 --- a/cores/arduino/USBSerial.cpp +++ b/cores/arduino/USBSerial.cpp @@ -24,126 +24,123 @@ #include "usbd_desc.h" #include "wiring.h" -#define USB_TIMEOUT 50 -/* USB Device Core handle declaration */ -extern USBD_HandleTypeDef hUSBD_Device_CDC; -extern __IO uint32_t device_connection_status; extern __IO uint32_t lineState; -extern __IO uint8_t UserTxBuffer[APP_TX_DATA_SIZE]; -extern __IO uint8_t UserRxBuffer[APP_RX_DATA_SIZE]; -extern __IO uint32_t UserTxBufPtrIn; -extern __IO uint32_t UserTxBufPtrOut; -extern __IO uint32_t UserRxBufPtrIn; -extern __IO uint32_t UserRxBufPtrOut; USBSerial SerialUSB; void serialEventUSB() __attribute__((weak)); +void USBSerial::begin(void) { + CDC_init(); +} + void USBSerial::begin(uint32_t /* baud_count */) { // uart config is ignored in USB-CDC + begin(); } void USBSerial::begin(uint32_t /* baud_count */, uint8_t /* config */) { // uart config is ignored in USB-CDC + begin(); } -void USBSerial::end(void) { - - USBD_LL_DeInit(&hUSBD_Device_CDC); +void USBSerial::end() { + CDC_deInit(); } -int USBSerial::availableForWrite(void) +int USBSerial::availableForWrite() { - int ret_val; - - /* UserTxBufPtrOut can be modified by TIM ISR, so in order to be sure that the */ - /* value that we read is correct, we need to disable TIM Interrupt. */ - CDC_disable_TIM_Interrupt(); - - if (UserTxBufPtrIn >= UserTxBufPtrOut) { - ret_val = (APP_TX_DATA_SIZE - 1 - UserTxBufPtrIn + UserTxBufPtrOut); - } else { - ret_val = (UserTxBufPtrOut - UserTxBufPtrIn - 1); - } - - CDC_enable_TIM_Interrupt(); - - return ret_val; + // Just transmit queue size, available for write + return static_cast(CDC_TransmitQueue_WriteSize(&TransmitQueue)); } size_t USBSerial::write(uint8_t ch) { - - /* UserTxBufPtrOut can be modified by TIM ISR, so in order to be sure that the */ - /* value that we read is correct, we need to disable TIM Interrupt. */ - CDC_disable_TIM_Interrupt(); - - if (((UserTxBufPtrIn + 1) % APP_TX_DATA_SIZE) == UserTxBufPtrOut) { - // Buffer full!!! Force a flush to not loose data and go on - CDC_flush(); - } - UserTxBuffer[UserTxBufPtrIn] = ch; - UserTxBufPtrIn = ((UserTxBufPtrIn + 1) % APP_TX_DATA_SIZE); - - CDC_enable_TIM_Interrupt(); - - return 1; + // Just write single-byte buffer. + return write(&ch, 1); } size_t USBSerial::write(const uint8_t *buffer, size_t size){ - size_t i = 0; - for (i=0; i < size; i++) { - if (write(buffer[i]) != 1) { - break; - } + size_t rest = size; + while(rest > 0) { + // Determine buffer size available for write + auto portion = (size_t)CDC_TransmitQueue_WriteSize(&TransmitQueue); + // Truncate it to content size (if rest is greater) + if (rest < portion) { + portion = rest; + } + if (portion > 0) { + // Only if some space in the buffer exists. + // TS: Only main thread calls write and writeSize methods, + // it's thread-safe since IRQ does not affects + // TransmitQueue write position + CDC_TransmitQueue_Enqueue(&TransmitQueue, buffer, portion); + rest -= portion; + buffer += portion; + // After storing data, start transmitting process + CDC_continue_transmit(); + } } - return i; + return size; } int USBSerial::available(void) { - return ((APP_RX_DATA_SIZE + (UserRxBufPtrIn - UserRxBufPtrOut)) % APP_RX_DATA_SIZE); + // Just ReceiveQueue size, available for reading + return static_cast(CDC_ReceiveQueue_ReadSize(&ReceiveQueue)); } int USBSerial::read(void) { - if (UserRxBufPtrOut == UserRxBufPtrIn) { - return -1; - } else { - unsigned char c = UserRxBuffer[UserRxBufPtrOut]; - UserRxBufPtrOut = ((UserRxBufPtrOut + 1) % APP_RX_DATA_SIZE); + // Dequeue only one char from queue + // TS: it safe, because only main thread affects ReceiveQueue->read pos + auto ch = CDC_ReceiveQueue_Dequeue(&ReceiveQueue); + // Resume receive process, if possible + CDC_resume_receive(); + return ch; +} + +size_t USBSerial::readBytes(char *buffer, size_t length) { + uint16_t read; + auto rest = static_cast(length); + _startMillis = millis(); + do { + read = CDC_ReceiveQueue_Read(&ReceiveQueue, reinterpret_cast(buffer), rest); CDC_resume_receive(); - return c; - } + rest -= read; + buffer += read; + if (rest == 0) return length; + } while(millis() - _startMillis < _timeout); + return length - rest; +} + +size_t USBSerial::readBytesUntil(char terminator, char *buffer, size_t length) { + uint16_t read; + auto rest = static_cast(length); + _startMillis = millis(); + do { + bool found = CDC_ReceiveQueue_ReadUntil(&ReceiveQueue, static_cast(terminator), + reinterpret_cast(buffer), rest, &read); + CDC_resume_receive(); + rest -= read; + buffer += read; + if (found) { + return length - rest; + } + if (rest == 0) { + return length; + } + } while(millis() - _startMillis < _timeout); + return length - rest; } int USBSerial::peek(void) { - if (UserRxBufPtrOut == UserRxBufPtrIn) { - return -1; - } else { - unsigned char c = UserRxBuffer[UserRxBufPtrOut]; - return c; - } + // Peek one symbol, it can't change receive avaiablity + return CDC_ReceiveQueue_Peek(&ReceiveQueue); } void USBSerial::flush(void) { - /* UserTxBufPtrOut can be modified by TIM ISR, so in order to be sure that the */ - /* value that we read is correct, we need to disable TIM Interrupt. */ - CDC_disable_TIM_Interrupt(); - CDC_flush(); - CDC_enable_TIM_Interrupt(); -} - -uint8_t USBSerial::pending(void) { - return 0; -} - -uint8_t USBSerial::isConnected(void) { - - if (device_connection_status == 1) { - return 1; - } else { - return 0; - } + // Wait for TransmitQueue read size becomes zero + // TS: safe, because it not be stopped while receive 0 + while(CDC_TransmitQueue_ReadSize(&TransmitQueue) > 0) {} } uint32_t USBSerial::baud() { diff --git a/cores/arduino/USBSerial.h b/cores/arduino/USBSerial.h index 10b28f996d..0667c3a294 100644 --- a/cores/arduino/USBSerial.h +++ b/cores/arduino/USBSerial.h @@ -27,8 +27,7 @@ // Serial over CDC class USBSerial : public Stream { public: - USBSerial(void) {}; - + void begin(void); void begin(uint32_t); void begin(uint32_t, uint8_t); void end(void); @@ -37,6 +36,8 @@ class USBSerial : public Stream { virtual int availableForWrite(void); virtual int peek(void); virtual int read(void); + virtual size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer + virtual size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character virtual void flush(void); virtual size_t write(uint8_t); virtual size_t write(const uint8_t *buffer, size_t size); @@ -64,9 +65,6 @@ class USBSerial : public Stream { MARK_PARITY = 3, SPACE_PARITY = 4, }; - - uint8_t isConnected(); - uint8_t pending(); }; extern USBSerial SerialUSB; diff --git a/cores/arduino/board.h b/cores/arduino/board.h index e88a237543..4bccf613c1 100644 --- a/cores/arduino/board.h +++ b/cores/arduino/board.h @@ -20,7 +20,6 @@ extern "C"{ #include "timer.h" #include "twi.h" #include "uart.h" -#include "usbd_interface.h" void init( void ) ; #ifdef __cplusplus diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 741f041d0a..b67ac74b2c 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -54,10 +54,6 @@ int main( void ) { initVariant(); -#if defined(USBCON) - usbd_interface_init(); -#endif - setup(); for (;;) diff --git a/cores/arduino/stm32/hw_config.c b/cores/arduino/stm32/hw_config.c index f5e9fc6d20..bf9e26da25 100644 --- a/cores/arduino/stm32/hw_config.c +++ b/cores/arduino/stm32/hw_config.c @@ -37,6 +37,7 @@ */ #include "stm32_def.h" #include "hw_config.h" +#include "usbd_if.h" #ifdef __cplusplus extern "C" { @@ -54,6 +55,10 @@ void hw_config_init(void) // Configure the system clock SystemClock_Config(); + +#if defined (USBCON) && defined(USBD_USE_CDC) + USBD_CDC_init(); +#endif } #ifdef __cplusplus } diff --git a/cores/arduino/stm32/usb/cdc/cdc_queue.c b/cores/arduino/stm32/usb/cdc/cdc_queue.c new file mode 100644 index 0000000000..15de13735a --- /dev/null +++ b/cores/arduino/stm32/usb/cdc/cdc_queue.c @@ -0,0 +1,234 @@ +/** + ****************************************************************************** + * @file cdc_queue.c + * @author makarenya + * @version V1.0.0 + * @date 23-December-2018 + * @brief Provides methods to manipulate with CDC cyclic buffers + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +#ifdef USBCON +#ifdef USBD_USE_CDC + +#include "cdc_queue.h" + +// Initialize read and write position of queue +void CDC_TransmitQueue_Init(CDC_TransmitQueue_TypeDef *queue) { + queue->read = 0; + queue->write = 0; +} + +// Determine size, available for write in queue +int CDC_TransmitQueue_WriteSize(CDC_TransmitQueue_TypeDef *queue) { + return (queue->read + CDC_TRANSMIT_QUEUE_BUFFER_SIZE - queue->write - 1) + % CDC_TRANSMIT_QUEUE_BUFFER_SIZE; +} + +// Determine size of data, stored in queue +int CDC_TransmitQueue_ReadSize(CDC_TransmitQueue_TypeDef *queue) { + return (queue->write + CDC_TRANSMIT_QUEUE_BUFFER_SIZE - queue->read) + % CDC_TRANSMIT_QUEUE_BUFFER_SIZE; +} + +// Write provided data into queue. +void CDC_TransmitQueue_Enqueue(CDC_TransmitQueue_TypeDef *queue, + const uint8_t *buffer, uint32_t size) { + uint32_t sizeToEnd = CDC_TRANSMIT_QUEUE_BUFFER_SIZE - queue->write; + if (sizeToEnd > size) { + memcpy(&queue->buffer[queue->write], &buffer[0], size); + } else { + memcpy(&queue->buffer[queue->write], &buffer[0], sizeToEnd); + memcpy(&queue->buffer[0], &buffer[sizeToEnd], size - sizeToEnd); + } + queue->write = (uint16_t)((queue->write + size) % + CDC_TRANSMIT_QUEUE_BUFFER_SIZE); +} + +// Read flat block from queue biggest as possible, but max QUEUE_MAX_PACKET_SIZE +uint8_t *CDC_TransmitQueue_ReadBlock(CDC_TransmitQueue_TypeDef *queue, + uint16_t *size) { + if (queue->write >= queue->read) { + *size = queue->write - queue->read; + } else { + *size = CDC_TRANSMIT_QUEUE_BUFFER_SIZE - queue->read; + } + queue->reserved = *size; + return &queue->buffer[queue->read]; +} + +void CDC_TransmitQueue_CommitRead(CDC_TransmitQueue_TypeDef *queue) { + queue->read = (queue->read + queue->reserved) % + CDC_TRANSMIT_QUEUE_BUFFER_SIZE; +} + +// Initialize read and write position of queue. +void CDC_ReceiveQueue_Init(CDC_ReceiveQueue_TypeDef *queue) { + queue->read = 0; + queue->write = 0; + queue->length = CDC_RECEIVE_QUEUE_BUFFER_SIZE; +} + +// Reserve block in queue and return pointer to it. +uint8_t *CDC_ReceiveQueue_ReserveBlock(CDC_ReceiveQueue_TypeDef *queue) { + const uint16_t limit = + CDC_RECEIVE_QUEUE_BUFFER_SIZE - CDC_QUEUE_MAX_PACKET_SIZE; + volatile uint16_t read = queue->read; + + if (read <= queue->write) { + // if write is limited only by buffer size. + if (queue->write < limit || (queue->write == limit && read > 0)) { + // if size in the rest of buffer is enough for full packet plus 1 byte + // or if it tight enough and write position can be set to 0 + return queue->buffer + queue->write; + } else if (read > CDC_QUEUE_MAX_PACKET_SIZE) { + // if size in the rest is not enough, but enough size in head + queue->length = queue->write; + queue->write = 0; + return queue->buffer + queue->write; + } + } else if (queue->write + CDC_QUEUE_MAX_PACKET_SIZE < read) { + // write position must be less than read position + // after reading largest possible packet + return queue->buffer + queue->write; + } + return 0; +} + +// Commits block in queue and make it available for reading +void CDC_ReceiveQueue_CommitBlock(CDC_ReceiveQueue_TypeDef *queue, + uint16_t size) { + queue->write += size; + if (queue->write >= queue->length) { + queue->length = CDC_RECEIVE_QUEUE_BUFFER_SIZE; + } + if (queue->write >= CDC_RECEIVE_QUEUE_BUFFER_SIZE) { + queue->write = 0; + } +} + +// Determine size, available for read +int CDC_ReceiveQueue_ReadSize(CDC_ReceiveQueue_TypeDef *queue) { + // reading length after write make guarantee, that length >= write + // and determined reading size will be smaller or equal than real one. + volatile uint16_t write = queue->write; + volatile uint16_t length = queue->length; + if (write >= queue->read) { + return write - queue->read; + } + return length + write - queue->read; +} + +// Read one byte from queue. +int CDC_ReceiveQueue_Dequeue(CDC_ReceiveQueue_TypeDef *queue) { + volatile uint16_t write = queue->write; + volatile uint16_t length = queue->length; + if (queue->read == length) queue->read = 0; + if (write == queue->read) return -1; + uint8_t ch = queue->buffer[queue->read++]; + if (queue->read >= length) { + queue->read = 0; + } + return ch; +} + +// Peek byte from queue. +int CDC_ReceiveQueue_Peek(CDC_ReceiveQueue_TypeDef *queue) { + volatile uint16_t write = queue->write; + volatile uint16_t length = queue->length; + if (queue->read >= length) queue->read = 0; + if (write == queue->read) return -1; + return queue->buffer[queue->read]; +} + +uint16_t CDC_ReceiveQueue_Read(CDC_ReceiveQueue_TypeDef *queue, + uint8_t *buffer, uint16_t size) { + volatile uint16_t write = queue->write; + volatile uint16_t length = queue->length; + uint16_t available; + + if (queue->read >= length) queue->read = 0; + if (write >= queue->read) { + available = write - queue->read; + } else { + available = length - queue->read; + } + if (available < size) { + size = available; + } + + memcpy(buffer, &queue->buffer[queue->read], size); + queue->read = queue->read + size; + if (queue->read >= length) { + queue->read = 0; + } + return size; +} + +bool CDC_ReceiveQueue_ReadUntil(CDC_ReceiveQueue_TypeDef *queue, + uint8_t terminator, uint8_t *buffer, uint16_t size, uint16_t* fetched) { + volatile uint16_t write = queue->write; + volatile uint16_t length = queue->length; + uint16_t available; + + if (queue->read >= length) queue->read = 0; + if (write >= queue->read) { + available = write - queue->read; + } else { + available = length - queue->read; + } + if (available < size) { + size = available; + } + + uint8_t* start = &queue->buffer[queue->read]; + for(uint16_t i = 0; i < size; i++) { + uint8_t ch = start[i]; + if (ch == terminator) { + queue->read += (uint16_t)(i + 1); + if (queue->read >= length) { + queue->read = 0; + } + *fetched = i; + return true; + } else { + buffer[i] = ch; + } + } + + *fetched = size; + queue->read += size; + if (queue->read >= length) { + queue->read = 0; + } + return false; +} +#endif /* USBD_USE_CDC */ +#endif /* USBCON */ diff --git a/cores/arduino/stm32/usb/cdc/cdc_queue.h b/cores/arduino/stm32/usb/cdc/cdc_queue.h new file mode 100644 index 0000000000..827f0aa889 --- /dev/null +++ b/cores/arduino/stm32/usb/cdc/cdc_queue.h @@ -0,0 +1,93 @@ +/** + ****************************************************************************** + * @file cdc_queue.h + * @author makarenya + * @version V1.0.0 + * @date 23-December-2018 + * @brief Header for cdc_queue.c module + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __CDC_QUEUE_H +#define __CDC_QUEUE_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#if USE_USB_HS +#define CDC_QUEUE_MAX_PACKET_SIZE USB_HS_MAX_PACKET_SIZE +#else +#define CDC_QUEUE_MAX_PACKET_SIZE USB_FS_MAX_PACKET_SIZE +#endif +#define CDC_TRANSMIT_QUEUE_BUFFER_SIZE ((uint16_t)(CDC_QUEUE_MAX_PACKET_SIZE * 2)) +#define CDC_RECEIVE_QUEUE_BUFFER_SIZE ((uint16_t)(CDC_QUEUE_MAX_PACKET_SIZE * 3)) + +typedef struct { + uint8_t buffer[CDC_TRANSMIT_QUEUE_BUFFER_SIZE]; + volatile uint16_t write; + volatile uint16_t read; + volatile uint16_t reserved; +} CDC_TransmitQueue_TypeDef; + +typedef struct { + uint8_t buffer[CDC_RECEIVE_QUEUE_BUFFER_SIZE]; + volatile uint16_t write; + volatile uint16_t read; + volatile uint16_t length; +} CDC_ReceiveQueue_TypeDef; + +void CDC_TransmitQueue_Init(CDC_TransmitQueue_TypeDef* queue); +int CDC_TransmitQueue_WriteSize(CDC_TransmitQueue_TypeDef* queue); +int CDC_TransmitQueue_ReadSize(CDC_TransmitQueue_TypeDef* queue); +void CDC_TransmitQueue_Enqueue(CDC_TransmitQueue_TypeDef* queue, const uint8_t* buffer, uint32_t size); +uint8_t* CDC_TransmitQueue_ReadBlock(CDC_TransmitQueue_TypeDef* queue, uint16_t* size); +void CDC_TransmitQueue_CommitRead(CDC_TransmitQueue_TypeDef *queue); + +void CDC_ReceiveQueue_Init(CDC_ReceiveQueue_TypeDef* queue); +int CDC_ReceiveQueue_ReadSize(CDC_ReceiveQueue_TypeDef* queue); +int CDC_ReceiveQueue_Dequeue(CDC_ReceiveQueue_TypeDef* queue); +int CDC_ReceiveQueue_Peek(CDC_ReceiveQueue_TypeDef* queue); +uint16_t CDC_ReceiveQueue_Read(CDC_ReceiveQueue_TypeDef* queue, uint8_t* buffer, uint16_t size); +bool CDC_ReceiveQueue_ReadUntil(CDC_ReceiveQueue_TypeDef* queue, uint8_t terminator, uint8_t* buffer, + uint16_t size, uint16_t* fetched); +uint8_t* CDC_ReceiveQueue_ReserveBlock(CDC_ReceiveQueue_TypeDef* queue); +void CDC_ReceiveQueue_CommitBlock(CDC_ReceiveQueue_TypeDef* queue, uint16_t size); + +#ifdef __cplusplus +} +#endif + +#endif // __CDC_QUEUE_H \ No newline at end of file diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc.c b/cores/arduino/stm32/usb/cdc/usbd_cdc.c index 1674333598..7c8b5a997b 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc.c @@ -678,6 +678,7 @@ static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) { USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)pdev->pClassData; PCD_HandleTypeDef *hpcd = pdev->pData; + USBD_CDC_ItfTypeDef* ctrl = (USBD_CDC_ItfTypeDef *)pdev->pUserData; if(pdev->pClassData != NULL) { @@ -692,6 +693,10 @@ static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) else { hcdc->TxState = 0U; + if (ctrl->Transferred) + { + ctrl->Transferred(); + } } return USBD_OK; } diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc.h b/cores/arduino/stm32/usb/cdc/usbd_cdc.h index 1cddfeaf8b..556ac47ef7 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc.h +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc.h @@ -104,6 +104,7 @@ typedef struct _USBD_CDC_Itf int8_t (* DeInit) (void); int8_t (* Control) (uint8_t cmd, uint8_t* pbuf, uint16_t length); int8_t (* Receive) (uint8_t* Buf, uint32_t *Len); + int8_t (* Transferred) (void); }USBD_CDC_ItfTypeDef; diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c index 76b3b54690..b292a94192 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c @@ -21,6 +21,7 @@ #ifdef USBD_USE_CDC /* Includes ------------------------------------------------------------------*/ +#include "usbd_desc.h" #include "usbd_cdc_if.h" #ifdef USE_USB_HS @@ -32,33 +33,17 @@ #endif /* USBD_CDC Private Variables */ +/* USB Device Core CDC handle declaration */ +USBD_HandleTypeDef hUSBD_Device_CDC; -/* Create buffer for reception and transmission */ -/* It's up to user to redefine and/or remove those define */ -extern USBD_HandleTypeDef hUSBD_Device_CDC; -/* Received Data over USB are stored in this buffer */ -__IO uint8_t UserRxBuffer[APP_RX_DATA_SIZE]; -__IO uint8_t StackRxBuffer[CDC_MAX_PACKET_SIZE]; - -/* Send Data over USB CDC are stored in this buffer */ -__IO uint8_t UserTxBuffer[APP_TX_DATA_SIZE]; -__IO uint8_t StackTxBuffer[APP_TX_DATA_SIZE]; - -__IO uint32_t UserTxBufPtrIn = 0; /* Increment this pointer or roll it back to - start address when data are received over write call */ -__IO uint32_t UserTxBufPtrOut = 0; /* Increment this pointer or roll it back to - start address when data are sent over USB */ - -__IO uint32_t UserRxBufPtrIn = 0; /* Increment this pointer or roll it back to - start address when data are received over USB */ -__IO uint32_t UserRxBufPtrOut = 0; /* Increment this pointer or roll it back to - start address when data are sent over read call */ +static bool CDC_initialized = false; +/* Received Data over USB are stored in this buffer */ +CDC_TransmitQueue_TypeDef TransmitQueue; +CDC_ReceiveQueue_TypeDef ReceiveQueue; __IO uint32_t lineState = 0; -__IO bool receiveSuspended = false; -__IO bool sendZLP = false; +__IO bool receivePended = true; -stimer_t CDC_TimHandle; /** USBD_CDC Private Function Prototypes */ @@ -66,15 +51,15 @@ static int8_t USBD_CDC_Init (void); static int8_t USBD_CDC_DeInit (void); static int8_t USBD_CDC_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length); static int8_t USBD_CDC_Receive (uint8_t* pbuf, uint32_t *Len); -static void CDC_TIM_Config(void); -void CDC_TIM_PeriodElapsedCallback(stimer_t *htim); +static int8_t USBD_CDC_Transferred (void); USBD_CDC_ItfTypeDef USBD_CDC_fops = { USBD_CDC_Init, USBD_CDC_DeInit, USBD_CDC_Control, - USBD_CDC_Receive + USBD_CDC_Receive, + USBD_CDC_Transferred }; USBD_CDC_LineCodingTypeDef linecoding = @@ -95,12 +80,11 @@ USBD_CDC_LineCodingTypeDef linecoding = */ static int8_t USBD_CDC_Init(void) { - /* Configure and start the TIM Base generation */ - CDC_TIM_Config(); - /* Set Application Buffers */ - USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, (uint8_t *)UserTxBuffer, 1); - USBD_CDC_SetRxBuffer(&hUSBD_Device_CDC, (uint8_t *)StackRxBuffer); + CDC_TransmitQueue_Init(&TransmitQueue); + CDC_ReceiveQueue_Init(&ReceiveQueue); + receivePended = true; + USBD_CDC_SetRxBuffer(&hUSBD_Device_CDC, CDC_ReceiveQueue_ReserveBlock(&ReceiveQueue)); return (USBD_OK); } @@ -217,155 +201,87 @@ static int8_t USBD_CDC_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length) * @param Len: Number of data received (in bytes) * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL */ -static int8_t USBD_CDC_Receive (uint8_t* Buf, uint32_t *Len) -{ - uint32_t packetSize = *Len; - - if (packetSize > 0) { - if (UserRxBufPtrIn + packetSize > APP_RX_DATA_SIZE) { - memcpy(((uint8_t *)UserRxBuffer + UserRxBufPtrIn), &Buf[0], - (APP_RX_DATA_SIZE - UserRxBufPtrIn)); - memcpy((uint8_t *)UserRxBuffer, - &Buf[(APP_RX_DATA_SIZE - UserRxBufPtrIn)], - (packetSize - (APP_RX_DATA_SIZE - UserRxBufPtrIn))); - UserRxBufPtrIn = ((UserRxBufPtrIn + packetSize) % APP_RX_DATA_SIZE); - } else { - memcpy(((uint8_t *)UserRxBuffer + UserRxBufPtrIn), Buf, packetSize); - UserRxBufPtrIn = ((UserRxBufPtrIn + packetSize) % APP_RX_DATA_SIZE); - } - } - - if ((UserRxBufPtrOut + APP_RX_DATA_SIZE - UserRxBufPtrIn - 1) % - APP_RX_DATA_SIZE + 1 >= CDC_MAX_PACKET_SIZE) { - USBD_CDC_ReceivePacket( - &hUSBD_Device_CDC); // Initiate next USB packet transfer once a packet - // is received and there is enouch space in the - // buffer - } else { - receiveSuspended = true; - } - return (USBD_OK); +static int8_t USBD_CDC_Receive (uint8_t* Buf, uint32_t *Len) { + UNUSED(Buf); + /* It always contains required amount of free space for writing */ + CDC_ReceiveQueue_CommitBlock(&ReceiveQueue, (uint16_t)(*Len)); + receivePended = false; + /* If enough space in the queue for a full buffer then continue receive */ + CDC_resume_receive(); + return USBD_OK; } -void CDC_flush(void) -{ - uint8_t status; - if(UserTxBufPtrOut != UserTxBufPtrIn) - { - if(UserTxBufPtrOut > UserTxBufPtrIn) /* Roll-back */ - { - memcpy((uint8_t *)&StackTxBuffer[0], - (uint8_t *)&UserTxBuffer[UserTxBufPtrOut], - (APP_TX_DATA_SIZE - UserTxBufPtrOut)); - memcpy((uint8_t *)&StackTxBuffer[APP_TX_DATA_SIZE - UserTxBufPtrOut], - (uint8_t *)&UserTxBuffer[0], UserTxBufPtrIn); - - USBD_CDC_SetTxBuffer( - &hUSBD_Device_CDC, (uint8_t *)&StackTxBuffer[0], - (APP_TX_DATA_SIZE - UserTxBufPtrOut + UserTxBufPtrIn)); - } else { - USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, - (uint8_t *)&UserTxBuffer[UserTxBufPtrOut], - (UserTxBufPtrIn - UserTxBufPtrOut)); - } +static int8_t USBD_CDC_Transferred (void) { + CDC_TransmitQueue_CommitRead(&TransmitQueue); + CDC_continue_transmit(); + return (USBD_OK); +} - do { - if (lineState == 0) { // Device disconnected - status = USBD_OK; - } else { - status = USBD_CDC_TransmitPacket(&hUSBD_Device_CDC); +void CDC_init(void) { + if (!CDC_initialized) { + /* Init Device Library */ + if (USBD_Init(&hUSBD_Device_CDC, &CDC_Desc, 0) == USBD_OK) { + /* Add Supported Class */ + if (USBD_RegisterClass(&hUSBD_Device_CDC, USBD_CDC_CLASS) == USBD_OK) { + /* Add CDC Interface Class */ + if (USBD_CDC_RegisterInterface(&hUSBD_Device_CDC, &USBD_CDC_fops) == USBD_OK) { + /* Start Device Process */ + USBD_Start(&hUSBD_Device_CDC); + CDC_initialized = true; + } } - } while (status == USBD_BUSY); - - if (status == USBD_OK) { - UserTxBufPtrOut = UserTxBufPtrIn; } } } -void CDC_resume_receive(void) { - if (receiveSuspended) { - if ((UserRxBufPtrOut + APP_RX_DATA_SIZE - UserRxBufPtrIn - 1) % - APP_RX_DATA_SIZE + 1 >= CDC_MAX_PACKET_SIZE) { - USBD_CDC_ReceivePacket( - &hUSBD_Device_CDC); // Initiate next USB packet transfer once a packet - // is received and there is enouch space in the - // buffer - receiveSuspended = false; - } +void CDC_deInit(void) { + if (CDC_initialized) { + USBD_Stop(&hUSBD_Device_CDC); + USBD_CDC_DeInit(); + USBD_DeInit(&hUSBD_Device_CDC); + CDC_initialized = false; } } -void CDC_disable_TIM_Interrupt(void) -{ - HAL_NVIC_DisableIRQ(CDC_TIM_IRQn); -} - -void CDC_enable_TIM_Interrupt(void) -{ - HAL_NVIC_EnableIRQ(CDC_TIM_IRQn); -} - -static void CDC_TIM_Config(void) -{ - /* Set TIMx instance */ - CDC_TimHandle.timer = CDC_TIM; - /* Initialize CDC_TIM peripheral as follow: - + Period = 10000 - 1 - + Prescaler = ((SystemCoreClock/2)/10000) - 1 - + ClockDivision = 0 - + Counter direction = Up - */ - TimerHandleInit(&CDC_TimHandle, (uint16_t)((CDC_POLLING_INTERVAL*1000) - 1), ((uint32_t)(getTimerClkFreq(CDC_TIM) / (1000000)) - 1)); - HAL_NVIC_SetPriority(CDC_TIM_IRQn, 6, 0); - - attachIntHandle(&CDC_TimHandle, CDC_TIM_PeriodElapsedCallback); -} - -void CDC_TIM_PeriodElapsedCallback(stimer_t *htim) -{ - UNUSED(htim); - if (UserTxBufPtrOut == UserTxBufPtrIn && - sendZLP == false) // Nothing to do, return immediately - return; - - uint8_t status; - uint16_t packetLength; - - if (UserTxBufPtrOut > UserTxBufPtrIn) { /* Roll-back */ - memcpy((uint8_t *)&StackTxBuffer[0], - (uint8_t *)&UserTxBuffer[UserTxBufPtrOut], - (APP_TX_DATA_SIZE - UserTxBufPtrOut)); - memcpy((uint8_t *)&StackTxBuffer[APP_TX_DATA_SIZE - UserTxBufPtrOut], - (uint8_t *)&UserTxBuffer[0], UserTxBufPtrIn); - - packetLength = (APP_TX_DATA_SIZE - UserTxBufPtrOut + UserTxBufPtrIn); - - USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, (uint8_t *)&StackTxBuffer[0], - packetLength); - } else if (UserTxBufPtrOut != UserTxBufPtrIn) { - packetLength = (UserTxBufPtrIn - UserTxBufPtrOut); - - USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, - (uint8_t *)&UserTxBuffer[UserTxBufPtrOut], - packetLength); - } else { - packetLength = 0; - - USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, NULL, 0); // Send Zero Length Packet - } - - if (lineState == 0) { // Device disconnected - status = USBD_OK; - } else { - status = USBD_CDC_TransmitPacket(&hUSBD_Device_CDC); +void CDC_continue_transmit(void) { + uint16_t size; + uint8_t *buffer; + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *) hUSBD_Device_CDC.pClassData; + /* + * TS: This method can be called both in the main thread + * (via USBSerial::write) and in the IRQ stream (via USBD_CDC_Transferred), + * BUT the main thread cannot pass this condition while waiting for a IRQ! + * This is not possible because TxState is not zero while waiting for data + * transfer ending! The IRQ thread is uninterrupted, since its priority + * is higher than that of the main thread. So this method is thread safe. + */ + if (hcdc->TxState == 0U) { + buffer = CDC_TransmitQueue_ReadBlock(&TransmitQueue, &size); + if (size > 0) { + USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, buffer, size); + /* + * size never exceed PMA buffer and USBD_CDC_TransmitPacket make full + * copy of block in PMA, so no need to worry about buffer damage + */ + USBD_CDC_TransmitPacket(&hUSBD_Device_CDC); + } } +} - if (status == USBD_OK) { - UserTxBufPtrOut = UserTxBufPtrIn; - - sendZLP = packetLength % CDC_MAX_PACKET_SIZE == 0; +void CDC_resume_receive(void) { + /* + * TS: main and IRQ threads can't pass it at same time, because + * IRQ may occur only if receivePended is true. So it is thread-safe! + */ + if (!receivePended) { + uint8_t* block = CDC_ReceiveQueue_ReserveBlock(&ReceiveQueue); + if (block != NULL) { + receivePended = true; + /* Set new buffer */ + USBD_CDC_SetRxBuffer(&hUSBD_Device_CDC, block); + USBD_CDC_ReceivePacket(&hUSBD_Device_CDC); + } } } diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h index 9956d42e97..4dfcd6601b 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h @@ -30,29 +30,7 @@ /* Includes ------------------------------------------------------------------*/ #include "usbd_cdc.h" -#include "timer.h" - -#ifndef APP_RX_DATA_SIZE -#define APP_RX_DATA_SIZE 2048 -#endif -#ifndef APP_TX_DATA_SIZE -#define APP_TX_DATA_SIZE 2048 -#endif - -#ifndef CDC_TIM -#ifdef TIM6 -#define CDC_TIM TIM6 -#else -#define CDC_TIM TIM4 -#endif -#endif -#ifndef CDC_TIM_IRQn -#ifdef TIM6 -#define CDC_TIM_IRQn TIM6_IRQn -#else -#define CDC_TIM_IRQn TIM4_IRQn -#endif -#endif +#include "cdc_queue.h" /* Periodically, the state of the buffer "UserTxBuffer" is checked. The period depends on CDC_POLLING_INTERVAL */ @@ -62,13 +40,16 @@ /* Exported constants --------------------------------------------------------*/ extern USBD_CDC_ItfTypeDef USBD_CDC_fops; +extern CDC_TransmitQueue_TypeDef TransmitQueue; +extern CDC_ReceiveQueue_TypeDef ReceiveQueue; + /* Exported macro ------------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */ -void CDC_disable_TIM_Interrupt(void); -void CDC_enable_TIM_Interrupt(void); -void CDC_flush(void); +void CDC_continue_transmit(void); void CDC_resume_receive(void); +void CDC_init(void); +void CDC_deInit(void); #ifdef __cplusplus } diff --git a/cores/arduino/stm32/usbd_interface.c b/cores/arduino/stm32/usb/hid/usbd_hid_composite_if.c similarity index 72% rename from cores/arduino/stm32/usbd_interface.c rename to cores/arduino/stm32/usb/hid/usbd_hid_composite_if.c index 57ae34b4f9..a87317325b 100644 --- a/cores/arduino/stm32/usbd_interface.c +++ b/cores/arduino/stm32/usb/hid/usbd_hid_composite_if.c @@ -1,7 +1,7 @@ /** ****************************************************************************** - * @file usbd_interface.c - * @brief Provide the USB device interface + * @file usbd_hid_composite_if.c + * @brief Provide the USB HID composite interface * ****************************************************************************** * @attention @@ -33,36 +33,26 @@ ****************************************************************************** */ #ifdef USBCON -#include "usbd_desc.h" -#include "usbd_interface.h" #ifdef USBD_USE_HID_COMPOSITE + +#include "usbd_desc.h" +#include "usbd_hid_composite_if.h" #include "usbd_hid_composite.h" -#endif -#ifdef USBD_USE_CDC -#include "usbd_cdc_if.h" -#endif #ifdef __cplusplus extern "C" { #endif -/* USB Device Core handle declaration */ -#ifdef USBD_USE_HID_COMPOSITE +/* USB Device Core HID composite handle declaration */ USBD_HandleTypeDef hUSBD_Device_HID; -#endif /* USBD_USE_HID_COMPOSITE*/ -#ifdef USBD_USE_CDC -USBD_HandleTypeDef hUSBD_Device_CDC; -#endif /* USBD_USE_CDC */ /** - * @brief initialize USB devices + * @brief Initialize USB devices * @param none * @retval none */ -__attribute__((weak)) -void usbd_interface_init(void) +void HID_Composite_Init(void) { -#ifdef USBD_USE_HID_COMPOSITE /* Init Device Library */ USBD_Init(&hUSBD_Device_HID, &HID_Desc, 0); @@ -71,32 +61,29 @@ void usbd_interface_init(void) /* Start Device Process */ USBD_Start(&hUSBD_Device_HID); -#endif /* USBD_USE_HID_COMPOSITE */ -#ifdef USBD_USE_CDC - /* Init Device Library */ - if (USBD_Init(&hUSBD_Device_CDC, &CDC_Desc, 0) == USBD_OK) { +} - /* Add Supported Class */ - if (USBD_RegisterClass(&hUSBD_Device_CDC, USBD_CDC_CLASS) == USBD_OK) { +/** + * @brief DeInitialize USB devices + * @param none + * @retval none + */ +void HID_Composite_DeInit(void) +{ + /* Stop Device Process */ + USBD_Stop(&hUSBD_Device_HID); - /* Add CDC Interface Class */ - if (USBD_CDC_RegisterInterface(&hUSBD_Device_CDC, &USBD_CDC_fops) == USBD_OK) { - /* Start Device Process */ - USBD_Start(&hUSBD_Device_CDC); - } - } - } -#endif /* USBD_USE_CDC */ + /* DeInit Device Library */ + USBD_DeInit(&hUSBD_Device_HID); } -#ifdef USBD_USE_HID_COMPOSITE /** * @brief Send HID mouse Report * @param report pointer to report * @param len report lenght * @retval none */ -void usbd_interface_mouse_sendReport(uint8_t *report, uint16_t len) +void HID_Composite_mouse_sendReport(uint8_t *report, uint16_t len) { USBD_HID_MOUSE_SendReport(&hUSBD_Device_HID, report, len); } @@ -107,14 +94,14 @@ void usbd_interface_mouse_sendReport(uint8_t *report, uint16_t len) * @param len report lenght * @retval none */ -void usbd_interface_keyboard_sendReport(uint8_t *report, uint16_t len) +void HID_Composite_keyboard_sendReport(uint8_t *report, uint16_t len) { USBD_HID_KEYBOARD_SendReport(&hUSBD_Device_HID, report, len); } -#endif /* USBD_USE_HID_COMPOSITE */ #ifdef __cplusplus } #endif +#endif /* USBD_USE_HID_COMPOSITE */ #endif /* USBCON */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usbd_interface.h b/cores/arduino/stm32/usb/hid/usbd_hid_composite_if.h similarity index 77% rename from cores/arduino/stm32/usbd_interface.h rename to cores/arduino/stm32/usb/hid/usbd_hid_composite_if.h index f32f184938..5c61b12bc5 100644 --- a/cores/arduino/stm32/usbd_interface.h +++ b/cores/arduino/stm32/usb/hid/usbd_hid_composite_if.h @@ -1,7 +1,7 @@ /** ****************************************************************************** - * @file usbd_interface.h - * @brief Header for USB device interface + * @file usbd_hid_composite_if.h + * @brief Header for USB HID composite interface ****************************************************************************** * @attention * @@ -33,32 +33,29 @@ */ /* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USBD_INTERFACE_H -#define __USBD_INTERFACE_H +#ifndef __USBD_HID_COMPOSITE_IF_H +#define __USBD_HID_COMPOSITE_IF_H #ifdef USBCON +#ifdef USBD_USE_HID_COMPOSITE /* Includes ------------------------------------------------------------------*/ #ifdef __cplusplus extern "C" { #endif -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported variables --------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */ -void usbd_interface_init(void); +void HID_Composite_Init(void); +void HID_Composite_DeInit(void); -#ifdef USBD_USE_HID_COMPOSITE -void usbd_interface_mouse_sendReport(uint8_t *report, uint16_t len); -void usbd_interface_keyboard_sendReport(uint8_t *report, uint16_t len); -#endif +void HID_Composite_mouse_sendReport(uint8_t *report, uint16_t len); +void HID_Composite_keyboard_sendReport(uint8_t *report, uint16_t len); #ifdef __cplusplus } #endif +#endif /* USBD_USE_HID_COMPOSITE */ #endif /* USBCON */ -#endif /* __USBD_INTERFACE_H */ +#endif /* __USBD_HID_COMPOSITE_IF_H */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/usbd_conf.c b/cores/arduino/stm32/usb/usbd_conf.c index e6f8379a94..2f2c7063f0 100644 --- a/cores/arduino/stm32/usb/usbd_conf.c +++ b/cores/arduino/stm32/usb/usbd_conf.c @@ -27,6 +27,12 @@ #else /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ +/* Size in words, byte size divided by 2 */ +#define PMA_EP0_OUT_ADDR (8 * 4) +#define PMA_EP0_IN_ADDR (PMA_EP0_OUT_ADDR + USB_MAX_EP0_SIZE / 2) +#define PMA_CDC_OUT_ADDR (PMA_EP0_IN_ADDR + USB_MAX_EP0_SIZE / 2) +#define PMA_CDC_IN_ADDR (PMA_CDC_OUT_ADDR + USB_FS_MAX_PACKET_SIZE / 2) +#define PMA_CDC_CMD_ADDR (PMA_CDC_IN_ADDR + USB_FS_MAX_PACKET_SIZE / 2) /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ PCD_HandleTypeDef g_hpcd; @@ -483,10 +489,11 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) HAL_PCDEx_SetTxFiFo(&g_hpcd, 1, 0x40); HAL_PCDEx_SetTxFiFo(&g_hpcd, 2, 0x40); #else - HAL_PCDEx_PMAConfig(&g_hpcd, 0x00 , PCD_SNG_BUF, 0x18); - HAL_PCDEx_PMAConfig(&g_hpcd, 0x80 , PCD_SNG_BUF, 0x58); - HAL_PCDEx_PMAConfig(&g_hpcd, 0x81 , PCD_SNG_BUF, 0x100); - HAL_PCDEx_PMAConfig(&g_hpcd, 0x82 , PCD_SNG_BUF, 0x100); + HAL_PCDEx_PMAConfig(&g_hpcd, 0x00, PCD_SNG_BUF, PMA_EP0_OUT_ADDR); + HAL_PCDEx_PMAConfig(&g_hpcd, 0x80, PCD_SNG_BUF, PMA_EP0_IN_ADDR); + HAL_PCDEx_PMAConfig(&g_hpcd, 0x01, PCD_SNG_BUF, PMA_CDC_OUT_ADDR); + HAL_PCDEx_PMAConfig(&g_hpcd, 0x81, PCD_SNG_BUF, PMA_CDC_IN_ADDR); + HAL_PCDEx_PMAConfig(&g_hpcd, 0x82, PCD_SNG_BUF, PMA_CDC_CMD_ADDR); #endif #endif /* USE_USB_HS */ return USBD_OK; diff --git a/cores/arduino/stm32/usb/usbd_if.c b/cores/arduino/stm32/usb/usbd_if.c index 74397f206b..a3f110a4af 100644 --- a/cores/arduino/stm32/usb/usbd_if.c +++ b/cores/arduino/stm32/usb/usbd_if.c @@ -8,6 +8,8 @@ #ifdef USBCON #include "usbd_if.h" +#include "usbd_cdc_if.h" + /** * @brief Force to re-enumerate USB * @param None @@ -38,4 +40,10 @@ void USBD_reenumerate(void) #endif /* USBD_REENUM_DISABLED */ } +#ifdef USBD_USE_CDC +void USBD_CDC_init(void) +{ + CDC_init(); +} +#endif /* USBD_USE_CDC */ #endif /* USBCON */ diff --git a/cores/arduino/stm32/usb/usbd_if.h b/cores/arduino/stm32/usb/usbd_if.h index befa37a9a6..13c6e6e892 100644 --- a/cores/arduino/stm32/usb/usbd_if.h +++ b/cores/arduino/stm32/usb/usbd_if.h @@ -24,7 +24,9 @@ #endif void USBD_reenumerate(void); - +#ifdef USBD_USE_CDC +void USBD_CDC_init(void); +#endif #ifdef __cplusplus } #endif diff --git a/libraries/Keyboard/library.properties b/libraries/Keyboard/library.properties index e220811d16..64a98c432a 100644 --- a/libraries/Keyboard/library.properties +++ b/libraries/Keyboard/library.properties @@ -1,5 +1,5 @@ name=Keyboard -version=1.0.1 +version=1.1.0 author=Arduino maintainer=Arduino sentence=Allows an Arduino/Genuino board with USB capabilites to act as a Keyboard. diff --git a/libraries/Keyboard/src/Keyboard.cpp b/libraries/Keyboard/src/Keyboard.cpp index a8d8ca6a41..dab08a39c3 100644 --- a/libraries/Keyboard/src/Keyboard.cpp +++ b/libraries/Keyboard/src/Keyboard.cpp @@ -22,6 +22,7 @@ #include "Keyboard.h" #if defined(USBCON) +#include "usbd_hid_composite_if.h" //================================================================================ //================================================================================ @@ -33,10 +34,12 @@ Keyboard_::Keyboard_(void) void Keyboard_::begin(void) { + HID_Composite_Init(); } void Keyboard_::end(void) { + HID_Composite_DeInit(); } void Keyboard_::sendReport(KeyReport* keys) @@ -44,7 +47,7 @@ void Keyboard_::sendReport(KeyReport* keys) uint8_t buf[8] = {keys->modifiers, keys->reserved, keys->keys[0], keys->keys[1], keys->keys[2], keys->keys[3], keys->keys[4], keys->keys[5]}; - usbd_interface_keyboard_sendReport(buf, 8); + HID_Composite_keyboard_sendReport(buf, 8); //delay required to prevent persistent key when call print delay(20); diff --git a/libraries/Mouse/library.properties b/libraries/Mouse/library.properties index c4a095caa5..8c48029eb0 100644 --- a/libraries/Mouse/library.properties +++ b/libraries/Mouse/library.properties @@ -1,5 +1,5 @@ name=Mouse -version=1.0.0 +version=1.1.0 author=Arduino maintainer=Arduino sentence=Allows an Arduino board with USB capabilites to act as a Mouse. For Leonardo/Micro only diff --git a/libraries/Mouse/src/Mouse.cpp b/libraries/Mouse/src/Mouse.cpp index a6b4cdd633..a6529b053e 100644 --- a/libraries/Mouse/src/Mouse.cpp +++ b/libraries/Mouse/src/Mouse.cpp @@ -22,6 +22,7 @@ #include "Mouse.h" #if defined(USBCON) +#include "usbd_hid_composite_if.h" //================================================================================ //================================================================================ @@ -33,10 +34,12 @@ Mouse_::Mouse_(void) : _buttons(0) void Mouse_::begin(void) { + HID_Composite_Init(); } void Mouse_::end(void) { + HID_Composite_DeInit(); } void Mouse_::click(uint8_t b) @@ -55,7 +58,7 @@ void Mouse_::move(signed char x, signed char y, signed char wheel) m[2] = y; m[3] = wheel; - usbd_interface_mouse_sendReport(m, 4); + HID_Composite_mouse_sendReport(m, 4); } void Mouse_::buttons(uint8_t b)