Skip to content

Commit

Permalink
Cleanup CDC/Uart; add async writes again, this time the working variant
Browse files Browse the repository at this point in the history
  • Loading branch information
GrumpyOldPizza committed Jan 30, 2017
1 parent f90e5b6 commit 0d61048
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 73 deletions.
97 changes: 76 additions & 21 deletions cores/stm32l4/CDC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ CDC::CDC(struct _stm32l4_usbd_cdc_t *usbd_cdc, bool serialEvent)
{
_usbd_cdc = usbd_cdc;

_blocking = true;

_rx_read = 0;
_rx_write = 0;
_rx_count = 0;
Expand All @@ -54,6 +52,10 @@ 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 @@ -99,6 +101,10 @@ int CDC::availableForWrite(void)
return 0;
}

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

return CDC_TX_BUFFER_SIZE - _tx_count;
}

Expand Down Expand Up @@ -170,19 +176,11 @@ size_t CDC::read(uint8_t *buffer, size_t size)
void CDC::flush()
{
if (armv7m_core_priority() <= STM32L4_USB_IRQ_PRIORITY) {
while (_tx_count != 0) {
stm32l4_usbd_cdc_poll(_usbd_cdc);
}

while (!stm32l4_usbd_cdc_done(_usbd_cdc)) {
while ((_tx_count != 0) || (_tx_size2 != 0) || !stm32l4_usbd_cdc_done(_usbd_cdc)) {
stm32l4_usbd_cdc_poll(_usbd_cdc);
}
} else {
while (_tx_count != 0) {
armv7m_core_yield();
}

while (!stm32l4_usbd_cdc_done(_usbd_cdc)) {
while ((_tx_count != 0) || (_tx_size2 != 0) || !stm32l4_usbd_cdc_done(_usbd_cdc)) {
armv7m_core_yield();
}
}
Expand All @@ -205,6 +203,16 @@ size_t CDC::write(const uint8_t *buffer, size_t size)
if (size == 0) {
return 0;
}

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

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

count = 0;

Expand All @@ -214,7 +222,7 @@ size_t CDC::write(const uint8_t *buffer, size_t size)

if (tx_count == 0) {

if (!_blocking || (__get_IPSR() != 0)) {
if (__get_IPSR() != 0) {
break;
}

Expand Down Expand Up @@ -290,19 +298,54 @@ size_t CDC::write(const uint8_t *buffer, size_t size)
return count;
}

void CDC::onReceive(void(*callback)(void))
bool CDC::write(const uint8_t *buffer, size_t size, void(*callback)(void))
{
_receiveCallback = callback;
if ((_usbd_cdc->state < USBD_CDC_STATE_READY) || !(stm32l4_usbd_cdc_info.lineState & 1)) {
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 (!stm32l4_usbd_cdc_transmit(_usbd_cdc, _tx_data2, _tx_size2)) {
_tx_data2 = NULL;
_tx_size2 = 0;
}
}

return true;
}

void CDC::blockOnOverrun(bool block)
bool CDC::done()
{
_blocking = block;
if (_tx_count) {
return false;
}

if (_tx_size2) {
return false;
}

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

return true;
}

bool CDC::isEnabled()
void CDC::onReceive(void(*callback)(void))
{
return (_usbd_cdc->state >= USBD_CDC_STATE_READY);
_receiveCallback = callback;
}

void CDC::EventCallback(uint32_t events)
Expand Down Expand Up @@ -372,12 +415,24 @@ void CDC::EventCallback(uint32_t events)
_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);
}
}
}
else {
} else {
_tx_count = 0;
_tx_read = _tx_write;
}
} else {
_tx_size2 = 0;
_tx_data2 = NULL;

if (_completionCallback) {
armv7m_pendsv_enqueue((armv7m_pendsv_routine_t)_completionCallback, NULL, 0);

_completionCallback = NULL;
}
}
}
}
Expand Down
15 changes: 8 additions & 7 deletions cores/stm32l4/USBAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,18 +100,15 @@ 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)(void));

// STM32L4 EXTENSTION: enable/disabe blocking writes
void blockOnOverrun(bool enable);

