Add one-shot recovery script for post-intervention testing
Waits for bare FX2 or SkyWalker-1 enumeration, loads firmware, then runs a full diagnostic: I2C gateway, BOOT_8PSK, signal monitor, and config status readback. Usage: bash tools/recover.sh
This commit is contained in:
parent
33b6aa92db
commit
2b87228e29
152
tools/recover.sh
Executable file
152
tools/recover.sh
Executable file
@ -0,0 +1,152 @@
|
||||
#!/bin/bash
|
||||
# Quick recovery script — run after physical intervention (SDA pull-up / SOIC clip)
|
||||
# Waits for bare FX2 or SkyWalker enumeration, loads firmware, runs full test
|
||||
set -euo pipefail
|
||||
|
||||
TOOLS="$(cd "$(dirname "$0")" && pwd)"
|
||||
FW="$TOOLS/../firmware/build/skywalker1.ihx"
|
||||
|
||||
if [ ! -f "$FW" ]; then
|
||||
echo "ERROR: Firmware not found at $FW"
|
||||
echo "Run: cd firmware && make"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== SkyWalker-1 Recovery ==="
|
||||
echo "Waiting for device to appear... (plug in now, Ctrl+C to stop)"
|
||||
echo ""
|
||||
|
||||
# Poll for up to 60 seconds
|
||||
for i in $(seq 1 120); do
|
||||
DEV=$(lsusb -d 09c0:0203 2>/dev/null || true)
|
||||
BARE=$(lsusb -d 04b4:8613 2>/dev/null || true)
|
||||
|
||||
if [ -n "$DEV" ]; then
|
||||
echo "FOUND SkyWalker-1 (09c0:0203): $DEV"
|
||||
echo "Device already has firmware — skipping load"
|
||||
break
|
||||
elif [ -n "$BARE" ]; then
|
||||
echo "FOUND bare FX2 (04b4:8613): $BARE"
|
||||
sleep 0.5
|
||||
echo "Loading firmware..."
|
||||
python3 "$TOOLS/fw_load.py" load "$FW"
|
||||
echo "Waiting 3s for re-enumeration..."
|
||||
sleep 3
|
||||
# Verify it came back
|
||||
DEV=$(lsusb -d 09c0:0203 2>/dev/null || true)
|
||||
if [ -z "$DEV" ]; then
|
||||
echo "WARNING: Device did not re-enumerate as SkyWalker-1"
|
||||
echo "Check dmesg for errors"
|
||||
exit 1
|
||||
fi
|
||||
echo "Re-enumerated: $DEV"
|
||||
break
|
||||
fi
|
||||
|
||||
[ $((i % 20)) -eq 0 ] && printf "."
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
# If we got here without finding anything
|
||||
DEV=$(lsusb -d 09c0:0203 2>/dev/null || true)
|
||||
if [ -z "$DEV" ]; then
|
||||
echo ""
|
||||
echo "Timeout — no device detected in 60s"
|
||||
echo "Check physical connections and try again"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "--- Running post-recovery test ---"
|
||||
python3 -c "
|
||||
import usb.core, usb.util, time, sys
|
||||
|
||||
dev = usb.core.find(idVendor=0x09C0, idProduct=0x0203)
|
||||
if not dev:
|
||||
print('Device not found'); sys.exit(1)
|
||||
print(f'Product: {dev.product}')
|
||||
|
||||
# Detach kernel drivers
|
||||
for c in dev:
|
||||
for i in c:
|
||||
if dev.is_kernel_driver_active(i.bInterfaceNumber):
|
||||
dev.detach_kernel_driver(i.bInterfaceNumber)
|
||||
try: dev.set_configuration()
|
||||
except: pass
|
||||
|
||||
A0 = 0xA0
|
||||
VIN = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_IN
|
||||
|
||||
# Read FX2 registers
|
||||
def read_reg(addr, n=1):
|
||||
return bytes(dev.ctrl_transfer(VIN, A0, addr, 0, n, 2000))
|
||||
|
||||
cpucs = read_reg(0xE600)[0]
|
||||
i2cs = read_reg(0xE678)[0]
|
||||
print(f'CPUCS=0x{cpucs:02X} I2CS=0x{i2cs:02X}')
|
||||
|
||||
# Test BCM3440 I2C gateway
|
||||
print()
|
||||
print('--- I2C Gateway Test ---')
|
||||
try:
|
||||
d = dev.ctrl_transfer(VIN, 0x84, 0x10, 0xA7, 1, 3000)
|
||||
print(f'BCM3440 gateway (A7): 0x{d[0]:02X} -- OK')
|
||||
except Exception as e:
|
||||
print(f'BCM3440 gateway: FAIL ({e})')
|
||||
|
||||
# Boot BCM4500 (wValue=1 = full boot, wIndex=0 = normal)
|
||||
print()
|
||||
print('--- BOOT_8PSK (wValue=1) ---')
|
||||
try:
|
||||
d = dev.ctrl_transfer(VIN, 0x89, 1, 0, 3, 15000)
|
||||
config = d[0]
|
||||
stage = d[1]
|
||||
print(f'config_status=0x{config:02X} boot_stage=0x{stage:02X}')
|
||||
if config & 0x03 == 0x03:
|
||||
print('Boot: SUCCESS (started + fw_loaded)')
|
||||
elif stage == 0xFF:
|
||||
print('Boot: SUCCESS (stage=0xFF = complete)')
|
||||
else:
|
||||
print(f'Boot: INCOMPLETE (check stage 0x{stage:02X})')
|
||||
except Exception as e:
|
||||
print(f'Boot: FAIL ({e})')
|
||||
|
||||
# Wait for demod to settle
|
||||
time.sleep(3)
|
||||
|
||||
# Signal check
|
||||
print()
|
||||
print('--- Signal Monitor ---')
|
||||
try:
|
||||
d = dev.ctrl_transfer(VIN, 0x90, 0, 0, 8, 3000)
|
||||
snr = (d[0] << 8) | d[1]
|
||||
agc1 = (d[2] << 8) | d[3]
|
||||
agc2 = (d[4] << 8) | d[5]
|
||||
lock = d[6]
|
||||
status = d[7]
|
||||
print(f'SNR={snr} AGC1={agc1} AGC2={agc2} Lock=0x{lock:02X} Status=0x{status:02X}')
|
||||
except Exception as e:
|
||||
print(f'Signal: FAIL ({e})')
|
||||
|
||||
# GET_8PSK_CONFIG
|
||||
print()
|
||||
print('--- Config Status ---')
|
||||
try:
|
||||
d = dev.ctrl_transfer(VIN, 0x80, 0, 0, 1, 2000)
|
||||
print(f'config_status: 0x{d[0]:02X}')
|
||||
flags = []
|
||||
if d[0] & 0x01: flags.append('STARTED')
|
||||
if d[0] & 0x02: flags.append('FW_LOADED')
|
||||
if d[0] & 0x04: flags.append('INTERSIL')
|
||||
if d[0] & 0x08: flags.append('DVB_MODE')
|
||||
if d[0] & 0x80: flags.append('ARMED')
|
||||
print(f'Flags: {\" | \".join(flags) if flags else \"(none)\"}')
|
||||
except Exception as e:
|
||||
print(f'Config: FAIL ({e})')
|
||||
|
||||
print()
|
||||
print('=== Recovery test complete ===')
|
||||
" 2>&1
|
||||
|
||||
echo ""
|
||||
echo "=== Done ==="
|
||||
Loading…
x
Reference in New Issue
Block a user