skywalker-1/docs/EEPROM-RECOVERY.md
Ryan Malloy 33b6aa92db Update EEPROM recovery guide with I2C bus latch root cause
Replaces speculative "corrupted boot data" with confirmed I2C bus
latch diagnosis from 100+ failed power cycle attempts.  Mark
Option D (wait + watch) as exhausted.  Add pending firmware fixes
table for post-recovery testing.
2026-02-20 12:04:18 -07:00

6.0 KiB

SkyWalker-1 EEPROM Recovery Guide

The device is soft-bricked: the FX2 boot ROM hangs trying to load corrupted firmware from EEPROM, preventing USB enumeration.

Symptoms

  • Hub shows 0101 power connect [] (D+ pull-up active, no enumeration)
  • dmesg: device descriptor read/8, error -110 (timeout)
  • Does not enumerate as bare FX2 (04B4:8613) either
  • NanoVNA on same hub works fine (hub hardware is OK)

Root Cause

The FX2LP boot ROM reads EEPROM (24C128 at I2C 0x51) at power-up. The I2C bus is shared with the BCM3440 tuner and BCM4500 demod. Two failure modes cause the hang:

  1. I2C bus latch (confirmed): The BCM4500 or BCM3440 holds SDA LOW from a prior incomplete transaction. I2C is open-drain — any device sinking SDA prevents all communication. The boot ROM loops waiting for ACK from the EEPROM, which can never respond because SDA is stuck.

  2. Corrupted C2 image (possible): If the EEPROM's C2 header is intact but load records have invalid lengths or addresses, the boot ROM hangs mid-load.

Either way, the boot ROM occupies the 8051 core and never reaches the USB enumeration handler. The D+ pull-up activates (hub sees the device as "present") but descriptor reads time out.

Tested and failed (2025-02-19/20):

  • 100+ USB power cycles via uhubctl (varied off-times: 0.2s to 30s)
  • Host-side I2C manipulation via 0xA0 vendor commands
  • xHCI controller reset, port deauthorization
  • Ultra-rapid cycling (0.2-1.0s off)
  • Historically ~3-6% success rate on power cycles, now 0%

The I2C bus state degrades with each failed attempt. Software-only recovery is not viable. Physical intervention (Options A or B) is required.

Recovery Options (pick one)

Blank the first byte of the EEPROM so the boot ROM falls back to bare FX2 enumeration. Then reload via USB.

Hardware needed:

  • SOIC-8 test clip (Pomona 5250 or similar, ~$5)
  • CH341A USB programmer (~$3) or Bus Pirate or any I2C-capable tool
  • OR: Raspberry Pi / Arduino with I2C

Steps:

  1. Power OFF the SkyWalker-1 (unplug USB)
  2. Locate the 24C128 EEPROM on the PCB (SOIC-8 package near the FX2)
  3. Clip the SOIC clip onto the EEPROM
  4. Connect to your I2C programmer (SDA, SCL, VCC, GND)
  5. Read and save the EEPROM contents (16KB backup!)
  6. Write 0xFF to address 0x0000 (corrupts the C2 magic byte)
  7. Remove clip, plug in SkyWalker-1
  8. Device should enumerate as bare FX2 (04B4:8613)
  9. Load custom firmware via fw_load.py
  10. Use the custom firmware to write good C2 image back to EEPROM

With CH341A:

# Read backup
flashrom -p ch341a_spi -c "AT24C128" -r eeprom_backup.bin

# Or use i2c-tools if CH341A is in I2C mode:
# i2cdetect -l  (find the CH341A bus)
# i2cdump -y <bus> 0x51 b > dump.txt

With Raspberry Pi (I2C):

# Enable I2C: raspi-config -> Interfaces -> I2C
# Connect EEPROM: SDA->GPIO2, SCL->GPIO3, VCC->3.3V, GND->GND
i2cdetect -y 1  # Should show 0x51
# Read first byte
i2cget -y 1 0x51 0x00
# Write 0xFF to byte 0 (corrupts C2 header)
i2cset -y 1 0x51 0x00 0xFF

Option B: Hold SDA HIGH During Boot

Prevent the EEPROM from responding by holding SDA HIGH, forcing the boot ROM to see "no EEPROM" and enumerate as bare FX2.

Steps:

  1. Locate the SDA test point or EEPROM pin 5 (SDA)
  2. Connect a 1kΩ pull-up to 3.3V on SDA
  3. Power on the SkyWalker-1
  4. If it enumerates as bare FX2 (04B4:8613), load firmware:
    python3 tools/fw_load.py load firmware/build/skywalker1.ihx
    
  5. Remove the pull-up
  6. Use the loaded firmware to reprogram the EEPROM

Note: This only works if the SDA pull-up is strong enough to override the EEPROM's SDA output. May need to experiment with pull-up values (470Ω to 4.7kΩ).

Option C: Desolder EEPROM Pin

Most reliable but requires soldering skill.

  1. Lift EEPROM pin 5 (SDA) from the PCB pad
  2. Power on → enumerates as bare FX2
  3. Load firmware via USB
  4. Resolder pin 5
  5. Use firmware to reprogram EEPROM with good C2 image

Option D: Wait + Watch (Exhausted — Do Not Use)

Tested extensively (100+ attempts, 2025-02-19/20) with no success. The I2C bus latch does not clear on its own.

# Watch for bare FX2 enumeration
sudo dmesg -w | grep -E "04b4|8613|New USB"

# In another terminal, keep power cycling every 5 minutes
while true; do
    sudo uhubctl -l 1-5.4.4 -p 3 -a off
    sleep 5
    sudo uhubctl -l 1-5.4.4 -p 3 -a on
    sleep 300  # wait 5 minutes
done

If it appears even briefly:

python3 tools/fw_load.py load firmware/build/skywalker1.ihx --force

After Recovery

Once the device enumerates (as bare FX2 or with loaded firmware):

  1. Load custom firmware to RAM:

    python3 tools/fw_load.py load firmware/build/skywalker1.ihx
    
  2. Reprogram EEPROM with good C2 image:

    # The custom firmware needs EEPROM write support first
    # (vendor command to relay I2C writes to EEPROM)
    python3 tools/eeprom_write.py flash firmware/build/skywalker1_eeprom.bin
    
  3. Or restore stock firmware: If you have a backup of the original EEPROM contents, flash that instead of the custom firmware.

Firmware Fixes Pending Hardware Test

The custom firmware at firmware/build/skywalker1.ihx (15,171 bytes) includes three fixes discovered from stock firmware analysis:

Commit Fix Stock Reference
e9e5ab8 Init block readback verify 0x0DDD readback
dffef75 bcm_wait_ready() 3-check 0x2000 pre-write
0259950 GPIF stop before boot 0x1D6A GPIF abort

Load immediately after recovery:

python3 tools/fw_load.py load firmware/build/skywalker1.ihx

Then test: BOOT_8PSK (wValue=1), read signal, verify lock.

Prevention

  • Never send BOOT_8PSK (0x89) with mode 0x84 ("firmware load") unless you know what data the firmware expects
  • Always backup EEPROM before experiments that touch vendor commands
  • The stock firmware's I2C proxy (0x83/0x84) may have side effects on the EEPROM that aren't documented