feat(firmware): validate configuration and migrate sensor-driven flight APIs
Validate configuration through its owning schemas and keep board declarations separate from shared F722 resource ownership. Bound USB transitions, isolate transport failures and retain restart-only activation. Migrate navigation and flight consumers with the sensor and schema contracts. Require explicit installation data and synchronous output authority; board motor outputs remain inhibited. Validation: assembled-prefix host tests, strict Clippy, platform/USB tests and both ARM release builds. Final-source coverage and scoped Miri/Kani evidence are retained separately from hardware qualification.
This commit is contained in:
1 parent
fb1b8af2d1
commit
f9a61a086f
211 files changed
+45657
-12740
No files matched your search
@@ -0,0 +1,53 @@
|
||||
use kaptan_spi::{CompletionError, SpiCompletion};
|
||||
use stm32f7::stm32f722::{dma2, spi1};
|
||||
|
||||
const QUIESCE_POLLS: usize = 1024;
|
||||
|
||||
pub(super) fn bus_finished(spi: &spi1::RegisterBlock) -> bool {
|
||||
let status = spi.sr().read();
|
||||
status.ftlvl().is_empty() && status.bsy().is_not_busy()
|
||||
}
|
||||
|
||||
pub(super) fn complete_transfer(
|
||||
spi: &spi1::RegisterBlock,
|
||||
rx: &dma2::ST,
|
||||
tx: &dma2::ST,
|
||||
completion: SpiCompletion,
|
||||
has_fault: impl FnOnce() -> bool,
|
||||
) -> Result<SpiCompletion, CompletionError> {
|
||||
spi.cr2()
|
||||
.modify(|_, write| write.rxdmaen().clear_bit().txdmaen().clear_bit());
|
||||
rx.cr().modify(|_, write| write.en().clear_bit());
|
||||
tx.cr().modify(|_, write| write.en().clear_bit());
|
||||
// Leave SPI enabled while queued frames drain. Writing EN=0 does not
|
||||
// establish that DMA stopped or that the final SPI clock completed.
|
||||
let quiescent = (0..QUIESCE_POLLS).any(|_| {
|
||||
rx.cr().read().en().is_disabled() && tx.cr().read().en().is_disabled() && bus_finished(spi)
|
||||
});
|
||||
spi.cr1().modify(|_, write| write.spe().clear_bit());
|
||||
cortex_m::asm::dsb();
|
||||
if !quiescent {
|
||||
return Err(CompletionError::Quarantined);
|
||||
}
|
||||
let complete = completion == SpiCompletion::Complete
|
||||
&& rx.ndtr().read().bits() == 0
|
||||
&& tx.ndtr().read().bits() == 0
|
||||
&& spi.sr().read().frlvl().is_empty()
|
||||
&& !has_fault();
|
||||
// Cancellation can leave old frames in the four-byte RX FIFO. Check
|
||||
// faults before draining: the DR/SR reads can clear an overrun.
|
||||
for _ in 0..4 {
|
||||
if spi.sr().read().frlvl().is_empty() {
|
||||
break;
|
||||
}
|
||||
let _ = spi.dr().read().bits();
|
||||
}
|
||||
if !spi.sr().read().frlvl().is_empty() {
|
||||
return Err(CompletionError::Quarantined);
|
||||
}
|
||||
Ok(if complete {
|
||||
SpiCompletion::Complete
|
||||
} else {
|
||||
SpiCompletion::TransferFault
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user