// STM32L4 EXTENSTION: isEnabled() check
bool isEnabled(void);

private:
struct _stm32l4_usbd_cdc_t *_usbd_cdc;
bool _blocking;
uint8_t _rx_data[CDC_RX_BUFFER_SIZE];
volatile uint16_t _rx_write;
volatile uint16_t _rx_read;
Expand All @@ -122,6 +119,10 @@ 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)(void);

static void _event_callback(void *context, uint32_t events);
Expand Down
91 changes: 72 additions & 19 deletions cores/stm32l4/Uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ Uart::Uart(struct _stm32l4_uart_t *uart, unsigned int instance, const struct _st
{
_uart = uart;

_blocking = true;

_rx_read = 0;
_rx_write = 0;
_rx_count = 0;
Expand All @@ -46,6 +44,10 @@ 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 @@ -89,6 +91,10 @@ int Uart::availableForWrite()
return 0;
}

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

return UART_TX_BUFFER_SIZE - _tx_count;
}

Expand Down Expand Up @@ -160,19 +166,11 @@ size_t Uart::read(uint8_t *buffer, size_t size)
void Uart::flush()
{
if (armv7m_core_priority() <= STM32L4_UART_IRQ_PRIORITY) {
while (_tx_count != 0) {
stm32l4_uart_poll(_uart);
}

while (!stm32l4_uart_done(_uart)) {
while ((_tx_count != 0) || (_tx_size2 != 0) || !stm32l4_uart_done(_uart)) {
stm32l4_uart_poll(_uart);
}
} else {
while (_tx_count != 0) {
armv7m_core_yield();
}

while (!stm32l4_uart_done(_uart)) {
while ((_tx_count != 0) || (_tx_size2 != 0) || !stm32l4_uart_done(_uart)) {
armv7m_core_yield();
}
}
Expand All @@ -196,6 +194,16 @@ size_t Uart::write(const uint8_t *buffer, size_t size)
return 0;
}

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

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

count = 0;

while (count < size) {
Expand All @@ -204,7 +212,7 @@ size_t Uart::write(const uint8_t *buffer, size_t size)

if (tx_count == 0) {

if (!_blocking || (__get_IPSR() != 0)) {
if (__get_IPSR() != 0) {
break;
}

Expand Down Expand Up @@ -272,19 +280,51 @@ size_t Uart::write(const uint8_t *buffer, size_t size)
return count;
}

void Uart::onReceive(void(*callback)(void))
bool Uart::write(const uint8_t *buffer, size_t size, void(*callback)(void))
{
_receiveCallback = callback;
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)) {
stm32l4_uart_transmit(_uart, _tx_data2, _tx_size2);
}

return true;
}

void Uart::blockOnOverrun(bool block)
bool Uart::done()
{
_blocking = block;
if (_tx_count) {
return false;
}

if (_tx_size2) {
return false;
}

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

return true;
}

bool Uart::isEnabled()
void Uart::onReceive(void(*callback)(void))
{
return (_uart->state >= UART_STATE_READY);
_receiveCallback = callback;
}

void Uart::EventCallback(uint32_t events)
Expand Down Expand Up @@ -353,6 +393,19 @@ 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;

if (_completionCallback) {
armv7m_pendsv_enqueue((armv7m_pendsv_routine_t)_completionCallback, NULL, 0);

_completionCallback = NULL;
}
}
}
Expand Down
15 changes: 8 additions & 7 deletions cores/stm32l4/Uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,15 @@ 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)(void));

// STM32L4 EXTENSTION: enable/disabe blocking writes
void blockOnOverrun(bool block);

// STM32L4 EXTENSTION: isEnabled() check
bool isEnabled(void);

private:
struct _stm32l4_uart_t *_uart;
bool _blocking;
uint8_t _rx_fifo[16];
uint8_t _rx_data[UART_RX_BUFFER_SIZE];
volatile uint16_t _rx_write;
Expand All @@ -77,6 +74,10 @@ 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)(void);

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.
Loading

0 comments on commit 0d61048

Please sign in to comment.