Skip to content
Merged
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,11 @@ name = "blinky"
[[example]]
name = "i2c"
required-features = ["stm32h503"]

[[example]]
name = "i2c_target"
required-features = ["stm32h503"]

[[example]]
name = "i2c_target_manual_ack"
required-features = ["stm32h503"]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ of support for peripherals is shown in the table below.
|------------|----|---|---|
| GPIO | ✅ | - | |
| ICache | ✅ | - | |
| I2C | ✅ | - | Controller operation is done; Target is 🚧 |
| I2C | ✅ | - | |
| CAN | 🚧 | - | |
| Rng | 🚧 | [#34](https://github.com/stm32-rs/stm32h5xx-hal/issues/34)| |
| SPI | 🚧 | [#36](https://github.com/stm32-rs/stm32h5xx-hal/issues/36) | |
Expand Down
65 changes: 65 additions & 0 deletions examples/i2c_target.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#![deny(warnings)]
#![no_main]
#![no_std]

#[macro_use]
mod utilities;
use stm32h5xx_hal::{
i2c::{TargetConfig, TargetListenEvent, Targetable},
pac,
prelude::*,
};

use cortex_m_rt::entry;

use log::info;

#[entry]
fn main() -> ! {
utilities::logger::init();
log::set_max_level(log::LevelFilter::Debug);
let dp = pac::Peripherals::take().unwrap();

// Constrain and Freeze power
info!("Setup PWR... ");
let pwr = dp.PWR.constrain();
let pwrcfg = pwr.freeze();

// Constrain and Freeze clock
info!("Setup RCC... ");
let rcc = dp.RCC.constrain();
let ccdr = rcc.sys_ck(100.MHz()).freeze(pwrcfg, &dp.SBS);

let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);

// Configure the SCL and the SDA pin for our I2C bus
let scl = gpiob.pb5.into_alternate_open_drain();
let sda = gpiob.pb3.into_alternate_open_drain();

info!("");
info!("stm32h5xx-hal example - I2C Target");
info!("");

let own_addr: u16 = 0x18;
let bus_freq_hz: u32 = 100_000;
let mut i2c = dp.I2C2.i2c_target_only(
(scl, sda),
TargetConfig::new(own_addr, bus_freq_hz),
ccdr.peripheral.I2C2,
&ccdr.clocks,
);

i2c.enable_listen_event(TargetListenEvent::PrimaryAddress);
let mut buf = [0u8; 2];

loop {
let count = i2c.wait_for_target_read(&mut buf).unwrap();
info!("Read {count} bytes: {:X?}", &buf[..count]);

let count = i2c.wait_for_target_write(b"Hello").unwrap();
info!("Wrote {count} bytes");

i2c.wait_for_stop().unwrap();
info!("==========");
}
}
80 changes: 80 additions & 0 deletions examples/i2c_target_manual_ack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#![deny(warnings)]
#![no_main]
#![no_std]

#[macro_use]
mod utilities;
use stm32h5xx_hal::{
i2c::{TargetConfig, TargetEvent, TargetListenEvent, Targetable},
pac,
prelude::*,
};

use cortex_m_rt::entry;

use log::info;

#[entry]
fn main() -> ! {
utilities::logger::init();
log::set_max_level(log::LevelFilter::Info);
let dp = pac::Peripherals::take().unwrap();

// Constrain and Freeze power
info!("Setup PWR... ");
let pwr = dp.PWR.constrain();
let pwrcfg = pwr.freeze();

// Constrain and Freeze clock
info!("Setup RCC... ");
let rcc = dp.RCC.constrain();
let ccdr = rcc.sys_ck(100.MHz()).freeze(pwrcfg, &dp.SBS);

let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);

// Configure the SCL and the SDA pin for our I2C bus
let scl = gpiob.pb5.into_alternate_open_drain();
let sda = gpiob.pb3.into_alternate_open_drain();

info!("");
info!("stm32h5xx-hal example - I2C Target");
info!("");

let own_addr: u16 = 0x18;
let bus_freq_hz: u32 = 100_000;
let mut i2c = dp
.I2C2
.i2c_target_only(
(scl, sda),
TargetConfig::new(own_addr, bus_freq_hz),
ccdr.peripheral.I2C2,
&ccdr.clocks,
)
.with_manual_ack_control();

i2c.enable_listen_event(TargetListenEvent::PrimaryAddress);
let mut buf = [0u8; 2];

loop {
let event = i2c.wait_for_event().unwrap();
let result = match event {
TargetEvent::Read { address: _ } => i2c.write(b"Hello"),
TargetEvent::Write { address: _ } => {
let result = i2c.read(&mut buf);
// An operation can be performed here while the clock is stretched low (ie.
// calculating or fetching data)
i2c.ack_transfer();
result
}
TargetEvent::Stop => Ok(0),
};

match result {
Err(error) => info!("Error: {event:?} - {error:?}"),
Ok(count) => match event {
TargetEvent::Stop => info!("=========="),
_ => info!("{event:?} ({count})"),
},
};
}
}
Loading