You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am currently using your excellent USBComposite_stm32f1 library for a MIDI project on STM32F1. I've encountered an issue where continuous sending of MIDI messages without the host reading them causes the STM32 to freeze after approximately 40 seconds, likely due to buffer overflow.
I've implemented a connection monitoring system that uses the transmission time of Active Sensing messages to detect when the buffer might be full:
.
#include <USBComposite.h>
/**
STM32F1 MIDI USB Composite Device with Buffer Management Test
This sketch demonstrates a potential issue with the USBComposite library
where continuous transmission of MIDI messages without host reading can
cause the device to freeze after approximately 40 seconds.
The code monitors connection status by checking the time it takes to send
Active Sensing messages, which can indicate if the buffer is full.
*/
#define SPEAKER_PIN PA1 // Pin for audio output
#define STATUS_LED_PIN PA0 // LED to indicate connection status
/**
Extended MIDI class that implements connection monitoring
by measuring the time it takes to send Active Sensing messages
*/
class myMidi : public USBMIDI {
private:
uint32_t lastActiveSensingTime = 0; // Last time we sent an Active Sensing message
uint32_t lastSuccessfulSend = 0; // Last time we successfully sent a message quickly
bool connectionActive = false; // Current connection status
public:
/**
Handle MIDI Note Off messages - turns off the speaker
*/
virtual void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) {
noTone(SPEAKER_PIN);
}
/**
Handle MIDI Note On messages - plays the corresponding frequency on the speaker
*/
virtual void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) {
tone(SPEAKER_PIN, (midiNoteFrequency_10ths[note]+5)/10);
}
/**
Check if the MIDI connection is active
This method sends an Active Sensing message (0xFE) every 5 seconds and
measures how long it takes to send. If the send operation is quick (<1ms),
it assumes the connection is active. If it takes too long (>5ms), it likely
means the buffer is full because the host isn't reading data.
@return true if connection is active, false otherwise
*/
bool checkConnection() {
uint32_t currentTime = millis();
// Send an Active Sensing message every 5 seconds
if (currentTime - lastActiveSensingTime > 5000) {
lastActiveSensingTime = currentTime;
// Record the time before sending
uint32_t sendStartTime = micros();
// Send Active Sensing message (0xFE)
// Active Sensing is a System Realtime message with MIDI code 0xFE
sendRealTime(0xFE);
// Check how long it took to send
uint32_t sendDuration = micros() - sendStartTime;
// If sending completed quickly (<1ms), consider connection active
if (sendDuration < 1000) {
connectionActive = true;
lastSuccessfulSend = currentTime;
}
// If sending took too long (>5ms), buffer is likely full
else if (sendDuration > 5000) {
connectionActive = false;
}
}
// If no successful send in the last 10 seconds, consider connection inactive
if (currentTime - lastSuccessfulSend > 10000) {
connectionActive = false;
}
return connectionActive;
}
/**
Get the current connection status
@return true if connection is active, false otherwise
*/
bool isConnected() {
return connectionActive;
}
/**
Send a MIDI System Realtime message
Uses the writePacket method directly from USBMIDI to send
the message with minimal overhead
@param rt The realtime message code to send (e.g., 0xFE for Active Sensing)
*/
void sendRealTime(uint8_t rt) {
// Directly use the writePacket method provided by USBMIDI class
writePacket(rt);
}
};
// Create instances of our MIDI and serial components
myMidi midi;
USBCompositeSerial CompositeSerial;
// Register both MIDI and Serial components to create a composite device
midi.registerComponent();
CompositeSerial.registerComponent();
USBComposite.begin();
}
void loop() {
// Process incoming MIDI messages
midi.poll();
// Send a Note Off message - this continuous sending without host reading
// will eventually fill the buffer and cause the MCU to freeze after ~40 seconds
midi.sendNoteOff(0, 0, 127);
// Check MIDI connection status
bool connected = midi.checkConnection();
// Update LED based on connection status
if (connected) {
digitalWrite(STATUS_LED_PIN, HIGH); // Turn LED on when connected
} else {
digitalWrite(STATUS_LED_PIN, LOW); // Turn LED off when disconnected
// OPTIONAL: Reset USB connection when buffer appears to be full
// Uncomment these lines to test automatic reconnection
/*
USBComposite.end();
delay(1000);
USBComposite.begin();
*/
}
}
The text was updated successfully, but these errors were encountered:
I've discovered an interesting pattern with this buffer overflow problem:
When using a laptop running on battery power (not connected to AC adapter), the device freezes after approximately 40 seconds of continuous MIDI transmission.
However, when any of these conditions are met, the problem disappears:
The laptop is connected to AC power
A MIDI application is actively reading the incoming MIDI data
When using a desktop PC (regardless of whether MIDI data is being read)
This suggests that the issue might be related to USB power management or polling rate changes when laptops enter battery-saving modes. Without active reading from the host, the USB buffer fills up, but this happens much faster on battery-powered laptops, possibly due to reduced USB polling frequency or power-saving features that affect USB endpoints.
I believe a buffer management solution in the library would help address this issue, as it appears to be a specific interaction between power-saving modes on laptops and the USB MIDI buffer management.
Finally, it was found that it cannot be registered together with the virtual USB serial port. If the virtual serial port is registered together, this problem will occur.
I am currently using your excellent USBComposite_stm32f1 library for a MIDI project on STM32F1. I've encountered an issue where continuous sending of MIDI messages without the host reading them causes the STM32 to freeze after approximately 40 seconds, likely due to buffer overflow.
I've implemented a connection monitoring system that uses the transmission time of Active Sensing messages to detect when the buffer might be full:
.
#include <USBComposite.h>
/**
*/
#define SPEAKER_PIN PA1 // Pin for audio output
#define STATUS_LED_PIN PA0 // LED to indicate connection status
/**
*/
class myMidi : public USBMIDI {
private:
uint32_t lastActiveSensingTime = 0; // Last time we sent an Active Sensing message
uint32_t lastSuccessfulSend = 0; // Last time we successfully sent a message quickly
bool connectionActive = false; // Current connection status
public:
/**
*/
virtual void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) {
noTone(SPEAKER_PIN);
}
/**
*/
virtual void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) {
tone(SPEAKER_PIN, (midiNoteFrequency_10ths[note]+5)/10);
}
/**
*/
bool checkConnection() {
uint32_t currentTime = millis();
}
/**
*/
bool isConnected() {
return connectionActive;
}
/**
*/
void sendRealTime(uint8_t rt) {
// Directly use the writePacket method provided by USBMIDI class
writePacket(rt);
}
};
// Create instances of our MIDI and serial components
myMidi midi;
USBCompositeSerial CompositeSerial;
void setup() {
USBComposite.setProductId(0x0030);
pinMode(SPEAKER_PIN, OUTPUT);
pinMode(STATUS_LED_PIN, OUTPUT);
}
void loop() {
// Process incoming MIDI messages
midi.poll();
// Send a Note Off message - this continuous sending without host reading
// will eventually fill the buffer and cause the MCU to freeze after ~40 seconds
midi.sendNoteOff(0, 0, 127);
// Check MIDI connection status
bool connected = midi.checkConnection();
// Update LED based on connection status
if (connected) {
digitalWrite(STATUS_LED_PIN, HIGH); // Turn LED on when connected
} else {
digitalWrite(STATUS_LED_PIN, LOW); // Turn LED off when disconnected
}
}
The text was updated successfully, but these errors were encountered: