Add experimental I2C debugging and EEPROM analysis tools
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
This commit is contained in:
parent
97c1000d8b
commit
0d6facb321
16 changed files with 3279 additions and 0 deletions
177
tools/boot_test.py
Normal file
177
tools/boot_test.py
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
#!/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 ===')
|
||||
Loading…
Add table
Add a link
Reference in a new issue