Skip to content

Commit

Permalink
Avoid CDC transmit blocking on USB disconnect
Browse files Browse the repository at this point in the history
  • Loading branch information
GrumpyOldPizza committed Jan 17, 2017
1 parent 4d2ccf1 commit 3249420
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 226 deletions.
131 changes: 30 additions & 101 deletions cores/stm32l4/CDC.cpp
Expand Up @@ -54,10 +54,6 @@ CDC::CDC(struct _stm32l4_usbd_cdc_t *usbd_cdc, bool serialEvent)
_tx_count = 0;
_tx_size = 0;

_tx_data2 = NULL;
_tx_size2 = 0;

_completionCallback = NULL;
_receiveCallback = NULL;

stm32l4_usbd_cdc_create(usbd_cdc);
Expand Down Expand Up @@ -103,10 +99,6 @@ int CDC::availableForWrite(void)
return 0;
}

if (_tx_size2 != 0) {
return 0;
}

return CDC_TX_BUFFER_SIZE - _tx_count;
}

Expand Down Expand Up @@ -178,10 +170,6 @@ void CDC::flush()
stm32l4_usbd_cdc_poll(_usbd_cdc);
}

while (_tx_size2 != 0) {
stm32l4_usbd_cdc_poll(_usbd_cdc);
}

while (!stm32l4_usbd_cdc_done(_usbd_cdc)) {
stm32l4_usbd_cdc_poll(_usbd_cdc);
}
Expand All @@ -190,10 +178,6 @@ void CDC::flush()
armv7m_core_yield();
}

while (_tx_size2 != 0) {
armv7m_core_yield();
}

while (!stm32l4_usbd_cdc_done(_usbd_cdc)) {
armv7m_core_yield();
}
Expand All @@ -210,24 +194,13 @@ size_t CDC::write(const uint8_t *buffer, size_t size)
unsigned int tx_read, tx_write, tx_count, tx_size;
size_t count;

if ((_usbd_cdc->state < USBD_CDC_STATE_READY) || !(stm32l4_usbd_cdc_info.lineState & 2)) {
if ((_usbd_cdc->state < USBD_CDC_STATE_READY) || !(stm32l4_usbd_cdc_info.lineState & 1)) {
return 0;
}

if (size == 0) {
return 0;
}

// If there is an async write pending, wait till it's done
if (_tx_size2 != 0) {
if (!_blocking || (__get_IPSR() != 0)) {
return 0;
}

while (_tx_size2 != 0) {
armv7m_core_yield();
}
}

count = 0;

Expand Down Expand Up @@ -255,7 +228,11 @@ size_t CDC::write(const uint8_t *buffer, size_t size)

_tx_size = tx_size;

stm32l4_usbd_cdc_transmit(_usbd_cdc, &_tx_data[tx_read], tx_size);
if (!stm32l4_usbd_cdc_transmit(_usbd_cdc, &_tx_data[tx_read], tx_size)) {
_tx_size = 0;
_tx_count = 0;
_tx_read = _tx_write;
}
}

while (CDC_TX_BUFFER_SIZE == _tx_count) {
Expand Down Expand Up @@ -298,57 +275,17 @@ size_t CDC::write(const uint8_t *buffer, size_t size)

_tx_size = tx_size;

stm32l4_usbd_cdc_transmit(_usbd_cdc, &_tx_data[tx_read], tx_size);
if (!stm32l4_usbd_cdc_transmit(_usbd_cdc, &_tx_data[tx_read], tx_size)) {
_tx_size = 0;
_tx_count = 0;
_tx_read = _tx_write;
}
}
}

return count;
}

