Skip to content

Commit c97ea3c

Browse files
CDC/Uart/SPI/Write API tweaks
1 parent e433e48 commit c97ea3c

File tree

8 files changed

+353
-162
lines changed

8 files changed

+353
-162
lines changed

cores/stm32l4/CDC.cpp

Lines changed: 124 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,13 @@ CDC::CDC(struct _stm32l4_usbd_cdc_t *usbd_cdc, bool serialEvent)
4949
_rx_count = 0;
5050
_tx_read = 0;
5151
_tx_write = 0;
52-
_tx_size = 0;
5352
_tx_count = 0;
54-
_tx_total = 0;
53+
_tx_size = 0;
54+
55+
_tx_data2 = NULL;
56+
_tx_size2 = 0;
5557

56-
_transmitCallback = NULL;
58+
_completionCallback = NULL;
5759
_receiveCallback = NULL;
5860

5961
stm32l4_usbd_cdc_create(usbd_cdc);
@@ -95,8 +97,13 @@ int CDC::available()
9597

9698
int CDC::availableForWrite(void)
9799
{
98-
if (_usbd_cdc->state < USBD_CDC_STATE_READY)
100+
if (_usbd_cdc->state < USBD_CDC_STATE_READY) {
99101
return 0;
102+
}
103+
104+
if (_tx_size2 != 0) {
105+
return 0;
106+
}
100107

101108
return CDC_TX_BUFFER_SIZE - _tx_count;
102109
}
@@ -164,10 +171,26 @@ size_t CDC::read(uint8_t *buffer, size_t size)
164171

165172
void CDC::flush()
166173
{
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 {
168187
while (_tx_count != 0) {
169188
armv7m_core_yield();
170189
}
190+
191+
while (_tx_size2 != 0) {
192+
armv7m_core_yield();
193+
}
171194

172195
while (!stm32l4_usbd_cdc_done(_usbd_cdc)) {
173196
armv7m_core_yield();
@@ -185,29 +208,36 @@ size_t CDC::write(const uint8_t *buffer, size_t size)
185208
unsigned int tx_read, tx_write, tx_count, tx_size;
186209
size_t count;
187210

188-
if ((_usbd_cdc->state < USBD_CDC_STATE_READY) || !(stm32l4_usbd_cdc_info.lineState & 2)) {
211+
if (_usbd_cdc->state < USBD_CDC_STATE_READY) {
189212
return 0;
190213
}
191214

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+
}
195218

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();
198227
}
199228
}
200-
201-
armv7m_atomic_add(&_tx_total, size);
202-
229+
203230
count = 0;
204231

205232
while (count < size) {
206233

207234
tx_count = CDC_TX_BUFFER_SIZE - _tx_count;
208235

209236
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+
}
211241

212242
if (stm32l4_usbd_cdc_done(_usbd_cdc)) {
213243
tx_size = _tx_count;
@@ -251,38 +281,53 @@ size_t CDC::write(const uint8_t *buffer, size_t size)
251281
armv7m_atomic_add(&_tx_count, tx_count);
252282
}
253283

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;
271295
}
296+
297+
_tx_size = tx_size;
298+
299+
stm32l4_usbd_cdc_transmit(_usbd_cdc, &_tx_data[tx_read], tx_size);
272300
}
273301
}
274302

275303
return count;
276304
}
277305

278-
void CDC::onTransmit(void(*callback)(void))
306+
bool CDC::write(const uint8_t *buffer, size_t size, void(*callback)(void))
279307
{
280-
_transmitCallback = callback;
281-
}
308+
if (_usbd_cdc->state < USBD_CDC_STATE_READY) {
309+
return false;
310+
}
282311

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;
286331
}
287332

288333
bool CDC::done()
@@ -291,13 +336,22 @@ bool CDC::done()
291336
return false;
292337
}
293338

339+
if (_tx_size2) {
340+
return false;
341+
}
342+
294343
if (!stm32l4_usbd_cdc_done(_usbd_cdc)) {
295344
return false;
296345
}
297346

298347
return true;
299348
}
300349

350+
void CDC::onReceive(void(*callback)(int))
351+
{
352+
_receiveCallback = callback;
353+
}
354+
301355
void CDC::blockOnOverrun(bool block)
302356
{
303357
_blocking = block;
@@ -313,6 +367,7 @@ void CDC::EventCallback(uint32_t events)
313367
unsigned int rx_write, rx_count, rx_size, count;
314368
unsigned int tx_read, tx_size;
315369
bool empty;
370+
void(*callback)(void);
316371

317372
if (events & USBD_CDC_EVENT_RECEIVE) {
318373
while (_rx_count != CDC_RX_BUFFER_SIZE) {
@@ -350,34 +405,46 @@ void CDC::EventCallback(uint32_t events)
350405
}
351406

352407
if (events & USBD_CDC_EVENT_TRANSMIT) {
408+
353409
tx_size = _tx_size;
410+
411+
if (tx_size != 0) {
412+
_tx_read = (_tx_read + tx_size) & (CDC_TX_BUFFER_SIZE -1);
354413

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);
359415

360-
_tx_size = 0;
416+
_tx_size = 0;
361417

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;
365421

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+
}
369425

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+
}
373429

374-
_tx_size = tx_size;
430+
_tx_size = tx_size;
375431

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;
378444

379-
if ((_tx_total == 0) &&_transmitCallback) {
380-
(*_transmitCallback)();
445+
if (callback) {
446+
(*callback)();
447+
}
381448
}
382449
}
383450
}

cores/stm32l4/CDC.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,13 @@ class CDC : public HardwareSerial
7979
// STM32L4 EXTENSTION: non-blocking multi-byte read
8080
size_t read(uint8_t *buffer, size_t size);
8181

82-
// STM32L4 EXTENSTION: asynchronous transmit/receive callbacks
83-
void onTransmit(void(*callback)(void));
84-
void onReceive(void(*callback)(int));
82+
// STM32L4 EXTENSTION: asynchronous write with callback
83+
bool write(const uint8_t *buffer, size_t size, void(*callback)(void));
8584
bool done(void);
8685

86+
// STM32L4 EXTENSTION: asynchronous receive
87+
void onReceive(void(*callback)(int));
88+
8789
// STM32L4 EXTENSTION: enable/disabe blocking writes
8890
void blockOnOverrun(bool enable);
8991

@@ -100,11 +102,13 @@ class CDC : public HardwareSerial
100102
uint8_t _tx_data[CDC_TX_BUFFER_SIZE];
101103
volatile uint16_t _tx_write;
102104
volatile uint16_t _tx_read;
103-
volatile uint32_t _tx_size;
104105
volatile uint32_t _tx_count;
105-
volatile uint32_t _tx_total;
106+
volatile uint32_t _tx_size;
107+
108+
const uint8_t *_tx_data2;
109+
volatile uint32_t _tx_size2;
106110

107-
void (*_transmitCallback)(void);
111+
void (*_completionCallback)(void);
108112
void (*_receiveCallback)(int);
109113

110114
static void _event_callback(void *context, uint32_t events);

0 commit comments

Comments
 (0)