mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 00:02:28 +00:00
Merge pull request #3233 from nautd/uart_half_duplex_fix
Convert uart half_duplex to use user configurable IO
This commit is contained in:
commit
1c466b81e6
@ -14,7 +14,7 @@ use embassy_sync::waitqueue::AtomicWaker;
|
||||
use futures_util::future::{select, Either};
|
||||
|
||||
use crate::dma::ChannelAndRequest;
|
||||
use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed};
|
||||
use crate::gpio::{self, AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed};
|
||||
use crate::interrupt::typelevel::Interrupt as _;
|
||||
use crate::interrupt::{self, Interrupt, InterruptExt};
|
||||
use crate::mode::{Async, Blocking, Mode};
|
||||
@ -211,6 +211,30 @@ impl Default for Config {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Half duplex IO mode
|
||||
pub enum HalfDuplexConfig {
|
||||
/// Push pull allows for faster baudrates, may require series resistor
|
||||
PushPull,
|
||||
/// Open drain output using external pull up resistor
|
||||
OpenDrainExternal,
|
||||
#[cfg(not(gpio_v1))]
|
||||
/// Open drain output using internal pull up resistor
|
||||
OpenDrainInternal,
|
||||
}
|
||||
|
||||
impl HalfDuplexConfig {
|
||||
fn af_type(self) -> gpio::AfType {
|
||||
match self {
|
||||
HalfDuplexConfig::PushPull => AfType::output(OutputType::PushPull, Speed::Medium),
|
||||
HalfDuplexConfig::OpenDrainExternal => AfType::output(OutputType::OpenDrain, Speed::Medium),
|
||||
#[cfg(not(gpio_v1))]
|
||||
HalfDuplexConfig::OpenDrainInternal => AfType::output_pull(OutputType::OpenDrain, Speed::Medium, Pull::Up),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Serial error
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
@ -1029,8 +1053,9 @@ impl<'d> Uart<'d, Async> {
|
||||
/// (when it is available for your chip). There is no functional difference between these methods, as both
|
||||
/// allow bidirectional communication.
|
||||
///
|
||||
/// The pin is always released when no data is transmitted. Thus, it acts as a standard
|
||||
/// I/O in idle or in reception.
|
||||
/// The TX pin is always released when no data is transmitted. Thus, it acts as a standard
|
||||
/// I/O in idle or in reception. It means that the I/O must be configured so that TX is
|
||||
/// configured as alternate function open-drain with an external pull-up
|
||||
/// Apart from this, the communication protocol is similar to normal USART mode. Any conflict
|
||||
/// on the line must be managed by software (for instance by using a centralized arbiter).
|
||||
#[doc(alias("HDSEL"))]
|
||||
@ -1041,6 +1066,7 @@ impl<'d> Uart<'d, Async> {
|
||||
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||
mut config: Config,
|
||||
half_duplex: HalfDuplexConfig,
|
||||
) -> Result<Self, ConfigError> {
|
||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||
{
|
||||
@ -1051,7 +1077,7 @@ impl<'d> Uart<'d, Async> {
|
||||
Self::new_inner(
|
||||
peri,
|
||||
None,
|
||||
new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
|
||||
new_pin!(tx, half_duplex.af_type()),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@ -1079,6 +1105,7 @@ impl<'d> Uart<'d, Async> {
|
||||
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||
mut config: Config,
|
||||
half_duplex: HalfDuplexConfig,
|
||||
) -> Result<Self, ConfigError> {
|
||||
config.swap_rx_tx = true;
|
||||
config.half_duplex = true;
|
||||
@ -1087,7 +1114,7 @@ impl<'d> Uart<'d, Async> {
|
||||
peri,
|
||||
None,
|
||||
None,
|
||||
new_pin!(rx, AfType::output(OutputType::PushPull, Speed::Medium)),
|
||||
new_pin!(rx, half_duplex.af_type()),
|
||||
None,
|
||||
None,
|
||||
new_dma!(tx_dma),
|
||||
@ -1192,6 +1219,7 @@ impl<'d> Uart<'d, Blocking> {
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||
mut config: Config,
|
||||
half_duplex: HalfDuplexConfig,
|
||||
) -> Result<Self, ConfigError> {
|
||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||
{
|
||||
@ -1202,7 +1230,7 @@ impl<'d> Uart<'d, Blocking> {
|
||||
Self::new_inner(
|
||||
peri,
|
||||
None,
|
||||
new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
|
||||
new_pin!(tx, half_duplex.af_type()),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@ -1227,6 +1255,7 @@ impl<'d> Uart<'d, Blocking> {
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||
mut config: Config,
|
||||
half_duplex: HalfDuplexConfig,
|
||||
) -> Result<Self, ConfigError> {
|
||||
config.swap_rx_tx = true;
|
||||
config.half_duplex = true;
|
||||
@ -1235,7 +1264,7 @@ impl<'d> Uart<'d, Blocking> {
|
||||
peri,
|
||||
None,
|
||||
None,
|
||||
new_pin!(rx, AfType::output(OutputType::PushPull, Speed::Medium)),
|
||||
new_pin!(rx, half_duplex.af_type()),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
|
Loading…
Reference in New Issue
Block a user