Implement I2C pullup configuration

This commit is contained in:
chemicstry 2022-08-09 22:13:35 +03:00
parent b7b4c84067
commit 6498324b58
7 changed files with 86 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,24 @@ 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 {
pullup_enable: bool,
}
impl Default for Config {
fn default() -> Self {
Self { pullup_enable: true }
}
}
pub struct State {} pub struct State {}
impl State { impl State {
@ -27,15 +40,21 @@ 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);
T::enable(); T::enable();
T::reset(); T::reset();
let pull = match config.pullup_enable {
true => Pull::Up,
false => Pull::None,
};
unsafe { unsafe {
scl.set_as_af(scl.af_num(), AFType::OutputOpenDrain); scl.set_as_af_pull(scl.af_num(), AFType::OutputOpenDrain, pull);
sda.set_as_af(sda.af_num(), AFType::OutputOpenDrain); sda.set_as_af_pull(sda.af_num(), AFType::OutputOpenDrain, pull);
} }
unsafe { unsafe {

View File

@ -10,12 +10,25 @@ 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 {
pullup_enable: bool,
}
impl Default for Config {
fn default() -> Self {
Self { pullup_enable: true }
}
}
pub struct State { pub struct State {
waker: AtomicWaker, waker: AtomicWaker,
chunks_transferred: AtomicUsize, chunks_transferred: AtomicUsize,
@ -46,15 +59,21 @@ 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);
T::enable(); T::enable();
T::reset(); T::reset();
let pull = match config.pullup_enable {
true => Pull::Up,
false => Pull::None,
};
unsafe { unsafe {
scl.set_as_af(scl.af_num(), AFType::OutputOpenDrain); scl.set_as_af_pull(scl.af_num(), AFType::OutputOpenDrain, pull);
sda.set_as_af(sda.af_num(), AFType::OutputOpenDrain); sda.set_as_af_pull(sda.af_num(), AFType::OutputOpenDrain, pull);
} }
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);