back
Unlike older Maple library, STM32duino USBDevice does not support composite USB for e.g. CDC + MIDI.
- USBLibrarySTM32 emulates AVR Arduino PluggableUSB API,
effectively replacing STM32duino core
USBDevice library
- reportedly works with Arduino sketches ported to PlatformIO, but had issues in Arduino 2.
- wanted to pretend that it is ARDUINO_ARCH_AVR ;
instead, hacked HID-project/src/HID-Settings.h and MIDIUSB/src/MIDIUSB.h :
- #if defined(ARDUINO_ARCH_AVR)
+ #if defined(ARDUINO_ARCH_AVR) || defined(HAL_PCD_MODULE_ENABLED)
- requires USBCON and HAL_PCD_MODULE_ENABLED build flags
probably set in menu based on usb_flags and platform.txt
- Arduino 2 does not see files in USBLibrarySTM32/include/ ;
moving those files to USBLibrarySTM32/src/ fixed that.
- reported my experience
- coordination with STM32duino core USB is discussed here;
likely integration would be as a menu option
This compiles with hacked MIDIUSB Library for Arduino example sketch,
but then failed to link because duplicated STM32duino USB library definitions.
working   5 Sep 2025
- sample SerialUSB sketch compiles, loads and runs on a Black Pill from VSCode-Arduino. then Arduino 2:
- moved
USBDevice folder out of Arduino15/packages/STMicroelectronics/hardware/stm32/2.11.0/libraries
Arduino 2 scripting wanted to use USBDevice source, whether referenced or not..
- added
USBLibrarySTM32 to Documents/Arduino/libraries
- in
USBLibrarySTM32 , moved files from include to src
- moved
SerialUSB example src/main.cpp to SerialUSB.ino , added build_opt.h
added syncopated LED blink code to SerialUSB.ino , for deducing execution state
- Arduino Serial Monitor or PuTTY can connect and pass data
initially failed, because COM8 conflict with com0com null modem
failed workarounds, leaving USBDevice folder in Arduino15/packages/STMicroelectronics/hardware/stm32/2.11.0/libraries
STM32duino USB multiple definition
- install and use a custom core version
more details: Platform specification
https://github.com/stm32duino/Arduino_Core_STM32
seemingly matches (658MB) content at
AppData/Local/Arduino15/packages/STMicroelectronics/hardware/stm32/2.11.0/
results from grep -R USBD_Init
- potential hack, based on feedback from @Levi--G
- add
../Arduino2/platform.local.txt file in packages/STMicroelectronics/hardware/stm32/2.11.0/ :
USBDevice_include_dir=/libraries/USBLibrarySTM32
With only this change, builds fail:
C:\Users\bleke\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.11.0\cores\arduino/WSerial.h:7:12:
fatal error: USBSerial.h: No such file or directory
7 | #include "USBSerial.h"
| ^~~~~~~~~~~~~
compilation terminated.
Success requires setting USB support (if available): "None" , then:
$ cat MIDIUSB_loop/build_opt.h
-DUSBCON -DHAL_PCD_MODULE_ENABLED
- Attempts to build a USBSerial library in user space failed
- Compiling STM32 core seemingly uses incompatible rules...
USB enumeration, endpoints and descriptors
hardware serial trace log; USBSerial COM session terminated after goodbye
USBLibrarySTM32 seemingly lacks means to detect COM port session disconnects;
USBSerial.availableForWrite() presumably reports space available when not.
- Want to configure Black Pill composite USB device with CDC and MIDI,
occasionally using CDC for logging and debugging...
13 Sep 2025 availableForWrite() fixed in
develop branch
Updated SerialUSB sketch
How it was
This library interfaces, via USBD_HandleTypeDef to
Arduino15/packages/STMicroelectronics/hardware/stm32/2.11.0/system/Middlewares/ST/STM32_USB_Device_Library/Core ,
specifically USBD_HandleTypeDef in STM32_USB_Device_Library/Core/Inc/usbd_def.h ,
as described in ST's wiki
For USBSerial , UDBCDC write(const uint8_t *buffer, size_t size) calls USB_Send(CDC_ENDPOINT_IN, buffer, size);
USB_Send() calls USB_SendQuick() ,
which grabs the CDC endpoint buffer class instance and invokes its Write method,
then, if endpoint state is HID_IDLE , invokes USB_SendTXBufferUnsafe() ,
which invokes USBD_LL_Transmit() , which calls HAL_PCD_EP_Transmit()
for the implicated chip type in STMicroelectronics/hardware/stm32/2.11.0/system/Drivers/ .
Curiously, this release: "Remove Lock mechanism from HAL_PCD_EP_Transmit() and HAL_PCD_EP_Receive() API’s"...
HAL_PCD_EP_Transmit() returns HAL_StatusTypeDef , which gets ignored.
After USB_SendQuick() , USB_Send() calls USB_Flush_Internal() ,
but ignores its return code.
USB_Flush_Internal() does nothing
if USB_SendAvailable_Internal() returns true.
USBLibrarySTM32 seemingly handles only fixed size buffers;
if only 1 byte is written, a full 64-byte buffer is used.
Thus, availableForWrite() returns either USB_EP_SIZE or 0.
Because default PACKETBUFFER_ALLOW_OVERWRITE was true, for e.g. Black Pill,
availableForWrite() always returned USB_EP_SIZE
int USBCDC::availableForWrite(void)
{
return USB_SendAvailable(CDC_ENDPOINT_OUT) ? USB_EP_SIZE : 0;
}
static bool USB_SendAvailable_Internal(USBD_HID_HandleTypeDef *&hhid, uint8_t endp)
{
uint8_t ep = SMALL_EP(endp);
#if PACKETBUFFER_USE_TX_BUFFERS
if (EP_Buffers[ep] != NULL && (!EP_Buffers[ep]->isFull() || PACKETBUFFER_ALLOW_OVERWRITE))
{
return true;
}
#endif
USBCDC write() error recovery
USBLibrarySTM32/src/USBCDC.cpp setWriteError() seems vestigial;
USBSerial.clearWriteError() did not help...
- neither did
USBSerial.end() .... USBSerial.begin(115200) by itself help
- What did work:
USBSerial.end(); USB_End(); , followed by restarting both
|