///|
pub(all) enum ThreadxHalHookKind {
ThreadxHookClock
ThreadxHookIrq
ThreadxHookDma
ThreadxHookMac
ThreadxHookCanFd
ThreadxHookUart
ThreadxHookFramePool
} derive(Eq, Debug)
///|
pub fn ThreadxHalHookKind::label(self : ThreadxHalHookKind) -> String {
match self {
ThreadxHookClock => "clock"
ThreadxHookIrq => "irq"
ThreadxHookDma => "dma"
ThreadxHookMac => "mac"
ThreadxHookCanFd => "can-fd"
ThreadxHookUart => "uart"
ThreadxHookFramePool => "frame-pool"
}
}
///|
pub(all) struct ThreadxHalHookDescriptor {
id : String
kind : ThreadxHalHookKind
hal_capability_id : String
bsp_hook_symbol : String
requires_bsp : Bool
requires_irq : Bool
requires_dma : Bool
link_port : Bool
evidence_slot : String
reference_path : String
} derive(Eq, Debug)
///|
pub fn ThreadxHalHookDescriptor::is_board_backed(
self : ThreadxHalHookDescriptor,
) -> Bool {
self.requires_bsp && self.bsp_hook_symbol != "" && self.evidence_slot != ""
}
///|
pub(all) struct ThreadxHalSkeletonDescriptor {
id : String
profile : @os.CapabilityProfile
reactor_id : String
board_family : String
reference_project_path : String
include_package_ids : Array[String]
excluded_package_ids : Array[String]
hook_descriptors : Array[ThreadxHalHookDescriptor]
requires_bsp_profile : Bool
requires_threadx_build : Bool
defer_thread_restricted_calls : Bool
moonbit_c_ffi_surface : Bool
sim_default_enabled : Bool
wasm_ui_default_enabled : Bool
board_evidence_present : Bool
threadx_build_evidence_present : Bool
} derive(Eq, Debug)
///|
pub fn ThreadxHalSkeletonDescriptor::hook_count(
self : ThreadxHalSkeletonDescriptor,
) -> Int {
self.hook_descriptors.length()
}
///|
pub fn ThreadxHalSkeletonDescriptor::has_hook_kind(
self : ThreadxHalSkeletonDescriptor,
kind : ThreadxHalHookKind,
) -> Bool {
self.hook_descriptors.any(fn(hook) { hook.kind == kind })
}
///|
pub fn ThreadxHalSkeletonDescriptor::has_hal_capability(
self : ThreadxHalSkeletonDescriptor,
id : String,
) -> Bool {
self.hook_descriptors.any(fn(hook) { hook.hal_capability_id == id })
}
///|
pub fn ThreadxHalSkeletonDescriptor::includes_package(
self : ThreadxHalSkeletonDescriptor,
id : String,
) -> Bool {
self.include_package_ids.any(fn(item) { item == id })
}
///|
pub fn ThreadxHalSkeletonDescriptor::excludes_package(
self : ThreadxHalSkeletonDescriptor,
id : String,
) -> Bool {
self.excluded_package_ids.any(fn(item) { item == id })
}
///|
pub fn ThreadxHalSkeletonDescriptor::missing_hal_reference_count(
self : ThreadxHalSkeletonDescriptor,
catalog : ArrayView[HalCapabilityDescriptor],
) -> Int {
count_threadx_hooks(self.hook_descriptors, fn(hook) {
!catalog.any(fn(capability) { capability.id == hook.hal_capability_id })
})
}
///|
pub fn ThreadxHalSkeletonDescriptor::passes_static_boundary(
self : ThreadxHalSkeletonDescriptor,
) -> Bool {
self.profile == @os.ProfileRealEmbedded &&
self.reactor_id == "reactor.threadx" &&
self.hook_count() == 7 &&
self.requires_bsp_profile &&
self.requires_threadx_build &&
self.defer_thread_restricted_calls &&
!self.moonbit_c_ffi_surface &&
!self.sim_default_enabled &&
!self.wasm_ui_default_enabled &&
!self.board_evidence_present &&
!self.threadx_build_evidence_present &&
self.includes_package("lockwire/core") &&
self.includes_package("lockwire/clock") &&
self.includes_package("lockwire/hal") &&
self.excludes_package("lockwire/sim") &&
self.excludes_package("lockwire/wasm") &&
self.excludes_package("lockwire/driver/native") &&
self.has_hook_kind(ThreadxHookClock) &&
self.has_hook_kind(ThreadxHookIrq) &&
self.has_hook_kind(ThreadxHookDma) &&
self.has_hook_kind(ThreadxHookMac) &&
self.has_hook_kind(ThreadxHookCanFd) &&
self.has_hook_kind(ThreadxHookUart) &&
self.has_hook_kind(ThreadxHookFramePool) &&
self.hook_descriptors.all(fn(hook) { hook.is_board_backed() })
}
///|
pub(all) struct ThreadxHalSkeletonReport {
descriptor_count : Int
hook_count : Int
bsp_hook_count : Int
irq_hook_count : Int
dma_hook_count : Int
link_port_hook_count : Int
missing_hal_reference_count : Int
include_package_count : Int
excluded_package_count : Int
c_ffi_surface_present : Bool
sim_default_enabled : Bool
wasm_ui_default_enabled : Bool
board_evidence_present : Bool
threadx_build_evidence_present : Bool
defer_thread_restricted_calls : Bool
} derive(Eq, Debug)
///|
pub fn ThreadxHalSkeletonReport::passes(
self : ThreadxHalSkeletonReport,
) -> Bool {
self.descriptor_count == 1 &&
self.hook_count == 7 &&
self.bsp_hook_count == self.hook_count &&
self.irq_hook_count >= 4 &&
self.dma_hook_count >= 3 &&
self.link_port_hook_count >= 4 &&
self.missing_hal_reference_count == 0 &&
self.include_package_count == 4 &&
self.excluded_package_count >= 5 &&
!self.c_ffi_surface_present &&
!self.sim_default_enabled &&
!self.wasm_ui_default_enabled &&
!self.board_evidence_present &&
!self.threadx_build_evidence_present &&
self.defer_thread_restricted_calls
}
///|
pub fn threadx_hal_skeleton_descriptor() -> ThreadxHalSkeletonDescriptor {
{
id: "hal.threadx.stm32.skeleton",
profile: @os.ProfileRealEmbedded,
reactor_id: "reactor.threadx",
board_family: "stm32-threadx",
reference_project_path: "local-reference:control_com_card/rs485_tcp",
include_package_ids: [
"lockwire/core", "lockwire/clock", "lockwire/hal", "lockwire/reactor/threadx",
],
excluded_package_ids: [
"lockwire/sim", "lockwire/wasm", "lockwire/driver/native", "lockwire/trace/pcapng",
"protocol-stack-runtime",
],
hook_descriptors: threadx_hal_hook_catalog(),
requires_bsp_profile: true,
requires_threadx_build: true,
defer_thread_restricted_calls: true,
moonbit_c_ffi_surface: false,
sim_default_enabled: false,
wasm_ui_default_enabled: false,
board_evidence_present: false,
threadx_build_evidence_present: false,
}
}
///|
pub fn threadx_hal_hook_catalog() -> Array[ThreadxHalHookDescriptor] {
[
{
id: "threadx.hook.clock",
kind: ThreadxHookClock,
hal_capability_id: "hal.clock.embedded",
bsp_hook_symbol: "lockwire_threadx_clock_now",
requires_bsp: true,
requires_irq: false,
requires_dma: false,
link_port: false,
evidence_slot: "board.clock.tick-or-cycle-counter",
reference_path: "docs/lockwire-plan.md#embedded-native",
},
{
id: "threadx.hook.irq",
kind: ThreadxHookIrq,
hal_capability_id: "hal.irq.embedded",
bsp_hook_symbol: "lockwire_threadx_irq_bind",
requires_bsp: true,
requires_irq: true,
requires_dma: false,
link_port: false,
evidence_slot: "board.irq.dispatch",
reference_path: "local-reference:control_com_card/rs485_tcp/Src/stm32f4xx_it.c",
},
{
id: "threadx.hook.dma",
kind: ThreadxHookDma,
hal_capability_id: "hal.dma.embedded",
bsp_hook_symbol: "lockwire_threadx_dma_region",
requires_bsp: true,
requires_irq: true,
requires_dma: true,
link_port: false,
evidence_slot: "board.dma.sram-placement",
reference_path: "local-reference:control_com_card/rs485_tcp/AGENTS.md",
},
{
id: "threadx.hook.mac",
kind: ThreadxHookMac,
hal_capability_id: "hal.mac.link_port.embedded",
bsp_hook_symbol: "lockwire_threadx_mac_link_port",
requires_bsp: true,
requires_irq: true,
requires_dma: true,
link_port: true,
evidence_slot: "board.mac.netxduo-link",
reference_path: "local-reference:control_com_card/rs485_tcp/Src/app_netxduo.c",
},
{
id: "threadx.hook.canfd",
kind: ThreadxHookCanFd,
hal_capability_id: "hal.canfd.link_port.embedded",
bsp_hook_symbol: "lockwire_threadx_canfd_link_port",
requires_bsp: true,
requires_irq: true,
requires_dma: false,
link_port: true,
evidence_slot: "board.canfd.link-port",
reference_path: "docs/lockwire-plan.md#threadx-hal",
},
{
id: "threadx.hook.uart",
kind: ThreadxHookUart,
hal_capability_id: "hal.uart.link_port.embedded",
bsp_hook_symbol: "lockwire_threadx_uart_link_port",
requires_bsp: true,
requires_irq: true,
requires_dma: false,
link_port: true,
evidence_slot: "board.uart.rs485-idle-frame",
reference_path: "local-reference:control_com_card/rs485_tcp/Src/app_netxduo.c",
},
{
id: "threadx.hook.frame_pool",
kind: ThreadxHookFramePool,
hal_capability_id: "hal.frame_pool.embedded",
bsp_hook_symbol: "lockwire_threadx_frame_pool_region",
requires_bsp: true,
requires_irq: false,
requires_dma: true,
link_port: true,
evidence_slot: "board.frame-pool.sram-or-dma-region",
reference_path: "local-reference:control_com_card/rs485_tcp/AGENTS.md",
},
]
}
///|
pub fn threadx_hal_skeleton_report() -> ThreadxHalSkeletonReport {
let descriptor = threadx_hal_skeleton_descriptor()
{
descriptor_count: 1,
hook_count: descriptor.hook_count(),
bsp_hook_count: count_threadx_hooks(descriptor.hook_descriptors, fn(hook) {
hook.requires_bsp
}),
irq_hook_count: count_threadx_hooks(descriptor.hook_descriptors, fn(hook) {
hook.requires_irq
}),
dma_hook_count: count_threadx_hooks(descriptor.hook_descriptors, fn(hook) {
hook.requires_dma
}),
link_port_hook_count: count_threadx_hooks(descriptor.hook_descriptors, fn(
hook,
) {
hook.link_port
}),
missing_hal_reference_count: descriptor.missing_hal_reference_count(
hal_capability_catalog(),
),
include_package_count: descriptor.include_package_ids.length(),
excluded_package_count: descriptor.excluded_package_ids.length(),
c_ffi_surface_present: descriptor.moonbit_c_ffi_surface,
sim_default_enabled: descriptor.sim_default_enabled,
wasm_ui_default_enabled: descriptor.wasm_ui_default_enabled,
board_evidence_present: descriptor.board_evidence_present,
threadx_build_evidence_present: descriptor.threadx_build_evidence_present,
defer_thread_restricted_calls: descriptor.defer_thread_restricted_calls,
}
}
///|
fn count_threadx_hooks(
hooks : ArrayView[ThreadxHalHookDescriptor],
predicate : (ThreadxHalHookDescriptor) -> Bool,
) -> Int {
let mut count = 0
for hook in hooks {
if predicate(hook) {
count += 1
}
}
count
}