@@ -49,11 +49,13 @@ CDC::CDC(struct _stm32l4_usbd_cdc_t *usbd_cdc, bool serialEvent)
49
49
_rx_count = 0 ;
50
50
_tx_read = 0 ;
51
51
_tx_write = 0 ;
52
- _tx_size = 0 ;
53
52
_tx_count = 0 ;
54
- _tx_total = 0 ;
53
+ _tx_size = 0 ;
54
+
55
+ _tx_data2 = NULL ;
56
+ _tx_size2 = 0 ;
55
57
56
- _transmitCallback = NULL ;
58
+ _completionCallback = NULL ;
57
59
_receiveCallback = NULL ;
58
60
59
61
stm32l4_usbd_cdc_create (usbd_cdc);
@@ -95,8 +97,13 @@ int CDC::available()
95
97
96
98
int CDC::availableForWrite (void )
97
99
{
98
- if (_usbd_cdc->state < USBD_CDC_STATE_READY)
100
+ if (_usbd_cdc->state < USBD_CDC_STATE_READY) {
99
101
return 0 ;
102
+ }
103
+
104
+ if (_tx_size2 != 0 ) {
105
+ return 0 ;
106
+ }
100
107
101
108
return CDC_TX_BUFFER_SIZE - _tx_count;
102
109
}
@@ -164,10 +171,26 @@ size_t CDC::read(uint8_t *buffer, size_t size)
164
171
165
172
void CDC::flush ()
166
173
{
167
- if (__get_IPSR () == 0 ) {
174
+ if (armv7m_core_priority () <= STM32L4_USB_IRQ_PRIORITY) {
175
+ while (_tx_count != 0 ) {
176
+ stm32l4_usbd_cdc_poll (_usbd_cdc);
177
+ }
178
+
179
+ while (_tx_size2 != 0 ) {
180
+ stm32l4_usbd_cdc_poll (_usbd_cdc);
181
+ }
182
+
183
+ while (!stm32l4_usbd_cdc_done (_usbd_cdc)) {
184
+ stm32l4_usbd_cdc_poll (_usbd_cdc);
185
+ }
186
+ } else {
168
187
while (_tx_count != 0 ) {
169
188
armv7m_core_yield ();
170
189
}
190
+
191
+ while (_tx_size2 != 0 ) {
192
+ armv7m_core_yield ();
193
+ }
171
194
172
195
while (!stm32l4_usbd_cdc_done (_usbd_cdc)) {
173
196
armv7m_core_yield ();
@@ -185,29 +208,36 @@ size_t CDC::write(const uint8_t *buffer, size_t size)
185
208
unsigned int tx_read, tx_write, tx_count, tx_size;
186
209
size_t count;
187
210
188
- if (( _usbd_cdc->state < USBD_CDC_STATE_READY) || !(stm32l4_usbd_cdc_info. lineState & 2 ) ) {
211
+ if (_usbd_cdc->state < USBD_CDC_STATE_READY) {
189
212
return 0 ;
190
213
}
191
214
192
- // Clamp " size" if called from an ISR to avoid blocking
193
- if (!_blocking || ( __get_IPSR () != 0 )) {
194
- tx_count = _tx_count;
215
+ if ( size == 0 ) {
216
+ return 0 ;
217
+ }
195
218
196
- if (size > (CDC_TX_BUFFER_SIZE - tx_count)) {
197
- size = (CDC_TX_BUFFER_SIZE - tx_count);
219
+ // If there is an async write pending, wait till it's done
220
+ if (_tx_size2 != 0 ) {
221
+ if (!_blocking || (__get_IPSR () != 0 )) {
222
+ return 0 ;
223
+ }
224
+
225
+ while (_tx_size2 != 0 ) {
226
+ armv7m_core_yield ();
198
227
}
199
228
}
200
-
201
- armv7m_atomic_add (&_tx_total, size);
202
-
229
+
203
230
count = 0 ;
204
231
205
232
while (count < size) {
206
233
207
234
tx_count = CDC_TX_BUFFER_SIZE - _tx_count;
208
235
209
236
if (tx_count == 0 ) {
210
- // Here we cannot block from within an ISR because "size" got limited clamped
237
+
238
+ if (!_blocking || (__get_IPSR () != 0 )) {
239
+ break ;
240
+ }
211
241
212
242
if (stm32l4_usbd_cdc_done (_usbd_cdc)) {
213
243
tx_size = _tx_count;
@@ -251,38 +281,53 @@ size_t CDC::write(const uint8_t *buffer, size_t size)
251
281
armv7m_atomic_add (&_tx_count, tx_count);
252
282
}
253
283
254
- if (__get_IPSR () == 0 ) {
255
- if (stm32l4_usbd_cdc_done (_usbd_cdc)) {
256
- tx_size = _tx_count;
257
- tx_read = _tx_read;
258
-
259
- if (tx_size) {
260
- if (tx_size > (CDC_TX_BUFFER_SIZE - tx_read)) {
261
- tx_size = (CDC_TX_BUFFER_SIZE - tx_read);
262
- }
263
-
264
- if (tx_size > CDC_TX_PACKET_SIZE) {
265
- tx_size = CDC_TX_PACKET_SIZE;
266
- }
267
-
268
- _tx_size = tx_size;
269
-
270
- stm32l4_usbd_cdc_transmit (_usbd_cdc, &_tx_data[tx_read], tx_size);
284
+ if (stm32l4_usbd_cdc_done (_usbd_cdc)) {
285
+ tx_size = _tx_count;
286
+ tx_read = _tx_read;
287
+
288
+ if (tx_size) {
289
+ if (tx_size > (CDC_TX_BUFFER_SIZE - tx_read)) {
290
+ tx_size = (CDC_TX_BUFFER_SIZE - tx_read);
291
+ }
292
+
293
+ if (tx_size > CDC_TX_PACKET_SIZE) {
294
+ tx_size = CDC_TX_PACKET_SIZE;
271
295
}
296
+
297
+ _tx_size = tx_size;
298
+
299
+ stm32l4_usbd_cdc_transmit (_usbd_cdc, &_tx_data[tx_read], tx_size);
272
300
}
273
301
}
274
302
275
303
return count;
276
304
}
277
305
278
- void CDC::onTransmit ( void (*callback)(void ))
306
+ bool CDC::write ( const uint8_t *buffer, size_t size, void (*callback)(void ))
279
307
{
280
- _transmitCallback = callback;
281
- }
308
+ if (_usbd_cdc->state < USBD_CDC_STATE_READY) {
309
+ return false ;
310
+ }
282
311
283
- void CDC::onReceive (void (*callback)(int ))
284
- {
285
- _receiveCallback = callback;
312
+ if (size == 0 ) {
313
+ return false ;
314
+ }
315
+
316
+ if (_tx_size2 != 0 ) {
317
+ return false ;
318
+ }
319
+
320
+ _completionCallback = callback;
321
+ _tx_data2 = buffer;
322
+ _tx_size2 = size;
323
+
324
+ if (stm32l4_usbd_cdc_done (_usbd_cdc)) {
325
+ if (_tx_size2 != 0 ) {
326
+ stm32l4_usbd_cdc_transmit (_usbd_cdc, _tx_data2, _tx_size2);
327
+ }
328
+ }
329
+
330
+ return true ;
286
331
}
287
332
288
333
bool CDC::done ()
@@ -291,13 +336,22 @@ bool CDC::done()
291
336
return false ;
292
337
}
293
338
339
+ if (_tx_size2) {
340
+ return false ;
341
+ }
342
+
294
343
if (!stm32l4_usbd_cdc_done (_usbd_cdc)) {
295
344
return false ;
296
345
}
297
346
298
347
return true ;
299
348
}
300
349
350
+ void CDC::onReceive (void (*callback)(int ))
351
+ {
352
+ _receiveCallback = callback;
353
+ }
354
+
301
355
void CDC::blockOnOverrun (bool block)
302
356
{
303
357
_blocking = block;
@@ -313,6 +367,7 @@ void CDC::EventCallback(uint32_t events)
313
367
unsigned int rx_write, rx_count, rx_size, count;
314
368
unsigned int tx_read, tx_size;
315
369
bool empty;
370
+ void (*callback)(void );
316
371
317
372
if (events & USBD_CDC_EVENT_RECEIVE) {
318
373
while (_rx_count != CDC_RX_BUFFER_SIZE) {
@@ -350,34 +405,46 @@ void CDC::EventCallback(uint32_t events)
350
405
}
351
406
352
407
if (events & USBD_CDC_EVENT_TRANSMIT) {
408
+
353
409
tx_size = _tx_size;
410
+
411
+ if (tx_size != 0 ) {
412
+ _tx_read = (_tx_read + tx_size) & (CDC_TX_BUFFER_SIZE -1 );
354
413
355
- _tx_read = (_tx_read + tx_size) & (CDC_TX_BUFFER_SIZE -1 );
356
-
357
- armv7m_atomic_sub (&_tx_count, tx_size);
358
- armv7m_atomic_sub (&_tx_total, tx_size);
414
+ armv7m_atomic_sub (&_tx_count, tx_size);
359
415
360
- _tx_size = 0 ;
416
+ _tx_size = 0 ;
361
417
362
- if (_tx_count != 0 ) {
363
- tx_size = _tx_count;
364
- tx_read = _tx_read;
418
+ if (_tx_count != 0 ) {
419
+ tx_size = _tx_count;
420
+ tx_read = _tx_read;
365
421
366
- if (tx_size > (CDC_TX_BUFFER_SIZE - tx_read)) {
367
- tx_size = (CDC_TX_BUFFER_SIZE - tx_read);
368
- }
422
+ if (tx_size > (CDC_TX_BUFFER_SIZE - tx_read)) {
423
+ tx_size = (CDC_TX_BUFFER_SIZE - tx_read);
424
+ }
369
425
370
- if (tx_size > CDC_TX_PACKET_SIZE) {
371
- tx_size = CDC_TX_PACKET_SIZE;
372
- }
426
+ if (tx_size > CDC_TX_PACKET_SIZE) {
427
+ tx_size = CDC_TX_PACKET_SIZE;
428
+ }
373
429
374
- _tx_size = tx_size;
430
+ _tx_size = tx_size;
375
431
376
- stm32l4_usbd_cdc_transmit (_usbd_cdc, &_tx_data[tx_read], tx_size);
377
- }
432
+ stm32l4_usbd_cdc_transmit (_usbd_cdc, &_tx_data[tx_read], tx_size);
433
+ } else {
434
+ if (_tx_size2 != 0 ) {
435
+ stm32l4_usbd_cdc_transmit (_usbd_cdc, _tx_data2, _tx_size2);
436
+ }
437
+ }
438
+ } else {
439
+ _tx_size2 = 0 ;
440
+ _tx_data2 = NULL ;
441
+
442
+ callback = _completionCallback;
443
+ _completionCallback = NULL ;
378
444
379
- if ((_tx_total == 0 ) &&_transmitCallback) {
380
- (*_transmitCallback)();
445
+ if (callback) {
446
+ (*callback)();
447
+ }
381
448
}
382
449
}
383
450
}
0 commit comments