Skip to content

Fix screen CS crosstalk window and add IRAM_ATTR to button ISRs#336

Open
Bullpuph123 wants to merge 1 commit into
brettdottech:devfrom
Bullpuph123:fix/screenmanager-isr
Open

Fix screen CS crosstalk window and add IRAM_ATTR to button ISRs#336
Bullpuph123 wants to merge 1 commit into
brettdottech:devfrom
Bullpuph123:fix/screenmanager-isr

Conversation

@Bullpuph123

@Bullpuph123 Bullpuph123 commented Jul 15, 2026

Copy link
Copy Markdown

Split from #330 (part 3 of 3), rebased onto dev as requested.

Summary

  • selectScreen: deselect-all-first: the previous single-pass loop wrote CS pins in order, which can transiently leave both the old and new panel selected, letting SPI data leak to the wrong orb during the transition (observed on hardware as stray pixels appearing on a different orb). Now all CS lines are raised first, then only the target is lowered. Also adds a bounds check on the screen index (logs a warning and leaves everything deselected instead of driving a wrong/out-of-range CS pin), and hoists the ConfigManager read out of the loop.
  • IRAM_ATTR on button ISRs: Button::isrButtonChange() and the MainHelper ISR wrappers run from GPIO interrupts but weren't placed in IRAM. If the interrupt fires while flash cache is disabled (NVS/LittleFS write), the ESP32 crashes with a Cache disabled but cached memory region accessed exception. millis() and digitalRead() are IRAM-safe, so marking the handlers is sufficient.

Test plan

  • Builds with pio run -e infoorbs-v0_3
  • Press buttons during a config save (flash write) — no crash
  • Verify widgets still render to the correct orbs with orbRotation 0-3

🤖 Generated with Claude Code

selectScreen wrote all CS pins in a single pass, which could transiently
select two panels at once and leak SPI data to the wrong orb. Now all
screens are deselected first, then only the target is selected, with a
bounds check on the screen index.

Button ISRs run from GPIO interrupts and must be in IRAM: without
IRAM_ATTR they can crash the ESP32 with a cache-disabled exception if
the interrupt fires during a flash write (NVS/LittleFS).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves ESP32 firmware reliability by (1) preventing transient SPI chip-select overlap when switching between TFT panels and (2) ensuring GPIO button interrupt handlers execute from IRAM to avoid crashes during flash cache-disabled windows.

Changes:

  • Updated ScreenManager::selectScreen() to deselect all CS lines first, validate the requested screen index, and only then assert the target CS (with rotation-aware mapping).
  • Marked button ISR entrypoints (MainHelper ISR wrappers and Button::isrButtonChange()) with IRAM_ATTR and documented the rationale (flash write / cache-disabled crash avoidance).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
firmware/src/core/utils/MainHelper.cpp Marks the attachInterrupt ISR wrappers as IRAM_ATTR and clarifies ISR/IRAM requirements in comments.
firmware/src/core/screenmanager/ScreenManager.cpp Makes screen selection a two-step “deselect-all then select-one” operation and adds an invalid-index guard + warning log.
firmware/src/core/button/Button.cpp Marks the button edge handler as IRAM_ATTR so the ISR path runs from IRAM during flash cache-disabled periods.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants