Fix BCM4500 boot: spurious I2C STOP corrupted FX2 controller
Removed I2CS bmSTOP "bus reset" from bcm4500_boot() and debug modes. Sending STOP with no active transaction puts the FX2 I2C controller into an inconsistent state where subsequent START+ACK detection fails. Root cause identified through incremental debug modes (wValue 0x80-0x85) on live hardware: mode 0x82 (with bmSTOP) fails, mode 0x85 (identical but without bmSTOP) succeeds. Raw I2C reads confirm BCM4500 is alive the entire time -- only the controller state is corrupted. BCM4500 now boots successfully in ~90ms. Three I2C devices found on bus: 0x08 (BCM4500), 0x10 (tuner/LNB), 0x51 (EEPROM). Also in this commit: - Timeout-protected I2C functions replacing fx2lib bare while loops - I2C bus scan and debug mode infrastructure - Kernel driver blacklist for dvb_usb_gp8psk - Test tools for incremental boot debugging - Technical findings documented in docs/boot-debug-findings.md
This commit is contained in:
parent
890a38bfa0
commit
d9f51548e0
7 changed files with 1296 additions and 51 deletions
171
tools/test_boot.py
Normal file
171
tools/test_boot.py
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Test BOOT_8PSK on SkyWalker-1 with custom firmware v3.01.0"""
|
||||
|
||||
import usb.core
|
||||
import usb.util
|
||||
import sys
|
||||
import time
|
||||
|
||||
def find_device():
|
||||
dev = usb.core.find(idVendor=0x09C0, idProduct=0x0203)
|
||||
if not dev:
|
||||
print("Device not found!")
|
||||
sys.exit(1)
|
||||
return dev
|
||||
|
||||
def setup_device(dev):
|
||||
"""Detach kernel driver and set configuration."""
|
||||
try:
|
||||
if dev.is_kernel_driver_active(0):
|
||||
dev.detach_kernel_driver(0)
|
||||
print("Detached kernel driver from interface 0")
|
||||
except Exception as e:
|
||||
print(f"Driver detach note: {e}")
|
||||
|
||||
try:
|
||||
dev.set_configuration()
|
||||
except usb.core.USBError:
|
||||
# Already configured, that's fine
|
||||
pass
|
||||
|
||||
def main():
|
||||
dev = find_device()
|
||||
setup_device(dev)
|
||||
|
||||
# GET_FW_VERS (0x92)
|
||||
print("=" * 50)
|
||||
ret = dev.ctrl_transfer(0xC0, 0x92, 0, 0, 6)
|
||||
major, minor, patch = ret[2], ret[1], ret[0]
|
||||
day, month, year = ret[3], ret[4], ret[5] + 2000
|
||||
print(f"Firmware: v{major}.{minor:02d}.{patch} ({year}-{month:02d}-{day:02d})")
|
||||
|
||||
# GET_8PSK_CONFIG (0x80)
|
||||
ret = dev.ctrl_transfer(0xC0, 0x80, 0, 0, 1)
|
||||
print(f"Config before boot: 0x{ret[0]:02X}")
|
||||
|
||||
# BOOT_8PSK (0x89) with wValue=1
|
||||
print()
|
||||
print("=" * 50)
|
||||
print("Sending BOOT_8PSK(1)...")
|
||||
print(" (This triggers: P0.5 reset, power on, 3-block register init)")
|
||||
print()
|
||||
|
||||
try:
|
||||
ret = dev.ctrl_transfer(0xC0, 0x89, 1, 0, 3, timeout=10000)
|
||||
except usb.core.USBError as e:
|
||||
print(f"BOOT_8PSK USB error: {e}")
|
||||
print("The device may have timed out during init.")
|
||||
print("Trying to read config status anyway...")
|
||||
try:
|
||||
ret = dev.ctrl_transfer(0xC0, 0x80, 0, 0, 1)
|
||||
print(f"Config after attempted boot: 0x{ret[0]:02X}")
|
||||
except:
|
||||
print("Device not responding. May need power cycle.")
|
||||
sys.exit(1)
|
||||
|
||||
status = ret[0]
|
||||
stage = ret[1] if len(ret) > 1 else 0
|
||||
stage_names = {
|
||||
0: "NOT_STARTED", 1: "GPIO_SETUP", 2: "PWR_SETTLED",
|
||||
3: "I2C_PROBE", 4: "INIT_BLK0", 5: "INIT_BLK1",
|
||||
6: "INIT_BLK2", 0xFF: "COMPLETE"
|
||||
}
|
||||
flags = []
|
||||
if status & 0x01: flags.append("STARTED")
|
||||
if status & 0x02: flags.append("FW_LOADED")
|
||||
if status & 0x04: flags.append("INTERSIL")
|
||||
if status & 0x08: flags.append("DVB_MODE")
|
||||
if status & 0x10: flags.append("22KHZ")
|
||||
if status & 0x20: flags.append("SEL18V")
|
||||
if status & 0x40: flags.append("DC_TUNED")
|
||||
if status & 0x80: flags.append("ARMED")
|
||||
print(f"BOOT_8PSK response: 0x{status:02X} [{' | '.join(flags) if flags else 'none'}]")
|
||||
print(f"Boot stage: 0x{stage:02X} [{stage_names.get(stage, 'UNKNOWN')}]")
|
||||
|
||||
if status & 0x03 == 0x03:
|
||||
print()
|
||||
print("*** BCM4500 BOOT SUCCESS! ***")
|
||||
print()
|
||||
|
||||
# Read direct I2C registers
|
||||
print("BCM4500 direct registers (via I2C_RAW_READ 0xB5):")
|
||||
for reg in [0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8]:
|
||||
try:
|
||||
r = dev.ctrl_transfer(0xC0, 0xB5, 0x08, reg, 1)
|
||||
print(f" Reg 0x{reg:02X} = 0x{r[0]:02X}")
|
||||
except Exception as e:
|
||||
print(f" Reg 0x{reg:02X}: ERROR {e}")
|
||||
|
||||
# Read indirect registers through our protocol
|
||||
print()
|
||||
print("BCM4500 indirect registers (via RAW_DEMOD_READ 0xB1):")
|
||||
for page in range(16):
|
||||
try:
|
||||
r = dev.ctrl_transfer(0xC0, 0xB1, page, 0, 1)
|
||||
print(f" Page 0x{page:02X} = 0x{r[0]:02X}")
|
||||
except Exception as e:
|
||||
print(f" Page 0x{page:02X}: ERROR {e}")
|
||||
|
||||
# I2C diagnostic
|
||||
print()
|
||||
print("I2C diagnostic (0xB6) for page 0x00:")
|
||||
try:
|
||||
r = dev.ctrl_transfer(0xC0, 0xB6, 0x00, 0, 8)
|
||||
labels = ["wr_A6", "rb_A6", "wr_A8", "rb_A8",
|
||||
"rb_A7", "fin_A6", "fin_A7", "fin_A8"]
|
||||
for i, lab in enumerate(labels):
|
||||
print(f" {lab}: 0x{r[i]:02X}")
|
||||
except Exception as e:
|
||||
print(f" ERROR: {e}")
|
||||
|
||||
# Signal strength
|
||||
print()
|
||||
try:
|
||||
r = dev.ctrl_transfer(0xC0, 0x87, 0, 0, 6)
|
||||
print(f"Signal strength: {' '.join(f'{b:02X}' for b in r)}")
|
||||
except Exception as e:
|
||||
print(f"Signal strength ERROR: {e}")
|
||||
|
||||
# Signal lock
|
||||
try:
|
||||
r = dev.ctrl_transfer(0xC0, 0x90, 0, 0, 1)
|
||||
print(f"Signal lock: 0x{r[0]:02X}")
|
||||
except Exception as e:
|
||||
print(f"Signal lock ERROR: {e}")
|
||||
|
||||
else:
|
||||
print()
|
||||
print("*** BOOT FAILED ***")
|
||||
print()
|
||||
|
||||
# I2C bus scan
|
||||
print("I2C bus scan:")
|
||||
try:
|
||||
r = dev.ctrl_transfer(0xC0, 0xB4, 0, 0, 16)
|
||||
addrs = []
|
||||
for bi in range(16):
|
||||
for bit in range(8):
|
||||
if r[bi] & (1 << bit):
|
||||
addrs.append(bi * 8 + bit)
|
||||
if addrs:
|
||||
print(f" Found devices at: {[f'0x{a:02X}' for a in addrs]}")
|
||||
else:
|
||||
print(" No I2C devices found!")
|
||||
except Exception as e:
|
||||
print(f" Scan error: {e}")
|
||||
|
||||
# Try raw I2C reads anyway
|
||||
print()
|
||||
print("Raw I2C reads to BCM4500 (0x08):")
|
||||
for reg in [0xA2, 0xA4, 0xA6, 0xA7, 0xA8]:
|
||||
try:
|
||||
r = dev.ctrl_transfer(0xC0, 0xB5, 0x08, reg, 1)
|
||||
print(f" Reg 0x{reg:02X} = 0x{r[0]:02X}")
|
||||
except Exception as e:
|
||||
print(f" Reg 0x{reg:02X}: ERROR {e}")
|
||||
|
||||
print()
|
||||
print("=" * 50)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue