fix ble latency

This commit is contained in:
J. Nick Koston
2025-11-01 14:58:24 -05:00
parent ff2e2bed66
commit 69af4cddb5
2 changed files with 22 additions and 10 deletions
+14 -3
View File
@@ -679,15 +679,26 @@ void ESP32BLE::setup_event_notification_() {
return;
}
// Get the assigned port for sendto()
socklen_t len = sizeof(this->notify_addr_);
if (lwip_getsockname(this->notify_fd_, (struct sockaddr *) &this->notify_addr_, &len) < 0) {
// Get the assigned address and connect to it
// Connecting a UDP socket allows using send() instead of sendto() for better performance
struct sockaddr_in notify_addr;
socklen_t len = sizeof(notify_addr);
if (lwip_getsockname(this->notify_fd_, (struct sockaddr *) &notify_addr, &len) < 0) {
ESP_LOGW(TAG, "Event socket address failed: %d", errno);
lwip_close(this->notify_fd_);
this->notify_fd_ = -1;
return;
}
// Connect to self (loopback) - allows using send() instead of sendto()
// After connect(), no need to store notify_addr - the socket remembers it
if (lwip_connect(this->notify_fd_, (struct sockaddr *) &notify_addr, sizeof(notify_addr)) < 0) {
ESP_LOGW(TAG, "Event socket connect failed: %d", errno);
lwip_close(this->notify_fd_);
this->notify_fd_ = -1;
return;
}
// Set non-blocking mode
int flags = lwip_fcntl(this->notify_fd_, F_GETFL, 0);
lwip_fcntl(this->notify_fd_, F_SETFL, flags | O_NONBLOCK);
+8 -7
View File
@@ -209,9 +209,9 @@ class ESP32BLE : public Component {
#ifdef USE_SOCKET_SELECT_SUPPORT
// Event notification socket for waking up main loop from BLE thread
// Uses UDP loopback to wake lwip_select() with ~12μs latency vs 0-16ms timeout
struct sockaddr_in notify_addr_ {}; // 16 bytes (sockaddr_in structure)
int notify_fd_{-1}; // 4 bytes (file descriptor)
// Uses connected UDP loopback socket to wake lwip_select() with ~12μs latency vs 0-16ms timeout
// Socket is connected during setup, allowing use of send() instead of sendto() for efficiency
int notify_fd_{-1}; // 4 bytes (file descriptor)
#endif
// 2-byte aligned members
@@ -235,12 +235,13 @@ static constexpr size_t BLE_EVENT_NOTIFY_DRAIN_BUFFER_SIZE = 16;
inline void ESP32BLE::notify_main_loop_() {
// Called from BLE thread context when events are queued
// Wakes up lwip_select() in main loop by writing to loopback socket
// Wakes up lwip_select() in main loop by writing to connected loopback socket
if (this->notify_fd_ >= 0) {
const char dummy = 1;
// Non-blocking sendto - if it fails (unlikely), select() will wake on timeout anyway
// This is safe to call from BLE thread - sendto() is thread-safe in lwip
lwip_sendto(this->notify_fd_, &dummy, 1, 0, (struct sockaddr *) &this->notify_addr_, sizeof(this->notify_addr_));
// Non-blocking send - if it fails (unlikely), select() will wake on timeout anyway
// This is safe to call from BLE thread - send() is thread-safe in lwip
// Socket is already connected to loopback address, so send() is faster than sendto()
lwip_send(this->notify_fd_, &dummy, 1, 0);
}
}