bool CDC::write(const uint8_t *buffer, size_t size, void(*callback)(void))
{
if ((_usbd_cdc->state < USBD_CDC_STATE_READY) || !(stm32l4_usbd_cdc_info.lineState & 2)) {
return false;
}

if (size == 0) {
return false;
}

if (_tx_size2 != 0) {
return false;
}

_completionCallback = callback;
_tx_data2 = buffer;
_tx_size2 = size;

if (stm32l4_usbd_cdc_done(_usbd_cdc)) {
if (_tx_size2 != 0) {
stm32l4_usbd_cdc_transmit(_usbd_cdc, _tx_data2, _tx_size2);
}
}

return true;
}

bool CDC::done()
{
if (_tx_count) {
return false;
}

if (_tx_size2) {
return false;
}

if (!stm32l4_usbd_cdc_done(_usbd_cdc)) {
return false;
}

return true;
}

void CDC::onReceive(void(*callback)(int))
{
_receiveCallback = callback;
Expand Down Expand Up @@ -422,35 +359,27 @@ void CDC::EventCallback(uint32_t events)

_tx_size = 0;

if (_tx_count != 0) {
tx_size = _tx_count;
tx_read = _tx_read;

if (tx_size > (CDC_TX_BUFFER_SIZE - tx_read)) {
tx_size = (CDC_TX_BUFFER_SIZE - tx_read);
}

if (tx_size > CDC_TX_PACKET_SIZE) {
tx_size = CDC_TX_PACKET_SIZE;
}

_tx_size = tx_size;

stm32l4_usbd_cdc_transmit(_usbd_cdc, &_tx_data[tx_read], tx_size);
} else {
if (_tx_size2 != 0) {
stm32l4_usbd_cdc_transmit(_usbd_cdc, _tx_data2, _tx_size2);
if (stm32l4_usbd_cdc_info.lineState & 1) {
if (_tx_count != 0) {
tx_size = _tx_count;
tx_read = _tx_read;

if (tx_size > (CDC_TX_BUFFER_SIZE - tx_read)) {
tx_size = (CDC_TX_BUFFER_SIZE - tx_read);
}

if (tx_size > CDC_TX_PACKET_SIZE) {
tx_size = CDC_TX_PACKET_SIZE;
}

_tx_size = tx_size;

stm32l4_usbd_cdc_transmit(_usbd_cdc, &_tx_data[tx_read], tx_size);
}
}
} else {
_tx_size2 = 0;
_tx_data2 = NULL;

callback = _completionCallback;
_completionCallback = NULL;

if (callback) {
(*callback)();
else {
_tx_count = 0;
_tx_read = _tx_write;
}
}
}
Expand Down
8 changes: 0 additions & 8 deletions cores/stm32l4/USBAPI.h
Expand Up @@ -100,10 +100,6 @@ class CDC : public HardwareSerial
// STM32L4 EXTENSTION: non-blocking multi-byte read
size_t read(uint8_t *buffer, size_t size);

// STM32L4 EXTENSTION: asynchronous write with callback
bool write(const uint8_t *buffer, size_t size, void(*callback)(void));
bool done(void);

// STM32L4 EXTENSTION: asynchronous receive
void onReceive(void(*callback)(int));

Expand All @@ -126,10 +122,6 @@ class CDC : public HardwareSerial
volatile uint32_t _tx_count;
volatile uint32_t _tx_size;

const uint8_t *_tx_data2;
volatile uint32_t _tx_size2;

void (*_completionCallback)(void);
void (*_receiveCallback)(int);

static void _event_callback(void *context, uint32_t events);
Expand Down
85 changes: 0 additions & 85 deletions cores/stm32l4/Uart.cpp
Expand Up @@ -46,10 +46,6 @@ Uart::Uart(struct _stm32l4_uart_t *uart, unsigned int instance, const struct _st
_tx_count = 0;
_tx_size = 0;

_tx_data2 = NULL;
_tx_size2 = 0;

_completionCallback = NULL;
_receiveCallback = NULL;

stm32l4_uart_create(uart, instance, pins, priority, mode);
Expand Down Expand Up @@ -93,10 +89,6 @@ int Uart::availableForWrite()
return 0;
}

if (_tx_size2 != 0) {
return 0;
}

return UART_TX_BUFFER_SIZE - _tx_count;
}

Expand Down Expand Up @@ -168,10 +160,6 @@ void Uart::flush()
stm32l4_uart_poll(_uart);
}

