Skip to content

fix(promicro): exclude emoji to fit under the warm-store region - #11256

Merged
thebentern merged 1 commit into
developfrom
promicro-exclude-emoji
Jul 27, 2026
Merged

fix(promicro): exclude emoji to fit under the warm-store region#11256
thebentern merged 1 commit into
developfrom
promicro-exclude-emoji

Conversation

@thebentern

@thebentern thebentern commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Problem

nrf52_promicro_diy_tcxo is failing the nrf52 warm-region guard on develop (example run):

*** nrf52 warm-region guard: image ends at 0xEA0C0, past the reserved warm-store region at 0xEA000 ***

It's only 192 bytes over. This variant deliberately compiles four radio driver families (SX126x/LLCC68, SX127x/RF95, LR11x0/LR1121, LR2021) so builders can solder on whatever module they have, which makes it the largest nRF52 image we ship. Measured from the ELF: SX126x/LLCC68 24.5 KB, SX127x/RF95 14.1 KB, LR2021 12.0 KB, LR11x0/LR1121 11.4 KB.

For reference, rak4631 on the same commit ends at 0xE46D8 — 22 KB clear.

Fix

Build the variant with -D EXCLUDE_EMOJI: −6,808 bytes, image ends at 0xE8618, 6.6 KB clear of the warm region.

That flag wasn't usable before this PR. With it set, graphics::emotes[] is empty and numEmotes == 0, but the canned-message emote picker never checked:

  • drawEmotePickerScreen() clamps emotePickerIndex to numEmotes - 1, i.e. -1
  • selecting then evaluates graphics::emotes[-1].label and constructs a String from it — an out-of-bounds read of whatever precedes the array in flash

So this adds two guards: don't open the picker when there are no emotes, and bounce back to freetext if the picker state is reached anyway. (Same latent bug applies to any board that wants this flag — it's not promicro-specific.)

A nice side effect: under whole-image LTO the guards fold to constants, so the entire picker — draw path and input handler — dead-strips on EXCLUDE_EMOJI builds. That's why the saving is larger than the ~5.7 KB of bitmap data.

Trade-off

On this variant only, received messages containing emoji render as their text label instead of a 16px bitmap, and the emote-list key becomes a no-op. Given the alternative is a variant that doesn't build at all, that seems like the right call — but I'm open to dropping USE_LR2021 instead (−13,504 bytes, measured), since LR2021 support landed on this variant only two weeks ago in #10998 and the readme's known-modules table doesn't list an LR2021 module yet.

Verification

Both built locally at 1e982fa:

env image end guard
nrf52_promicro_diy_tcxo before 0xEA0B0 FAIL
nrf52_promicro_diy_tcxo after 0xE8618 OK, 6.6 KB clear
rak4631 (emoji enabled, unchanged) 0xE46D8 OK, 22 KB clear

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling when no emotes are available, preventing invalid picker access.
    • The emote picker now closes safely and returns to text entry when its list is empty.
  • Configuration

    • Added support for excluding emotes in the memory-constrained device variant.

nrf52_promicro_diy_tcxo has been failing the nrf52 warm-region guard on
develop: the image ends at 0xEA0C0, 192 bytes past the 12 KB WarmNodeStore
record-ring reserved at 0xEA000. This variant compiles four radio driver
families (SX126x/LLCC68, SX127x/RF95, LR11x0/LR1121, LR2021) so any module
can be soldered on, which makes it the largest nrf52 image we ship.

Building it with -D EXCLUDE_EMOJI saves 6,808 bytes and puts the image at
0xE8618, 6.6 KB clear of the warm region.

EXCLUDE_EMOJI was not previously usable: graphics::emotes[] becomes empty,
but the canned-message emote picker never checked for that. Entering the
picker clamped emotePickerIndex to numEmotes - 1 (i.e. -1), and selecting
read emotes[-1].label into a String - an out-of-bounds read of whatever
precedes the array in flash. Guard both entry points instead: refuse to
open the picker when there are no emotes, and bounce back to freetext if
the picker state is somehow reached anyway.

Under whole-image LTO those guards fold to constants, so the picker draw
and input paths dead-strip entirely on builds that set EXCLUDE_EMOJI -
which is where the savings come from beyond the bitmap data itself.

Received messages containing emoji render as text on this variant, and
the emote-list key is a no-op. Verified rak4631 (emoji enabled) is
unaffected: 0xE46D8, 22 KB clear.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2f6034cf-e314-4adc-b295-ca9d6a195ec3

📥 Commits

Reviewing files that changed from the base of the PR and between 1e982fa and 4bb474a.

