Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/defib/profiles/data/hi3516av200.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"name": "hi3516av200", "PRESTEP0": [4, 224, 45, 229, 60, 1, 0, 227, 2, 2, 65, 227, 78, 23, 5, 227, 79, 20, 68, 227, 0, 16, 128, 229, 64, 1, 0, 227, 2, 2, 65, 227, 117, 26, 6, 227, 105, 26, 71, 227, 4, 16, 128, 228, 0, 224, 128, 229, 4, 240, 157, 228, 239, 190, 173, 222, 239, 190, 173, 222, 239, 190, 173, 222], "DDRSTEP0": [4, 224, 45, 229, 60, 1, 0, 227, 2, 2, 65, 227, 120, 22, 5, 227, 52, 18, 65, 227, 0, 16, 128, 229, 64, 1, 0, 227, 2, 2, 65, 227, 117, 26, 6, 227, 105, 26, 71, 227, 4, 16, 128, 228, 0, 224, 128, 229, 4, 240, 157, 228, 239, 190, 173, 222, 239, 190, 173, 222, 239, 190, 173, 222], "ADDRESS": ["0x04013000", "0x04010500", "0x81000000"], "FILELEN": ["0x0040", "0x4F00"], "STEPLEN": ["0x0040", "0x0080"]}
{"name": "hi3516av200", "PRESTEP0": [4, 224, 45, 229, 60, 1, 0, 227, 2, 2, 65, 227, 78, 23, 5, 227, 79, 20, 68, 227, 0, 16, 128, 229, 64, 1, 0, 227, 2, 2, 65, 227, 117, 26, 6, 227, 105, 26, 71, 227, 4, 16, 128, 228, 0, 224, 128, 229, 4, 240, 157, 228, 239, 190, 173, 222, 239, 190, 173, 222, 239, 190, 173, 222], "PRESTEP1": [4, 224, 45, 229, 64, 1, 0, 227, 2, 2, 65, 227, 255, 31, 15, 227, 255, 31, 79, 227, 0, 16, 128, 229, 60, 1, 0, 227, 2, 2, 65, 227, 78, 23, 5, 227, 79, 20, 68, 227, 0, 16, 128, 229, 60, 0, 159, 229, 0, 0, 144, 229, 32, 98, 160, 225, 3, 96, 6, 226, 0, 0, 86, 227, 5, 243, 160, 3, 1, 0, 86, 227, 5, 243, 160, 3, 80, 1, 0, 227, 2, 2, 65, 227, 67, 29, 4, 227, 77, 21, 68, 227, 0, 16, 128, 229, 4, 224, 157, 228, 14, 240, 160, 225, 239, 190, 173, 222, 239, 190, 173, 222, 140, 0, 2, 18, 0, 0, 160, 225, 0, 0, 160, 225, 0, 0, 160, 225], "DDRSTEP0": [4, 224, 45, 229, 60, 1, 0, 227, 2, 2, 65, 227, 120, 22, 5, 227, 52, 18, 65, 227, 0, 16, 128, 229, 64, 1, 0, 227, 2, 2, 65, 227, 117, 26, 6, 227, 105, 26, 71, 227, 4, 16, 128, 228, 0, 224, 128, 229, 4, 240, 157, 228, 239, 190, 173, 222, 239, 190, 173, 222, 239, 190, 173, 222], "ADDRESS": ["0x04013000", "0x04010500", "0x81000000"], "FILELEN": ["0x0040", "0x4F00"], "STEPLEN": ["0x0040", "0x0080"]}
10 changes: 10 additions & 0 deletions src/defib/profiles/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ class SoCProfile(BaseModel):
default=None, alias="PRESTEP0",
description="Pre-DDR init bytecode (sent before DDRSTEP0)",
)
prestep1: list[int] | None = Field(
default=None, alias="PRESTEP1",
description="DDR training verification bytecode (sent after DDRSTEP0)",
)
ddrstep0: list[int] = Field(alias="DDRSTEP0", description="DDR initialization bytecode")
addresses: list[str] = Field(
alias="ADDRESS",
Expand Down Expand Up @@ -56,4 +60,10 @@ def prestep_data(self) -> bytes | None:
return None
return bytes(self.prestep0)

@property
def prestep1_data(self) -> bytes | None:
if self.prestep1 is None:
return None
return bytes(self.prestep1)

model_config = {"populate_by_name": True}
21 changes: 18 additions & 3 deletions src/defib/protocol/hisilicon_standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ async def _send_head(
logger.debug("HEAD: length=%d address=0x%08X", length, address)
frame = HeadFrame(length=length, address=address).encode()
return await self._send_frame_with_retry(
transport, frame, FRAME_SEND_RETRIES_SHORT, timeout=0.03
transport, frame, FRAME_SEND_RETRIES_SHORT, timeout=0.15
)

async def _send_data(
Expand Down Expand Up @@ -293,7 +293,8 @@ async def _send_ddr_step(
if not await self._send_data(transport, 1, prestep):
return False
if not await self._send_tail(transport, 2):
return False
logger.debug("PRESTEP0 TAIL not ACKed (non-fatal)")
await self._rehandshake(transport)

# DDRSTEP0: actual DDR init trigger
logger.debug(
Expand All @@ -308,7 +309,21 @@ async def _send_ddr_step(
return False

if not await self._send_tail(transport, 2):
return False
logger.debug("DDRSTEP0 TAIL not ACKed (non-fatal)")

# PRESTEP1: DDR training verification (waits for DDR to be ready)
prestep1 = profile.prestep1_data
if prestep1 is not None:
logger.debug(
"=== PRESTEP1 === address=0x%08X data=%d bytes",
addr, len(prestep1),
)
if not await self._send_head(transport, len(prestep1), addr):
return False
if not await self._send_data(transport, 1, prestep1):
return False
if not await self._send_tail(transport, 2):
logger.debug("PRESTEP1 TAIL not ACKed (non-fatal)")

_emit(on_progress, ProgressEvent(
stage=Stage.DDR_INIT, bytes_sent=64, bytes_total=64,
Expand Down
30 changes: 17 additions & 13 deletions src/defib/recovery/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,9 @@ async def run(
message=f"Power-cycling {self._poe_port}...",
))

# Start handshake (flooding 0xAA) BEFORE power cycle so the
# bootrom sees 0xAA immediately when power returns.
if on_log:
on_log(LogEvent(
level="info",
message=f"Starting {self._protocol_cls.name()} handshake for {self.chip}",
))
import asyncio
handshake_task = asyncio.create_task(
protocol.handshake(transport, on_progress)
)

try:
await self._power.power_cycle(self._poe_port)
except Exception as e:
handshake_task.cancel()
elapsed = (time.monotonic() - start_time) * 1000
if on_log:
on_log(LogEvent(level="error", message=f"Power cycle failed: {e}"))
Expand All @@ -132,6 +119,23 @@ async def run(
elapsed_ms=elapsed,
)

# Wait for power to actually be cut, then flush any warm-reboot
# garbage from the serial buffer before starting the handshake.
import asyncio
await asyncio.sleep(1.0)
await transport.flush_input()

# Now start handshake — floods 0xAA so the bootrom sees it
# immediately when power returns from the cycle.
if on_log:
on_log(LogEvent(
level="info",
message=f"Starting {self._protocol_cls.name()} handshake for {self.chip}",
))
handshake_task = asyncio.create_task(
protocol.handshake(transport, on_progress)
)

if on_progress:
on_progress(ProgressEvent(
stage=Stage.POWER_CYCLE, bytes_sent=1, bytes_total=1,
Expand Down
4 changes: 2 additions & 2 deletions tests/test_protocol_robustness.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ async def test_full_transfer_with_rehandshake(self):
protocol = HiSiliconStandard()
protocol.set_profile(profile)

# Phase 0: PRESTEP0 ACKs (head + data + tail = 3 ACKs, if profile has it)
prestep_acks = 3 if profile.prestep_data is not None else 0
# Phase 0: PRESTEP0 ACKs (head + data + tail = 3, + 1 consumed by rehandshake)
prestep_acks = 4 if profile.prestep_data is not None else 0
# Phase 1: DDR step ACKs (head + data + tail = 3 ACKs)
# Phase 2: SPL ACKs (head + spl_chunks + tail)
spl_size = profile.spl_max_size
Expand Down
Loading