Description
Right now the Pins
trait looks like this:
pub trait Pins<USART> {
fn setup(&self);
}
It is then implemented for pin pairs using a macro:
macro_rules! impl_pins {
($($instance:ty, $tx:ident, $rx:ident, $alt:ident;)*) => {
$(
impl<Tx, Rx> Pins<$instance> for ($tx<Tx>, $rx<Rx>) {
fn setup(&self) {
self.0.set_alt_mode(AltMode::$alt);
self.1.set_alt_mode(AltMode::$alt);
}
}
)*
}
}
impl_pins!(
USART1, PA9, PA10, AF4;
USART1, PB6, PB7, AF0;
USART2, PA2, PA3, AF4;
USART2, PA14, PA15, AF4;
USART2, PD5, PD6, AF0;
// ..
);
The problem with this is, that it assumes that a single pin pair can be used for an USART peripheral. However, pins can be mixed, so I could use USART1 with PA9 and PB7.
One approach would be to generate Pins
implementations for all permutations (which can go into dozens or even hundreds of impls), but that's a workaround for a design problem in my opinion: Different pins can act as Tx
and as Rx
for an USART independently. (You could even use multiple Tx
pins for the same USART if you wanted...)
My suggestion would be to drop the Pins<USART>
trait, and to add TxPin<USART>
and RxPin<USART>
traits instead.
Here's a quick way to play around with this idea without having to adjust the serial trait:
pub trait TxPin<USART> {
fn setup(&self);
}
pub trait RxPin<USART> {
fn setup(&self);
}
impl<USART, TX, RX> Pins<USART> for (TX, RX) where TX: TxPin<USART>, RX: RxPin<USART> {
fn setup(&self) {
self.0.setup();
self.1.setup();
}
}
impl<Mode> TxPin<USART1> for PA9<Mode> { fn setup(&self) { self.set_alt_mode(AltMode::AF4); } }
impl<Mode> RxPin<USART1> for PA10<Mode> { fn setup(&self) { self.set_alt_mode(AltMode::AF4); } }
impl<Mode> TxPin<USART1> for PB6<Mode> { fn setup(&self) { self.set_alt_mode(AltMode::AF0); } }
impl<Mode> RxPin<USART1> for PB7<Mode> { fn setup(&self) { self.set_alt_mode(AltMode::AF0); } }
What do you think about this? I can create a PR with a concrete implementation if you want.
If dropping the Pins
directly is not an option, we could also deprecate it and implement the Serial trait for both Pins
and RxPin
/ TxPin
.
cc @rnestler