while (_tx_size2 != 0) {
stm32l4_uart_poll(_uart);
}

while (!stm32l4_uart_done(_uart)) {
stm32l4_uart_poll(_uart);
}
Expand All @@ -180,10 +168,6 @@ void Uart::flush()
armv7m_core_yield();
}

while (_tx_size2 != 0) {
armv7m_core_yield();
}

while (!stm32l4_uart_done(_uart)) {
armv7m_core_yield();
}
Expand All @@ -208,17 +192,6 @@ size_t Uart::write(const uint8_t *buffer, size_t size)
return 0;
}

// If there is an async write pending, wait till it's done
if (_tx_size2 != 0) {
if (!_blocking || (__get_IPSR() != 0)) {
return 0;
}

while (_tx_size2 != 0) {
armv7m_core_yield();
}
}

count = 0;

while (count < size) {
Expand Down Expand Up @@ -295,50 +268,6 @@ size_t Uart::write(const uint8_t *buffer, size_t size)
return count;
}

bool Uart::write(const uint8_t *buffer, size_t size, void(*callback)(void))
{
if (_uart->state < UART_STATE_READY) {
return false;
}

if (size == 0) {
return false;
}

if (_tx_size2 != 0) {
return false;
}

_completionCallback = callback;
_tx_data2 = buffer;
_tx_size2 = size;

if (stm32l4_uart_done(_uart)) {
if (_tx_size2 != 0) {
stm32l4_uart_transmit(_uart, _tx_data2, _tx_size2);
}
}

return true;
}

bool Uart::done()
{
if (_tx_count) {
return false;
}

if (_tx_size2) {
return false;
}

if (!stm32l4_uart_done(_uart)) {
return false;
}

return true;
}

void Uart::onReceive(void(*callback)(int))
{
_receiveCallback = callback;
Expand Down Expand Up @@ -427,20 +356,6 @@ void Uart::EventCallback(uint32_t events)
_tx_size = tx_size;

stm32l4_uart_transmit(_uart, &_tx_data[tx_read], tx_size);
} else {
if (_tx_size2 != 0) {
stm32l4_uart_transmit(_uart, _tx_data2, _tx_size2);
}
}
} else {
_tx_size2 = 0;
_tx_data2 = NULL;

callback = _completionCallback;
_completionCallback = NULL;

if (callback) {
(*callback)();
}
}
}
Expand Down
8 changes: 0 additions & 8 deletions cores/stm32l4/Uart.h
Expand Up @@ -54,10 +54,6 @@ class Uart : public HardwareSerial
// STM32L4 EXTENSTION: non-blocking multi-byte read
size_t read(uint8_t *buffer, size_t size);

// STM32L4 EXTENSTION: asynchronous write with callback
bool write(const uint8_t *buffer, size_t size, void(*callback)(void));
bool done(void);

// STM32L4 EXTENSTION: asynchronous receive
void onReceive(void(*callback)(int));

Expand All @@ -81,10 +77,6 @@ class Uart : public HardwareSerial
volatile uint32_t _tx_count;
volatile uint32_t _tx_size;

const uint8_t *_tx_data2;
volatile uint32_t _tx_size2;

void (*_completionCallback)(void);
void (*_receiveCallback)(int);

static void _event_callback(void *context, uint32_t events);
Expand Down
Binary file modified system/STM32L4xx/Lib/libstm32l432.a
Binary file not shown.
Binary file modified system/STM32L4xx/Lib/libstm32l433.a
Binary file not shown.
Binary file modified system/STM32L4xx/Lib/libstm32l476.a
Binary file not shown.

0 comments on commit 3249420

Please sign in to comment.