Fix firmware size limits and refresh CI compatibility checks

Compact the existing STM32 field arithmetic and ESP-NOW tail-frame storage without removing features or lowering memory reserves. Refresh power-saving fixtures and pin official-app tests to a published archive.
This commit is contained in:
mikecarper committed 2026-10-23 19:04:43 -07:00
1 parent cf98125c65
commit c563c40c66
15 files changed
+494 -66

No files matched your search

+28 -1
View File
@@ -35,20 +35,47 @@ static constexpr size_t ESPNOW_RAW_FRAGMENT_MAGIC_SIZE =
static constexpr size_t ESPNOW_RAW_FRAGMENT_HEADER_SIZE = 13;
static constexpr size_t ESPNOW_RAW_FRAGMENT_DATA_SIZE =
ESPNOW_RAW_MAX_FRAME_SIZE - ESPNOW_RAW_FRAGMENT_HEADER_SIZE;
static constexpr size_t ESPNOW_RAW_MAX_SECOND_FRAME_SIZE =
ESPNOW_RAW_FRAGMENT_HEADER_SIZE + ESPNOW_RAW_MAX_PACKET_SIZE
- ESPNOW_RAW_FRAGMENT_DATA_SIZE;
static_assert(ESPNOW_RAW_FRAGMENT_DATA_SIZE < ESPNOW_RAW_MAX_FRAME_SIZE,
"ESP-NOW fragment header must leave room for data");
static_assert(ESPNOW_RAW_FRAGMENT_DATA_SIZE * ESPNOW_RAW_FRAGMENT_COUNT >=
ESPNOW_RAW_MAX_PACKET_SIZE,
"two ESP-NOW fragments must hold one maximum MeshCore packet");
static_assert(ESPNOW_RAW_FRAGMENT_COUNT == 2
&& ESPNOW_RAW_MAX_SECOND_FRAME_SIZE <= ESPNOW_RAW_MAX_FRAME_SIZE,
"compact frame storage requires one full frame and one bounded tail");
// Only the first frame can reach 250 bytes. The second holds a 13-byte header
// and at most 18 remaining packet bytes. Keep both frames owned by the queue
// without reserving another full frame for each of its six transmit slots.
struct ESPNowRawFrameData {
uint8_t first[ESPNOW_RAW_MAX_FRAME_SIZE];
uint8_t second[ESPNOW_RAW_MAX_SECOND_FRAME_SIZE];
uint8_t* operator[](size_t index) {
return index == 0 ? first : index == 1 ? second : nullptr;
}
const uint8_t* operator[](size_t index) const {
return index == 0 ? first : index == 1 ? second : nullptr;
}
static constexpr size_t capacity(size_t index) {
return index == 0 ? ESPNOW_RAW_MAX_FRAME_SIZE
: index == 1 ? ESPNOW_RAW_MAX_SECOND_FRAME_SIZE : 0;
}
};
struct ESPNowRawFrames {
uint8_t count;
uint16_t lengths[ESPNOW_RAW_FRAGMENT_COUNT];
uint8_t data[ESPNOW_RAW_FRAGMENT_COUNT][ESPNOW_RAW_MAX_FRAME_SIZE];
ESPNowRawFrameData data;
ESPNowRawFrames() : count(0), lengths{0, 0}, data{} {}
};
static_assert(sizeof(ESPNowRawFrames) <= 288,
"raw transmit frames must retain compact second-frame storage");
inline uint32_t espNowRawCrc32(const uint8_t* data, size_t len) {
if (data == nullptr && len != 0) return 0;
+4 -3
View File
@@ -381,7 +381,7 @@ bool ESPNowBridge::queueTransmitFrames(
}
for (uint8_t i = 0; i < frames.count; ++i) {
if (frames.lengths[i] == 0
|| frames.lengths[i] > MAX_ESPNOW_PACKET_SIZE) {
|| frames.lengths[i] > frames.data.capacity(i)) {
return false;
}
}
@@ -486,7 +486,8 @@ void ESPNowBridge::pumpTransmitQueue() {
QueuedTransmit& queued_tx = _tx_queue[_tx_tail];
if (queued_tx.next_frame < queued_tx.frames.count) {
frame_len = queued_tx.frames.lengths[queued_tx.next_frame];
if (frame_len > 0 && frame_len <= sizeof(frame)) {
if (frame_len > 0 && frame_len <= sizeof(frame)
&& frame_len <= queued_tx.frames.data.capacity(queued_tx.next_frame)) {
memcpy(frame, queued_tx.frames.data[queued_tx.next_frame], frame_len);
} else {
frame_len = 0;
@@ -869,7 +870,7 @@ bool ESPNowBridge::sendTest(uint32_t nonce) {
probe.nonce = nonce;
probe.format = _active_format;
probe.channel = _prefs->bridge_channel;
if (!encodeProbe(frames.data[0], sizeof(frames.data[0]), probe)) {
if (!encodeProbe(frames.data[0], frames.data.capacity(0), probe)) {
recordError(Stage::TestQueue, ESP_ERR_INVALID_ARG);
return false;
}