Skip to content

Commit fbf56b0

Browse files
committed
Document the i2c module
1 parent 0d39f26 commit fbf56b0

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

src/i2c.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Safe abstractions for an I2C bus.
2+
13
use core::iter::TrustedLen;
24
use core::marker::PhantomData;
35
use embedded_hal;
@@ -8,17 +10,24 @@ use stm32f7::stm32f7x6::{
810

911
// TODO use &mut when svd2rust API has changed (modification should require &mut)
1012
//pub struct I2C<'a>(&'a mut RegisterBlock);
13+
/// Represents an I2C (Inter-Integrated Circuit) bus.
1114
pub struct I2C<'a>(&'a RegisterBlock);
1215

16+
/// Errors that can happen while accessing the I2C bus.
1317
#[derive(Debug)]
1418
pub enum Error {
19+
/// A NACK flag (negative acknowledgement) was detected.
1520
Nack,
1621
}
1722

23+
/// An I2C address.
24+
///
25+
/// Currently only 7 bit addresses are supported.
1826
#[derive(Debug, Clone, Copy)]
1927
pub struct Address(u16);
2028

2129
impl Address {
30+
/// Create a 7 bit I2C address.
2231
pub const fn bits_7(addr: u8) -> Address {
2332
Address((addr as u16) << 1)
2433
}
@@ -37,16 +46,26 @@ fn icr_clear_all(w: &mut i2c1::icr::W) -> &mut i2c1::icr::W {
3746
w
3847
}
3948

49+
/// An active connection to a device on the I2C bus.
50+
///
51+
/// Allows reading and writing the registers of the device.
4052
pub struct I2cConnection<'a, 'i: 'a, T: RegisterType> {
4153
i2c: &'a mut I2C<'i>,
4254
device_address: Address,
4355
register_type: PhantomData<T>,
4456
}
4557

58+
/// Valid register types of I2C devices.
59+
///
60+
/// This trait is implemented for the `u8` and `u16` types.
4661
pub trait RegisterType: Sized {
62+
/// Convert the register type into a byte slice and pass it to the specified closure.
4763
fn write<F>(&self, f: F) -> Result<(), Error>
4864
where
4965
F: FnOnce(&[u8]) -> Result<(), Error>;
66+
67+
/// Call the specified closure with a mutable reference to a byte slice and then convert it
68+
/// to the register type.
5069
fn read<F>(f: F) -> Result<Self, Error>
5170
where
5271
F: FnOnce(&mut [u8]) -> Result<(), Error>;
@@ -165,6 +184,7 @@ impl<'a, 'i: 'a, T: RegisterType> I2cConnection<'a, 'i, T> {
165184
self.i2c.0.icr.write(|w| icr_clear_all(w));
166185
}
167186

187+
/// Read the current value from the specified register.
168188
pub fn read(&mut self, register_address: T) -> Result<T, Error> {
169189
self.pre();
170190

@@ -173,6 +193,7 @@ impl<'a, 'i: 'a, T: RegisterType> I2cConnection<'a, 'i, T> {
173193
T::read(|val_bytes| self.read_bytes_raw(val_bytes.iter_mut()))
174194
}
175195

196+
/// Read bytes from the specified register into the specified buffer.
176197
pub fn read_bytes(&mut self, register_address: T, bytes: &mut [u8]) -> Result<(), Error> {
177198
self.pre();
178199

@@ -181,6 +202,7 @@ impl<'a, 'i: 'a, T: RegisterType> I2cConnection<'a, 'i, T> {
181202
self.read_bytes_raw(bytes.iter_mut())
182203
}
183204

205+
/// Write the specified bytes into to specified register.
184206
pub fn write(&mut self, register_address: T, value: T) -> Result<(), Error> {
185207
self.pre();
186208
register_address.write(|addr_bytes| {
@@ -192,6 +214,10 @@ impl<'a, 'i: 'a, T: RegisterType> I2cConnection<'a, 'i, T> {
192214
}
193215

194216
impl<'a> I2C<'a> {
217+
/// Connects to the specified device and run the closure `f` with the connection as argument.
218+
///
219+
/// This function takes an exclusive reference to the `I2C` type because it blocks the I2C
220+
/// bus. The connection is active until the closure `f` returns.
195221
pub fn connect<T, F>(&mut self, device_address: Address, f: F) -> Result<(), Error>
196222
where
197223
T: RegisterType,
@@ -208,6 +234,7 @@ impl<'a> I2C<'a> {
208234
self.stop()
209235
}
210236

237+
/// Stop the active connection by sending a stop symbol.
211238
pub fn stop(&mut self) -> Result<(), Error> {
212239
self.0.cr2.modify(|_, w| w.stop().set_bit());
213240

@@ -217,6 +244,7 @@ impl<'a> I2C<'a> {
217244
self.wait_for_stop()
218245
}
219246

247+
/// Update a device register.
220248
pub fn update<F>(
221249
&mut self,
222250
device_address: Address,
@@ -291,7 +319,7 @@ impl<'a> I2C<'a> {
291319
}
292320
}
293321

294-
// provokes a NACK
322+
/// Provokes a NACK and checks if the response is as expected. Panics otherwise.
295323
pub fn test_1(&mut self) {
296324
let i2c = &mut self.0;
297325

@@ -316,7 +344,7 @@ impl<'a> I2C<'a> {
316344
i2c.icr.write(|w| icr_clear_all(w));
317345
}
318346

319-
// try all addresses
347+
/// Try to access all I2C addresses. Panics on test failure.
320348
#[allow(dead_code)]
321349
pub fn test_2(&mut self) {
322350
let i2c = &mut self.0;
@@ -397,6 +425,12 @@ impl<'a> embedded_hal::blocking::i2c::WriteRead for I2C<'a> {
397425
}
398426
}
399427

428+
/// Initialize the I2C bus and return an `I2C` type.
429+
///
430+
/// The IC2 type assumes that it has ownership of the I2C buffer. Therefore it is unsafe to access
431+
/// the passed RegisterBlock as long as the I2C lives. (This function should take a
432+
/// `&mut RegisterBlock`, but this is not possible due to the API that svd2rust generates. See
433+
/// [stm32f7-discovery#72](https://github.com/embed-rs/stm32f7-discovery/issues/72) for more info.
400434
pub fn init<'a>(i2c: &'a RegisterBlock, rcc: &mut RCC) -> I2C<'a> {
401435
// enable clocks
402436
rcc.apb1enr.modify(|_, w| w.i2c3en().enabled());

0 commit comments

Comments
 (0)