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.
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:
-
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.
-
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)
Option A: SOIC Clip + External Programmer (Recommended)
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:
- Power OFF the SkyWalker-1 (unplug USB)
- Locate the 24C128 EEPROM on the PCB (SOIC-8 package near the FX2)
- Clip the SOIC clip onto the EEPROM
- Connect to your I2C programmer (SDA, SCL, VCC, GND)
- Read and save the EEPROM contents (16KB backup!)
- Write 0xFF to address 0x0000 (corrupts the C2 magic byte)
- Remove clip, plug in SkyWalker-1
- Device should enumerate as bare FX2 (04B4:8613)
- Load custom firmware via
fw_load.py - 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:
- Locate the SDA test point or EEPROM pin 5 (SDA)
- Connect a 1kΩ pull-up to 3.3V on SDA
- Power on the SkyWalker-1
- If it enumerates as bare FX2 (04B4:8613), load firmware:
python3 tools/fw_load.py load firmware/build/skywalker1.ihx - Remove the pull-up
- 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.
- Lift EEPROM pin 5 (SDA) from the PCB pad
- Power on → enumerates as bare FX2
- Load firmware via USB
- Resolder pin 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):
-
Load custom firmware to RAM:
python3 tools/fw_load.py load firmware/build/skywalker1.ihx -
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 -
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