Repository navigation
P0 Studio PTP START transactional readback and visible exact firmware build #264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: fix/p0-flight-recorder-race-timestamp-20261020
Are you sure you want to change the base?
Changes from all commits
f77bb39
63af909
461ab6c
e44bdf1
f84db8a
57564b8
337d94d
372c9cc
1df962f
1ed81f4
c8fb568
fafc6f0
248be0e
69bace4
de765e0
0a45f55
8a71e0b
c427c23
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1309,6 +1309,7 @@ void DeviceController::resetPtpStartup() noexcept { | |
| pendingPtpRole_.clear(); | ||
| pendingPtpConfig_.clear(); | ||
| ptpRuntimeRoleSeen_ = false; | ||
| ptpRuntimeRunningSeen_ = false; | ||
| } | ||
|
|
||
| bool DeviceController::beginPtpStopVerification() { | ||
|
|
@@ -1318,6 +1319,7 @@ bool DeviceController::beginPtpStopVerification() { | |
| pendingPtpRole_.clear(); | ||
| pendingPtpConfig_.clear(); | ||
| ptpRuntimeRoleSeen_ = false; | ||
| ptpRuntimeRunningSeen_ = false; | ||
| ptpStatus_ = QStringLiteral("Stopping PTP; waiting for board confirmation..."); | ||
| emit ptpStateChanged(); | ||
| // Emergency STOP has one reserved slot in the existing serial owner and | ||
|
|
@@ -1342,14 +1344,16 @@ void DeviceController::markPtpStopUnconfirmed(const QString& reason) { | |
| } | ||
|
|
||
| void DeviceController::failPtpStartup(const QString& reason, const bool rollback) { | ||
| ptpLastStartFailure_ = reason; | ||
| emit ptpStateChanged(); | ||
| setError(reason); | ||
| if (rollback && connected_ && sessionGeneration_ != 0) { | ||
| static_cast<void>(beginPtpStopVerification()); | ||
| return; | ||
| } | ||
| resetPtpStartup(); | ||
| ptpRunning_ = false; | ||
| ptpStatus_ = QStringLiteral("PTP start failed"); | ||
| ptpStatus_ = QStringLiteral("PTP start failed: %1").arg(reason); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This changes the rejection result from the exact string AGENTS.md reference: AGENTS.md:L230-L236 Useful? React with 👍 / 👎. |
||
| emit ptpStateChanged(); | ||
| } | ||
|
|
||
|
|
@@ -1369,6 +1373,7 @@ bool DeviceController::startPtpConfigured(const QString& requestedRole, | |
| setError(QStringLiteral("Invalid PTP settings. Check domain, VLAN and timing intervals.")); | ||
| return false; | ||
| } | ||
| ptpLastStartFailure_.clear(); | ||
| pendingPtpRole_ = role; | ||
| pendingPtpConfig_ = command; | ||
| ptpStartStage_ = PtpStartStage::awaiting_role_ack; | ||
|
|
@@ -1423,7 +1428,7 @@ void DeviceController::advancePtpStartup(const QString& line) { | |
| if (rejected) { | ||
| const bool rollback = ptpStartStage_ == PtpStartStage::awaiting_start || | ||
| ptpStartStage_ == PtpStartStage::awaiting_runtime; | ||
| failPtpStartup(QStringLiteral("Board rejected PTP mode, settings or start."), rollback); | ||
| failPtpStartup(QStringLiteral("Board rejected command: %1").arg(line), rollback); | ||
| return; | ||
| } | ||
| if (ptpStartStage_ == PtpStartStage::awaiting_role_ack) { | ||
|
|
@@ -1432,6 +1437,12 @@ void DeviceController::advancePtpStartup(const QString& line) { | |
| ptpStartStage_ = PtpStartStage::awaiting_role_readback; | ||
| ptpStatus_ = QStringLiteral("Confirming PTP mode on board..."); | ||
| emit ptpStateChanged(); | ||
| // Explicit role readback is mandatory; ACK alone cannot prove | ||
| // the firmware role. Do not rely on unrelated periodic polling. | ||
| if (!sendCommand(QStringLiteral("PROFILE SHOW"))) { | ||
| failPtpStartup(QStringLiteral("Could not request verified PTP role readback."), false); | ||
| return; | ||
| } | ||
| ptpStartTimer_.start(5000); | ||
| } | ||
| return; | ||
|
|
@@ -1469,6 +1480,7 @@ void DeviceController::advancePtpStartup(const QString& line) { | |
| line.contains(QStringLiteral("PTP start accepted"), Qt::CaseInsensitive)) { | ||
| ptpStartStage_ = PtpStartStage::awaiting_runtime; | ||
| ptpRuntimeRoleSeen_ = false; | ||
| ptpRuntimeRunningSeen_ = false; | ||
| ptpStatus_ = QStringLiteral("Verifying live PTP role and runtime..."); | ||
| emit ptpStateChanged(); | ||
| if (!sendPtpShow()) { | ||
|
|
@@ -1477,21 +1489,29 @@ void DeviceController::advancePtpStartup(const QString& line) { | |
| } | ||
| ptpStartTimer_.start(5000); | ||
| } else if (ptpStartStage_ == PtpStartStage::awaiting_runtime) { | ||
| // PTP SHOW may deliver RUNNING before periodic PTP2 role telemetry. | ||
| // Collect both independent facts in any order, under the same bounded | ||
| // five-second deadline. Missing evidence is NOT an immediate failure | ||
| // and NEVER an automatic success. Wrong role remains fail-closed. | ||
| const auto roleEvidence = kPtpMeasuredStateExpression.match(line); | ||
| if (roleEvidence.hasMatch()) { | ||
| if (roleEvidence.captured(1).toUpper() != pendingPtpRole_) { | ||
| failPtpStartup(QStringLiteral("PTP runtime role differs from the selected mode."), true); | ||
| return; | ||
| } | ||
| ptpRuntimeRoleSeen_ = true; | ||
| return; | ||
| } | ||
| const auto readback = kPtpStatusExpression.match(line); | ||
| if (!readback.hasMatch()) return; | ||
| if (!ptpRuntimeRoleSeen_ || !ptpRunning_ || ptpRole_ != pendingPtpRole_) { | ||
| failPtpStartup(QStringLiteral("PTP requires matching PTP2 role and RUNNING readback."), true); | ||
| return; | ||
| if (readback.hasMatch()) { | ||
| if (readback.captured(1).compare(QStringLiteral("RUNNING"), Qt::CaseInsensitive) == 0) | ||
| ptpRuntimeRunningSeen_ = true; | ||
| else { | ||
| failPtpStartup(QStringLiteral("PTP START acknowledged but board readback is STOPPED."), true); | ||
| return; | ||
| } | ||
| } | ||
| if (!ptpRuntimeRoleSeen_ || !ptpRuntimeRunningSeen_ || | ||
| !ptpRunning_ || ptpRole_ != pendingPtpRole_) return; | ||
| resetPtpStartup(); | ||
| ptpStatus_ = QStringLiteral("PTP runtime active; external timing still unqualified"); | ||
| emit ptpStateChanged(); | ||
|
|
@@ -1942,8 +1962,9 @@ void DeviceController::processLine(const QString& rawLine) { | |
| static_cast<void>(sendPtpShow()); | ||
| } | ||
| if (line.contains(QStringLiteral("PTP start rejected"), Qt::CaseInsensitive) || line.contains(QStringLiteral("PTP source readiness timeout"), Qt::CaseInsensitive)) { | ||
| ptpLastStartFailure_ = line; | ||
| ptpRunning_ = false; | ||
| ptpStatus_ = QStringLiteral("PTP start failed"); | ||
| ptpStatus_ = QStringLiteral("PTP start failed: %1").arg(line); | ||
| emit ptpStateChanged(); | ||
| setError(ptpRole_ == QStringLiteral("SOURCE") | ||
| ? QStringLiteral("PTP source did not emit Announce/Sync/Follow_Up. Check the Ethernet link and retry Start PTP Source.") | ||
|
|
@@ -1969,6 +1990,7 @@ void DeviceController::resetTelemetry() { | |
|
|
||
| void DeviceController::resetPtpState() { | ||
| resetPtpStartup(); | ||
| ptpLastStartFailure_.clear(); | ||
| syncDiagnostics_ = QStringLiteral( | ||
| "No current-board SV lock evidence. Select Inspect SV lock after verification."); | ||
| syncFlightLatest_.clear(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
requestStartPtpConfigured()fails synchronously—for example, because an expert interval field is empty or outside the firmware bounds—startPtpConfigured()records the actionable reason inlastErrorbut does not updateptpStatus. This line then replaces the detaileddeviceMessagetoast with stale state such asPTP could not start: Lab TX stopped, hiding the validation failure the operator needs; uselastErroror propagate the request failure reason instead.AGENTS.md reference: AGENTS.md:L68-L72
Useful? React with 👍 / 👎.