📒 Files selected for processing (2)
  • src/modules/CannedMessageModule.cpp
  • variants/nrf52840/diy/nrf52_promicro_diy_tcxo/platformio.ini

📝 Walkthrough

Walkthrough

The emote picker now remains closed when no emotes are available and exits safely if emote picker input is active with an empty list. The TCXO variant enables EXCLUDE_EMOJI to omit emoji assets.

Changes

Emote picker safety

Layer / File(s) Summary
Empty emote handling
src/modules/CannedMessageModule.cpp, variants/nrf52840/diy/nrf52_promicro_diy_tcxo/platformio.ini
The TCXO variant defines EXCLUDE_EMOJI; canned message handling only opens the picker when emotes exist and returns to freetext when picker input encounters an empty list.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested labels: bugfix

Suggested reviewers: nomdetom, caveman99

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: excluding emoji for the ProMicro variant to fit under the warm-store region.
Description check ✅ Passed It covers the problem, fix, trade-off, and verification clearly; only the template's attestation checklist is omitted.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch promicro-exclude-emoji

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

⚡ Try this PR in the Web Flasher

Flash this PR in the Web Flasher

firmware commit boards expires

Warning

This is an automated, unreviewed CI test build. Back up your device configuration
before flashing, and only flash devices you are able to recover.

Supported boards built by this PR (31)
Device Board Platform
Crowpanel Adv 3.5 TFT elecrow-adv-35-tft esp32-s3
Heltec HT62 heltec-ht62-esp32c3-sx1262 esp32-c3
Heltec Mesh Node 096 heltec-mesh-node-t096 nrf52840
Heltec Mesh Node T1 heltec-mesh-node-t1 nrf52840
Heltec Mesh Node T114 heltec-mesh-node-t114 nrf52840
Heltec V3 heltec-v3 esp32-s3
Heltec V4 heltec-v4 esp32-s3
Meshnology W10 meshnology_w10 esp32-s3
Meshnology W12 meshnology_w12 esp32-s3
Raspberry Pi Pico pico rp2040
Raspberry Pi Pico W picow rp2040
RAK WisMesh Pocket V3 rak_wismesh_pocket nrf52840
RAK WisMesh Pod rak_wismesh_pod nrf52840
RAK WisMesh Repeater Mini V2 rak_wismesh_repeater_mini nrf52840
RAK WisMesh Tag rak_wismeshtag nrf52840
RAK WisBlock 11200 rak11200 esp32
RAK WisBlock 11310 rak11310 rp2040
RAK3312 rak3312 esp32-s3
RAK WisBlock 4631 rak4631 nrf52840
Seeed SenseCAP Mesh-Tracker-X1 seeed_mesh_tracker_X1 nrf52840
Seeed Wio Tracker L1 seeed_wio_tracker_L1 nrf52840
Seeed Xiao NRF52840 Kit seeed_xiao_nrf52840_kit nrf52840
Seeed Xiao ESP32-S3 seeed-xiao-s3 esp32-s3
Station G2 station-g2 esp32-s3
Station G3 station-g3 esp32-s3
LILYGO T-Deck t-deck-tft esp32-s3
LILYGO T-Echo t-echo nrf52840
LILYGO T-Echo Plus t-echo-plus nrf52840
LILYGO T-Impulse Plus t-impulse-plus nrf52840
LilyGo T3-C6 tlora-c6 esp32-c6
Seeed SenseCAP T1000-E tracker-t1000-e nrf52840

Build artifacts expire on 2026-08-26. Updated for 4bb474a.

@vidplace7 vidplace7 added the bugfix Pull request that fixes bugs label Jul 27, 2026
@vidplace7
vidplace7 requested a review from NomDeTom July 27, 2026 14:03
@thebentern
thebentern added this pull request to the merge queue Jul 27, 2026
Merged via the queue into develop with commit f61f658 Jul 27, 2026
102 of 104 checks passed
jackyes pushed a commit to jackyes/meshtastic-firmware that referenced this pull request Jul 29, 2026
Conflict in variants/nrf52840/diy/nrf52_promicro_diy_tcxo/platformio.ini:
both sides fixed the same warm-store overflow, differently.

d33ceeb excluded canned messages (12360 bytes). Upstream meshtastic#11256 excludes
emoji instead (6808 bytes) and additionally fixes an out-of-bounds read in the
emote picker that made EXCLUDE_EMOJI unusable before.

Kept upstream's flag and dropped ours: it clears the guard while leaving canned
messages working on the board, which is the better outcome for the variant.
Verified - the image now ends at 0xE8EE8, 4376 bytes below the 0xEA000 region,
with the module present again.

Only that one target was rebuilt; the rest of the merge is upstream code that
their CI covers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Pull request that fixes bugs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants