896: Implement I2C pullup configuration r=lulf a=chemicstry

I wasn't sure if I should put frequency into config struct, so left it separate as in SPI periph.

Also added Copy derives to gpio types, not sure why they weren't?

Co-authored-by: chemicstry <chemicstry@gmail.com>
This commit is contained in:
bors[bot] 2022-08-10 10:08:27 +00:00 committed by GitHub
commit 0e524247fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 112 additions and 12 deletions

View File

@ -213,7 +213,7 @@ impl<'d, T: Pin> Drop for Flex<'d, T> {
} }
/// Pull setting for an input. /// Pull setting for an input.
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Pull { pub enum Pull {
None, None,
@ -235,7 +235,7 @@ impl From<Pull> for vals::Pupdr {
} }
/// Speed settings /// Speed settings
#[derive(Debug)] #[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Speed { pub enum Speed {
Low, Low,
@ -303,7 +303,7 @@ impl<'d, T: Pin> Input<'d, T> {
} }
/// Digital input or output level. /// Digital input or output level.
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Level { pub enum Level {
Low, Low,
@ -470,7 +470,7 @@ pub(crate) mod sealed {
use super::*; use super::*;
/// Alternate function type settings /// Alternate function type settings
#[derive(Debug)] #[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum AFType { pub enum AFType {
Input, Input,

View File

@ -4,11 +4,28 @@ use embassy_embedded_hal::SetConfig;
use embassy_hal_common::into_ref; use embassy_hal_common::into_ref;
use crate::gpio::sealed::AFType; use crate::gpio::sealed::AFType;
use crate::gpio::Pull;
use crate::i2c::{Error, Instance, SclPin, SdaPin}; use crate::i2c::{Error, Instance, SclPin, SdaPin};
use crate::pac::i2c; use crate::pac::i2c;
use crate::time::Hertz; use crate::time::Hertz;
use crate::Peripheral; use crate::Peripheral;
#[non_exhaustive]
#[derive(Copy, Clone)]
pub struct Config {
pub sda_pullup: bool,
pub scl_pullup: bool,
}
impl Default for Config {
fn default() -> Self {
Self {
sda_pullup: false,
scl_pullup: false,
}
}
}
pub struct State {} pub struct State {}
impl State { impl State {
@ -27,6 +44,7 @@ impl<'d, T: Instance> I2c<'d, T> {
scl: impl Peripheral<P = impl SclPin<T>> + 'd, scl: impl Peripheral<P = impl SclPin<T>> + 'd,
sda: impl Peripheral<P = impl SdaPin<T>> + 'd, sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
freq: Hertz, freq: Hertz,
config: Config,
) -> Self { ) -> Self {
into_ref!(scl, sda); into_ref!(scl, sda);
@ -34,8 +52,22 @@ impl<'d, T: Instance> I2c<'d, T> {
T::reset(); T::reset();
unsafe { unsafe {
scl.set_as_af(scl.af_num(), AFType::OutputOpenDrain); scl.set_as_af_pull(
sda.set_as_af(sda.af_num(), AFType::OutputOpenDrain); scl.af_num(),
AFType::OutputOpenDrain,
match config.scl_pullup {
true => Pull::Up,
false => Pull::None,
},
);
sda.set_as_af_pull(
sda.af_num(),
AFType::OutputOpenDrain,
match config.sda_pullup {
true => Pull::Up,
false => Pull::None,
},
);
} }
unsafe { unsafe {

View File

@ -10,12 +10,29 @@ use futures::future::poll_fn;
use crate::dma::NoDma; use crate::dma::NoDma;
use crate::gpio::sealed::AFType; use crate::gpio::sealed::AFType;
use crate::gpio::Pull;
use crate::i2c::{Error, Instance, SclPin, SdaPin}; use crate::i2c::{Error, Instance, SclPin, SdaPin};
use crate::interrupt::InterruptExt; use crate::interrupt::InterruptExt;
use crate::pac::i2c; use crate::pac::i2c;
use crate::time::Hertz; use crate::time::Hertz;
use crate::Peripheral; use crate::Peripheral;
#[non_exhaustive]
#[derive(Copy, Clone)]
pub struct Config {
pub sda_pullup: bool,
pub scl_pullup: bool,
}
impl Default for Config {
fn default() -> Self {
Self {
sda_pullup: false,
scl_pullup: false,
}
}
}
pub struct State { pub struct State {
waker: AtomicWaker, waker: AtomicWaker,
chunks_transferred: AtomicUsize, chunks_transferred: AtomicUsize,
@ -46,6 +63,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
tx_dma: impl Peripheral<P = TXDMA> + 'd, tx_dma: impl Peripheral<P = TXDMA> + 'd,
rx_dma: impl Peripheral<P = RXDMA> + 'd, rx_dma: impl Peripheral<P = RXDMA> + 'd,
freq: Hertz, freq: Hertz,
config: Config,
) -> Self { ) -> Self {
into_ref!(peri, irq, scl, sda, tx_dma, rx_dma); into_ref!(peri, irq, scl, sda, tx_dma, rx_dma);
@ -53,8 +71,22 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
T::reset(); T::reset();
unsafe { unsafe {
scl.set_as_af(scl.af_num(), AFType::OutputOpenDrain); scl.set_as_af_pull(
sda.set_as_af(sda.af_num(), AFType::OutputOpenDrain); scl.af_num(),
AFType::OutputOpenDrain,
match config.scl_pullup {
true => Pull::Up,
false => Pull::None,
},
);
sda.set_as_af_pull(
sda.af_num(),
AFType::OutputOpenDrain,
match config.sda_pullup {
true => Pull::Up,
false => Pull::None,
},
);
} }
unsafe { unsafe {

View File

@ -39,7 +39,16 @@ async fn main(_spawner: Spawner, p: Peripherals) {
let mut led = Output::new(p.PE3, Level::High, Speed::Low); let mut led = Output::new(p.PE3, Level::High, Speed::Low);
let i2c_irq = interrupt::take!(I2C1_EV); let i2c_irq = interrupt::take!(I2C1_EV);
let cam_i2c = I2c::new(p.I2C1, p.PB8, p.PB9, i2c_irq, p.DMA1_CH1, p.DMA1_CH2, khz(100)); let cam_i2c = I2c::new(
p.I2C1,
p.PB8,
p.PB9,
i2c_irq,
p.DMA1_CH1,
p.DMA1_CH2,
khz(100),
Default::default(),
);
let mut camera = Ov7725::new(cam_i2c, mco); let mut camera = Ov7725::new(cam_i2c, mco);

View File

@ -16,7 +16,16 @@ const WHOAMI: u8 = 0x0F;
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner, p: Peripherals) -> ! { async fn main(_spawner: Spawner, p: Peripherals) -> ! {
let irq = interrupt::take!(I2C2_EV); let irq = interrupt::take!(I2C2_EV);
let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, irq, NoDma, NoDma, Hertz(100_000)); let mut i2c = I2c::new(
p.I2C2,
p.PB10,
p.PB11,
irq,
NoDma,
NoDma,
Hertz(100_000),
Default::default(),
);
let mut data = [0u8; 1]; let mut data = [0u8; 1];
unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data)); unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data));

View File

@ -18,7 +18,16 @@ const WHOAMI: u8 = 0x0F;
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner, p: Peripherals) -> ! { async fn main(_spawner: Spawner, p: Peripherals) -> ! {
let irq = interrupt::take!(I2C2_EV); let irq = interrupt::take!(I2C2_EV);
let i2c = I2c::new(p.I2C2, p.PB10, p.PB11, irq, NoDma, NoDma, Hertz(100_000)); let i2c = I2c::new(
p.I2C2,
p.PB10,
p.PB11,
irq,
NoDma,
NoDma,
Hertz(100_000),
Default::default(),
);
let mut i2c = BlockingAsync::new(i2c); let mut i2c = BlockingAsync::new(i2c);
let mut data = [0u8; 1]; let mut data = [0u8; 1];

View File

@ -15,7 +15,16 @@ const WHOAMI: u8 = 0x0F;
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner, p: Peripherals) -> ! { async fn main(_spawner: Spawner, p: Peripherals) -> ! {
let irq = interrupt::take!(I2C2_EV); let irq = interrupt::take!(I2C2_EV);
let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, irq, p.DMA1_CH4, p.DMA1_CH5, Hertz(100_000)); let mut i2c = I2c::new(
p.I2C2,
p.PB10,
p.PB11,
irq,
p.DMA1_CH4,
p.DMA1_CH5,
Hertz(100_000),
Default::default(),
);
let mut data = [0u8; 1]; let mut data = [0u8; 1];
unwrap!(i2c.write_read(ADDRESS, &[WHOAMI], &mut data).await); unwrap!(i2c.write_read(ADDRESS, &[WHOAMI], &mut data).await);