Skip to content

Commit ea8bee6

Browse files
authored
I2C interrupt support (#124)
* i2c interrupt support * code cleanup * code cleanup * update i2c slave implementation
1 parent 9582c4a commit ea8bee6

File tree

4 files changed

+62
-23
lines changed

4 files changed

+62
-23
lines changed

src/i2c/blocking.rs

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
//! I2C
22
use crate::gpio::*;
33
use crate::i2c::config::Config;
4-
use crate::i2c::{Error, I2c, I2cDirection, I2cExt, SCLPin, SDAPin};
4+
use crate::i2c::{self, Error, I2c, I2cDirection, I2cExt, SCLPin, SDAPin};
55
use crate::rcc::*;
66
use crate::stm32::{I2C1, I2C2};
77
use hal::blocking::i2c::{Read, Write, WriteRead};
88

99
pub trait I2cSlave {
10-
/// Enable/ disable sbc. Default sbc is switched on.
10+
/// Enable/Disable Slave Byte Control. Default SBC is switched on.
1111
/// For master write/read the transaction should start with sbc disabled.
12-
/// So ACK will be send on the last received byte. Then before the send phase sbc should enabled again
12+
/// So ACK will be send on the last received byte.
13+
/// Before the send phase SBC should be enabled again.
1314
fn slave_sbc(&mut self, sbc_enabled: bool);
1415

16+
/// An optional tuple is returned with the address as sent by the master. The address is for 7 bit in range of 0..127
17+
fn slave_addressed(&mut self) -> Result<Option<(u16, I2cDirection)>, Error>;
18+
1519
/// Wait until this slave is addressed by the master.
1620
/// A tuple is returned with the address as sent by the master. The address is for 7 bit in range of 0..127
1721
fn slave_wait_addressed(&mut self) -> Result<(u16, I2cDirection), Error>;
@@ -75,7 +79,7 @@ macro_rules! busy_wait {
7579
// This condition Will only happen when reload == 1 and sbr == 1 (slave) and nbytes was written.
7680
// Send a NACK, set nbytes to clear tcr flag
7781
$i2c.cr2.modify(|_, w| unsafe {
78-
w.nack().set_bit().nbytes().bits( 1 as u8)
82+
w.nack().set_bit().nbytes().bits(1 as u8)
7983
});
8084
// Make one extra loop here to wait on the stop condition
8185
} else if isr.addr().bit_is_set() {
@@ -198,7 +202,7 @@ macro_rules! i2c {
198202
.oa2en().set_bit()
199203
});
200204
// Enable acknowlidge control
201-
i2c.cr1.modify(|_, w| w.sbc().set_bit() );
205+
i2c.cr1.modify(|_, w| w.sbc().set_bit() );
202206
}
203207

204208
// Enable pins
@@ -208,6 +212,27 @@ macro_rules! i2c {
208212
I2c { i2c, sda, scl }
209213
}
210214

215+
pub fn listen(&mut self, ev: i2c::Event) {
216+
match ev {
217+
i2c::Event::AddressMatch => self.i2c.cr1.modify(|_, w| w.addrie().set_bit()),
218+
i2c::Event::Rxne => self.i2c.cr1.modify(|_, w| w.rxie().set_bit()),
219+
}
220+
}
221+
222+
pub fn unlisten(&mut self, ev: i2c::Event) {
223+
match ev {
224+
i2c::Event::AddressMatch => self.i2c.cr1.modify(|_, w| w.addrie().clear_bit()),
225+
i2c::Event::Rxne => self.i2c.cr1.modify(|_, w| w.rxie().clear_bit()),
226+
}
227+
}
228+
229+
pub fn clear_irq(&mut self, ev: i2c::Event) {
230+
match ev {
231+
i2c::Event::AddressMatch => self.i2c.icr.write(|w| w.addrcf().set_bit()),
232+
_ => {},
233+
}
234+
}
235+
211236
pub fn release(self) -> ($I2CX, SDA, SCL) {
212237
(self.i2c, self.sda.release(), self.scl.release())
213238
}
@@ -384,29 +409,36 @@ macro_rules! i2c {
384409
impl<SDA, SCL> I2cSlave for I2c<$I2CX, SDA, SCL> {
385410

386411
fn slave_sbc(&mut self, sbc_enabled: bool) {
387-
// enable acknowlidge control
412+
// Enable Slave byte control
388413
self.i2c.cr1.modify(|_, w| w.sbc().bit(sbc_enabled) );
389414
}
390415

416+
fn slave_addressed(&mut self) -> Result<Option<(u16, I2cDirection)>, Error> {
417+
if self.i2c.isr.read().addr().bit_is_set() {
418+
let isr = self.i2c.isr.read();
419+
let current_address = isr.addcode().bits() as u16;
391420

392-
fn slave_wait_addressed(&mut self) -> Result<(u16, I2cDirection), Error>{
393-
// blocking wait until addressed
394-
while self.i2c.isr.read().addr().bit_is_clear() {};
395-
396-
397-
let isr = self.i2c.isr.read();
398-
let current_address = isr.addcode().bits() as u16;
399-
400-
// if the dir bit is set it is a master write slave read operation
401-
let direction = if isr.dir().bit_is_set()
402-
{
421+
// if the dir bit is set it is a master write slave read operation
422+
let direction = if isr.dir().bit_is_set() {
403423
I2cDirection::MasterReadSlaveWrite
404424
} else {
405425
I2cDirection::MasterWriteSlaveRead
406426
};
407-
// do not yet release the clock stretching here.
408-
// In the slave read function the nbytes is send, for this the addr bit must be set
409-
Ok((current_address, direction))
427+
// do not yet release the clock stretching here.
428+
// In the slave read function the nbytes is send, for this the addr bit must be set
429+
Ok(Some((current_address, direction)))
430+
431+
} else {
432+
Ok(None)
433+
}
434+
}
435+
436+
fn slave_wait_addressed(&mut self) -> Result<(u16, I2cDirection), Error> {
437+
loop {
438+
if let Some(res) = self.slave_addressed()? {
439+
return Ok(res)
440+
}
441+
}
410442
}
411443

412444
fn slave_write(&mut self, bytes: &[u8]) -> Result<(), Error> {

src/i2c/config.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,22 +73,22 @@ impl Config {
7373
};
7474
psc << 28 | scldel << 20 | sdadel << 16 | sclh << 8 | scll
7575
}
76+
7677
/// Slave address 1 as 7 bit address, in range 0 .. 127
7778
pub fn slave_address(&mut self, own_address: u8) {
78-
//assert!(own_address < (2 ^ 7));
7979
self.slave_address_1 = own_address as u16;
8080
self.address_11bits = false;
8181
}
82+
8283
/// Slave address 1 as 11 bit address in range 0 .. 2047
8384
pub fn slave_address_11bits(&mut self, own_address: u16) {
84-
//assert!(own_address < (2 ^ 11));
8585
self.slave_address_1 = own_address;
8686
self.address_11bits = true;
8787
}
88+
8889
/// Slave address 2 as 7 bit address in range 0 .. 127.
8990
/// The mask makes all slaves within the mask addressable
9091
pub fn slave_address_2(&mut self, own_address: u8, mask: SlaveAddressMask) {
91-
//assert!(own_address < (2 ^ 7));
9292
self.slave_address_2 = own_address;
9393
self.slave_address_mask = mask;
9494
}

src/i2c/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ pub enum I2cDirection {
3636
MasterWriteSlaveRead = 1,
3737
}
3838

39+
#[derive(Debug, Clone, Copy)]
40+
pub enum Event {
41+
AddressMatch,
42+
Rxne,
43+
}
44+
3945
/// I2C error
4046
#[derive(Debug, Clone, Copy)]
4147
pub enum Error {

src/prelude.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub use crate::dma::DmaExt as _;
2424
pub use crate::exti::ExtiExt as _;
2525
pub use crate::flash::FlashExt as _;
2626
pub use crate::gpio::GpioExt as _;
27+
pub use crate::i2c::blocking::I2cSlave;
2728
pub use crate::i2c::I2cExt as _;
2829
pub use crate::power::PowerExt as _;
2930
pub use crate::rcc::LSCOExt as _;

0 commit comments

Comments
 (0)