From d371298a27b37c3f79adf24d375fd7a1171bf8e1 Mon Sep 17 00:00:00 2001
From: Mariusz Ryndzionek <mryndzionek@gmail.com>
Date: Fri, 24 Sep 2021 18:39:07 +0200
Subject: [PATCH] Small adjustment to 'set_as_af' interface

Small adjustment to 'set_as_af' interface - v2
---
 embassy-stm32/src/can/bxcan.rs  |  9 ++++++---
 embassy-stm32/src/eth/v2/mod.rs |  4 ++--
 embassy-stm32/src/gpio.rs       | 21 ++++++++++++++++++++-
 embassy-stm32/src/i2c/v1.rs     | 14 +++-----------
 embassy-stm32/src/spi/v1.rs     | 12 ++++++++----
 embassy-stm32/src/usart/v1.rs   |  5 +++--
 embassy-stm32/src/usart/v2.rs   |  5 +++--
 7 files changed, 45 insertions(+), 25 deletions(-)

diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index 906978e8b..c9ed196e1 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -4,7 +4,10 @@ use core::ops::{Deref, DerefMut};
 use embassy::util::Unborrow;
 use embassy_hal_common::unborrow;
 
-use crate::gpio::Pin;
+use crate::gpio::{
+    OutputType::{OpenDrain, PushPull},
+    Pin,
+};
 use crate::{peripherals, rcc::RccPeripheral};
 
 pub use bxcan::*;
@@ -23,8 +26,8 @@ impl<'d, T: Instance + bxcan::Instance> Can<'d, T> {
         unborrow!(peri, rx, tx);
 
         unsafe {
-            rx.set_as_af(rx.af_num());
-            tx.set_as_af(tx.af_num());
+            rx.set_as_af(rx.af_num(), OpenDrain);
+            tx.set_as_af(tx.af_num(), PushPull);
         }
 
         T::enable();
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index ff734f78c..5d4151ecd 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -9,8 +9,8 @@ use embassy_hal_common::unborrow;
 use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU};
 
 use crate::gpio::sealed::Pin as __GpioPin;
-use crate::gpio::AnyPin;
 use crate::gpio::Pin as GpioPin;
+use crate::gpio::{AnyPin, OutputType::PushPull};
 use crate::pac::gpio::vals::Ospeedr;
 use crate::pac::{ETH, RCC, SYSCFG};
 use crate::peripherals;
