Skip to content

Commit 09533e5

Browse files
authored
Merge pull request #419 from fpistm/USB_enhancement
USB enhancement
2 parents cf942e0 + 55b8f81 commit 09533e5

21 files changed

+577
-345
lines changed

cores/arduino/Stream.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,12 @@ class Stream : public Print
9494
float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR);
9595
// float version of parseInt
9696

97-
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
97+
virtual size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
9898
size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
9999
// terminates if length characters have been read or timeout (see setTimeout)
100100
// returns the number of characters placed in the buffer (0 means no valid data found)
101101

102-
size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
102+
virtual size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
103103
size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
104104
// terminates if length characters have been read, timeout, or if the terminator character detected
105105
// returns the number of characters placed in the buffer (0 means no valid data found)

cores/arduino/USBSerial.cpp

+79-82
Original file line numberDiff line numberDiff line change
@@ -24,126 +24,123 @@
2424
#include "usbd_desc.h"
2525
#include "wiring.h"
2626

27-
#define USB_TIMEOUT 50
28-
/* USB Device Core handle declaration */
29-
extern USBD_HandleTypeDef hUSBD_Device_CDC;
30-
extern __IO uint32_t device_connection_status;
3127
extern __IO uint32_t lineState;
32-
extern __IO uint8_t UserTxBuffer[APP_TX_DATA_SIZE];
33-
extern __IO uint8_t UserRxBuffer[APP_RX_DATA_SIZE];
34-
extern __IO uint32_t UserTxBufPtrIn;
35-
extern __IO uint32_t UserTxBufPtrOut;
36-
extern __IO uint32_t UserRxBufPtrIn;
37-
extern __IO uint32_t UserRxBufPtrOut;
3828

3929
USBSerial SerialUSB;
4030
void serialEventUSB() __attribute__((weak));
4131

32+
void USBSerial::begin(void) {
33+
CDC_init();
34+
}
35+
4236
void USBSerial::begin(uint32_t /* baud_count */) {
4337
// uart config is ignored in USB-CDC
38+
begin();
4439
}
4540

4641
void USBSerial::begin(uint32_t /* baud_count */, uint8_t /* config */) {
4742
// uart config is ignored in USB-CDC
43+
begin();
4844
}
4945

