Skip to content

fix: wipe nRF52 EEPROM before provisioning to initialize LittleFS#554

Merged
torlando-tech merged 1 commit intorelease/v0.8.xfrom
fix/nrf52-eeprom-wipe-provisioning-v0.8.x
Feb 25, 2026
Merged

fix: wipe nRF52 EEPROM before provisioning to initialize LittleFS#554
torlando-tech merged 1 commit intorelease/v0.8.xfrom
fix/nrf52-eeprom-wipe-provisioning-v0.8.x

Conversation

@torlando-tech
Copy link
Copy Markdown
Owner

Summary

  • Wipe EEPROM (format LittleFS) before writing provisioning data on nRF52 boards, matching rnodeconf's behavior
  • Make provisioning failure non-fatal — device works without it since Columba sends radio params at runtime
  • Fix post-provisioning verify to scan for re-enumerated devices instead of using stale device ID

Root Cause

After DFU flashing an nRF52 device, the LittleFS filesystem (used to emulate EEPROM) may be uninitialized. Individual CMD_ROM_WRITE byte writes crash the firmware after ~40 writes, disconnecting USB. rnodeconf avoids this by calling wipe_eeprom() (CMD_UNLOCK_ROM / 0x59) first, which calls InternalFS.format() + hard_reset() in the firmware, initializing the filesystem.

Changes

  • RNodeDetector.kt: Add wipeEeprom() method that sends CMD_UNLOCK_ROM with ROM_UNLOCK_BYTE
  • RNodeFlasher.kt:
    • Add EEPROM wipe + 18s wait + reconnect for nRF52 boards before provisioning
    • Override FlashState.ErrorFlashState.Complete when provisioning fails but flash succeeded
    • Fix post-provisioning verify to use actualDeviceId and scan for re-enumerated devices

Test plan

  • Flash + provision T114 via USB — confirmed working on real hardware
  • EEPROM wipe sent, device rebooted, reconnected, all 168 EEPROM bytes written successfully
  • Firmware hash set and verified
  • Regression: ESP32 boards (no wipe, provisioning unchanged)

🤖 Generated with Claude Code

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Feb 25, 2026

Greptile Summary

This PR fixes nRF52 EEPROM provisioning crashes by wiping (formatting) LittleFS before writing, matching rnodeconf's approach. It also makes provisioning failures non-fatal since Columba sends radio params at runtime.

Key changes:

  • Added wipeEeprom() method to send CMD_UNLOCK_ROM command
  • For nRF52 boards: wipe EEPROM, wait 18s for format, then reconnect before provisioning
  • Override provisioning errors to FlashState.Complete when flash succeeded
  • Improved post-provisioning verification to handle device re-enumeration

Critical issue: RAK4631 boards use Nordic VID 0x1915, which is not in SUPPORTED_VIDS (only Adafruit 0x239A is included). After EEPROM wipe, RAK4631 devices will not be found during reconnection, causing provisioning to fail with "Failed to reconnect after EEPROM wipe." The implementation will work for T114 and T-Echo (both use Adafruit VID) but not RAK4631.

Device matching concern: The reconnection logic at lines 880 and 935 uses devices.find { it.deviceId != actualDeviceId } which selects the first USB serial device that differs from the original. If users have multiple compatible USB devices connected, this could connect to the wrong one.

Confidence Score: 2/5

  • Works for some nRF52 boards but will fail for RAK4631 due to missing VID support
  • The implementation correctly handles EEPROM wipe for nRF52 boards with Adafruit VID (0x239A) like T114 and T-Echo, but RAK4631 boards use Nordic VID (0x1915) which is not in SUPPORTED_VIDS, causing reconnection to fail. Device reconnection logic could also select wrong device if multiple USB serial devices are present.
  • RNodeFlasher.kt needs VID filtering fix and improved device matching logic to support RAK4631 and handle multi-device scenarios

Important Files Changed

Filename Overview
reticulum/src/main/java/com/lxmf/messenger/reticulum/flasher/RNodeDetector.kt Added wipeEeprom() method to send CMD_UNLOCK_ROM command for formatting LittleFS on nRF52 devices - straightforward implementation with proper documentation
reticulum/src/main/java/com/lxmf/messenger/reticulum/flasher/RNodeFlasher.kt Added nRF52 EEPROM wipe + reconnection logic and made provisioning failures non-fatal - has device reconnection issues and VID filtering problem for RAK4631 boards

Sequence Diagram