@@ -416,7 +416,7 @@ macro_rules! impl_pin {
             fn configure(&mut self) {
                 // NOTE(unsafe) Exclusive access to the registers
                 critical_section::with(|_| unsafe {
-                    self.set_as_af($af);
+                    self.set_as_af($af, PushPull);
                     self.block()
                         .ospeedr()
                         .modify(|w| w.set_ospeedr(self.pin() as usize, Ospeedr::VERYHIGHSPEED));
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index 7812709ce..d5792d6f7 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -55,6 +55,14 @@ impl From<Speed> for vals::Ospeedr {
     }
 }
 
+/// Type settings
+#[derive(Debug)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum OutputType {
+    PushPull,
+    OpenDrain,
+}
+
 /// GPIO input driver.
 pub struct Input<'d, T: Pin> {
     pub(crate) pin: T,
@@ -299,7 +307,7 @@ pub(crate) mod sealed {
             }
         }
 
-        unsafe fn set_as_af(&self, af_num: u8) {
+        unsafe fn set_as_af(&self, af_num: u8, af_type: OutputType) {
             let pin = self._pin() as usize;
             let block = self.block();
             block
@@ -308,6 +316,17 @@ pub(crate) mod sealed {
             block
                 .afr(pin / 8)
                 .modify(|w| w.set_afr(pin % 8, vals::Afr(af_num)));
+            match af_type {
+                OutputType::PushPull => {
+                    block.otyper().modify(|w| w.set_ot(pin, vals::Ot::PUSHPULL))
+                }
+                OutputType::OpenDrain => block
+                    .otyper()
+                    .modify(|w| w.set_ot(pin, vals::Ot::OPENDRAIN)),
+            }
+            block
+                .pupdr()
+                .modify(|w| w.set_pupdr(pin, vals::Pupdr::FLOATING));
         }
 
         unsafe fn set_as_analog(&self) {
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index 578536855..c7b7c81fd 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -9,8 +9,7 @@ use embedded_hal::blocking::i2c::WriteRead;
 
 use crate::pac::i2c;
 
-use crate::pac::gpio::vals::{Afr, Moder, Ot};
-use crate::pac::gpio::Gpio;
+use crate::gpio::OutputType::OpenDrain;
 
 pub struct I2c<'d, T: Instance> {
     phantom: PhantomData<&'d mut T>,
@@ -31,8 +30,8 @@ impl<'d, T: Instance> I2c<'d, T> {
         T::enable();
 
         unsafe {
-            Self::configure_pin(scl.block(), scl.pin() as _, scl.af_num());
-            Self::configure_pin(sda.block(), sda.pin() as _, sda.af_num());
+            scl.set_as_af(scl.af_num(), OpenDrain);
+            sda.set_as_af(sda.af_num(), OpenDrain);
         }
 
         unsafe {
@@ -69,13 +68,6 @@ impl<'d, T: Instance> I2c<'d, T> {
         }
     }
 
-    unsafe fn configure_pin(block: Gpio, pin: usize, af_num: u8) {
-        let (afr, n_af) = if pin < 8 { (0, pin) } else { (1, pin - 8) };
-        block.moder().modify(|w| w.set_moder(pin, Moder::ALTERNATE));
-        block.afr(afr).modify(|w| w.set_afr(n_af, Afr(af_num)));
-        block.otyper().modify(|w| w.set_ot(pin, Ot::OPENDRAIN));
-    }
-
     unsafe fn check_and_clear_error_flags(&self) -> Result<i2c::regs::Sr1, Error> {
         // Note that flags should only be cleared once they have been registered. If flags are
         // cleared otherwise, there may be an inherent race condition and flags may be missed.
diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs
index 302b7a2a1..297d232bc 100644
--- a/embassy-stm32/src/spi/v1.rs
+++ b/embassy-stm32/src/spi/v1.rs
@@ -1,7 +1,11 @@
 #![macro_use]
 
 use crate::dma::NoDma;
-use crate::gpio::{sealed::Pin, AnyPin};
+use crate::gpio::{
+    sealed::Pin,
+    AnyPin,
+    OutputType::{OpenDrain, PushPull},
+};
 use crate::pac::spi;
 use crate::spi::{
     ByteOrder, Config, Error, Instance, MisoPin, MosiPin, RxDmaChannel, SckPin, TxDmaChannel,
@@ -53,9 +57,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
         unborrow!(sck, mosi, miso, txdma, rxdma);
 
         unsafe {
-            sck.set_as_af(sck.af_num());
-            mosi.set_as_af(mosi.af_num());
-            miso.set_as_af(miso.af_num());
+            sck.set_as_af(sck.af_num(), PushPull);
+            mosi.set_as_af(mosi.af_num(), PushPull);
+            miso.set_as_af(miso.af_num(), OpenDrain);
         }
 
         let sck = sck.degrade();
diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs
index ec6677699..16c1af387 100644
--- a/embassy-stm32/src/usart/v1.rs
+++ b/embassy-stm32/src/usart/v1.rs
@@ -1,3 +1,4 @@
+use crate::gpio::OutputType::{OpenDrain, PushPull};
 use core::future::Future;
 use core::marker::PhantomData;
 use embassy::util::Unborrow;
@@ -36,8 +37,8 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
         let r = inner.regs();
 
         unsafe {
-            rx.set_as_af(rx.af_num());
-            tx.set_as_af(tx.af_num());
+            rx.set_as_af(rx.af_num(), OpenDrain);
+            tx.set_as_af(tx.af_num(), PushPull);
 
             r.brr().write_value(regs::Brr(div));
             r.cr1().write(|w| {
diff --git a/embassy-stm32/src/usart/v2.rs b/embassy-stm32/src/usart/v2.rs
index fc3036404..e3f88c0aa 100644
--- a/embassy-stm32/src/usart/v2.rs
+++ b/embassy-stm32/src/usart/v2.rs
@@ -13,6 +13,7 @@ use futures::TryFutureExt;
 
 use super::*;
 use crate::dma::NoDma;
+use crate::gpio::OutputType::{OpenDrain, PushPull};
 use crate::pac::usart::{regs, vals};
 
 pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
@@ -42,8 +43,8 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
         let r = inner.regs();
 
         unsafe {
-            rx.set_as_af(rx.af_num());
-            tx.set_as_af(tx.af_num());
+            rx.set_as_af(rx.af_num(), OpenDrain);
+            tx.set_as_af(tx.af_num(), PushPull);
 
             r.cr2().write(|_w| {});
             r.cr3().write(|_w| {});