50-
void USBSerial::end(void) {
51-
52-
USBD_LL_DeInit(&hUSBD_Device_CDC);
46+
void USBSerial::end() {
47+
CDC_deInit();
5348
}
5449

55-
int USBSerial::availableForWrite(void)
50+
int USBSerial::availableForWrite()
5651
{
57-
int ret_val;
58-
59-
/* UserTxBufPtrOut can be modified by TIM ISR, so in order to be sure that the */
60-
/* value that we read is correct, we need to disable TIM Interrupt. */
61-
CDC_disable_TIM_Interrupt();
62-
63-
if (UserTxBufPtrIn >= UserTxBufPtrOut) {
64-
ret_val = (APP_TX_DATA_SIZE - 1 - UserTxBufPtrIn + UserTxBufPtrOut);
65-
} else {
66-
ret_val = (UserTxBufPtrOut - UserTxBufPtrIn - 1);
67-
}
68-
69-
CDC_enable_TIM_Interrupt();
70-
71-
return ret_val;
52+
// Just transmit queue size, available for write
53+
return static_cast<int>(CDC_TransmitQueue_WriteSize(&TransmitQueue));
7254
}
7355

7456
size_t USBSerial::write(uint8_t ch) {
75-
76-
/* UserTxBufPtrOut can be modified by TIM ISR, so in order to be sure that the */
77-
/* value that we read is correct, we need to disable TIM Interrupt. */
78-
CDC_disable_TIM_Interrupt();
79-
80-
if (((UserTxBufPtrIn + 1) % APP_TX_DATA_SIZE) == UserTxBufPtrOut) {
81-
// Buffer full!!! Force a flush to not loose data and go on
82-
CDC_flush();
83-
}
84-
UserTxBuffer[UserTxBufPtrIn] = ch;
85-
UserTxBufPtrIn = ((UserTxBufPtrIn + 1) % APP_TX_DATA_SIZE);
86-
87-
CDC_enable_TIM_Interrupt();
88-
89-
return 1;
57+
// Just write single-byte buffer.
58+
return write(&ch, 1);
9059
}
9160

9261
size_t USBSerial::write(const uint8_t *buffer, size_t size){
93-
size_t i = 0;
94-
for (i=0; i < size; i++) {
95-
if (write(buffer[i]) != 1) {
96-
break;
97-
}
62+
size_t rest = size;
63+
while(rest > 0) {
64+
// Determine buffer size available for write
65+
auto portion = (size_t)CDC_TransmitQueue_WriteSize(&TransmitQueue);
66+
// Truncate it to content size (if rest is greater)
67+
if (rest < portion) {
68+
portion = rest;
69+
}
70+
if (portion > 0) {
71+
// Only if some space in the buffer exists.
72+
// TS: Only main thread calls write and writeSize methods,
73+
// it's thread-safe since IRQ does not affects
74+
// TransmitQueue write position
75+
CDC_TransmitQueue_Enqueue(&TransmitQueue, buffer, portion);
76+
rest -= portion;
77+
buffer += portion;
78+
// After storing data, start transmitting process
79+
CDC_continue_transmit();
80+
}
9881
}
99-
return i;
82+
return size;
10083
}
10184

10285
int USBSerial::available(void) {
103-
return ((APP_RX_DATA_SIZE + (UserRxBufPtrIn - UserRxBufPtrOut)) % APP_RX_DATA_SIZE);
86+
// Just ReceiveQueue size, available for reading
87+
return static_cast<int>(CDC_ReceiveQueue_ReadSize(&ReceiveQueue));
10488
}
10589

10690
int USBSerial::read(void) {
107-
if (UserRxBufPtrOut == UserRxBufPtrIn) {
108-
return -1;
109-
} else {
110-
unsigned char c = UserRxBuffer[UserRxBufPtrOut];
111-
UserRxBufPtrOut = ((UserRxBufPtrOut + 1) % APP_RX_DATA_SIZE);
91+
// Dequeue only one char from queue
92+
// TS: it safe, because only main thread affects ReceiveQueue->read pos
93+
auto ch = CDC_ReceiveQueue_Dequeue(&ReceiveQueue);
94+
// Resume receive process, if possible
95+
CDC_resume_receive();
96+
return ch;
97+
}
98+
99+
size_t USBSerial::readBytes(char *buffer, size_t length) {
100+
uint16_t read;
101+
auto rest = static_cast<uint16_t>(length);
102+
_startMillis = millis();
103+
do {
104+
read = CDC_ReceiveQueue_Read(&ReceiveQueue, reinterpret_cast<uint8_t*>(buffer), rest);
112105
CDC_resume_receive();
113-
return c;
114-
}
106+
rest -= read;
107+
buffer += read;
108+
if (rest == 0) return length;
109+
} while(millis() - _startMillis < _timeout);
110+
return length - rest;
111+
}
112+
113+
size_t USBSerial::readBytesUntil(char terminator, char *buffer, size_t length) {
114+
uint16_t read;
115+
auto rest = static_cast<uint16_t>(length);
116+
_startMillis = millis();
117+
do {
118+
bool found = CDC_ReceiveQueue_ReadUntil(&ReceiveQueue, static_cast<uint8_t>(terminator),
119+
reinterpret_cast<uint8_t*>(buffer), rest, &read);
120+
CDC_resume_receive();
121+
rest -= read;
122+
buffer += read;
123+
if (found) {
124+
return length - rest;
125+
}
126+
if (rest == 0) {
127+
return length;
128+
}
129+
} while(millis() - _startMillis < _timeout);
130+
return length - rest;
115131
}
116132

117133
int USBSerial::peek(void)
118134
{
119-
if (UserRxBufPtrOut == UserRxBufPtrIn) {
120-
return -1;
121-
} else {
122-
unsigned char c = UserRxBuffer[UserRxBufPtrOut];
123-
return c;
124-
}
135+
// Peek one symbol, it can't change receive avaiablity
136+
return CDC_ReceiveQueue_Peek(&ReceiveQueue);
125137
}
126138

127139
void USBSerial::flush(void)
128140
{
129-
/* UserTxBufPtrOut can be modified by TIM ISR, so in order to be sure that the */
130-
/* value that we read is correct, we need to disable TIM Interrupt. */
131-
CDC_disable_TIM_Interrupt();
132-
CDC_flush();
133-
CDC_enable_TIM_Interrupt();
134-
}
135-
136-
uint8_t USBSerial::pending(void) {
137-
return 0;
138-
}
139-
140-
uint8_t USBSerial::isConnected(void) {
141-
142-
if (device_connection_status == 1) {
143-
return 1;
144-
} else {
145-
return 0;
146-
}
141+
// Wait for TransmitQueue read size becomes zero
142+
// TS: safe, because it not be stopped while receive 0
143+
while(CDC_TransmitQueue_ReadSize(&TransmitQueue) > 0) {}
147144
}
148145

149146
uint32_t USBSerial::baud() {

cores/arduino/USBSerial.h

+3-5
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@
2727
// Serial over CDC
2828
class USBSerial : public Stream {
2929
public:
30-
USBSerial(void) {};
31-
30+
void begin(void);
3231
void begin(uint32_t);
3332
void begin(uint32_t, uint8_t);
3433
void end(void);
@@ -37,6 +36,8 @@ class USBSerial : public Stream {
3736
virtual int availableForWrite(void);
3837
virtual int peek(void);
3938
virtual int read(void);
39+
virtual size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
40+
virtual size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
4041
virtual void flush(void);
4142
virtual size_t write(uint8_t);
4243
virtual size_t write(const uint8_t *buffer, size_t size);
@@ -64,9 +65,6 @@ class USBSerial : public Stream {
6465
MARK_PARITY = 3,
6566
SPACE_PARITY = 4,
6667
};
67-
68-
uint8_t isConnected();
69-
uint8_t pending();
7068
};
7169

7270
extern USBSerial SerialUSB;

cores/arduino/board.h

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ extern "C"{
2020
#include "timer.h"
2121
#include "twi.h"
2222
#include "uart.h"
23-
#include "usbd_interface.h"
2423

2524
void init( void ) ;
2625
#ifdef __cplusplus

cores/arduino/main.cpp

-4
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,6 @@ int main( void )
5454
{
5555
initVariant();
5656

57-
#if defined(USBCON)
58-
usbd_interface_init();
59-
#endif
60-
6157
setup();
6258

6359
for (;;)

cores/arduino/stm32/hw_config.c

+5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
*/
3838
#include "stm32_def.h"
3939
#include "hw_config.h"
40+
#include "usbd_if.h"
4041

4142
#ifdef __cplusplus
4243
extern "C" {
@@ -54,6 +55,10 @@ void hw_config_init(void)
5455

5556
// Configure the system clock
5657
SystemClock_Config();
58+
59+
#if defined (USBCON) && defined(USBD_USE_CDC)
60+
USBD_CDC_init();
61+
#endif
5762
}
5863
#ifdef __cplusplus
5964
}

0 commit comments

Comments
 (0)