One-off diagnostic scripts from experiments 0xD7-0xDB investigating the I2C BERR deadlock. Documents the systematic elimination of software-only recovery approaches: - i2c_host_test.py: Proved 0xA0 register writes cannot drive I2C bus - i2c_register_test.py: Tested I2C register writability from host - i2c_recovery_boot.py: Attempted I2C state machine recovery via boot - eeprom_flash_a0.py: Host-side EEPROM flash attempt (failed) - boot_ab_test.py / boot_test.py: EEPROM boot reliability testing - a8_autoclear_test.py: BCM4500 command register auto-clear behavior - addr_gateway_test.py: BCM3440 gateway address routing analysis - stock_fw_compare.py / stock_fw_test.py: Stock vs custom fw analysis
178 lines
5.8 KiB
Python
178 lines
5.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Quick boot test for PLL config firmware."""
|
|
import sys
|
|
sys.path.insert(0, 'tools')
|
|
from skywalker_lib import SkyWalker1
|
|
|
|
CMD_RAW_DEMOD_READ = 0xB1
|
|
CMD_I2C_SCAN = 0xB4
|
|
CMD_GET_PLL_DIAG = 0xBF
|
|
|
|
sw = SkyWalker1()
|
|
sw.open()
|
|
print('=== SkyWalker-1 Custom Firmware Boot Test ===')
|
|
print()
|
|
|
|
# Check firmware version
|
|
ver = sw.get_fw_version()
|
|
print(f'Firmware version: {ver}')
|
|
|
|
# Check config status
|
|
cfg = sw.get_config()
|
|
print(f'Config status: 0x{cfg:02X}')
|
|
bits = []
|
|
if cfg & 0x01: bits.append('Started')
|
|
if cfg & 0x02: bits.append('FW_Loaded')
|
|
if cfg & 0x04: bits.append('Intersil')
|
|
if cfg & 0x08: bits.append('DVBmode')
|
|
if cfg & 0x10: bits.append('22kHz')
|
|
if cfg & 0x20: bits.append('18V')
|
|
if cfg & 0x40: bits.append('DCtuned')
|
|
if cfg & 0x80: bits.append('Armed')
|
|
print(f' Flags: {" | ".join(bits) if bits else "(none)"}')
|
|
print()
|
|
|
|
# Check last error before boot
|
|
err = sw.get_last_error()
|
|
print(f'Last error (pre-boot): 0x{err:02X}')
|
|
print()
|
|
|
|
# Boot the BCM4500
|
|
print('--- Booting BCM4500 ---')
|
|
boot_result = sw.boot()
|
|
print(f'Boot result: {boot_result}')
|
|
cfg = sw.get_config()
|
|
print(f'Config after boot: 0x{cfg:02X}')
|
|
bits = []
|
|
if cfg & 0x01: bits.append('Started')
|
|
if cfg & 0x02: bits.append('FW_Loaded')
|
|
if cfg & 0x04: bits.append('Intersil')
|
|
if cfg & 0x08: bits.append('DVBmode')
|
|
if cfg & 0x10: bits.append('22kHz')
|
|
if cfg & 0x20: bits.append('18V')
|
|
if cfg & 0x40: bits.append('DCtuned')
|
|
if cfg & 0x80: bits.append('Armed')
|
|
print(f' Flags: {" | ".join(bits) if bits else "(none)"}')
|
|
|
|
err = sw.get_last_error()
|
|
ERR_NAMES = {
|
|
0x00: 'ERR_OK',
|
|
0x01: 'ERR_I2C_TIMEOUT',
|
|
0x02: 'ERR_I2C_NAK',
|
|
0x03: 'ERR_I2C_ARB_LOST',
|
|
0x04: 'ERR_BCM_NOT_READY (PLL config failed)',
|
|
0x05: 'ERR_BCM_TIMEOUT',
|
|
}
|
|
print(f'Last error after boot: 0x{err:02X} = {ERR_NAMES.get(err, "unknown")}')
|
|
print()
|
|
|
|
# PLL config diagnostics
|
|
print('--- PLL Config Diagnostics ---')
|
|
try:
|
|
pd = sw._vendor_in(CMD_GET_PLL_DIAG, value=0, index=0, length=10)
|
|
print(f' EEPROM present: {"YES" if pd[0] else "NO"}')
|
|
print(f' First block count: 0x{pd[1]:02X}' + (' (sentinel=0, no PLL data!)' if pd[1] == 0 else
|
|
(' (not reached)' if pd[1] == 0xFF else f' ({pd[1]} AB bytes)')))
|
|
print(f' Blocks written: {pd[2]}')
|
|
print(f' Last A9 value: 0x{pd[3]:02X}' + (' (none)' if pd[3] == 0xFF else ''))
|
|
print(f' Last AA value: 0x{pd[4]:02X}' + (' (none)' if pd[4] == 0xFF else ''))
|
|
print(f' Last AB count: 0x{pd[5]:02X}' + (' (none)' if pd[5] == 0xFF else ''))
|
|
print(f' Config mode exit: {"OK" if pd[6] == 1 else ("FAIL" if pd[6] == 0 else "not reached")}')
|
|
print(f' Overall PLL result: {"SUCCESS" if pd[7] == 1 else "FAILED"}')
|
|
print(f' Boot stage: 0x{pd[8]:02X}' + (' (all complete)' if pd[8] == 0xFF else f' (stopped at stage {pd[8]})'))
|
|
print(f' Last error: 0x{pd[9]:02X}')
|
|
except Exception as e:
|
|
print(f' PLL diag failed: {e}')
|
|
print()
|
|
|
|
# I2C bus scan
|
|
print('--- I2C Bus Scan ---')
|
|
try:
|
|
bitmap = sw._vendor_in(CMD_I2C_SCAN, value=0, index=0, length=16)
|
|
found = []
|
|
for byte_idx in range(16):
|
|
for bit_idx in range(8):
|
|
if bitmap[byte_idx] & (1 << bit_idx):
|
|
addr = byte_idx * 8 + bit_idx
|
|
found.append(addr)
|
|
labels = {0x08: 'BCM4500', 0x10: 'BCM3440', 0x51: 'EEPROM'}
|
|
for addr in found:
|
|
label = labels.get(addr, '')
|
|
print(f' 0x{addr:02X} {label}')
|
|
if not found:
|
|
print(' (no devices found!)')
|
|
except Exception as e:
|
|
print(f' Scan failed: {e}')
|
|
print()
|
|
|
|
# Try reading signal
|
|
print('--- Signal Check ---')
|
|
try:
|
|
sig = sw.signal_monitor()
|
|
print(f'Signal monitor: {sig}')
|
|
except Exception as e:
|
|
print(f'Signal monitor failed: {e}')
|
|
|
|
# Read BCM4500 direct registers via 0xB1 vendor command
|
|
# wValue=register address, wIndex=1 for direct read mode
|
|
print()
|
|
print('--- BCM4500 Direct Register Reads ---')
|
|
key_regs = [
|
|
(0xA0, 'CFG_MODE'),
|
|
(0xA2, 'STATUS'),
|
|
(0xA4, 'LOCK'),
|
|
(0xA9, 'PLL_A9'),
|
|
(0xAA, 'PLL_AA'),
|
|
(0xAB, 'PLL_AB'),
|
|
]
|
|
for reg, label in key_regs:
|
|
try:
|
|
data = sw._vendor_in(CMD_RAW_DEMOD_READ, value=reg, index=1, length=1)
|
|
val = data[0]
|
|
print(f' 0x{reg:02X} ({label:8s}): 0x{val:02X}')
|
|
except Exception as e:
|
|
print(f' 0x{reg:02X} ({label:8s}): FAILED ({e})')
|
|
|
|
# Indirect register reads via 0xB1 with wIndex=0 (indirect mode)
|
|
# wValue=page, wIndex=0. Only meaningful if the DSP core is running.
|
|
print()
|
|
print('--- BCM4500 Indirect Register Reads (DSP core test) ---')
|
|
for page in [0x06, 0x07, 0x0F]:
|
|
try:
|
|
data = sw._vendor_in(CMD_RAW_DEMOD_READ, value=page, index=0, length=1)
|
|
val = data[0]
|
|
alive = ' << DSP responding' if val != 0 else ''
|
|
print(f' Page 0x{page:02X}: 0x{val:02X}{alive}')
|
|
except Exception as e:
|
|
print(f' Page 0x{page:02X}: FAILED ({e})')
|
|
|
|
# Cross-check: read key registers via 0xB5 (raw I2C, writes into EP0BUF directly)
|
|
# This bypasses the 0xB1 handler's val variable entirely
|
|
CMD_I2C_RAW_READ = 0xB5
|
|
BCM4500_ADDR = 0x08
|
|
print()
|
|
print('--- Cross-check via 0xB5 Raw I2C Read (BCM4500 @ 0x08) ---')
|
|
for reg, label in key_regs:
|
|
try:
|
|
data = sw._vendor_in(CMD_I2C_RAW_READ, value=BCM4500_ADDR, index=reg, length=1)
|
|
val = data[0]
|
|
tag = ' ** I2C FAIL (0xFF) **' if val == 0xFF else ''
|
|
print(f' 0x{reg:02X} ({label:8s}): 0x{val:02X}{tag}')
|
|
except Exception as e:
|
|
print(f' 0x{reg:02X} ({label:8s}): FAILED ({e})')
|
|
|
|
# Full register dump 0xA0-0xBF via 0xB5 raw I2C (ground truth)
|
|
print()
|
|
print('--- Full Direct Register Dump 0xA0-0xBF (via 0xB5 raw I2C) ---')
|
|
for reg in range(0xA0, 0xC0):
|
|
try:
|
|
data = sw._vendor_in(CMD_I2C_RAW_READ, value=BCM4500_ADDR, index=reg, length=1)
|
|
val = data[0]
|
|
print(f' 0x{reg:02X}: 0x{val:02X}')
|
|
except Exception as e:
|
|
print(f' 0x{reg:02X}: FAIL')
|
|
|
|
sw.close()
|
|
print()
|
|
print('=== Test Complete ===')
|