feat(f722): add usb mavlink transport

This commit is contained in:
Onur Özkan committed 2026-09-06 23:14:00 +03:00
1 parent 7dc3ccb619
commit 604a7aba86
18 files changed
+1087 -208

No files matched your search

@@ -1,12 +1,12 @@
//! F722 transport and vertical-route adapters for the portable data channel.
use super::peripherals;
use kaptan_data_channel::FrameSink;
use kaptan_dma::TxCompletion;
use kaptan_mavlink::{
MavlinkFrame,
transmitter::{EnqueueResult, FrameClass, MavlinkTransmitter},
MavlinkFrame, receiver::IntegrityCheckedFrame, transmitter::MavlinkTransmitter,
};
use kaptan_tx::PendingFrame;
use peripherals::F722UsbMavlink;
// Baud, sensor topology, and mounting remain immutable build-time policy. The
// output-inhibited board image may recover endpoint identity and selected
@@ -28,16 +28,25 @@ enum F722MavlinkTransport {
Usart2(MavlinkTransmitter<peripherals::DcacheDisabledDmaMemory, peripherals::Usart2TxDma, 4>),
}
/// Sole F722 MAVLink DMA owner.
pub(crate) struct F722MavlinkTransmitter {
inner: F722MavlinkTransport,
/// Physical link on which an inbound frame arrived.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum MavlinkIngress {
Uart,
Usb,
}
impl F722MavlinkTransmitter {
/// Concrete F722 MAVLink link ownership.
pub(crate) struct F722MavlinkLink {
uart: F722MavlinkTransport,
usb: F722UsbMavlink,
}
impl F722MavlinkLink {
pub(crate) fn usart1(
rcc: &stm32f7::stm32f722::RCC,
uart: stm32f7::stm32f722::USART1,
baud: u32,
usb: F722UsbMavlink,
) -> Result<Self, ()> {
let uart = peripherals::Usart1Tx::new(rcc, uart, UART1_CLOCK_HZ, baud).map_err(|_| ())?;
// SAFETY: platform initialization disables D-cache before this object
@@ -45,10 +54,11 @@ impl F722MavlinkTransmitter {
// this platform receives a terminal DMA completion notification.
let memory = unsafe { peripherals::DcacheDisabledDmaMemory::new() };
Ok(Self {
inner: F722MavlinkTransport::Usart1(MavlinkTransmitter::new(
uart: F722MavlinkTransport::Usart1(MavlinkTransmitter::new(
memory,
peripherals::Usart1TxDma::new(rcc, uart),
)),
usb,
})
}
@@ -56,45 +66,73 @@ impl F722MavlinkTransmitter {
rcc: &stm32f7::stm32f722::RCC,
uart: stm32f7::stm32f722::USART2,
baud: u32,
usb: F722UsbMavlink,
) -> Result<Self, ()> {
let uart = peripherals::Usart2Tx::new(rcc, uart, UART2_CLOCK_HZ, baud).map_err(|_| ())?;
// SAFETY: identical DMA-memory invariant to the USART1 route above;
// only the fixed platform DMA endpoint differs.
let memory = unsafe { peripherals::DcacheDisabledDmaMemory::new() };
Ok(Self {
inner: F722MavlinkTransport::Usart2(MavlinkTransmitter::new(
uart: F722MavlinkTransport::Usart2(MavlinkTransmitter::new(
memory,
peripherals::Usart2TxDma::new(rcc, uart),
)),
usb,
})
}
}
impl FrameSink for F722MavlinkTransmitter {
fn send(&mut self, class: FrameClass, frame: MavlinkFrame) -> EnqueueResult {
match &mut self.inner {
/// Sends publications on the open USB link, or on UART when USB is closed.
pub(crate) fn send_active(&mut self, pending: PendingFrame<MavlinkFrame>) -> bool {
if self.usb.is_open() {
self.usb.send(pending)
} else {
self.send_uart(pending)
}
}
/// Sends a protocol reply only on the link that supplied its request.
pub(crate) fn send_to(
&mut self,
ingress: MavlinkIngress,
pending: PendingFrame<MavlinkFrame>,
) -> bool {
match ingress {
MavlinkIngress::Uart => self.send_uart(pending),
MavlinkIngress::Usb => self.usb.send(pending),
}
}
fn send_uart(&mut self, pending: PendingFrame<MavlinkFrame>) -> bool {
match &mut self.uart {
F722MavlinkTransport::Usart1(transmitter) => transmitter
.admit_and_start(pending.class, pending.frame)
.admission
.is_retained(),
F722MavlinkTransport::Usart2(transmitter) => transmitter
.admit_and_start(pending.class, pending.frame)
.admission
.is_retained(),
}
}
pub(crate) fn on_dma_complete(&mut self, completion: TxCompletion) {
match &mut self.uart {
F722MavlinkTransport::Usart1(transmitter) => {
let outcome = transmitter.admit_and_start(class, frame);
let _ = outcome.start;
outcome.admission
let _ = transmitter.on_dma_complete(completion);
}
F722MavlinkTransport::Usart2(transmitter) => {
let outcome = transmitter.admit_and_start(class, frame);
let _ = outcome.start;
outcome.admission
let _ = transmitter.on_dma_complete(completion);
}
}
}
fn on_dma_complete(&mut self, completion: TxCompletion) {
match &mut self.inner {
F722MavlinkTransport::Usart1(transmitter) => {
let _ = transmitter.on_dma_complete(completion);
}
F722MavlinkTransport::Usart2(transmitter) => {
let _ = transmitter.on_dma_complete(completion);
}
}
/// Services USB and reports whether the protocol worker has bytes to parse.
pub(crate) fn poll_usb(&mut self) -> bool {
self.usb.poll()
}
pub(crate) fn take_usb_received(&mut self) -> Option<IntegrityCheckedFrame> {
self.usb.take_received()
}
}