sequenceDiagram
    participant F as RNodeFlasher
    participant D as RNodeDetector
    participant U as USBBridge
    participant Dev as nRF52 Device
    
    Note over F: nRF52 provisioning flow
    F->>D: wipeEeprom()
    D->>U: write(CMD_UNLOCK_ROM)
    U->>Dev: CMD_UNLOCK_ROM + ROM_UNLOCK_BYTE
    Dev-->>Dev: Format LittleFS<br/>(~18s)
    Dev-->>Dev: Hard reset
    F->>U: disconnect()
    F->>F: delay(18s)
    
    Note over F,Dev: Reconnection (5 retries)
    loop 5 attempts
        F->>U: connect(actualDeviceId)
        alt Original ID works
            U-->>F: Connected
        else Scan for re-enumerated device
            F->>U: getConnectedUsbDevices()
            U-->>F: List of devices
            F->>F: find { it.deviceId != actualDeviceId }
            F->>U: connect(reEnumeratedDevice.deviceId)
            U-->>F: Connected
        end
    end
    
    F->>D: provisionAndSetFirmwareHash()
    D->>U: write(EEPROM bytes)
    U->>Dev: 168 EEPROM bytes
    F->>D: resetDevice()
    D->>U: write(CMD_RESET)
    U->>Dev: CMD_RESET
    Dev-->>Dev: Reboot
    F->>U: disconnect()
    F->>F: delay(3s)
    
    Note over F,Dev: Verification (3 retries)
    loop 3 attempts
        F->>U: connect(actualDeviceId)
        alt Can verify
            U-->>F: Connected
            F->>D: getDeviceInfo()
            D-->>F: Verified info
        else Cannot verify
            Note over F: Complete anyway<br/>(provisioning likely succeeded)
        end
    end
Loading

Last reviewed commit: a9a0037

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment thread reticulum/src/main/java/com/lxmf/messenger/reticulum/flasher/RNodeFlasher.kt Outdated
Comment thread reticulum/src/main/java/com/lxmf/messenger/reticulum/flasher/RNodeFlasher.kt Outdated
@torlando-tech torlando-tech force-pushed the fix/nrf52-eeprom-wipe-provisioning-v0.8.x branch from bb2e7d9 to 181b5a2 Compare February 25, 2026 05:30
@torlando-tech
Copy link
Copy Markdown
Owner Author

@greptileai

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread reticulum/src/main/java/com/lxmf/messenger/reticulum/flasher/RNodeFlasher.kt Outdated
}
// Scan for re-enumerated device (new ID after reset)
val devices = usbBridge.getConnectedUsbDevices()
val reEnumerated = devices.find { it.deviceId != actualDeviceId }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

matches ANY USB device with different ID (mouse, keyboard, unrelated RNode) — could connect to wrong device during verification

Suggested change
val reEnumerated = devices.find { it.deviceId != actualDeviceId }
val reEnumerated = devices.find { it.deviceId != actualDeviceId && (it.vendorId == 0x239A || it.vendorId == 0x1915) }
Prompt To Fix With AI
This is a comment left during a code review.
Path: reticulum/src/main/java/com/lxmf/messenger/reticulum/flasher/RNodeFlasher.kt
Line: 938

Comment:
matches ANY USB device with different ID (mouse, keyboard, unrelated RNode) — could connect to wrong device during verification

```suggestion
                    val reEnumerated = devices.find { it.deviceId != actualDeviceId && (it.vendorId == 0x239A || it.vendorId == 0x1915) }
```

How can I resolve this? If you propose a fix, please make it concise.

The nRF52 emulates EEPROM using LittleFS on internal flash. After DFU
flashing, the filesystem may be uninitialized, causing individual byte
writes to crash the device after ~40 writes. This matches rnodeconf's
behavior of always calling wipe_eeprom() before provisioning nRF52
devices.

Changes:
- Add wipeEeprom() to RNodeDetector (sends CMD_UNLOCK_ROM/0x59)
- Call wipe before nRF52 provisioning with 18s wait for LittleFS
  format + reboot, then reconnect with device scan
- Make provisioning failure non-fatal (device works without it since
  Columba sends radio params at runtime)
- Fix post-provisioning verify to use actualDeviceId and scan for
  re-enumerated devices instead of using stale original deviceId

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@torlando-tech torlando-tech force-pushed the fix/nrf52-eeprom-wipe-provisioning-v0.8.x branch from 181b5a2 to a9a0037 Compare February 25, 2026 05:48
@torlando-tech
Copy link
Copy Markdown
Owner Author

@greptileai

@torlando-tech torlando-tech merged commit c8184d2 into release/v0.8.x Feb 25, 2026
2 checks passed
@torlando-tech torlando-tech deleted the fix/nrf52-eeprom-wipe-provisioning-v0.8.x branch February 25, 2026 06:05
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.

1 participant