support bi-directional mavlink
Signed-off-by: Onur Özkan <work@onurozkan.dev>
This commit is contained in:
1 parent
2d35d935b4
commit
d32d9f4d36
16 files changed
+651
-344
No files matched your search
@@ -70,6 +70,16 @@ pub fn configure_usart1_tx_pin_pa9(port: &stm32f722::GPIOA) {
|
||||
port.pupdr().modify(|_, write| write.pupdr9().floating());
|
||||
}
|
||||
|
||||
/// Configures PA10 for USART1 receive alternate function 7.
|
||||
pub fn configure_usart1_rx_pin_pa10(port: &stm32f722::GPIOA) {
|
||||
port.moder().modify(|_, write| write.moder10().alternate());
|
||||
port.afrh().modify(|_, write| {
|
||||
// SAFETY: AF7 selects USART1 RX on PA10 on STM32F722.
|
||||
unsafe { write.afrh10().bits(0b0111) }
|
||||
});
|
||||
port.pupdr().modify(|_, write| write.pupdr10().floating());
|
||||
}
|
||||
|
||||
/// Active-low status LED connected to PD2.
|
||||
pub struct ActiveLowLedPd2 {
|
||||
port: stm32f722::GPIOD,
|
||||
|
||||
@@ -16,10 +16,10 @@ pub use clock::{ClockProfileError, select_hsi16_profile};
|
||||
pub use dma_buffer::DcacheDisabledDmaMemory;
|
||||
pub use gpio::{
|
||||
ActiveLowLedPd2, configure_exti4_pin_pa4, configure_spi1_pins_pa5_pa6_pa7,
|
||||
configure_usart1_tx_pin_pa9,
|
||||
configure_usart1_rx_pin_pa10, configure_usart1_tx_pin_pa9,
|
||||
};
|
||||
pub use spi1::{Spi1, Spi1Error};
|
||||
pub use tim2::{Tim2Periodic, Tim2PeriodicConfig};
|
||||
pub use time::{DwtClockStartError, DwtMicrosecondClock};
|
||||
pub use usart::{BaudRateError, Usart1Tx};
|
||||
pub use usart::{BaudRateError, ReceiveInterrupt, Usart1Tx};
|
||||
pub use usart1_tx_dma2_stream7::{StartError, Usart1TxDma};
|
||||
@@ -11,7 +11,18 @@ pub enum BaudRateError {
|
||||
OutOfRange,
|
||||
}
|
||||
|
||||
/// Owns configured transmit-only USART1 hardware.
|
||||
/// Terminal result from acknowledging the USART1 receive interrupt.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum ReceiveInterrupt {
|
||||
/// One received byte was removed from the UART data register.
|
||||
Byte(u8),
|
||||
/// A serial transport fault invalidated the current receive stream.
|
||||
Fault,
|
||||
/// This USART1 interrupt did not have a receive event pending.
|
||||
NotPending,
|
||||
}
|
||||
|
||||
/// Owns configured full-duplex USART1 hardware.
|
||||
///
|
||||
/// Pin alternate-function setup remains board-owned because it depends on the
|
||||
/// schematic. Configure pins before constructing this type.
|
||||
@@ -20,7 +31,7 @@ pub struct Usart1Tx {
|
||||
}
|
||||
|
||||
impl Usart1Tx {
|
||||
/// Enables USART1 and configures 8N1 transmit-only operation.
|
||||
/// Enables USART1 and configures 8N1 transmit and receive operation.
|
||||
pub fn new(
|
||||
rcc: &stm32f722::RCC,
|
||||
peripheral: stm32f722::USART1,
|
||||
@@ -38,9 +49,17 @@ impl Usart1Tx {
|
||||
// SAFETY: `brr` is validated to fit the complete BRR register.
|
||||
unsafe { write.bits(u32::from(brr)) }
|
||||
});
|
||||
peripheral
|
||||
.cr1()
|
||||
.write(|write| write.te().set_bit().ue().set_bit());
|
||||
peripheral.cr1().write(|write| {
|
||||
write
|
||||
.te()
|
||||
.set_bit()
|
||||
.re()
|
||||
.set_bit()
|
||||
.rxneie()
|
||||
.set_bit()
|
||||
.ue()
|
||||
.set_bit()
|
||||
});
|
||||
peripheral.cr2().write(|write| write.stop().stop1());
|
||||
|
||||
Ok(Self { peripheral })
|
||||
@@ -53,6 +72,51 @@ impl Usart1Tx {
|
||||
pub(crate) fn transmit_data_register_address(&self) -> u32 {
|
||||
self.peripheral.tdr().as_ptr() as u32
|
||||
}
|
||||
|
||||
/// Acknowledges one USART1 receive interrupt without accessing TX state.
|
||||
///
|
||||
/// The board invokes this only from the `USART1` interrupt. USART1 TX DMA
|
||||
/// owns its disjoint data register and DMA stream, so this static route may
|
||||
/// safely acknowledge RX while that transfer is active.
|
||||
pub fn acknowledge_receive_interrupt() -> ReceiveInterrupt {
|
||||
// SAFETY: the board binds USART1 exactly once and this function touches
|
||||
// only its receive/error registers, never the TX DMA configuration.
|
||||
let peripheral = unsafe { &*stm32f722::USART1::ptr() };
|
||||
let status = peripheral.isr().read();
|
||||
let fault = status.pe().is_error()
|
||||
|| status.fe().is_error()
|
||||
|| status.nf().is_noise()
|
||||
|| status.ore().is_overrun();
|
||||
|
||||
if status.rxne().is_data_ready() {
|
||||
let byte = peripheral.rdr().read().rdr().bits() as u8;
|
||||
if fault {
|
||||
clear_receive_errors(peripheral);
|
||||
ReceiveInterrupt::Fault
|
||||
} else {
|
||||
ReceiveInterrupt::Byte(byte)
|
||||
}
|
||||
} else if fault {
|
||||
clear_receive_errors(peripheral);
|
||||
ReceiveInterrupt::Fault
|
||||
} else {
|
||||
ReceiveInterrupt::NotPending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_receive_errors(peripheral: &stm32f722::usart1::RegisterBlock) {
|
||||
peripheral.icr().write(|write| {
|
||||
write
|
||||
.pecf()
|
||||
.clear()
|
||||
.fecf()
|
||||
.clear()
|
||||
.ncf()
|
||||
.clear()
|
||||
.orecf()
|
||||
.clear()
|
||||
});
|
||||
}
|
||||
|
||||
const fn calculate_brr(peripheral_clock_hz: u32, baud: u32) -> Result<u16, BaudRateError> {
|
||||
|
||||
Reference in new issue
Block a user