From 0785caa0df66d85d2124226c5480c4709c2c4697 Mon Sep 17 00:00:00 2001 From: Rob Dobson Date: Sun, 25 Oct 2026 18:18:20 +0100 Subject: [PATCH 1/2] ProtocolRawMsg: const getBuf() and getBufLen() So a message can be read in place in a queue (ThreadSafeQueue::peekWith passes it as const) - BLE sends a large message in pieces and copied the whole message for each piece. Co-Authored-By: Claude Opus 5.5 --- components/comms/ProtocolRawMsg/ProtocolRawMsg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/comms/ProtocolRawMsg/ProtocolRawMsg.h b/components/comms/ProtocolRawMsg/ProtocolRawMsg.h index 2aad38fc..f765957c 100644 --- a/components/comms/ProtocolRawMsg/ProtocolRawMsg.h +++ b/components/comms/ProtocolRawMsg/ProtocolRawMsg.h @@ -55,11 +55,11 @@ class ProtocolRawMsg } // Access to command vector - const uint8_t* getBuf() + const uint8_t* getBuf() const { return _cmdVector.data(); } - uint32_t getBufLen() + uint32_t getBufLen() const { return _cmdVector.size(); } From 050ba3f5234168e9b18da9ef0402767ac9edde75 Mon Sep 17 00:00:00 2001 From: Rob Dobson Date: Sun, 25 Oct 2026 18:26:10 +0100 Subject: [PATCH 2/2] A channel may take a just-encoded message's buffer instead of copying it CommsChannelMsg::setBufTakeable()/isBufTakeable(): set by a protocol codec on a message it made to send and doesn't use afterwards, so the channel sending it may move the buffer out rather than copy it. RICSerial sets it on its encoded message. A message passed on as it is (RICJSON, RICFrame) may be sent again - e.g. on each channel for MSG_CHANNEL_ID_ALL - so its buffer isn't takeable. ProtocolRawMsg::takeBuffer() takes a buffer's contents without copying. BLE queues the message this way, which saves a copy of each camera frame published (about 2 ms for a 10 KB frame on an ESP32-S3 with PSRAM). Co-Authored-By: Claude Opus 5.5 --- components/comms/CommsChannelMsg/CommsChannelMsg.h | 13 +++++++++++++ .../comms/ProtocolRICSerial/ProtocolRICSerial.cpp | 3 +++ components/comms/ProtocolRawMsg/ProtocolRawMsg.h | 11 +++++++++++ 3 files changed, 27 insertions(+) diff --git a/components/comms/CommsChannelMsg/CommsChannelMsg.h b/components/comms/CommsChannelMsg/CommsChannelMsg.h index 64bdd919..7bdf3145 100644 --- a/components/comms/CommsChannelMsg/CommsChannelMsg.h +++ b/components/comms/CommsChannelMsg/CommsChannelMsg.h @@ -190,11 +190,24 @@ class CommsChannelMsg return _cmdVector; } + // Whether the buffer may be taken (moved out, leaving it empty) by the channel sending the message, rather + // than copied. Set by a protocol codec on a message it made to send and doesn't use afterwards - a message + // passed on as it is may be sent again (e.g. on each channel), so its buffer mustn't be taken + void setBufTakeable(bool takeable) + { + _bufTakeable = takeable; + } + bool isBufTakeable() const + { + return _bufTakeable; + } + private: uint32_t _channelID; CommsMsgProtocol _msgProtocol; uint32_t _msgNum; CommsMsgTypeCode _msgTypeCode; + bool _bufTakeable = false; #ifdef IMPLEMENT_NO_PSRAM_FOR_COMMS_CHANNEL_MSG std::vector _cmdVector; #else diff --git a/components/comms/ProtocolRICSerial/ProtocolRICSerial.cpp b/components/comms/ProtocolRICSerial/ProtocolRICSerial.cpp index e6fa69f6..4e24fb89 100644 --- a/components/comms/ProtocolRICSerial/ProtocolRICSerial.cpp +++ b/components/comms/ProtocolRICSerial/ProtocolRICSerial.cpp @@ -162,6 +162,9 @@ void ProtocolRICSerial::encodeTxMsgAndSend(CommsChannelMsg& msg) _pHDLC->appendFramePayload(encoded, fcs, ricSerialRec, sizeof(ricSerialRec)); _pHDLC->appendFramePayload(encoded, fcs, msg.getBuf(), msg.getBufLen()); _pHDLC->appendFrameEnd(encoded, fcs); + + // Nothing uses the encoded message after it is sent, so the channel may take its buffer + encodedMsg.setBufTakeable(true); #endif // Debug diff --git a/components/comms/ProtocolRawMsg/ProtocolRawMsg.h b/components/comms/ProtocolRawMsg/ProtocolRawMsg.h index f765957c..ce6a0e07 100644 --- a/components/comms/ProtocolRawMsg/ProtocolRawMsg.h +++ b/components/comms/ProtocolRawMsg/ProtocolRawMsg.h @@ -41,6 +41,17 @@ class ProtocolRawMsg _cmdVector.assign(pBuf, pBuf+bufLen); } + // Take the contents of a buffer without copying (it is left empty) + void takeBuffer(SpiramAwareUint8Vector& buf) + { +#ifdef IMPLEMENT_NO_PSRAM_FOR_PROTOCOL_RAW_MSG + _cmdVector.assign(buf.begin(), buf.end()); + buf.clear(); +#else + _cmdVector.swap(buf); +#endif + } + void setBufferSize(uint32_t bufSize) { _cmdVector.resize(bufSize);