Apply .gitattributes normalization to convert all CRLF line endings inherited from Windows-origin source files to Unix LF. 175 files, zero content changes.
123 lines
3.9 KiB
Python
123 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Pinpoint which element in mode 0x82 causes bcm_direct_read to fail.
|
|
|
|
Test sequence:
|
|
1. Power on via 0x81, confirm alive with raw read
|
|
2. 0x84: bcm_direct_read ONLY (no GPIO, no reset, no bus reset)
|
|
3. 0x85: GPIO + reset + power but NO I2C bus reset (no bmSTOP)
|
|
4. 0x82: GPIO + I2C bus reset + reset + power + probe (the one that fails)
|
|
"""
|
|
|
|
import usb.core
|
|
import usb.util
|
|
import sys
|
|
import time
|
|
|
|
BOOT_8PSK = 0x89
|
|
|
|
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):
|
|
try:
|
|
if dev.is_kernel_driver_active(0):
|
|
dev.detach_kernel_driver(0)
|
|
except Exception:
|
|
pass
|
|
try:
|
|
dev.set_configuration()
|
|
except usb.core.USBError:
|
|
pass
|
|
|
|
def decode_stage(stage):
|
|
names = {
|
|
0x00: "NOT_STARTED", 0xA1: "GPIO_OK", 0xA2: "PROBE_OK(0x82)",
|
|
0xA3: "BLK0_OK", 0xA4: "PROBE_OK(0x84)", 0xA5: "PROBE_OK(0x85)",
|
|
0xE3: "PROBE_FAIL", 0xE4: "BLK0_FAIL",
|
|
}
|
|
return names.get(stage, f"0x{stage:02X}")
|
|
|
|
def test_boot_mode(dev, wval, label, timeout_ms=3000):
|
|
print(f"\n{'─' * 55}")
|
|
print(f" Mode 0x{wval:02X}: {label}")
|
|
print(f"{'─' * 55}")
|
|
|
|
t0 = time.monotonic()
|
|
try:
|
|
ret = dev.ctrl_transfer(0xC0, BOOT_8PSK, wval, 0, 3, timeout=timeout_ms)
|
|
except usb.core.USBError as e:
|
|
elapsed = (time.monotonic() - t0) * 1000
|
|
print(f" TIMEOUT after {elapsed:.0f}ms: {e}")
|
|
return None
|
|
elapsed = (time.monotonic() - t0) * 1000
|
|
|
|
stage = ret[1]
|
|
probe = ret[2]
|
|
ok = stage not in (0xE3, 0xE4)
|
|
status_str = "SUCCESS" if ok else "FAILED"
|
|
print(f" {status_str} in {elapsed:.0f}ms")
|
|
print(f" stage=0x{stage:02X} [{decode_stage(stage)}] probe=0x{probe:02X}")
|
|
return ret
|
|
|
|
def raw_read(dev, addr, reg):
|
|
try:
|
|
r = dev.ctrl_transfer(0xC0, 0xB5, addr, reg, 1, timeout=1000)
|
|
return r[0]
|
|
except:
|
|
return None
|
|
|
|
def main():
|
|
dev = find_device()
|
|
setup_device(dev)
|
|
|
|
ret = dev.ctrl_transfer(0xC0, 0x92, 0, 0, 6, timeout=2000)
|
|
major, minor, patch = ret[2], ret[1], ret[0]
|
|
print(f"Firmware: v{major}.{minor:02d}.{patch}")
|
|
|
|
# Step 1: Power on via GPIO-only mode
|
|
print("\n=== STEP 1: Power on BCM4500 (mode 0x81) ===")
|
|
ret = dev.ctrl_transfer(0xC0, BOOT_8PSK, 0x81, 0, 3, timeout=3000)
|
|
print(f" GPIO setup done, stage=0x{ret[1]:02X}")
|
|
time.sleep(1.0)
|
|
|
|
# Confirm alive
|
|
val = raw_read(dev, 0x08, 0xA2)
|
|
print(f" Raw read 0x08:0xA2 = 0x{val:02X}" if val is not None else " Raw read FAILED")
|
|
|
|
# Step 2: Test 0x84 (I2C read ONLY, no GPIO manipulation)
|
|
test_boot_mode(dev, 0x84, "bcm_direct_read ONLY (no GPIO, chip already powered)")
|
|
|
|
# Confirm still alive
|
|
val = raw_read(dev, 0x08, 0xA2)
|
|
print(f" Raw read after 0x84: 0x{val:02X}" if val is not None else " Raw read FAILED")
|
|
|
|
# Step 3: Test 0x85 (GPIO + reset but NO I2C bus reset)
|
|
test_boot_mode(dev, 0x85, "GPIO + reset + power, NO bmSTOP (no I2C bus reset)")
|
|
|
|
# Confirm still alive
|
|
time.sleep(0.1)
|
|
val = raw_read(dev, 0x08, 0xA2)
|
|
print(f" Raw read after 0x85: 0x{val:02X}" if val is not None else " Raw read FAILED")
|
|
|
|
# Step 4: For comparison, test 0x82 (the one that fails)
|
|
test_boot_mode(dev, 0x82, "GPIO + I2C bmSTOP + reset + power + probe")
|
|
|
|
# Confirm still alive
|
|
val = raw_read(dev, 0x08, 0xA2)
|
|
print(f" Raw read after 0x82: 0x{val:02X}" if val is not None else " Raw read FAILED")
|
|
|
|
print(f"\n{'=' * 55}")
|
|
print("Analysis complete.")
|
|
print()
|
|
print("If 0x84 works → bcm_direct_read is fine, issue is in reset/GPIO sequence")
|
|
print("If 0x84 fails → bcm_direct_read itself has a bug")
|
|
print("If 0x85 works → I2CS bmSTOP (I2C bus reset) is the culprit in 0x82")
|
|
print("If 0x85 fails → re-reset of BCM4500 needs more delay")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|