fix: wait for TPU allowed state before triggering flash write

This commit is contained in:
2026-07-27 11:25:54 +08:00
parent 4e3400ab87
commit cf06b97524
+41 -2
View File
@@ -62,6 +62,17 @@ PASSWORD_HI = 0xCEE5
# TPU trigger: holding coil bit 49 (fenghuang-dsp modbus_mapping.h)
TPU_BIT_WRITE_FLASH = 49 # MODBUS_ALL_CFG_CMD_BIT → main_app.write_flash
# TPU state register: input reg 61 (MODBUS_MAIN_STATE), read via FC4.
# Firmware only processes write_flash in these states (app_modbus.c update_modbus_input).
ADDR_TPU_STATE = 61
TPU_TRIGGER_ALLOWED_STATES = {
2, # TPU_READY
10, # TPU_INITIALIZATION
15, # TPU_DEBUG_CONFIG
16, # TPU_TEST_MODE
0xEE, # TPU_ERROR
}
# Auto-detection register (holding reg 163, same address for both RPU and TPU)
ADDR_HARDWARE_REV_HI = 163 # MODBUS_HARDWARE_REVISION_HI
HW_REV_TPU = 0x0021
@@ -310,7 +321,7 @@ def read_reg(instr: minimalmodbus.Instrument, addr: int, data_type: str):
def write_reg(instr: minimalmodbus.Instrument, addr: int, value, data_type: str) -> None:
if _is_float(data_type):
instr.write_float(addr, float(value), functioncode=16, number_of_registers=2,
instr.write_float(addr, float(value), number_of_registers=2,
byteorder=minimalmodbus.BYTEORDER_BIG)
return
signed = (data_type == 'int16')
@@ -352,8 +363,31 @@ def trigger_rewrite_rpu(instr: minimalmodbus.Instrument) -> None:
_wait_for_device(instr, ADDR_PASSWORD_LO)
def _wait_for_tpu_trigger_state(instr: minimalmodbus.Instrument) -> bool:
"""Poll input reg 61 (MODBUS_MAIN_STATE) until state allows write_flash trigger.
Returns True if state reached, False if timed out.
Required because firmware only processes write_flash in specific states.
"""
deadline = time.monotonic() + REWRITE_WAIT
while time.monotonic() < deadline:
try:
state = instr.read_register(ADDR_TPU_STATE, number_of_decimals=0,
functioncode=4, signed=False)
if state in TPU_TRIGGER_ALLOWED_STATES:
print(f" (trigger: TPU state=0x{state:02X} — ready to accept trigger)")
return True
print(f" (trigger: TPU state=0x{state:02X} — waiting for allowed state...)")
except minimalmodbus.ModbusException:
pass
time.sleep(0.5)
print(" (trigger: WARNING — TPU state never reached allowed state; trigger may be ignored)")
return False
def trigger_rewrite_tpu(instr: minimalmodbus.Instrument) -> None:
"""Write coil bit 49 (MODBUS_ALL_CFG_CMD_BIT) → modbus_to_config() + write_all_flash() + soft_reset()."""
_wait_for_tpu_trigger_state(instr)
try:
instr.write_bit(TPU_BIT_WRITE_FLASH, 1, functioncode=5)
print(" (trigger: coil bit write ack received)")
@@ -392,9 +426,11 @@ def run_tests(port: str) -> tuple[str, list[dict]]:
if device_type == 'TPU':
TESTS = TPU_TESTS
trigger_fn = trigger_rewrite_tpu
time.sleep(5)
else:
TESTS = RPU_TESTS
trigger_fn = trigger_rewrite_rpu
time.sleep(5)
print(f" Device type: {device_type}{len(TESTS)} registers in test list")
# -------------------------------------------------------------------------
@@ -427,7 +463,8 @@ def run_tests(port: str) -> tuple[str, list[dict]]:
print("\n[Phase 1] Triggering rewrite...")
trigger_fn(instr)
time.sleep(5)
print("[Phase 1] Reading back...")
below_readbacks: dict[int, any] = {}
for (_, addr, data_type, *_) in TESTS:
@@ -452,6 +489,7 @@ def run_tests(port: str) -> tuple[str, list[dict]]:
print("\n[Phase 2] Triggering rewrite...")
trigger_fn(instr)
time.sleep(5)
print("[Phase 2] Reading back...")
above_readbacks: dict[int, any] = {}
@@ -474,6 +512,7 @@ def run_tests(port: str) -> tuple[str, list[dict]]:
except minimalmodbus.ModbusException as e:
print(f" addr {addr:3d}: restore write ERROR — {e}")
trigger_fn(instr)
time.sleep(5)
print("[Restore] Done.")
# -------------------------------------------------------------------------