diff --git a/cores/stm32l4/CDC.cpp b/cores/stm32l4/CDC.cpp index faf2fb83..867fb4db 100644 --- a/cores/stm32l4/CDC.cpp +++ b/cores/stm32l4/CDC.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Thomas Roell. All rights reserved. + * Copyright (c) 2016-2017 Thomas Roell. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -32,21 +32,22 @@ #if defined(USBCON) -/* STM32L4x5/STM32L4x6 have USB_OTG_FS with a multi-packet FIFO. However - * to avoid sending ZLP packets, the CDC_TX_PACKET_SIZE is one byte - * less than the maximum FIFO size in terms of 64 byte packets. - */ -#define CDC_TX_PACKET_SIZE (((USBD_CDC_FIFO_SIZE + 63) & ~63) -1) +#define CDC_TX_PACKET_SIZE 128 +#define CDC_TX_PACKET_SMALL 64 stm32l4_usbd_cdc_t stm32l4_usbd_cdc; +extern int (*stm32l4_stdio_put)(char, FILE*); + +static int serialusb_stdio_put(char data, FILE *fp) +{ + return Serial.write(&data, 1); +} + CDC::CDC(struct _stm32l4_usbd_cdc_t *usbd_cdc, bool serialEvent) { _usbd_cdc = usbd_cdc; - _rx_read = 0; - _rx_write = 0; - _rx_count = 0; _tx_read = 0; _tx_write = 0; _tx_count = 0; @@ -54,6 +55,8 @@ CDC::CDC(struct _stm32l4_usbd_cdc_t *usbd_cdc, bool serialEvent) _tx_data2 = NULL; _tx_size2 = 0; + + _tx_timeout = 0; _completionCallback = NULL; _receiveCallback = NULL; @@ -75,24 +78,36 @@ void CDC::begin(unsigned long baudrate, uint16_t config) /* If USBD_CDC has already been enabled/initialized by STDIO, just add the notify. */ if (_usbd_cdc->state == USBD_CDC_STATE_INIT) { - stm32l4_usbd_cdc_enable(_usbd_cdc, 0, CDC::_event_callback, (void*)this, (USBD_CDC_EVENT_RECEIVE | USBD_CDC_EVENT_TRANSMIT)); + 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)); + + if (stm32l4_stdio_put == NULL) { + stm32l4_stdio_put = serialusb_stdio_put; + } } else { flush(); stm32l4_usbd_cdc_notify(_usbd_cdc, CDC::_event_callback, (void*)this, (USBD_CDC_EVENT_RECEIVE | USBD_CDC_EVENT_TRANSMIT)); } + + USBD_SOFCallback(CDC::_sof_callback, (void*)this); } void CDC::end() { flush(); + USBD_SOFCallback(NULL, NULL); + + if (stm32l4_stdio_put == serialusb_stdio_put) { + stm32l4_stdio_put = NULL; + } + stm32l4_usbd_cdc_disable(_usbd_cdc); } int CDC::available() { - return _rx_count; + return stm32l4_usbd_cdc_count(_usbd_cdc); } int CDC::availableForWrite(void) @@ -110,67 +125,25 @@ int CDC::availableForWrite(void) int CDC::peek() { - if (_rx_count == 0) { - return -1; - } - - return _rx_data[_rx_read]; + return stm32l4_usbd_cdc_peek(_usbd_cdc); } int CDC::read() { - unsigned int rx_read; uint8_t data; - if (_rx_count == 0) { + if (!stm32l4_usbd_cdc_count(_usbd_cdc)) { return -1; } - rx_read = _rx_read; + stm32l4_usbd_cdc_receive(_usbd_cdc, &data, 1); - data = _rx_data[rx_read]; - - _rx_read = (unsigned int)(rx_read + 1) & (CDC_RX_BUFFER_SIZE -1); - - armv7m_atomic_sub(&_rx_count, 1); - return data; } size_t CDC::read(uint8_t *buffer, size_t size) { - unsigned int rx_read, rx_count; - size_t count; - - count = 0; - - while (count < size) { - - rx_count = _rx_count; - - if (rx_count == 0) { - break; - } - - rx_read = _rx_read; - - if (rx_count > (CDC_RX_BUFFER_SIZE - rx_read)) { - rx_count = (CDC_RX_BUFFER_SIZE - rx_read); - } - - if (rx_count > (size - count)) { - rx_count = (size - count); - } - - memcpy(&buffer[count], &_rx_data[rx_read], rx_count); - count += rx_count; - - _rx_read = (rx_read + rx_count) & (CDC_RX_BUFFER_SIZE -1); - - armv7m_atomic_sub(&_rx_count, rx_count); - } - - return count; + return stm32l4_usbd_cdc_receive(_usbd_cdc, buffer, size); } void CDC::flush() @@ -276,7 +249,7 @@ size_t CDC::write(const uint8_t *buffer, size_t size) tx_size = _tx_count; tx_read = _tx_read; - if (tx_size) { + if (tx_size >= CDC_TX_PACKET_SMALL) { if (tx_size > (CDC_TX_BUFFER_SIZE - tx_read)) { tx_size = (CDC_TX_BUFFER_SIZE - tx_read); } @@ -350,46 +323,18 @@ void CDC::onReceive(void(*callback)(void)) void CDC::EventCallback(uint32_t events) { - unsigned int rx_write, rx_count, rx_size, count; unsigned int tx_read, tx_size; - bool empty; - - if (events & USBD_CDC_EVENT_RECEIVE) { - empty = (_rx_count == 0); - - count = 0; - - do { - rx_size = 0; - rx_count = CDC_RX_BUFFER_SIZE - _rx_count; - - if (rx_count == 0) { - break; - } - - rx_write = _rx_write; - - if (rx_count > (CDC_RX_BUFFER_SIZE - rx_write)) { - rx_count = (CDC_RX_BUFFER_SIZE - rx_write); - } - - rx_size = stm32l4_usbd_cdc_receive(_usbd_cdc, &_rx_data[rx_write], rx_count); - - _rx_write = (rx_write + rx_size) & (CDC_RX_BUFFER_SIZE -1); - - armv7m_atomic_add(&_rx_count, rx_size); - - count += rx_size; - - } while (rx_size); - if (empty && count && _receiveCallback) { + if (events & USBD_CDC_EVENT_RECEIVE) { + if (_receiveCallback) { armv7m_pendsv_enqueue((armv7m_pendsv_routine_t)_receiveCallback, NULL, 0); } } if (events & USBD_CDC_EVENT_TRANSMIT) { + _tx_timeout = 0; + tx_size = _tx_size; if (tx_size != 0) { @@ -437,11 +382,45 @@ void CDC::EventCallback(uint32_t events) } } +void CDC::SOFCallback() +{ + unsigned int tx_read, tx_size; + + if (_tx_count && !_tx_size && !_tx_size2) + { + _tx_timeout++; + + // Small packets get only send after 8ms latency + if (_tx_timeout >= 8) + { + 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); + } + } +} + void CDC::_event_callback(void *context, uint32_t events) { reinterpret_cast(context)->EventCallback(events); } +void CDC::_sof_callback(void *context) +{ + reinterpret_cast(context)->SOFCallback(); +} + CDC::operator bool() { return stm32l4_usbd_cdc_connected(_usbd_cdc); diff --git a/cores/stm32l4/USBAPI.h b/cores/stm32l4/USBAPI.h index 2e429a7e..00965f8d 100644 --- a/cores/stm32l4/USBAPI.h +++ b/cores/stm32l4/USBAPI.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Thomas Roell. All rights reserved. + * Copyright (c) 2016-2017 Thomas Roell. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -110,9 +110,6 @@ class CDC : public HardwareSerial private: struct _stm32l4_usbd_cdc_t *_usbd_cdc; uint8_t _rx_data[CDC_RX_BUFFER_SIZE]; - volatile uint16_t _rx_write; - volatile uint16_t _rx_read; - volatile uint32_t _rx_count; uint8_t _tx_data[CDC_TX_BUFFER_SIZE]; volatile uint16_t _tx_write; volatile uint16_t _tx_read; @@ -122,9 +119,13 @@ class CDC : public HardwareSerial const uint8_t *_tx_data2; volatile uint32_t _tx_size2; + volatile uint32_t _tx_timeout; + void (*_completionCallback)(void); void (*_receiveCallback)(void); static void _event_callback(void *context, uint32_t events); + static void _sof_callback(void *context); void EventCallback(uint32_t events); + void SOFCallback(); }; diff --git a/cores/stm32l4/Uart.cpp b/cores/stm32l4/Uart.cpp index be2af892..26434d9d 100644 --- a/cores/stm32l4/Uart.cpp +++ b/cores/stm32l4/Uart.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Thomas Roell. All rights reserved. + * Copyright (c) 2016-2017 Thomas Roell. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -36,9 +36,6 @@ Uart::Uart(struct _stm32l4_uart_t *uart, unsigned int instance, const struct _st { _uart = uart; - _rx_read = 0; - _rx_write = 0; - _rx_count = 0; _tx_read = 0; _tx_write = 0; _tx_count = 0; @@ -59,18 +56,27 @@ Uart::Uart(struct _stm32l4_uart_t *uart, unsigned int instance, const struct _st void Uart::begin(unsigned long baudrate) { - begin(baudrate, SERIAL_8N1); + begin(baudrate, SERIAL_8N1, &_rx_data[0], sizeof(_rx_data)); } void Uart::begin(unsigned long baudrate, uint16_t config) { - if (_uart->state == UART_STATE_INIT) { - stm32l4_uart_enable(_uart, &_rx_fifo[0], sizeof(_rx_fifo), baudrate, config, Uart::_event_callback, (void*)this, (UART_EVENT_RECEIVE | UART_EVENT_TRANSMIT)); - } else { - flush(); + begin(baudrate, config, &_rx_data[0], sizeof(_rx_data)); +} + +void Uart::begin(unsigned long baudrate, uint8_t *buffer, size_t size) +{ + begin(baudrate, SERIAL_8N1, buffer, size); +} - stm32l4_uart_configure(_uart, baudrate, config); +void Uart::begin(unsigned long baudrate, uint16_t config, uint8_t *buffer, size_t size) +{ + if (_uart->state != UART_STATE_INIT) { + flush(); + stm32l4_uart_disable(_uart); } + + stm32l4_uart_enable(_uart, buffer, size, baudrate, config, Uart::_event_callback, (void*)this, (UART_EVENT_RECEIVE | UART_EVENT_TRANSMIT)); } void Uart::end() @@ -82,7 +88,7 @@ void Uart::end() int Uart::available() { - return _rx_count; + return stm32l4_uart_count(_uart); } int Uart::availableForWrite() @@ -100,67 +106,25 @@ int Uart::availableForWrite() int Uart::peek() { - if (_rx_count == 0) { - return -1; - } - - return _rx_data[_rx_read]; + return stm32l4_uart_peek(_uart); } int Uart::read() { - unsigned int rx_read; uint8_t data; - if (_rx_count == 0) { + if (!stm32l4_uart_count(_uart)) { return -1; } - rx_read = _rx_read; + stm32l4_uart_receive(_uart, &data, 1); - data = _rx_data[rx_read]; - - _rx_read = (unsigned int)(rx_read + 1) & (UART_RX_BUFFER_SIZE -1); - - armv7m_atomic_sub(&_rx_count, 1); - return data; } size_t Uart::read(uint8_t *buffer, size_t size) { - unsigned int rx_read, rx_count; - size_t count; - - count = 0; - - while (count < size) { - - rx_count = _rx_count; - - if (rx_count == 0) { - break; - } - - rx_read = _rx_read; - - if (rx_count > (UART_RX_BUFFER_SIZE - rx_read)) { - rx_count = (UART_RX_BUFFER_SIZE - rx_read); - } - - if (rx_count > (size - count)) { - rx_count = (size - count); - } - - memcpy(&buffer[count], &_rx_data[rx_read], rx_count); - count += rx_count; - - _rx_read = (rx_read + rx_count) & (UART_RX_BUFFER_SIZE -1); - - armv7m_atomic_sub(&_rx_count, rx_count); - } - - return count; + return stm32l4_uart_receive(_uart, buffer, size); } void Uart::flush() @@ -329,40 +293,10 @@ void Uart::onReceive(void(*callback)(void)) void Uart::EventCallback(uint32_t events) { - unsigned int rx_write, rx_count, rx_size, count; unsigned int tx_read, tx_size; - bool empty; if (events & UART_EVENT_RECEIVE) { - empty = (_rx_count == 0); - - count = 0; - - do { - rx_size = 0; - rx_count = UART_RX_BUFFER_SIZE - _rx_count; - - if (rx_count == 0) { - break; - } - - rx_write = _rx_write; - - if (rx_count > (UART_RX_BUFFER_SIZE - rx_write)) { - rx_count = (UART_RX_BUFFER_SIZE - rx_write); - } - - rx_size = stm32l4_uart_receive(_uart, &_rx_data[rx_write], rx_count); - - _rx_write = (rx_write + rx_size) & (UART_RX_BUFFER_SIZE -1); - - armv7m_atomic_add(&_rx_count, rx_size); - - count += rx_size; - - } while (rx_size); - - if (empty && count && _receiveCallback) { + if (_receiveCallback) { armv7m_pendsv_enqueue((armv7m_pendsv_routine_t)_receiveCallback, NULL, 0); } } diff --git a/cores/stm32l4/Uart.h b/cores/stm32l4/Uart.h index d97a8abf..e427f293 100644 --- a/cores/stm32l4/Uart.h +++ b/cores/stm32l4/Uart.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Thomas Roell. All rights reserved. + * Copyright (c) 2016-2017 Thomas Roell. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -30,8 +30,8 @@ #include "HardwareSerial.h" -#define UART_RX_BUFFER_SIZE 128 -#define UART_TX_BUFFER_SIZE 128 +#define UART_RX_BUFFER_SIZE 64 +#define UART_TX_BUFFER_SIZE 64 class Uart : public HardwareSerial { @@ -39,6 +39,8 @@ class Uart : public HardwareSerial Uart(struct _stm32l4_uart_t *uart, unsigned int instance, const struct _stm32l4_uart_pins_t *pins, unsigned int priority, unsigned int mode, bool serialEvent); void begin(unsigned long baudRate); void begin(unsigned long baudrate, uint16_t config); + void begin(unsigned long baudRate, uint8_t *buffer, size_t size); + void begin(unsigned long baudrate, uint16_t config, uint8_t *buffer, size_t size); void end(); int available(); int availableForWrite(void); @@ -63,11 +65,7 @@ class Uart : public HardwareSerial private: struct _stm32l4_uart_t *_uart; - uint8_t _rx_fifo[16]; uint8_t _rx_data[UART_RX_BUFFER_SIZE]; - volatile uint16_t _rx_write; - volatile uint16_t _rx_read; - volatile uint32_t _rx_count; uint8_t _tx_data[UART_TX_BUFFER_SIZE]; volatile uint16_t _tx_write; volatile uint16_t _tx_read; diff --git a/cores/stm32l4/stm32l4_wiring_private.h b/cores/stm32l4/stm32l4_wiring_private.h index 4cbe7182..ab63380d 100644 --- a/cores/stm32l4/stm32l4_wiring_private.h +++ b/cores/stm32l4/stm32l4_wiring_private.h @@ -84,6 +84,7 @@ extern void USBD_Poll(void); extern bool USBD_Connected(void); extern bool USBD_Configured(void); extern bool USBD_Suspended(void); +extern void USBD_SOFCallback(void(*callback)(void*), void*); /************************************************************************ * diff --git a/system/STM32L4xx/Include/stm32l4_uart.h b/system/STM32L4xx/Include/stm32l4_uart.h index e37d8bba..4cacd3d4 100644 --- a/system/STM32L4xx/Include/stm32l4_uart.h +++ b/system/STM32L4xx/Include/stm32l4_uart.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Thomas Roell. All rights reserved. + * Copyright (c) 2016-2017 Thomas Roell. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -93,6 +93,7 @@ enum { #define UART_EVENT_PARITY 0x00000008 #define UART_EVENT_FRAMING 0x00000010 #define UART_EVENT_OVERRUN 0x00000020 +#define UART_EVENT_TIMEOUT 0x20000000 #define UART_EVENT_RECEIVE 0x40000000 #define UART_EVENT_TRANSMIT 0x80000000 @@ -126,9 +127,14 @@ typedef struct _stm32l4_uart_t { const uint8_t *tx_data; uint16_t tx_count; volatile uint16_t tx_size; + uint8_t rx_fifo[16]; uint8_t *rx_data; uint16_t rx_size; - volatile uint16_t rx_index; + uint16_t rx_read; + uint16_t rx_write; + uint16_t rx_index; + uint16_t rx_event; + volatile uint32_t rx_count; stm32l4_dma_t tx_dma; stm32l4_dma_t rx_dma; } stm32l4_uart_t; @@ -140,6 +146,8 @@ extern bool stm32l4_uart_disable(stm32l4_uart_t *uart); extern bool stm32l4_uart_configure(stm32l4_uart_t *uart, uint32_t bitrate, uint32_t option); extern bool stm32l4_uart_notify(stm32l4_uart_t *uart, stm32l4_uart_callback_t callback, void *context, uint32_t events); extern unsigned int stm32l4_uart_receive(stm32l4_uart_t *uart, uint8_t *rx_data, uint16_t rx_count); +extern unsigned int stm32l4_uart_count(stm32l4_uart_t *uart); +extern int stm32l4_uart_peek(stm32l4_uart_t *uart); extern bool stm32l4_uart_transmit(stm32l4_uart_t *uart, const uint8_t *tx_data, uint16_t tx_count); extern bool stm32l4_uart_send_break(stm32l4_uart_t *uart); extern bool stm32l4_uart_done(stm32l4_uart_t *uart); diff --git a/system/STM32L4xx/Include/stm32l4_usbd_cdc.h b/system/STM32L4xx/Include/stm32l4_usbd_cdc.h index 06f6495d..4655e9e3 100644 --- a/system/STM32L4xx/Include/stm32l4_usbd_cdc.h +++ b/system/STM32L4xx/Include/stm32l4_usbd_cdc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Thomas Roell. All rights reserved. + * Copyright (c) 2016-2017 Thomas Roell. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -54,7 +54,6 @@ typedef struct _stm32l4_usbd_cdc_info_t { extern volatile stm32l4_usbd_cdc_info_t stm32l4_usbd_cdc_info; -#define USBD_CDC_EVENT_OVERRUN 0x00000001 #define USBD_CDC_EVENT_RECEIVE 0x40000000 #define USBD_CDC_EVENT_TRANSMIT 0x80000000 @@ -71,17 +70,22 @@ typedef struct _stm32l4_usbd_cdc_t { void *context; uint32_t events; uint8_t *rx_data; - uint32_t rx_size; - volatile uint32_t rx_index; + uint16_t rx_size; + uint16_t rx_read; + uint16_t rx_write; + volatile uint16_t rx_wrap; + volatile uint32_t rx_count; } stm32l4_usbd_cdc_t; extern bool stm32l4_usbd_cdc_create(stm32l4_usbd_cdc_t *usbd_cdc); extern bool stm32l4_usbd_cdc_destroy(stm32l4_usbd_cdc_t *usbd_cdc); -extern bool stm32l4_usbd_cdc_enable(stm32l4_usbd_cdc_t *usbd_cdc, uint32_t option, stm32l4_usbd_cdc_callback_t callback, void *context, uint32_t events); +extern bool stm32l4_usbd_cdc_enable(stm32l4_usbd_cdc_t *usbd_cdc, uint8_t *rx_data, uint16_t rx_size, uint32_t option, stm32l4_usbd_cdc_callback_t callback, void *context, uint32_t events); extern bool stm32l4_usbd_cdc_disable(stm32l4_usbd_cdc_t *usbd_cdc); extern bool stm32l4_usbd_cdc_configure(stm32l4_usbd_cdc_t *usbd_cdc, uint32_t option); extern bool stm32l4_usbd_cdc_notify(stm32l4_usbd_cdc_t *usbd_cdc, stm32l4_usbd_cdc_callback_t callback, void *context, uint32_t events); -extern unsigned int stm32l4_usbd_cdc_receive(stm32l4_usbd_cdc_t *usbd_cdc, uint8_t *rx_data, uint32_t rx_count); +extern unsigned int stm32l4_usbd_cdc_receive(stm32l4_usbd_cdc_t *usbd_cdc, uint8_t *rx_data, uint16_t rx_count); +extern unsigned int stm32l4_usbd_cdc_count(stm32l4_usbd_cdc_t *usbd_cdc); +extern int stm32l4_usbd_cdc_peek(stm32l4_usbd_cdc_t *usbd_cdc); extern bool stm32l4_usbd_cdc_transmit(stm32l4_usbd_cdc_t *usbd_cdc, const uint8_t *tx_data, uint32_t tx_count); extern bool stm32l4_usbd_cdc_done(stm32l4_usbd_cdc_t *usbd_cdc); extern void stm32l4_usbd_cdc_poll(stm32l4_usbd_cdc_t *usbd_cdc); diff --git a/system/STM32L4xx/Lib/libstm32l432.a b/system/STM32L4xx/Lib/libstm32l432.a index b7e6b91f..57ced6d3 100644 Binary files a/system/STM32L4xx/Lib/libstm32l432.a and b/system/STM32L4xx/Lib/libstm32l432.a differ diff --git a/system/STM32L4xx/Lib/libstm32l433.a b/system/STM32L4xx/Lib/libstm32l433.a index a5b9fbdc..53ffe2f2 100644 Binary files a/system/STM32L4xx/Lib/libstm32l433.a and b/system/STM32L4xx/Lib/libstm32l433.a differ diff --git a/system/STM32L4xx/Lib/libstm32l476.a b/system/STM32L4xx/Lib/libstm32l476.a index bf00d16d..5e11c58e 100644 Binary files a/system/STM32L4xx/Lib/libstm32l476.a and b/system/STM32L4xx/Lib/libstm32l476.a differ diff --git a/system/STM32L4xx/Source/USB/usbd_conf.c b/system/STM32L4xx/Source/USB/usbd_conf.c index 36be8e10..7d07fd64 100644 --- a/system/STM32L4xx/Source/USB/usbd_conf.c +++ b/system/STM32L4xx/Source/USB/usbd_conf.c @@ -57,7 +57,6 @@ #include "armv7m.h" #include "stm32l4_system.h" #include "stm32l4_gpio.h" -#include "stm32l4_usbd_cdc.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ @@ -65,11 +64,11 @@ /* Private variables ---------------------------------------------------------*/ static PCD_HandleTypeDef hpcd; -extern stm32l4_usbd_cdc_t stm32l4_usbd_cdc; - static unsigned int usbd_pin_vbus; static unsigned int usbd_pin_vbus_count = 0; static bool usbd_connected = false; +static void (*usbd_sof_callback)(void*) = NULL; +static void *usbd_sof_context; /* Private functions ---------------------------------------------------------*/ @@ -272,67 +271,11 @@ bool USBD_Suspended(void) return (USBD_Device.dev_state == USBD_STATE_SUSPENDED); } -int stm32l4_console(char *buf, int nbytes) +void USBD_SOFCallback(void(*callback)(void*), void *context) { - if (stm32l4_usbd_cdc.state == USBD_CDC_STATE_NONE) - { - stm32l4_usbd_cdc_create(&stm32l4_usbd_cdc); - } - - if (stm32l4_usbd_cdc.state == USBD_CDC_STATE_INIT) - { - stm32l4_usbd_cdc_enable(&stm32l4_usbd_cdc, 0, NULL, NULL, 0); - } - - if (stm32l4_usbd_cdc_connected(&stm32l4_usbd_cdc)) - { - if (!stm32l4_usbd_cdc_done(&stm32l4_usbd_cdc)) - { -#if defined(STM32L476xx) - if (armv7m_core_priority() <= (int)NVIC_GetPriority(OTG_FS_IRQn)) -#else - if (armv7m_core_priority() <= (int)NVIC_GetPriority(USB_IRQn)) -#endif - { - while (!stm32l4_usbd_cdc_done(&stm32l4_usbd_cdc)) - { - stm32l4_usbd_cdc_poll(&stm32l4_usbd_cdc); - } - } - else - { - while (!stm32l4_usbd_cdc_done(&stm32l4_usbd_cdc)) - { - armv7m_core_yield(); - } - } - } - - stm32l4_usbd_cdc_transmit(&stm32l4_usbd_cdc, (const uint8_t*)buf, nbytes); - -#if defined(STM32L476xx) - if (armv7m_core_priority() <= (int)NVIC_GetPriority(OTG_FS_IRQn)) -#else - if (armv7m_core_priority() <= (int)NVIC_GetPriority(USB_IRQn)) -#endif - { - while (!stm32l4_usbd_cdc_done(&stm32l4_usbd_cdc)) - { - stm32l4_usbd_cdc_poll(&stm32l4_usbd_cdc); - } - } - else - { - while (!stm32l4_usbd_cdc_done(&stm32l4_usbd_cdc)) - { - armv7m_core_yield(); - } - } - } - - return nbytes; + usbd_sof_callback = callback; + usbd_sof_context = context; } - /******************************************************************************* PCD BSP Routines @@ -470,6 +413,10 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_SOF(hpcd->pData); + + if (usbd_sof_callback) { + (*usbd_sof_callback)(usbd_sof_context); + } } /** diff --git a/system/STM32L4xx/Source/stm32l4_clib.c b/system/STM32L4xx/Source/stm32l4_clib.c index b6fa232f..5f2690d4 100644 --- a/system/STM32L4xx/Source/stm32l4_clib.c +++ b/system/STM32L4xx/Source/stm32l4_clib.c @@ -35,7 +35,6 @@ #include #include "armv7m.h" -#include "stm32l4_usbd_cdc.h" int (*stm32l4_stdio_put)(char, FILE*) = NULL; int (*stm32l4_stdio_get)(FILE*) = NULL; @@ -43,13 +42,9 @@ int (*stm32l4_stdio_get)(FILE*) = NULL; #undef errno extern int errno; -extern stm32l4_usbd_cdc_t stm32l4_usbd_cdc; - extern uint32_t __HeapBase[]; extern uint32_t __StackLimit[]; -__attribute__((weak)) int stm32l4_console(char *buf, int nbytes) { return 0; } - void * _sbrk (int nbytes) { void *p; @@ -174,10 +169,6 @@ int _write(int file, char *buf, int nbytes) } while (nbytes != 0); } - else - { - n = stm32l4_console(buf, nbytes); - } } return n; diff --git a/system/STM32L4xx/Source/stm32l4_uart.c b/system/STM32L4xx/Source/stm32l4_uart.c index 83f9bb5b..aae9108b 100644 --- a/system/STM32L4xx/Source/stm32l4_uart.c +++ b/system/STM32L4xx/Source/stm32l4_uart.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Thomas Roell. All rights reserved. + * Copyright (c) 2016-2017 Thomas Roell. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -91,14 +91,74 @@ static const IRQn_Type stm32l4_uart_xlate_IRQn[UART_INSTANCE_COUNT] = { static void stm32l4_uart_dma_callback(stm32l4_uart_t *uart, uint32_t events) { - /* DMA_EVENT_TRANSFER_DONE or DMA_EVENT_TRANSFER_HALF - */ + uint32_t rx_index, rx_count, rx_total, rx_size, rx_write; + bool overrun = false; + + rx_index = uart->rx_index; + rx_count = stm32l4_dma_count(&uart->rx_dma); - if (uart->rx_index != stm32l4_dma_count(&uart->rx_dma)) + if (rx_index != rx_count) { - if (uart->events & UART_EVENT_RECEIVE) + rx_count = (rx_count - rx_index) & 15; + + uart->rx_index = (rx_index + rx_count) & 15; + + if (rx_count > (uart->rx_size - uart->rx_count)) + { + rx_count = (uart->rx_size - uart->rx_count); + + overrun = true; + } + + rx_total = rx_count; + rx_write = uart->rx_write; + rx_size = rx_total; + + if (rx_size > (uart->rx_size - rx_write)) + { + rx_size = (uart->rx_size - rx_write); + } + + memcpy(&uart->rx_data[rx_write], &uart->rx_fifo[rx_index], rx_size); + + rx_write += rx_size; + rx_index += rx_size; + rx_total -= rx_size; + + if (rx_write == uart->rx_size) { - (*uart->callback)(uart->context, UART_EVENT_RECEIVE); + rx_write = 0; + } + + if (rx_total) + { + memcpy(&uart->rx_data[rx_write], &uart->rx_fifo[rx_index], rx_total); + + rx_write += rx_total; + } + + uart->rx_write = rx_write; + + armv7m_atomic_add(&uart->rx_count, rx_count); + + uart->rx_event += rx_count; + + if (uart->rx_event >= 16) + { + uart->rx_event = 0; + + if (uart->events & UART_EVENT_RECEIVE) + { + (*uart->callback)(uart->context, UART_EVENT_RECEIVE); + } + } + + if (overrun) + { + if (uart->events & UART_EVENT_OVERRUN) + { + (*uart->callback)(uart->context, UART_EVENT_OVERRUN); + } } } } @@ -106,56 +166,116 @@ static void stm32l4_uart_dma_callback(stm32l4_uart_t *uart, uint32_t events) static void stm32l4_uart_interrupt(stm32l4_uart_t *uart) { USART_TypeDef *USART = uart->USART; - uint32_t events; - + uint32_t events, rx_index, rx_count, rx_total, rx_size, rx_write; + uint8_t rx_data; + events = 0; - if (USART->ISR & (USART_ISR_PE | USART_ISR_FE | USART_ISR_NE | USART_ISR_ORE | USART_ISR_IDLE | USART_ISR_LBDF)) + if (USART->ISR & USART_ISR_RXNE) { - if (uart->events & (UART_EVENT_IDLE | UART_EVENT_BREAK | UART_EVENT_NOISE | UART_EVENT_PARITY | UART_EVENT_FRAMING | UART_EVENT_OVERRUN)) + if (USART->CR1 & USART_CR1_RXNEIE) { - if (USART->ISR & USART_ISR_PE) - { - events |= UART_EVENT_PARITY; - } - - if (USART->ISR & USART_ISR_FE) - { - events |= UART_EVENT_FRAMING; - } - - if (USART->ISR & USART_ISR_NE) - { - events |= UART_EVENT_NOISE; - } - - if (USART->ISR & USART_ISR_IDLE) + rx_data = USART->RDR; + + if (uart->rx_count != uart->rx_size) { - events |= UART_EVENT_IDLE; + rx_write = uart->rx_write; + + uart->rx_data[rx_write] = rx_data; + + rx_write++; + + if (rx_write == uart->rx_size) + { + rx_write = 0; + } + + uart->rx_write = rx_write; + + armv7m_atomic_add(&uart->rx_count, 1); + + uart->rx_event++; + + if (uart->rx_event >= 16) + { + uart->rx_event = 0; + + events |= UART_EVENT_RECEIVE; + } } - - if (USART->ISR & USART_ISR_ORE) + else { events |= UART_EVENT_OVERRUN; } - - if (USART->ISR & USART_ISR_LBDF) - { - events |= UART_EVENT_BREAK; - } } - - USART->ICR = (USART_ICR_PECF | USART_ICR_FECF | USART_ICR_NCF | USART_ICR_ORECF | USART_ICR_IDLECF | USART_ICR_LBDCF); } - if (USART->ISR & USART_ISR_RXNE) + if (USART->ISR & USART_ISR_RTOF) { - if (USART->CR1 & USART_CR1_RXNEIE) + if (USART->CR1 & USART_CR1_RTOIE) { - uart->rx_index = USART->RDR; + if (uart->mode & UART_MODE_RX_DMA) + { + rx_index = uart->rx_index; + rx_count = stm32l4_dma_count(&uart->rx_dma); + + if (rx_index != rx_count) + { + rx_count = (rx_count - rx_index) & 15; + + uart->rx_index = (rx_index + rx_count) & 15; + + if (rx_count > (uart->rx_size - uart->rx_count)) + { + rx_count = (uart->rx_size - uart->rx_count); + + events |= UART_EVENT_OVERRUN; + } + + rx_total = rx_count; + rx_write = uart->rx_write; + rx_size = rx_total; + + if (rx_size > (uart->rx_size - rx_write)) + { + rx_size = (uart->rx_size - rx_write); + } + + memcpy(&uart->rx_data[rx_write], &uart->rx_fifo[rx_index], rx_size); + + rx_write += rx_size; + rx_index += rx_size; + rx_total -= rx_size; + + if (rx_write == uart->rx_size) + { + rx_write = 0; + } + + if (rx_total) + { + memcpy(&uart->rx_data[rx_write], &uart->rx_fifo[rx_index], rx_total); + + rx_write += rx_total; + } + + uart->rx_write = rx_write; + + armv7m_atomic_add(&uart->rx_count, rx_count); + + uart->rx_event += rx_count; + } + } - events |= UART_EVENT_RECEIVE; + if (uart->rx_event) + { + uart->rx_event = 0; + + events |= UART_EVENT_RECEIVE; + } } + + USART->ICR = USART_ICR_RTOCF; } if (USART->ISR & USART_ISR_TXE) @@ -195,17 +315,42 @@ static void stm32l4_uart_interrupt(stm32l4_uart_t *uart) } } - if (USART->ISR & USART_ISR_RTOF) + if (USART->ISR & (USART_ISR_PE | USART_ISR_FE | USART_ISR_NE | USART_ISR_ORE | USART_ISR_IDLE | USART_ISR_LBDF)) { - if (USART->CR1 & USART_CR1_RTOIE) + if (uart->events & (UART_EVENT_IDLE | UART_EVENT_BREAK | UART_EVENT_NOISE | UART_EVENT_PARITY | UART_EVENT_FRAMING | UART_EVENT_OVERRUN)) { - if (uart->rx_index != stm32l4_dma_count(&uart->rx_dma)) + if (USART->ISR & USART_ISR_PE) { - events |= UART_EVENT_RECEIVE; + events |= UART_EVENT_PARITY; + } + + if (USART->ISR & USART_ISR_FE) + { + events |= UART_EVENT_FRAMING; + } + + if (USART->ISR & USART_ISR_NE) + { + events |= UART_EVENT_NOISE; + } + + if (USART->ISR & USART_ISR_IDLE) + { + events |= UART_EVENT_IDLE; + } + + if (USART->ISR & USART_ISR_ORE) + { + events |= UART_EVENT_OVERRUN; + } + + if (USART->ISR & USART_ISR_LBDF) + { + events |= UART_EVENT_BREAK; } } - USART->ICR = USART_ICR_RTOCF; + USART->ICR = (USART_ICR_PECF | USART_ICR_FECF | USART_ICR_NCF | USART_ICR_ORECF | USART_ICR_IDLECF | USART_ICR_LBDCF); } events &= uart->events; @@ -369,22 +514,19 @@ bool stm32l4_uart_enable(stm32l4_uart_t *uart, uint8_t *rx_data, uint16_t rx_siz return false; } - if (uart->mode & UART_MODE_RX_DMA) - { - if ((rx_data == NULL) || (rx_size < 8)) - { - return false; - } - - uart->rx_data = rx_data; - uart->rx_size = rx_size; - uart->rx_index = 0; - } - else + if ((rx_data == NULL) || (rx_size < 16)) { - uart->rx_index = UART_RX_DATA_NONE; + return false; } + uart->rx_data = rx_data; + uart->rx_size = rx_size; + uart->rx_read = 0; + uart->rx_write = 0; + uart->rx_index = 0; + uart->rx_event = 0; + uart->rx_count = 0; + if (uart->instance != UART_INSTANCE_LPUART1) { stm32l4_system_hsi16_enable(); @@ -543,19 +685,19 @@ bool stm32l4_uart_configure(stm32l4_uart_t *uart, uint32_t bitrate, uint32_t opt if ((uart->pins.rx != GPIO_PIN_NONE) || ((uart->pins.tx != GPIO_PIN_NONE) && (option & UART_OPTION_HALF_DUPLEX_MODE))) { usart_cr1 |= USART_CR1_RE; + usart_cr1 |= USART_CR1_RTOIE; + usart_cr2 |= USART_CR2_RTOEN; if (uart->mode & UART_MODE_RX_DMA) { - usart_cr1 |= USART_CR1_RTOIE; - usart_cr2 |= USART_CR2_RTOEN; usart_cr3 |= USART_CR3_DMAR; - - USART->RTOR = 32; } else { usart_cr1 |= USART_CR1_RXNEIE; } + + USART->RTOR = 32; } if (uart->pins.tx != GPIO_PIN_NONE) @@ -680,7 +822,7 @@ bool stm32l4_uart_configure(stm32l4_uart_t *uart, uint32_t bitrate, uint32_t opt if (uart->state == UART_STATE_BUSY) { stm32l4_dma_enable(&uart->rx_dma, (stm32l4_dma_callback_t)stm32l4_uart_dma_callback, uart); - stm32l4_dma_start(&uart->rx_dma, (uint32_t)uart->rx_data, (uint32_t)&USART->RDR, uart->rx_size, UART_RX_DMA_OPTION); + stm32l4_dma_start(&uart->rx_dma, (uint32_t)uart->rx_fifo, (uint32_t)&USART->RDR, 16, UART_RX_DMA_OPTION); } } @@ -813,56 +955,81 @@ bool stm32l4_uart_notify(stm32l4_uart_t *uart, stm32l4_uart_callback_t callback, unsigned int stm32l4_uart_receive(stm32l4_uart_t *uart, uint8_t *rx_data, uint16_t rx_count) { - uint16_t rx_size, rx_index, dma_count, rx_receive; + uint32_t rx_total, rx_size, rx_read; if (uart->state < UART_STATE_READY) { return false; } - rx_size = 0; + rx_size = uart->rx_count; - if (uart->mode & UART_MODE_RX_DMA) + if (rx_count > rx_size) { - rx_index = uart->rx_index; - dma_count = stm32l4_dma_count(&uart->rx_dma); + rx_count = rx_size; + } - while ((rx_index != dma_count) && (rx_size < rx_count)) - { - rx_data[rx_size++] = uart->rx_data[rx_index]; + rx_total = rx_count; - rx_index++; + rx_read = uart->rx_read; + rx_size = rx_total; - if (rx_index == uart->rx_size) - { - rx_index = 0; - } + if ((rx_read + rx_size) > uart->rx_size) + { + rx_size = uart->rx_size - rx_read; + } - if (rx_index == dma_count) - { - dma_count = stm32l4_dma_count(&uart->rx_dma); - } - } + memcpy(rx_data, &uart->rx_data[rx_read], rx_size); + + rx_read += rx_size; + rx_total -= rx_size; - uart->rx_index = rx_index; + if (rx_read == uart->rx_size) + { + rx_read = 0; } - else + + uart->rx_read = rx_read; + + armv7m_atomic_sub(&uart->rx_count, rx_size); + + if (rx_total) { - do - { - rx_receive = uart->rx_index; + memcpy(rx_data + rx_size, &uart->rx_data[rx_read], rx_total); - if (rx_receive != UART_RX_DATA_NONE) - { - uart->rx_index = UART_RX_DATA_NONE; + rx_read += rx_total; - rx_data[rx_size++] = rx_receive; - } - } - while ((rx_receive != UART_RX_DATA_NONE) && (rx_size < rx_count)); + uart->rx_read = rx_read; + + armv7m_atomic_sub(&uart->rx_count, rx_total); + } + + return rx_count; +} + +unsigned int stm32l4_uart_count(stm32l4_uart_t *uart) +{ + if (uart->state < UART_STATE_READY) + { + return 0; + } + + return uart->rx_count; +} + +int stm32l4_uart_peek(stm32l4_uart_t *uart) +{ + if (uart->state < UART_STATE_READY) + { + return -1; + } + + if (!uart->rx_count) + { + return -1; } - return rx_size; + return uart->rx_data[uart->rx_read]; } bool stm32l4_uart_transmit(stm32l4_uart_t *uart, const uint8_t *tx_data, uint16_t tx_count) diff --git a/system/STM32L4xx/Source/stm32l4_usbd_cdc.c b/system/STM32L4xx/Source/stm32l4_usbd_cdc.c index addb7cfc..449ef267 100644 --- a/system/STM32L4xx/Source/stm32l4_usbd_cdc.c +++ b/system/STM32L4xx/Source/stm32l4_usbd_cdc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Thomas Roell. All rights reserved. + * Copyright (c) 2016-2017 Thomas Roell. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -46,8 +46,8 @@ static stm32l4_usbd_cdc_driver_t stm32l4_usbd_cdc_driver; typedef struct _stm32l4_usbd_cdc_device_t { struct _USBD_HandleTypeDef *USBD; + volatile uint8_t rx_busy; volatile uint8_t tx_busy; - uint8_t rx_data[USBD_CDC_DATA_MAX_PACKET_SIZE]; uint64_t connect; armv7m_timer_t timeout; } stm32l4_usbd_cdc_device_t; @@ -56,7 +56,10 @@ static stm32l4_usbd_cdc_device_t stm32l4_usbd_cdc_device; static void stm32l4_usbd_cdc_init(USBD_HandleTypeDef *USBD) { + stm32l4_usbd_cdc_t *usbd_cdc = stm32l4_usbd_cdc_driver.instances[0]; + stm32l4_usbd_cdc_device.USBD = USBD; + stm32l4_usbd_cdc_device.rx_busy = 0; stm32l4_usbd_cdc_device.tx_busy = 0; stm32l4_usbd_cdc_device.connect = 0;; @@ -68,8 +71,13 @@ static void stm32l4_usbd_cdc_init(USBD_HandleTypeDef *USBD) armv7m_timer_create(&stm32l4_usbd_cdc_device.timeout, (armv7m_timer_callback_t)&stm32l4_system_dfu); - USBD_CDC_SetRxBuffer(stm32l4_usbd_cdc_device.USBD, &stm32l4_usbd_cdc_device.rx_data[0]); - USBD_CDC_ReceivePacket(stm32l4_usbd_cdc_device.USBD); + if (usbd_cdc && (usbd_cdc->state > USBD_CDC_STATE_INIT)) + { + USBD_CDC_SetRxBuffer(stm32l4_usbd_cdc_device.USBD, &usbd_cdc->rx_data[usbd_cdc->rx_write]); + USBD_CDC_ReceivePacket(stm32l4_usbd_cdc_device.USBD); + + stm32l4_usbd_cdc_device.rx_busy = 1; + } } static void stm32l4_usbd_cdc_deinit(void) @@ -80,6 +88,8 @@ static void stm32l4_usbd_cdc_deinit(void) stm32l4_usbd_cdc_info.lineState = 0; + stm32l4_usbd_cdc_device.rx_busy = 0; + if (stm32l4_usbd_cdc_device.tx_busy) { stm32l4_usbd_cdc_device.tx_busy = 0; @@ -150,30 +160,33 @@ static void stm32l4_usbd_cdc_data_receive(uint8_t *data, uint32_t length) { stm32l4_usbd_cdc_t *usbd_cdc = stm32l4_usbd_cdc_driver.instances[0]; + stm32l4_usbd_cdc_device.rx_busy = 0; + if (usbd_cdc && (usbd_cdc->state > USBD_CDC_STATE_INIT)) { - usbd_cdc->rx_data = data; - usbd_cdc->rx_size = length; + usbd_cdc->rx_write += length; - if (usbd_cdc->events & USBD_CDC_EVENT_RECEIVE) + armv7m_atomic_add(&usbd_cdc->rx_count, length); + + if ((usbd_cdc->rx_write + USBD_CDC_DATA_MAX_PACKET_SIZE) > usbd_cdc->rx_size) { - (*usbd_cdc->callback)(usbd_cdc->context, USBD_CDC_EVENT_RECEIVE); + usbd_cdc->rx_wrap = usbd_cdc->rx_write; + usbd_cdc->rx_write = 0; } - if (usbd_cdc->rx_index != usbd_cdc->rx_size) + if ((usbd_cdc->rx_wrap - usbd_cdc->rx_count) >= USBD_CDC_DATA_MAX_PACKET_SIZE) { - if (usbd_cdc->events & USBD_CDC_EVENT_OVERRUN) - { - (*usbd_cdc->callback)(usbd_cdc->context, USBD_CDC_EVENT_OVERRUN); - } + USBD_CDC_SetRxBuffer(stm32l4_usbd_cdc_device.USBD, &usbd_cdc->rx_data[usbd_cdc->rx_write]); + USBD_CDC_ReceivePacket(stm32l4_usbd_cdc_device.USBD); + + stm32l4_usbd_cdc_device.rx_busy = 1; } - usbd_cdc->rx_data = NULL; - usbd_cdc->rx_size = 0; - usbd_cdc->rx_index = 0; + if (usbd_cdc->events & USBD_CDC_EVENT_RECEIVE) + { + (*usbd_cdc->callback)(usbd_cdc->context, USBD_CDC_EVENT_RECEIVE); + } } - - USBD_CDC_ReceivePacket(stm32l4_usbd_cdc_device.USBD); } static void stm32l4_usbd_cdc_data_transmit(void) @@ -205,7 +218,10 @@ bool stm32l4_usbd_cdc_create(stm32l4_usbd_cdc_t *usbd_cdc) usbd_cdc->rx_data = NULL; usbd_cdc->rx_size = 0; - usbd_cdc->rx_index = 0; + usbd_cdc->rx_read = 0; + usbd_cdc->rx_write = 0; + usbd_cdc->rx_wrap = 0; + usbd_cdc->rx_count = 0; usbd_cdc->callback = NULL; usbd_cdc->context = NULL; @@ -228,16 +244,19 @@ bool stm32l4_usbd_cdc_destroy(stm32l4_usbd_cdc_t *usbd_cdc) return true; } -bool stm32l4_usbd_cdc_enable(stm32l4_usbd_cdc_t *usbd_cdc, uint32_t option, stm32l4_usbd_cdc_callback_t callback, void *context, uint32_t events) +bool stm32l4_usbd_cdc_enable(stm32l4_usbd_cdc_t *usbd_cdc, uint8_t *rx_data, uint16_t rx_size, uint32_t option, stm32l4_usbd_cdc_callback_t callback, void *context, uint32_t events) { if (usbd_cdc->state != USBD_CDC_STATE_INIT) { return false; } - usbd_cdc->rx_data = NULL; - usbd_cdc->rx_size = 0; - usbd_cdc->rx_index = 0; + usbd_cdc->rx_data = rx_data; + usbd_cdc->rx_size = rx_size; + usbd_cdc->rx_read = 0; + usbd_cdc->rx_write = 0; + usbd_cdc->rx_wrap = rx_size; + usbd_cdc->rx_count = 0; usbd_cdc->option = option; @@ -247,6 +266,14 @@ bool stm32l4_usbd_cdc_enable(stm32l4_usbd_cdc_t *usbd_cdc, uint32_t option, stm3 usbd_cdc->state = USBD_CDC_STATE_READY; + if (stm32l4_usbd_cdc_device.USBD) + { + USBD_CDC_SetRxBuffer(stm32l4_usbd_cdc_device.USBD, &usbd_cdc->rx_data[usbd_cdc->rx_write]); + USBD_CDC_ReceivePacket(stm32l4_usbd_cdc_device.USBD); + + stm32l4_usbd_cdc_device.rx_busy = 1; + } + return true; } @@ -261,7 +288,10 @@ bool stm32l4_usbd_cdc_disable(stm32l4_usbd_cdc_t *usbd_cdc) usbd_cdc->rx_data = NULL; usbd_cdc->rx_size = 0; - usbd_cdc->rx_index = 0; + usbd_cdc->rx_read = 0; + usbd_cdc->rx_write = 0; + usbd_cdc->rx_wrap = 0; + usbd_cdc->rx_count = 0; usbd_cdc->callback = NULL; usbd_cdc->context = NULL; @@ -286,29 +316,97 @@ bool stm32l4_usbd_cdc_notify(stm32l4_usbd_cdc_t *usbd_cdc, stm32l4_usbd_cdc_call return true; } -unsigned int stm32l4_usbd_cdc_receive(stm32l4_usbd_cdc_t *usbd_cdc, uint8_t *rx_data, uint32_t rx_count) +unsigned int stm32l4_usbd_cdc_receive(stm32l4_usbd_cdc_t *usbd_cdc, uint8_t *rx_data, uint16_t rx_count) { - uint32_t rx_size, rx_index; + uint32_t rx_total, rx_size, rx_read, rx_wrap; if (usbd_cdc->state < USBD_CDC_STATE_READY) { return false; } - rx_size = 0; + rx_size = usbd_cdc->rx_count; + + if (rx_count > rx_size) + { + rx_count = rx_size; + } + + rx_total = rx_count; + + rx_read = usbd_cdc->rx_read; + rx_wrap = usbd_cdc->rx_wrap; + rx_size = rx_total; + + if ((rx_read + rx_size) > rx_wrap) + { + rx_size = rx_wrap - rx_read; + } + + memcpy(rx_data, &usbd_cdc->rx_data[rx_read], rx_size); + + rx_read += rx_size; + rx_total -= rx_size; + + if (rx_read == rx_wrap) + { + rx_read = 0; + + usbd_cdc->rx_wrap = usbd_cdc->rx_size; + } + + usbd_cdc->rx_read = rx_read; + + armv7m_atomic_sub(&usbd_cdc->rx_count, rx_size); + + if (rx_total) + { + memcpy(rx_data + rx_size, &usbd_cdc->rx_data[rx_read], rx_total); + + rx_read += rx_total; + + usbd_cdc->rx_read = rx_read; + + armv7m_atomic_sub(&usbd_cdc->rx_count, rx_total); + } + + if (stm32l4_usbd_cdc_device.USBD && !stm32l4_usbd_cdc_device.rx_busy) + { + if ((usbd_cdc->rx_wrap - usbd_cdc->rx_count) >= USBD_CDC_DATA_MAX_PACKET_SIZE) + { + USBD_CDC_SetRxBuffer(stm32l4_usbd_cdc_device.USBD, &usbd_cdc->rx_data[usbd_cdc->rx_write]); + USBD_CDC_ReceivePacket(stm32l4_usbd_cdc_device.USBD); + + stm32l4_usbd_cdc_device.rx_busy = 1; + } + } - rx_index = usbd_cdc->rx_index; + return rx_count; +} - while ((rx_index != usbd_cdc->rx_size) && (rx_size < rx_count)) +unsigned int stm32l4_usbd_cdc_count(stm32l4_usbd_cdc_t *usbd_cdc) +{ + if (usbd_cdc->state < USBD_CDC_STATE_READY) { - rx_data[rx_size++] = usbd_cdc->rx_data[rx_index]; + return 0; + } + + return usbd_cdc->rx_count; +} - rx_index++; +int stm32l4_usbd_cdc_peek(stm32l4_usbd_cdc_t *usbd_cdc) +{ + if (usbd_cdc->state < USBD_CDC_STATE_READY) + { + return -1; } - usbd_cdc->rx_index = rx_index; + if (!usbd_cdc->rx_count) + { + return -1; + } - return rx_size; + return usbd_cdc->rx_data[usbd_cdc->rx_read]; } bool stm32l4_usbd_cdc_transmit(stm32l4_usbd_cdc_t *usbd_cdc, const uint8_t *tx_data, uint32_t tx_count) diff --git a/variants/STM32L432KC-Ladybug/variant.cpp b/variants/STM32L432KC-Ladybug/variant.cpp index 07468d6a..acdb6d7b 100644 --- a/variants/STM32L432KC-Ladybug/variant.cpp +++ b/variants/STM32L432KC-Ladybug/variant.cpp @@ -41,7 +41,7 @@ extern const PinDescription g_APinDescription[NUM_TOTAL_PINS] = { // 0..13 - Digital pins { GPIOA, GPIO_PIN_MASK(GPIO_PIN_PA10), GPIO_PIN_PA10_TIM1_CH3, (PIN_ATTR_PWM | PIN_ATTR_EXTI), PWM_INSTANCE_TIM1, PWM_CHANNEL_3, ADC_INPUT_NONE }, - { GPIOA, GPIO_PIN_MASK(GPIO_PIN_PA9), GPIO_PIN_PA9_TIM1_CH2, (PIN_ATTR_PWM | PIN_ATTR_EXTI), PWM_INSTANCE_TIM1, PWM_CHANNEL_3, ADC_INPUT_NONE }, + { GPIOA, GPIO_PIN_MASK(GPIO_PIN_PA9), GPIO_PIN_PA9_TIM1_CH2, (PIN_ATTR_PWM | PIN_ATTR_EXTI), PWM_INSTANCE_TIM1, PWM_CHANNEL_2, ADC_INPUT_NONE }, { NULL, 0, GPIO_PIN_NONE, 0, PWM_INSTANCE_NONE, PWM_CHANNEL_NONE, ADC_INPUT_NONE }, { GPIOB, GPIO_PIN_MASK(GPIO_PIN_PB3), GPIO_PIN_PB3_TIM2_CH2, (PIN_ATTR_PWM | PIN_ATTR_EXTI), PWM_INSTANCE_TIM2, PWM_CHANNEL_2, ADC_INPUT_NONE }, { GPIOB, GPIO_PIN_MASK(GPIO_PIN_PB4), GPIO_PIN_PB4, (PIN_ATTR_EXTI), PWM_INSTANCE_NONE, PWM_CHANNEL_NONE, ADC_INPUT_NONE },