Skip to content

Commit 429903e

Browse files
committed
i2c: implement embedded-hal traits
1 parent 2d179f4 commit 429903e

File tree

3 files changed

+160
-127
lines changed

3 files changed

+160
-127
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ cortex-m-log = { version = "0.7", features = ["log-integration"] }
7474
cfg-if = "0.1.10"
7575
mpu6050 = "0.1.4"
7676
bme680 = "0.6.0"
77+
sh1106 = { git = "https://github.com/techmccat/sh1106.git", branch = "hal-1", version = "0.5.0" }
78+
embedded-graphics = "0.8.0"
7779
embedded-sdmmc = "0.3.0"
7880

7981
#TODO: Separate feature sets

examples/i2c.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ use hal::time::RateExtU32;
1010
use stm32g4xx_hal as hal;
1111

1212
use cortex_m_rt::entry;
13-
use log::info;
1413

1514
#[macro_use]
1615
mod utils;
16+
use utils::logger::info;
1717

1818
#[entry]
1919
fn main() -> ! {

src/i2c.rs

Lines changed: 157 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! I2C
22
use hal::blocking::i2c::{Read, Write, WriteRead};
3+
use embedded_hal_one::i2c::{ErrorKind, Operation, SevenBitAddress, TenBitAddress};
34

45
use crate::gpio::{gpioa::*, gpiob::*, gpioc::*, gpiof::*};
56
#[cfg(any(
@@ -116,15 +117,29 @@ pub trait SDAPin<I2C> {}
116117
pub trait SCLPin<I2C> {}
117118

118119
/// I2C error
120+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
119121
#[derive(Debug)]
120122
pub enum Error {
121123
Overrun,
124+
// TODO: store NACK source (address/data)
122125
Nack,
123126
PECError,
124127
BusError,
125128
ArbitrationLost,
126129
}
127130

131+
impl embedded_hal_one::i2c::Error for Error {
132+
fn kind(&self) -> embedded_hal_one::i2c::ErrorKind {
133+
match self {
134+
Self::Overrun => ErrorKind::Overrun,
135+
Self::Nack => ErrorKind::NoAcknowledge(embedded_hal_one::i2c::NoAcknowledgeSource::Unknown),
136+
Self::PECError => ErrorKind::Other,
137+
Self::BusError => ErrorKind::Bus,
138+
Self::ArbitrationLost => ErrorKind::ArbitrationLoss
139+
}
140+
}
141+
}
142+
128143
pub trait I2cExt<I2C> {
129144
fn i2c<SDA, SCL>(self, sda: SDA, scl: SCL, config: Config, rcc: &mut Rcc) -> I2c<I2C, SDA, SCL>
130145
where
@@ -252,6 +267,143 @@ macro_rules! i2c {
252267
}
253268
}
254269

270+
impl<SDA, SCL> I2c<$I2CX, SDA, SCL> {
271+
// copied from f3 hal
272+
fn read_inner(&mut self, mut addr: u16, addr_10b: bool, buffer: &mut [u8]) -> Result<(), Error> {
273+
if !addr_10b { addr <<= 1 };
274+
let end = buffer.len() / 0xFF;
275+
276+
// Process 255 bytes at a time
277+
for (i, buffer) in buffer.chunks_mut(0xFF).enumerate() {
278+
// Prepare to receive `bytes`
279+
self.i2c.cr2.modify(|_, w| {
280+
if i == 0 {
281+
w.add10().bit(addr_10b);
282+
w.sadd().bits(addr);
283+
w.rd_wrn().read();
284+
w.start().start();
285+
}
286+
w.nbytes().bits(buffer.len() as u8);
287+
if i == end {
288+
w.reload().completed().autoend().automatic()
289+
} else {
290+
w.reload().not_completed()
291+
}
292+
});
293+
294+
for byte in buffer {
295+
// Wait until we have received something
296+
busy_wait!(self.i2c, rxne, is_not_empty);
297+
*byte = self.i2c.rxdr.read().rxdata().bits();
298+
}
299+
300+
if i != end {
301+
// Wait until the last transmission is finished
302+
busy_wait!(self.i2c, tcr, is_complete);
303+
}
304+
}
305+
306+
// Wait until the last transmission is finished
307+
// auto stop is set
308+
busy_wait!(self.i2c, stopf, is_stop);
309+
Ok(self.i2c.icr.write(|w| w.stopcf().clear()))
310+
}
311+
312+
fn write_inner(&mut self, mut addr: u16, addr_10b: bool, buffer: &[u8]) -> Result<(), Error> {
313+
if !addr_10b { addr <<= 1 };
314+
let end = buffer.len() / 0xFF;
315+
316+
if buffer.is_empty() {
317+
// 0 byte write
318+
self.i2c.cr2.modify(|_, w| {
319+
w.add10().bit(addr_10b);
320+
w.sadd().bits(addr);
321+
w.rd_wrn().write();
322+
w.nbytes().bits(0);
323+
w.reload().completed();
324+
w.autoend().automatic();
325+
w.start().start()
326+
});
327+
return Ok(())
328+
}
329+
// Process 255 bytes at a time
330+
for (i, buffer) in buffer.chunks(0xFF).enumerate() {
331+
// Prepare to receive `bytes`
332+
self.i2c.cr2.modify(|_, w| {
333+
if i == 0 {
334+
w.add10().bit(addr_10b);
335+
w.sadd().bits(addr);
336+
w.rd_wrn().write();
337+
w.start().start();
338+
}
339+
w.nbytes().bits(buffer.len() as u8);
340+
if i == end {
341+
w.reload().completed().autoend().automatic()
342+
} else {
343+
w.reload().not_completed()
344+
}
345+
});
346+
347+
for byte in buffer {
348+
// Wait until we are allowed to send data
349+
// (START has been ACKed or last byte went through)
350+
busy_wait!(self.i2c, txis, is_empty);
351+
self.i2c.txdr.write(|w| w.txdata().bits(*byte));
352+
}
353+
354+
if i != end {
355+
// Wait until the last transmission is finished
356+
busy_wait!(self.i2c, tcr, is_complete);
357+
}
358+
}
359+
360+
// Wait until the last transmission is finished
361+
// auto stop is set
362+
busy_wait!(self.i2c, stopf, is_stop);
363+
Ok(self.i2c.icr.write(|w| w.stopcf().clear()))
364+
}
365+
}
366+
367+
impl<SDA, SCL> embedded_hal_one::i2c::ErrorType for I2c<$I2CX, SDA, SCL> {
368+
type Error = Error;
369+
}
370+
371+
// TODO: custom read/write/read_write impl with hardware stop logic
372+
impl<SDA, SCL> embedded_hal_one::i2c::I2c for I2c<$I2CX, SDA, SCL> {
373+
fn transaction(
374+
&mut self,
375+
address: SevenBitAddress,
376+
operation: &mut [Operation<'_>]
377+
) -> Result<(), Self::Error> {
378+
Ok(for op in operation {
379+
// Wait for any operation on the bus to finish
380+
// for example in the case of another bus master having claimed the bus
381+
while self.i2c.isr.read().busy().bit_is_set() {};
382+
match op {
383+
Operation::Read(data) => self.read_inner(address as u16, false, data)?,
384+
Operation::Write(data) => self.write_inner(address as u16, false, data)?,
385+
}
386+
})
387+
}
388+
}
389+
impl<SDA, SCL> embedded_hal_one::i2c::I2c<TenBitAddress> for I2c<$I2CX, SDA, SCL> {
390+
fn transaction(
391+
&mut self,
392+
address: TenBitAddress,
393+
operation: &mut [Operation<'_>]
394+
) -> Result<(), Self::Error> {
395+
Ok(for op in operation {
396+
// Wait for any operation on the bus to finish
397+
// for example in the case of another bus master having claimed the bus
398+
while self.i2c.isr.read().busy().bit_is_set() {};
399+
match op {
400+
Operation::Read(data) => self.read_inner(address, true, data)?,
401+
Operation::Write(data) => self.write_inner(address, true, data)?,
402+
}
403+
})
404+
}
405+
}
406+
255407
impl<SDA, SCL> WriteRead for I2c<$I2CX, SDA, SCL> {
256408
type Error = Error;
257409

@@ -261,71 +413,8 @@ macro_rules! i2c {
261413
bytes: &[u8],
262414
buffer: &mut [u8],
263415
) -> Result<(), Self::Error> {
264-
// TODO support transfers of more than 255 bytes
265-
assert!(bytes.len() < 256 && bytes.len() > 0);
266-
assert!(buffer.len() < 256 && buffer.len() > 0);
267-
268-
// Wait for any previous address sequence to end automatically.
269-
// This could be up to 50% of a bus cycle (ie. up to 0.5/freq)
270-
while self.i2c.cr2.read().start().bit_is_set() {};
271-
272-
// Set START and prepare to send `bytes`.
273-
// The START bit can be set even if the bus is BUSY or
274-
// I2C is in slave mode.
275-
self.i2c.cr2.write(|w| {
276-
w
277-
// Start transfer
278-
.start().set_bit()
279-
// Set number of bytes to transfer
280-
.nbytes().bits(bytes.len() as u8)
281-
// Set address to transfer to/from
282-
.sadd().bits((addr << 1) as u16)
283-
// 7-bit addressing mode
284-
.add10().clear_bit()
285-
// Set transfer direction to write
286-
.rd_wrn().clear_bit()
287-
// Software end mode
288-
.autoend().clear_bit()
289-
});
290-
291-
for byte in bytes {
292-
// Wait until we are allowed to send data
293-
// (START has been ACKed or last byte went through)
294-
busy_wait!(self.i2c, txis, bit_is_set);
295-
296-
// Put byte on the wire
297-
self.i2c.txdr.write(|w| { w.txdata().bits(*byte) });
298-
}
299-
300-
// Wait until the write finishes before beginning to read.
301-
busy_wait!(self.i2c, tc, bit_is_set);
302-
303-
// reSTART and prepare to receive bytes into `buffer`
304-
self.i2c.cr2.write(|w| {
305-
w
306-
// Start transfer
307-
.start().set_bit()
308-
// Set number of bytes to transfer
309-
.nbytes().bits(buffer.len() as u8)
310-
// Set address to transfer to/from
311-
.sadd().bits((addr << 1) as u16)
312-
// 7-bit addressing mode
313-
.add10().clear_bit()
314-
// Set transfer direction to read
315-
.rd_wrn().set_bit()
316-
// Automatic end mode
317-
.autoend().set_bit()
318-
});
319-
320-
for byte in buffer {
321-
// Wait until we have received something
322-
busy_wait!(self.i2c, rxne, bit_is_set);
323-
324-
*byte = self.i2c.rxdr.read().rxdata().bits();
325-
}
326-
327-
// automatic STOP
328-
416+
self.write_inner(addr as u16, false, bytes)?;
417+
self.read_inner(addr as u16, false, buffer)?;
329418
Ok(())
330419
}
331420
}
@@ -334,33 +423,7 @@ macro_rules! i2c {
334423
type Error = Error;
335424

336425
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
337-
assert!(bytes.len() < 256 && bytes.len() > 0);
338-
339-
self.i2c.cr2.modify(|_, w| {
340-
w
341-
// Start transfer
342-
.start().set_bit()
343-
// Set number of bytes to transfer
344-
.nbytes().bits(bytes.len() as u8)
345-
// Set address to transfer to/from
346-
.sadd().bits((addr << 1) as u16)
347-
// Set transfer direction to write
348-
.rd_wrn().clear_bit()
349-
// Automatic end mode
350-
.autoend().set_bit()
351-
});
352-
353-
for byte in bytes {
354-
// Wait until we are allowed to send data
355-
// (START has been ACKed or last byte when through)
356-
busy_wait!(self.i2c, txis, bit_is_set);
357-
358-
// Put byte on the wire
359-
self.i2c.txdr.write(|w| w.txdata().bits(*byte) );
360-
}
361-
362-
// automatic STOP
363-
426+
self.write_inner(addr as u16, false, bytes)?;
364427
Ok(())
365428
}
366429
}
@@ -369,43 +432,11 @@ macro_rules! i2c {
369432
type Error = Error;
370433

371434
fn read(&mut self, addr: u8, bytes: &mut [u8]) -> Result<(), Self::Error> {
372-
// TODO support transfers of more than 255 bytes
373-
assert!(bytes.len() < 256 && bytes.len() > 0);
374-
375-
// Wait for any previous address sequence to end automatically.
376-
// This could be up to 50% of a bus cycle (ie. up to 0.5/freq)
377-
while self.i2c.cr2.read().start().bit_is_set() {};
378-
379-
// Set START and prepare to receive bytes into `buffer`.
380-
// The START bit can be set even if the bus
381-
// is BUSY or I2C is in slave mode.
382-
self.i2c.cr2.modify(|_, w| {
383-
w
384-
// Start transfer
385-
.start().set_bit()
386-
// Set number of bytes to transfer
387-
.nbytes().bits(bytes.len() as u8)
388-
// Set address to transfer to/from
389-
.sadd().bits((addr << 1) as u16)
390-
// Set transfer direction to read
391-
.rd_wrn().set_bit()
392-
// automatic end mode
393-
.autoend().set_bit()
394-
});
395-
396-
for byte in bytes {
397-
// Wait until we have received something
398-
busy_wait!(self.i2c, rxne, bit_is_set);
399-
400-
*byte = self.i2c.rxdr.read().rxdata().bits();
401-
}
402-
403-
// automatic STOP
404-
435+
self.read_inner(addr as u16, false, bytes)?;
405436
Ok(())
406437
}
407438
}
408-
};
439+
}
409440
}
410441

411442
i2c!(

0 commit comments

Comments
 (0)