diff --git a/device/mcu.py b/device/mcu.py index a875afe..21292dc 100644 --- a/device/mcu.py +++ b/device/mcu.py @@ -16,6 +16,7 @@ McuCoherencyError, McuMagicError, McuMapVersionError, + McuProtocolError, ) from .base import Device @@ -256,6 +257,7 @@ class PowerFsmState(IntEnum): POWER_L5ON = 8 POWER_L6ON = 9 POWER_ON = 10 + POWER_CONFIG = 11 class PowerFlags(IntFlag): @@ -593,7 +595,14 @@ def read_power(self, retries: int = 3, generation = self._read_u32(page, PowerReg.GENERATION) if generation & 1: continue - fsm_state = PowerFsmState(self._read_u8(page, PowerReg.FSM_STATE)) + raw_fsm_state = self._read_u8(page, PowerReg.FSM_STATE) + try: + fsm_state = PowerFsmState(raw_fsm_state) + except ValueError: + raise McuProtocolError( + "unknown MCU power FSM state %d; firmware has a state that " + "PowerFsmState does not -- update the enum" % raw_fsm_state + ) from None flags = PowerFlags(self._read_u8(page, PowerReg.FLAGS)) live_pg_mask = self._read_u32(page, PowerReg.LIVE_PG_MASK) expected_pg_mask = self._read_u32(page, PowerReg.EXPECTED_PG_MASK) diff --git a/tests/test_wire_contract.py b/tests/test_wire_contract.py index 74d4345..21eccf3 100644 --- a/tests/test_wire_contract.py +++ b/tests/test_wire_contract.py @@ -173,6 +173,19 @@ def test_alarm_temp_device_enum_matches_firmware(): assert int(mcu.AlarmTempDevice[name]) == index +def test_power_fsm_state_enum_matches_firmware(): + """PWR_OFF_STATE carries enum power_system_state, built from an X-macro list.""" + with open(TASKS_H) as handle: + text = _strip_comments(handle.read()) + text = re.sub(r"//.*", "", text) + match = re.search(r"#define\s+X_MACRO_PS_SYSTEM_STATES((?:[^\n]*\\\n)*[^\n]*)", text) + assert match, "X_MACRO_PS_SYSTEM_STATES not found in Tasks.h" + names = re.findall(r"X\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)", match.group(1)) + assert names == [member.name for member in mcu.PowerFsmState] + for index, name in enumerate(names): + assert int(mcu.PowerFsmState[name]) == index + + def test_config_write_clamps(defines): """Client and firmware must refuse the same values (the clamp is a safety control).""" assert _resolve("CFG_TEMP_MIN_C", defines) == mcu.ALARM_TEMP_MIN_C