///|
pub(all) enum ThreadxEvidenceKind {
ThreadxEvidenceBspProfile
ThreadxEvidenceThreadxBuild
ThreadxEvidenceClockCalibration
ThreadxEvidenceIrqDispatch
ThreadxEvidenceDmaRegion
ThreadxEvidenceMacSmoke
ThreadxEvidenceCanFdSmoke
ThreadxEvidenceUartSmoke
ThreadxEvidenceEmbeddedTrace
ThreadxEvidenceBoardOracle
} derive(Eq, Debug)
///|
pub fn ThreadxEvidenceKind::label(self : ThreadxEvidenceKind) -> String {
match self {
ThreadxEvidenceBspProfile => "bsp-profile"
ThreadxEvidenceThreadxBuild => "threadx-build"
ThreadxEvidenceClockCalibration => "clock-calibration"
ThreadxEvidenceIrqDispatch => "irq-dispatch"
ThreadxEvidenceDmaRegion => "dma-region"
ThreadxEvidenceMacSmoke => "mac-smoke"
ThreadxEvidenceCanFdSmoke => "can-fd-smoke"
ThreadxEvidenceUartSmoke => "uart-smoke"
ThreadxEvidenceEmbeddedTrace => "embedded-trace"
ThreadxEvidenceBoardOracle => "board-oracle"
}
}
///|
pub(all) struct ThreadxEvidenceRequirement {
id : String
kind : ThreadxEvidenceKind
hook_id : String
artifact_slot : String
checker_id : String
blocked_reason : String
requires_board : Bool
requires_threadx_build : Bool
requires_external_oracle : Bool
live_evidence_present : Bool
} derive(Eq, Debug)
///|
pub fn ThreadxEvidenceRequirement::is_blocked(
self : ThreadxEvidenceRequirement,
) -> Bool {
self.blocked_reason != "" && !self.live_evidence_present
}
///|
pub fn ThreadxEvidenceRequirement::references_hook(
self : ThreadxEvidenceRequirement,
hooks : ArrayView[ThreadxHalHookDescriptor],
) -> Bool {
self.hook_id == "" || hooks.any(fn(hook) { hook.id == self.hook_id })
}
///|
pub(all) struct ThreadxEvidencePlanReport {
requirement_count : Int
hook_backed_count : Int
board_required_count : Int
threadx_build_required_count : Int
external_oracle_required_count : Int
blocked_count : Int
live_evidence_present_count : Int
missing_hook_reference_count : Int
mac_smoke_count : Int
canfd_smoke_count : Int
uart_smoke_count : Int
trace_artifact_count : Int
board_oracle_count : Int
} derive(Eq, Debug)
///|
pub fn ThreadxEvidencePlanReport::passes_static_plan(
self : ThreadxEvidencePlanReport,
) -> Bool {
self.requirement_count == 10 &&
self.hook_backed_count >= 7 &&
self.board_required_count == self.requirement_count &&
self.threadx_build_required_count >= 8 &&
self.external_oracle_required_count >= 4 &&
self.blocked_count == self.requirement_count &&
self.live_evidence_present_count == 0 &&
self.missing_hook_reference_count == 0 &&
self.mac_smoke_count == 1 &&
self.canfd_smoke_count == 1 &&
self.uart_smoke_count == 1 &&
self.trace_artifact_count == 1 &&
self.board_oracle_count == 1
}
///|
pub fn threadx_evidence_requirements() -> Array[ThreadxEvidenceRequirement] {
[
evidence_requirement(
"threadx.evidence.bsp-profile",
ThreadxEvidenceBspProfile,
"",
"board.bsp-profile.json",
"check-threadx-bsp-profile",
"缺少选定 STM32 board、toolchain、BSP symbol map 和 memory/DMA placement profile",
requires_threadx_build=false,
requires_external_oracle=false,
),
evidence_requirement(
"threadx.evidence.threadx-build",
ThreadxEvidenceThreadxBuild,
"",
"board.threadx-build-log.txt",
"check-threadx-build-log",
"缺少 ThreadX/NetX/EIDE 或等价交叉编译日志与 link map",
requires_threadx_build=true,
requires_external_oracle=false,
),
evidence_requirement(
"threadx.evidence.clock-calibration",
ThreadxEvidenceClockCalibration,
"threadx.hook.clock",
"board.clock-calibration.json",
"check-threadx-clock-calibration",
"缺少硬件计数器、比较中断、δ_probe 或 SYNC0/示波器对标证据",
requires_threadx_build=true,
requires_external_oracle=true,
),
evidence_requirement(
"threadx.evidence.irq-dispatch",
ThreadxEvidenceIrqDispatch,
"threadx.hook.irq",
"board.irq-dispatch-log.txt",
"check-threadx-irq-dispatch",
"缺少 IRQ bind/dispatch/cleanup 板级日志",
requires_threadx_build=true,
requires_external_oracle=false,
),
evidence_requirement(
"threadx.evidence.dma-region",
ThreadxEvidenceDmaRegion,
"threadx.hook.dma",
"board.dma-region-map.txt",
"check-threadx-dma-region",
"缺少 DMA buffer 位于可用 SRAM/非 cache hazard 区域的 link map 或 runtime dump",
requires_threadx_build=true,
requires_external_oracle=false,
),
evidence_requirement(
"threadx.evidence.mac-smoke",
ThreadxEvidenceMacSmoke,
"threadx.hook.mac",
"board.mac-smoke-trace.bin",
"check-threadx-mac-smoke",
"缺少 MAC/NetX link up、rx/tx counter、frame echo 或外部抓包证据",
requires_threadx_build=true,
requires_external_oracle=true,
),
evidence_requirement(
"threadx.evidence.canfd-smoke",
ThreadxEvidenceCanFdSmoke,
"threadx.hook.canfd",
"board.canfd-smoke-trace.bin",
"check-threadx-canfd-smoke",
"缺少 CAN-FD controller init、tx/rx、error counter 或外部 CAN oracle 证据",
requires_threadx_build=true,
requires_external_oracle=true,
),
evidence_requirement(
"threadx.evidence.uart-rs485-smoke",
ThreadxEvidenceUartSmoke,
"threadx.hook.uart",
"board.uart-rs485-smoke-log.txt",
"check-threadx-uart-rs485-smoke",
"缺少 UART/RS-485 idle frame、echo filter、RTU queue 或外部 serial oracle 证据",
requires_threadx_build=true,
requires_external_oracle=true,
),
evidence_requirement(
"threadx.evidence.embedded-trace",
ThreadxEvidenceEmbeddedTrace,
"threadx.hook.frame_pool",
"board.lockwire-embedded-trace.isotrace",
"check-threadx-embedded-trace",
"缺少可导入 Lockwire trace/replay 的板级事件 artifact",
requires_threadx_build=true,
requires_external_oracle=false,
),
evidence_requirement(
"threadx.evidence.board-oracle",
ThreadxEvidenceBoardOracle,
"threadx.hook.frame_pool",
"board.evidence-summary.json",
"check-threadx-board-evidence-summary",
"缺少汇总 BSP/build/smoke/trace checker 的板级 evidence summary",
requires_threadx_build=true,
requires_external_oracle=false,
),
]
}
///|
pub fn threadx_evidence_plan_report() -> ThreadxEvidencePlanReport {
let requirements = threadx_evidence_requirements()
let hooks = threadx_hal_hook_catalog()
{
requirement_count: requirements.length(),
hook_backed_count: count_evidence_where(requirements, fn(item) {
item.hook_id != ""
}),
board_required_count: count_evidence_where(requirements, fn(item) {
item.requires_board
}),
threadx_build_required_count: count_evidence_where(requirements, fn(item) {
item.requires_threadx_build
}),
external_oracle_required_count: count_evidence_where(requirements, fn(
item,
) {
item.requires_external_oracle
}),
blocked_count: count_evidence_where(requirements, fn(item) {
item.is_blocked()
}),
live_evidence_present_count: count_evidence_where(requirements, fn(item) {
item.live_evidence_present
}),
missing_hook_reference_count: count_evidence_where(requirements, fn(item) {
!item.references_hook(hooks)
}),
mac_smoke_count: count_evidence_kind(requirements, ThreadxEvidenceMacSmoke),
canfd_smoke_count: count_evidence_kind(
requirements,
ThreadxEvidenceCanFdSmoke,
),
uart_smoke_count: count_evidence_kind(
requirements,
ThreadxEvidenceUartSmoke,
),
trace_artifact_count: count_evidence_kind(
requirements,
ThreadxEvidenceEmbeddedTrace,
),
board_oracle_count: count_evidence_kind(
requirements,
ThreadxEvidenceBoardOracle,
),
}
}
///|
fn evidence_requirement(
id : String,
kind : ThreadxEvidenceKind,
hook_id : String,
artifact_slot : String,
checker_id : String,
blocked_reason : String,
requires_threadx_build~ : Bool,
requires_external_oracle~ : Bool,
) -> ThreadxEvidenceRequirement {
{
id,
kind,
hook_id,
artifact_slot,
checker_id,
blocked_reason,
requires_board: true,
requires_threadx_build,
requires_external_oracle,
live_evidence_present: false,
}
}
///|
fn count_evidence_kind(
requirements : ArrayView[ThreadxEvidenceRequirement],
kind : ThreadxEvidenceKind,
) -> Int {
count_evidence_where(requirements, fn(item) { item.kind == kind })
}
///|
fn count_evidence_where(
requirements : ArrayView[ThreadxEvidenceRequirement],
predicate : (ThreadxEvidenceRequirement) -> Bool,
) -> Int {
let mut count = 0
for item in requirements {
if predicate(item) {
count += 1
}
}
count
}