Skip to content

Commit

Permalink
Add I2C slave
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-nicolai-hansten committed Oct 22, 2024
1 parent 0d1a7f4 commit 740e038
Show file tree
Hide file tree
Showing 5 changed files with 589 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- PWM complementary output capability for TIM1 with new example to demonstrate
- Implement interface for reading and writing to the internal flash memory and an example for demonstration.
- PWM output on complementary channels only for single channel timers (TIM16 + TIM17)
- I2C slave added

### Fixed

Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,7 @@ required-features = ["stm32f042", "rt"]
[[example]]
name = "usb_serial"
required-features = ["rt", "stm32f042", "stm32-usbd"]

[[example]]
name = "i2c_slave"
required-features = ["stm32f030x4", "rt"]
89 changes: 89 additions & 0 deletions examples/i2c_slave.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#![no_main]
#![no_std]

use crate::hal::{
gpio::*,
pac::{interrupt, Interrupt, Peripherals},
};
use cortex_m_rt::entry;
use panic_halt as _;

// use rtt_target::{rprintln, rtt_init_print};
use stm32f0xx_hal::i2c_slave::{self, I2CSlave, State};
use stm32f0xx_hal::{self as hal, prelude::*};

use core::cell::RefCell;
use cortex_m::{interrupt::Mutex, peripheral::Peripherals as c_m_Peripherals};
type SCL = gpioa::PA9<Alternate<AF4>>;
type SDA = gpioa::PA10<Alternate<AF4>>;
type I2C = hal::pac::I2C1;
// Make I2C pin globally available
static GI2C: Mutex<RefCell<Option<I2CSlave<I2C, SCL, SDA>>>> = Mutex::new(RefCell::new(None));

#[interrupt]
fn I2C1() {
static mut I2C: Option<I2CSlave<I2C, SCL, SDA>> = None;

let i2c = I2C.get_or_insert_with(|| {
cortex_m::interrupt::free(|cs| {
// Move I2C pin here, leaving a None in its place
GI2C.borrow(cs).replace(None).unwrap()
})
});
match i2c.interrupt() {
Ok(State::Buzy(_flag)) => {
// rprintln!("I2C is busy {:?}", _flag);
}
Ok(State::DataReceived(_reg)) => {
let _data = i2c.get_received_data();
// rprintln!("Reg: {:?} Data: {:?}", _reg, _data);
}
Ok(State::DataRequested(_reg)) => {
// rprintln!("Data requested: {:?}", _reg);
if let Err(_e) = i2c.send_data(&[0x01, 0x02, 0x03]) {
// rprintln!("Error {:?}", _e);
}
}
Err(_e) => {
// rprintln!("Error {:?}", e);
}
}
}

static I2C_ADDR: u8 = 0x52;
#[entry]
fn main() -> ! {
// rtt_init_print!();
// rprintln!("Starting I2C Slave example...");
if let (Some(mut p), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) {
cortex_m::interrupt::free(move |cs| {
p.RCC.apb1enr.modify(|_, w| w.i2c1en().set_bit());
let mut rcc = p
.RCC
.configure()
.sysclk(48.mhz())
.pclk(24.mhz())
.freeze(&mut p.FLASH);
let gpioa = p.GPIOA.split(&mut rcc);

// Configure pins for I2C
let sda = gpioa.pa10.into_alternate_af4(cs);
let scl = gpioa.pa9.into_alternate_af4(cs);
let i2c = i2c_slave::I2CSlave::i2c1_slave(p.I2C1, (scl, sda), I2C_ADDR, &mut rcc);
*GI2C.borrow(cs).borrow_mut() = Some(i2c);

// Enable I2C IRQ, set prio 1 and clear any pending IRQs
let mut nvic = cp.NVIC;
unsafe {
nvic.set_priority(Interrupt::I2C1, 1);
cortex_m::peripheral::NVIC::unmask(Interrupt::I2C1);
}

cortex_m::peripheral::NVIC::unpend(Interrupt::I2C1);
});
}

loop {
continue;
}
}
Loading

0 comments on commit 740e038

Please sign in to comment.