Skip to content

Commit d393ee2

Browse files
committed
I2C 10-bit address support
1 parent 6c995d6 commit d393ee2

File tree

4 files changed

+153
-80
lines changed

4 files changed

+153
-80
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Added
1111

12+
- I2C 10-bit address support for I2c
1213
- `i2c_scanner` example [#758]
1314
- Enable `sdio` for stm32f446
1415
- port LTDC implementation and example from stm32f7xx-hal [#731]

src/i2c.rs

Lines changed: 85 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ use crate::gpio;
88
use crate::rcc::Clocks;
99
use fugit::{HertzU32 as Hertz, RateExtU32};
1010

11+
mod common;
1112
mod hal_02;
1213
mod hal_1;
1314

15+
pub use common::{Address, Error, NoAcknowledgeSource};
16+
use common::{Hal02Operation, Hal1Operation};
17+
1418
pub mod dma;
1519

1620
#[derive(Debug, Eq, PartialEq)]
@@ -70,39 +74,6 @@ pub struct I2c<I2C: Instance> {
7074
pins: (I2C::Scl, I2C::Sda),
7175
}
7276

73-
pub use embedded_hal::i2c::NoAcknowledgeSource;
74-
75-
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
76-
#[non_exhaustive]
77-
pub enum Error {
78-
Overrun,
79-
NoAcknowledge(NoAcknowledgeSource),
80-
Timeout,
81-
// Note: The Bus error type is not currently returned, but is maintained for compatibility.
82-
Bus,
83-
Crc,
84-
ArbitrationLoss,
85-
}
86-
87-
impl Error {
88-
pub(crate) fn nack_addr(self) -> Self {
89-
match self {
90-
Error::NoAcknowledge(NoAcknowledgeSource::Unknown) => {
91-
Error::NoAcknowledge(NoAcknowledgeSource::Address)
92-
}
93-
e => e,
94-
}
95-
}
96-
pub(crate) fn nack_data(self) -> Self {
97-
match self {
98-
Error::NoAcknowledge(NoAcknowledgeSource::Unknown) => {
99-
Error::NoAcknowledge(NoAcknowledgeSource::Data)
100-
}
101-
e => e,
102-
}
103-
}
104-
}
105-
10677
pub trait Instance:
10778
crate::Sealed
10879
+ crate::Ptr<RB = i2c1::RegisterBlock>
@@ -155,10 +126,7 @@ impl<I2C: Instance> I2cExt for I2C {
155126
}
156127
}
157128

158-
impl<I2C> I2c<I2C>
159-
where
160-
I2C: Instance,
161-
{
129+
impl<I2C: Instance> I2c<I2C> {
162130
pub fn new(
163131
i2c: I2C,
164132
pins: (impl Into<I2C::Scl>, impl Into<I2C::Sda>),
@@ -287,7 +255,7 @@ impl<I2C: Instance> I2c<I2C> {
287255

288256
/// Sends START and Address for writing
289257
#[inline(always)]
290-
fn prepare_write(&self, addr: u8) -> Result<(), Error> {
258+
fn prepare_write(&self, addr: Address) -> Result<(), Error> {
291259
// Wait until a previous STOP condition finishes. When the previous
292260
// STOP was generated inside an ISR (e.g. DMA interrupt handler),
293261
// the ISR returns without waiting for the STOP condition to finish.
@@ -313,9 +281,20 @@ impl<I2C: Instance> I2c<I2C> {
313281
}
314282

315283
// Set up current address, we're trying to talk to
316-
self.i2c
317-
.dr()
318-
.write(|w| unsafe { w.bits(u32::from(addr) << 1) });
284+
match addr {
285+
Address::Seven(addr) => {
286+
self.i2c
287+
.dr()
288+
.write(|w| unsafe { w.bits(u32::from(addr) << 1) });
289+
}
290+
Address::Ten(addr) => {
291+
let [msbs, lsbs] = addr.to_be_bytes();
292+
let msbs = ((msbs & 0b11) << 1) & 0b11110000;
293+
let dr = self.i2c.dr();
294+
dr.write(|w| unsafe { w.bits(u32::from(msbs)) });
295+
dr.write(|w| unsafe { w.bits(u32::from(lsbs)) });
296+
}
297+
}
319298

320299
// Wait until address was sent
321300
loop {
@@ -337,7 +316,7 @@ impl<I2C: Instance> I2c<I2C> {
337316
}
338317

339318
/// Sends START and Address for reading
340-
fn prepare_read(&self, addr: u8) -> Result<(), Error> {
319+
fn prepare_read(&self, addr: Address, first_transaction: bool) -> Result<(), Error> {
341320
// Wait until a previous STOP condition finishes. When the previous
342321
// STOP was generated inside an ISR (e.g. DMA interrupt handler),
343322
// the ISR returns without waiting for the STOP condition to finish.
@@ -361,9 +340,26 @@ impl<I2C: Instance> I2c<I2C> {
361340
} {}
362341

363342
// Set up current address, we're trying to talk to
364-
self.i2c
365-
.dr()
366-
.write(|w| unsafe { w.bits((u32::from(addr) << 1) + 1) });
343+
match addr {
344+
Address::Seven(addr) => {
345+
self.i2c
346+
.dr()
347+
.write(|w| unsafe { w.bits((u32::from(addr) << 1) & 1) });
348+
}
349+
Address::Ten(addr) => {
350+
let [msbs, lsbs] = addr.to_be_bytes();
351+
let msbs = ((msbs & 0b11) << 1) & 0b11110000;
352+
let dr = self.i2c.dr();
353+
if first_transaction {
354+
dr.write(|w| unsafe { w.bits(u32::from(msbs)) });
355+
dr.write(|w| unsafe { w.bits(u32::from(lsbs)) });
356+
}
357+
self.i2c.cr1().modify(|_, w| w.start().set_bit());
358+
// Wait until START condition was generated
359+
while self.i2c.sr1().read().sb().bit_is_clear() {}
360+
dr.write(|w| unsafe { w.bits(u32::from(msbs & 1)) });
361+
}
362+
}
367363

368364
// Wait until address was sent
369365
loop {
@@ -439,12 +435,22 @@ impl<I2C: Instance> I2c<I2C> {
439435
Ok(())
440436
}
441437

442-
pub fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
438+
pub fn read(&mut self, addr: impl Into<Address>, buffer: &mut [u8]) -> Result<(), Error> {
439+
self.read_inner(addr.into(), buffer, true)
440+
}
441+
442+
#[inline(always)]
443+
fn read_inner(
444+
&mut self,
445+
addr: Address,
446+
buffer: &mut [u8],
447+
first_transaction: bool,
448+
) -> Result<(), Error> {
443449
if buffer.is_empty() {
444450
return Err(Error::Overrun);
445451
}
446452

447-
self.prepare_read(addr)?;
453+
self.prepare_read(addr.into(), first_transaction)?;
448454
self.read_wo_prepare(buffer)
449455
}
450456

@@ -476,8 +482,8 @@ impl<I2C: Instance> I2c<I2C> {
476482
}
477483
}
478484

479-
pub fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
480-
self.prepare_write(addr)?;
485+
pub fn write(&mut self, addr: impl Into<Address>, bytes: &[u8]) -> Result<(), Error> {
486+
self.prepare_write(addr.into())?;
481487
self.write_wo_prepare(bytes)
482488
}
483489

@@ -499,11 +505,11 @@ impl<I2C: Instance> I2c<I2C> {
499505
Ok(())
500506
}
501507

502-
pub fn write_iter<B>(&mut self, addr: u8, bytes: B) -> Result<(), Error>
508+
pub fn write_iter<B>(&mut self, addr: impl Into<Address>, bytes: B) -> Result<(), Error>
503509
where
504510
B: IntoIterator<Item = u8>,
505511
{
506-
self.prepare_write(addr)?;
512+
self.prepare_write(addr.into())?;
507513
self.write_bytes(bytes.into_iter())?;
508514

509515
// Send a STOP condition
@@ -520,30 +526,43 @@ impl<I2C: Instance> I2c<I2C> {
520526
Ok(())
521527
}
522528

523-
pub fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
529+
pub fn write_read(
530+
&mut self,
531+
addr: impl Into<Address>,
532+
bytes: &[u8],
533+
buffer: &mut [u8],
534+
) -> Result<(), Error> {
535+
let addr = addr.into();
524536
self.prepare_write(addr)?;
525537
self.write_bytes(bytes.iter().cloned())?;
526-
self.read(addr, buffer)
538+
self.read_inner(addr, buffer, false)
527539
}
528540

529-
pub fn write_iter_read<B>(&mut self, addr: u8, bytes: B, buffer: &mut [u8]) -> Result<(), Error>
541+
pub fn write_iter_read<B>(
542+
&mut self,
543+
addr: impl Into<Address>,
544+
bytes: B,
545+
buffer: &mut [u8],
546+
) -> Result<(), Error>
530547
where
531548
B: IntoIterator<Item = u8>,
532549
{
550+
let addr = addr.into();
533551
self.prepare_write(addr)?;
534552
self.write_bytes(bytes.into_iter())?;
535-
self.read(addr, buffer)
553+
self.read_inner(addr, buffer, false)
536554
}
537555

538556
pub fn transaction<'a>(
539557
&mut self,
540-
addr: u8,
558+
addr: impl Into<Address>,
541559
mut ops: impl Iterator<Item = Hal1Operation<'a>>,
542560
) -> Result<(), Error> {
561+
let addr = addr.into();
543562
if let Some(mut prev_op) = ops.next() {
544563
// 1. Generate Start for operation
545564
match &prev_op {
546-
Hal1Operation::Read(_) => self.prepare_read(addr)?,
565+
Hal1Operation::Read(_) => self.prepare_read(addr, true)?,
547566
Hal1Operation::Write(_) => self.prepare_write(addr)?,
548567
};
549568

@@ -558,7 +577,9 @@ impl<I2C: Instance> I2c<I2C> {
558577
(Hal1Operation::Read(_), Hal1Operation::Write(_)) => {
559578
self.prepare_write(addr)?
560579
}
561-
(Hal1Operation::Write(_), Hal1Operation::Read(_)) => self.prepare_read(addr)?,
580+
(Hal1Operation::Write(_), Hal1Operation::Read(_)) => {
581+
self.prepare_read(addr, false)?
582+
}
562583
_ => {} // No changes if operation have not changed
563584
}
564585

@@ -578,19 +599,21 @@ impl<I2C: Instance> I2c<I2C> {
578599

579600
pub fn transaction_slice(
580601
&mut self,
581-
addr: u8,
602+
addr: impl Into<Address>,
582603
ops_slice: &mut [Hal1Operation<'_>],
583604
) -> Result<(), Error> {
605+
let addr = addr.into();
584606
transaction_impl!(self, addr, ops_slice, Hal1Operation);
585607
// Fallthrough is success
586608
Ok(())
587609
}
588610

589611
fn transaction_slice_hal_02(
590612
&mut self,
591-
addr: u8,
613+
addr: impl Into<Address>,
592614
ops_slice: &mut [Hal02Operation<'_>],
593615
) -> Result<(), Error> {
616+
let addr = addr.into();
594617
transaction_impl!(self, addr, ops_slice, Hal02Operation);
595618
// Fallthrough is success
596619
Ok(())
@@ -606,7 +629,7 @@ macro_rules! transaction_impl {
606629
if let Some(mut prev_op) = ops.next() {
607630
// 1. Generate Start for operation
608631
match &prev_op {
609-
$Operation::Read(_) => i2c.prepare_read(addr)?,
632+
$Operation::Read(_) => i2c.prepare_read(addr, true)?,
610633
$Operation::Write(_) => i2c.prepare_write(addr)?,
611634
};
612635

@@ -619,7 +642,7 @@ macro_rules! transaction_impl {
619642
// 3. If operation changes type we must generate new start
620643
match (&prev_op, &op) {
621644
($Operation::Read(_), $Operation::Write(_)) => i2c.prepare_write(addr)?,
622-
($Operation::Write(_), $Operation::Read(_)) => i2c.prepare_read(addr)?,
645+
($Operation::Write(_), $Operation::Read(_)) => i2c.prepare_read(addr, false)?,
623646
_ => {} // No changes if operation have not changed
624647
}
625648

@@ -635,6 +658,3 @@ macro_rules! transaction_impl {
635658
};
636659
}
637660
use transaction_impl;
638-
639-
type Hal1Operation<'a> = embedded_hal::i2c::Operation<'a>;
640-
type Hal02Operation<'a> = embedded_hal_02::blocking::i2c::Operation<'a>;

src/i2c/common.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2+
pub enum Address {
3+
Seven(u8),
4+
Ten(u16),
5+
}
6+
7+
impl From<u8> for Address {
8+
fn from(value: u8) -> Self {
9+
Self::Seven(value)
10+
}
11+
}
12+
13+
impl From<u16> for Address {
14+
fn from(value: u16) -> Self {
15+
Self::Ten(value)
16+
}
17+
}
18+
19+
pub use embedded_hal::i2c::NoAcknowledgeSource;
20+
21+
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
22+
#[non_exhaustive]
23+
pub enum Error {
24+
Overrun,
25+
NoAcknowledge(NoAcknowledgeSource),
26+
Timeout,
27+
// Note: The Bus error type is not currently returned, but is maintained for compatibility.
28+
Bus,
29+
Crc,
30+
ArbitrationLoss,
31+
}
32+
33+
impl Error {
34+
pub(crate) fn nack_addr(self) -> Self {
35+
match self {
36+
Error::NoAcknowledge(NoAcknowledgeSource::Unknown) => {
37+
Error::NoAcknowledge(NoAcknowledgeSource::Address)
38+
}
39+
e => e,
40+
}
41+
}
42+
pub(crate) fn nack_data(self) -> Self {
43+
match self {
44+
Error::NoAcknowledge(NoAcknowledgeSource::Unknown) => {
45+
Error::NoAcknowledge(NoAcknowledgeSource::Data)
46+
}
47+
e => e,
48+
}
49+
}
50+
}
51+
52+
use embedded_hal::i2c::ErrorKind;
53+
impl embedded_hal::i2c::Error for Error {
54+
fn kind(&self) -> ErrorKind {
55+
match *self {
56+
Self::Overrun => ErrorKind::Overrun,
57+
Self::Bus => ErrorKind::Bus,
58+
Self::ArbitrationLoss => ErrorKind::ArbitrationLoss,
59+
Self::NoAcknowledge(nack) => ErrorKind::NoAcknowledge(nack),
60+
Self::Crc | Self::Timeout => ErrorKind::Other,
61+
}
62+
}
63+
}
64+
65+
pub(crate) type Hal1Operation<'a> = embedded_hal::i2c::Operation<'a>;
66+
pub(crate) type Hal02Operation<'a> = embedded_hal_02::blocking::i2c::Operation<'a>;

src/i2c/hal_1.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,4 @@
1-
use embedded_hal::i2c::{Error, ErrorKind, ErrorType};
2-
3-
impl Error for super::Error {
4-
fn kind(&self) -> ErrorKind {
5-
match *self {
6-
Self::Overrun => ErrorKind::Overrun,
7-
Self::Bus => ErrorKind::Bus,
8-
Self::ArbitrationLoss => ErrorKind::ArbitrationLoss,
9-
Self::NoAcknowledge(nack) => ErrorKind::NoAcknowledge(nack),
10-
Self::Crc | Self::Timeout => ErrorKind::Other,
11-
}
12-
}
13-
}
14-
15-
impl<I2C: super::Instance> ErrorType for super::I2c<I2C> {
1+
impl<I2C: super::Instance> embedded_hal::i2c::ErrorType for super::I2c<I2C> {
162
type Error = super::Error;
173
}
184

0 commit comments

Comments
 (0)