1
1
/*
2
- * Copyright (c) 2016 Thomas Roell. All rights reserved.
2
+ * Copyright (c) 2016-2017 Thomas Roell. All rights reserved.
3
3
*
4
4
* Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
* of this software and associated documentation files (the "Software"), to
32
32
33
33
#if defined(USBCON)
34
34
35
- /* STM32L4x5/STM32L4x6 have USB_OTG_FS with a multi-packet FIFO. However
36
- * to avoid sending ZLP packets, the CDC_TX_PACKET_SIZE is one byte
37
- * less than the maximum FIFO size in terms of 64 byte packets.
38
- */
39
- #define CDC_TX_PACKET_SIZE (((USBD_CDC_FIFO_SIZE + 63 ) & ~63 ) -1 )
35
+ #define CDC_TX_PACKET_SIZE 128
36
+ #define CDC_TX_PACKET_SMALL 64
40
37
41
38
stm32l4_usbd_cdc_t stm32l4_usbd_cdc;
42
39
40
+ extern int (*stm32l4_stdio_put)(char , FILE*);
41
+
42
+ static int serialusb_stdio_put (char data, FILE *fp)
43
+ {
44
+ return Serial.write (&data, 1 );
45
+ }
46
+
43
47
CDC::CDC (struct _stm32l4_usbd_cdc_t *usbd_cdc, bool serialEvent)
44
48
{
45
49
_usbd_cdc = usbd_cdc;
46
50
47
- _rx_read = 0 ;
48
- _rx_write = 0 ;
49
- _rx_count = 0 ;
50
51
_tx_read = 0 ;
51
52
_tx_write = 0 ;
52
53
_tx_count = 0 ;
53
54
_tx_size = 0 ;
54
55
55
56
_tx_data2 = NULL ;
56
57
_tx_size2 = 0 ;
58
+
59
+ _tx_timeout = 0 ;
57
60
58
61
_completionCallback = NULL ;
59
62
_receiveCallback = NULL ;
@@ -75,24 +78,36 @@ void CDC::begin(unsigned long baudrate, uint16_t config)
75
78
/* If USBD_CDC has already been enabled/initialized by STDIO, just add the notify.
76
79
*/
77
80
if (_usbd_cdc->state == USBD_CDC_STATE_INIT) {
78
- stm32l4_usbd_cdc_enable (_usbd_cdc, 0 , CDC::_event_callback, (void *)this , (USBD_CDC_EVENT_RECEIVE | USBD_CDC_EVENT_TRANSMIT));
81
+ stm32l4_usbd_cdc_enable (_usbd_cdc, &_rx_data[0 ], sizeof (_rx_data), 0 , CDC::_event_callback, (void *)this , (USBD_CDC_EVENT_RECEIVE | USBD_CDC_EVENT_TRANSMIT));
82
+
83
+ if (stm32l4_stdio_put == NULL ) {
84
+ stm32l4_stdio_put = serialusb_stdio_put;
85
+ }
79
86
} else {
80
87
flush ();
81
88
82
89
stm32l4_usbd_cdc_notify (_usbd_cdc, CDC::_event_callback, (void *)this , (USBD_CDC_EVENT_RECEIVE | USBD_CDC_EVENT_TRANSMIT));
83
90
}
91
+
92
+ USBD_SOFCallback (CDC::_sof_callback, (void *)this );
84
93
}
85
94
86
95
void CDC::end ()
87
96
{
88
97
flush ();
89
98
99
+ USBD_SOFCallback (NULL , NULL );
100
+
101
+ if (stm32l4_stdio_put == serialusb_stdio_put) {
102
+ stm32l4_stdio_put = NULL ;
103
+ }
104
+
90
105
stm32l4_usbd_cdc_disable (_usbd_cdc);
91
106
}
92
107
93
108
int CDC::available ()
94
109
{
95
- return _rx_count ;
110
+ return stm32l4_usbd_cdc_count (_usbd_cdc) ;
96
111
}
97
112
98
113
int CDC::availableForWrite (void )
@@ -110,67 +125,25 @@ int CDC::availableForWrite(void)
110
125
111
126
int CDC::peek ()
112
127
{
113
- if (_rx_count == 0 ) {
114
- return -1 ;
115
- }
116
-
117
- return _rx_data[_rx_read];
128
+ return stm32l4_usbd_cdc_peek (_usbd_cdc);
118
129
}
119
130
120
131
int CDC::read ()
121
132
{
122
- unsigned int rx_read;
123
133
uint8_t data;
124
134
125
- if (_rx_count == 0 ) {
135
+ if (! stm32l4_usbd_cdc_count (_usbd_cdc) ) {
126
136
return -1 ;
127
137
}
128
138
129
- rx_read = _rx_read ;
139
+ stm32l4_usbd_cdc_receive (_usbd_cdc, &data, 1 ) ;
130
140
131
- data = _rx_data[rx_read];
132
-
133
- _rx_read = (unsigned int )(rx_read + 1 ) & (CDC_RX_BUFFER_SIZE -1 );
134
-
135
- armv7m_atomic_sub (&_rx_count, 1 );
136
-
137
141
return data;
138
142
}
139
143
140
144
size_t CDC::read (uint8_t *buffer, size_t size)
141
145
{
142
- unsigned int rx_read, rx_count;
143
- size_t count;
144
-
145
- count = 0 ;
146
-
147
- while (count < size) {
148
-
149
- rx_count = _rx_count;
150
-
151
- if (rx_count == 0 ) {
152
- break ;
153
- }
154
-
155
- rx_read = _rx_read;
156
-
157
- if (rx_count > (CDC_RX_BUFFER_SIZE - rx_read)) {
158
- rx_count = (CDC_RX_BUFFER_SIZE - rx_read);
159
- }
160
-
161
- if (rx_count > (size - count)) {
162
- rx_count = (size - count);
163
- }
164
-
165
- memcpy (&buffer[count], &_rx_data[rx_read], rx_count);
166
- count += rx_count;
167
-
168
- _rx_read = (rx_read + rx_count) & (CDC_RX_BUFFER_SIZE -1 );
169
-
170
- armv7m_atomic_sub (&_rx_count, rx_count);
171
- }
172
-
173
- return count;
146
+ return stm32l4_usbd_cdc_receive (_usbd_cdc, buffer, size);
174
147
}
175
148
176
149
void CDC::flush ()
@@ -276,7 +249,7 @@ size_t CDC::write(const uint8_t *buffer, size_t size)
276
249
tx_size = _tx_count;
277
250
tx_read = _tx_read;
278
251
279
- if (tx_size) {
252
+ if (tx_size >= CDC_TX_PACKET_SMALL ) {
280
253
if (tx_size > (CDC_TX_BUFFER_SIZE - tx_read)) {
281
254
tx_size = (CDC_TX_BUFFER_SIZE - tx_read);
282
255
}
@@ -350,46 +323,18 @@ void CDC::onReceive(void(*callback)(void))
350
323
351
324
void CDC::EventCallback (uint32_t events)
352
325
{
353
- unsigned int rx_write, rx_count, rx_size, count;
354
326
unsigned int tx_read, tx_size;
355
- bool empty;
356
-
357
- if (events & USBD_CDC_EVENT_RECEIVE) {
358
- empty = (_rx_count == 0 );
359
-
360
- count = 0 ;
361
-
362
- do {
363
- rx_size = 0 ;
364
- rx_count = CDC_RX_BUFFER_SIZE - _rx_count;
365
-
366
- if (rx_count == 0 ) {
367
- break ;
368
- }
369
-
370
- rx_write = _rx_write;
371
-
372
- if (rx_count > (CDC_RX_BUFFER_SIZE - rx_write)) {
373
- rx_count = (CDC_RX_BUFFER_SIZE - rx_write);
374
- }
375
-
376
- rx_size = stm32l4_usbd_cdc_receive (_usbd_cdc, &_rx_data[rx_write], rx_count);
377
-
378
- _rx_write = (rx_write + rx_size) & (CDC_RX_BUFFER_SIZE -1 );
379
-
380
- armv7m_atomic_add (&_rx_count, rx_size);
381
-
382
- count += rx_size;
383
-
384
- } while (rx_size);
385
327
386
- if (empty && count && _receiveCallback) {
328
+ if (events & USBD_CDC_EVENT_RECEIVE) {
329
+ if (_receiveCallback) {
387
330
armv7m_pendsv_enqueue ((armv7m_pendsv_routine_t )_receiveCallback, NULL , 0 );
388
331
}
389
332
}
390
333
391
334
if (events & USBD_CDC_EVENT_TRANSMIT) {
392
335
336
+ _tx_timeout = 0 ;
337
+
393
338
tx_size = _tx_size;
394
339
395
340
if (tx_size != 0 ) {
@@ -437,11 +382,45 @@ void CDC::EventCallback(uint32_t events)
437
382
}
438
383
}
439
384
385
+ void CDC::SOFCallback ()
386
+ {
387
+ unsigned int tx_read, tx_size;
388
+
389
+ if (_tx_count && !_tx_size && !_tx_size2)
390
+ {
391
+ _tx_timeout++;
392
+
393
+ // Small packets get only send after 8ms latency
394
+ if (_tx_timeout >= 8 )
395
+ {
396
+ tx_size = _tx_count;
397
+ tx_read = _tx_read;
398
+
399
+ if (tx_size > (CDC_TX_BUFFER_SIZE - tx_read)) {
400
+ tx_size = (CDC_TX_BUFFER_SIZE - tx_read);
401
+ }
402
+
403
+ if (tx_size > CDC_TX_PACKET_SIZE) {
404
+ tx_size = CDC_TX_PACKET_SIZE;
405
+ }
406
+
407
+ _tx_size = tx_size;
408
+
409
+ stm32l4_usbd_cdc_transmit (_usbd_cdc, &_tx_data[tx_read], tx_size);
410
+ }
411
+ }
412
+ }
413
+
440
414
void CDC::_event_callback (void *context, uint32_t events)
441
415
{
442
416
reinterpret_cast <class CDC *>(context)->EventCallback (events);
443
417
}
444
418
419
+ void CDC::_sof_callback (void *context)
420
+ {
421
+ reinterpret_cast <class CDC *>(context)->SOFCallback ();
422
+ }
423
+
445
424
CDC::operator bool ()
446
425
{
447
426
return stm32l4_usbd_cdc_connected (_usbd_cdc);
0 commit comments