Skip to content

Commit ede6e2e

Browse files
Add I2C slave
1 parent 0d1a7f4 commit ede6e2e

File tree

5 files changed

+586
-0
lines changed

5 files changed

+586
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2020
- PWM complementary output capability for TIM1 with new example to demonstrate
2121
- Implement interface for reading and writing to the internal flash memory and an example for demonstration.
2222
- PWM output on complementary channels only for single channel timers (TIM16 + TIM17)
23+
- I2C slave added
2324

2425
### Fixed
2526

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,7 @@ required-features = ["stm32f042", "rt"]
9898
[[example]]
9999
name = "usb_serial"
100100
required-features = ["rt", "stm32f042", "stm32-usbd"]
101+
102+
[[example]]
103+
name = "i2c_slave"
104+
required-features = ["stm32f030x4", "rt"]

examples/i2c_slave.rs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
use crate::hal::{
5+
gpio::*,
6+
pac::{interrupt, Interrupt, Peripherals},
7+
};
8+
use cortex_m_rt::entry;
9+
use panic_halt as _;
10+
11+
// use rtt_target::{rprintln, rtt_init_print};
12+
use stm32f0xx_hal::i2c_slave::{self, I2CSlave, State};
13+
use stm32f0xx_hal::{self as hal, prelude::*};
14+
15+
use core::cell::RefCell;
16+
use cortex_m::{interrupt::Mutex, peripheral::Peripherals as c_m_Peripherals};
17+
type SCL = gpioa::PA9<Alternate<AF4>>;
18+
type SDA = gpioa::PA10<Alternate<AF4>>;
19+
type I2C = hal::pac::I2C1;
20+
// Make I2C pin globally available
21+
static GI2C: Mutex<RefCell<Option<I2CSlave<I2C, SCL, SDA>>>> = Mutex::new(RefCell::new(None));
22+
23+
#[interrupt]
24+
fn I2C1() {
25+
static mut I2C: Option<I2CSlave<I2C, SCL, SDA>> = None;
26+
27+
let i2c = I2C.get_or_insert_with(|| {
28+
cortex_m::interrupt::free(|cs| {
29+
// Move I2C pin here, leaving a None in its place
30+
GI2C.borrow(cs).replace(None).unwrap()
31+
})
32+
});
33+
match i2c.interrupt() {
34+
Ok(State::Buzy(_flag)) => {
35+
// rprintln!("I2C is busy {:?}", _flag);
36+
}
37+
Ok(State::DataReceived(_reg)) => {
38+
let _data = i2c.get_received_data();
39+
// rprintln!("Reg: {:?} Data: {:?}", _reg, _data);
40+
}
41+
Ok(State::DataRequested(_reg)) => {
42+
// rprintln!("Data requested: {:?}", _reg);
43+
if let Err(_e) = i2c.send_data(&[0x01, 0x02, 0x03]) {
44+
// rprintln!("Error {:?}", _e);
45+
}
46+
}
47+
Err(_e) => {
48+
// rprintln!("Error {:?}", e);
49+
}
50+
}
51+
}
52+
53+
static I2C_ADDR: u8 = 0x52;
54+
#[entry]
55+
fn main() -> ! {
56+
// rtt_init_print!();
57+
// rprintln!("Starting I2C Slave example...");
58+
if let (Some(mut p), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) {
59+
cortex_m::interrupt::free(move |cs| {
60+
p.RCC.apb1enr.modify(|_, w| w.i2c1en().set_bit());
61+
let mut rcc = p.RCC.configure().sysclk(48.mhz()).pclk(24.mhz()).freeze(&mut p.FLASH);
62+
let gpioa = p.GPIOA.split(&mut rcc);
63+
64+
// Configure pins for I2C
65+
let sda = gpioa.pa10.into_alternate_af4(cs);
66+
let scl = gpioa.pa9.into_alternate_af4(cs);
67+
let i2c = i2c_slave::I2CSlave::i2c1_slave(p.I2C1, (scl, sda), I2C_ADDR, &mut rcc);
68+
*GI2C.borrow(cs).borrow_mut() = Some(i2c);
69+
70+
// Enable I2C IRQ, set prio 1 and clear any pending IRQs
71+
let mut nvic = cp.NVIC;
72+
unsafe {
73+
nvic.set_priority(Interrupt::I2C1, 1);
74+
cortex_m::peripheral::NVIC::unmask(Interrupt::I2C1);
75+
}
76+
77+
cortex_m::peripheral::NVIC::unpend(Interrupt::I2C1);
78+
});
79+
}
80+
81+
loop {
82+
continue;
83+
}
84+
}

0 commit comments

Comments
 (0)