Skip to content

Commit 09a7513

Browse files
phil-oppoli-obk
authored andcommitted
Store singleton directly in I2C type to take ownership
Make the I2C type generic over a new I2cTrait so that all I2C busses are suppored.
1 parent 6650509 commit 09a7513

File tree

5 files changed

+36
-32
lines changed

5 files changed

+36
-32
lines changed

src/bin/async-await.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ extern crate futures;
2121
extern crate smoltcp;
2222
extern crate spin;
2323

24-
use alloc::boxed::Box;
2524
use alloc::sync::Arc;
2625
use alloc::vec::Vec;
2726
use alloc_cortex_m::CortexMHeap;
@@ -43,6 +42,7 @@ use smoltcp::{
4342
};
4443
use stm32f7::stm32f7x6::{
4544
CorePeripherals, Interrupt, Peripherals, ETHERNET_DMA, ETHERNET_MAC, RCC, SAI2, SYSCFG,
45+
self as device,
4646
};
4747
use stm32f7_discovery::{
4848
ethernet,
@@ -135,7 +135,7 @@ fn run() -> ! {
135135
// example allocation
136136
let _xs = vec![1, 2, 3];
137137

138-
let mut i2c_3 = init::init_i2c_3(Box::leak(Box::new(peripherals.I2C3)), &mut rcc);
138+
let mut i2c_3 = init::init_i2c_3(peripherals.I2C3, &mut rcc);
139139
i2c_3.test_1();
140140
i2c_3.test_2();
141141

@@ -340,7 +340,7 @@ where
340340
F: Framebuffer,
341341
{
342342
touch_int_stream: S,
343-
i2c_3_mutex: Arc<FutureMutex<I2C<'static>>>,
343+
i2c_3_mutex: Arc<FutureMutex<I2C<device::I2C3>>>,
344344
layer_mutex: Arc<FutureMutex<Layer<F>>>,
345345
}
346346

src/bin/polling.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use smoltcp::{
3232
wire::{EthernetAddress, IpEndpoint, Ipv4Address, IpCidr},
3333
dhcp::Dhcpv4Client,
3434
};
35-
use stm32f7::stm32f7x6::{CorePeripherals, Interrupt, Peripherals};
35+
use stm32f7::stm32f7x6::{self as device, CorePeripherals, Interrupt, Peripherals};
3636
use stm32f7_discovery::{
3737
ethernet,
3838
gpio::{GpioPort, InputPin, OutputPin},
@@ -111,7 +111,7 @@ fn main() -> ! {
111111

112112
let _xs = vec![1, 2, 3];
113113

114-
let mut i2c_3 = init::init_i2c_3(&peripherals.I2C3, &mut rcc);
114+
let mut i2c_3 = init::init_i2c_3(peripherals.I2C3, &mut rcc);
115115
i2c_3.test_1();
116116
i2c_3.test_2();
117117

src/i2c.rs

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,24 @@
22
33
use core::iter::TrustedLen;
44
use core::marker::PhantomData;
5+
use core::ops::Deref;
56
use embedded_hal;
67
use stm32f7::stm32f7x6::{
7-
i2c1::{self, RegisterBlock},
8+
i2c1,
89
RCC,
10+
self as device,
911
};
1012

11-
// TODO use &mut when svd2rust API has changed (modification should require &mut)
12-
//pub struct I2C<'a>(&'a mut RegisterBlock);
13+
pub trait I2cTrait: Deref<Target = i2c1::RegisterBlock> {
14+
15+
}
16+
17+
impl I2cTrait for device::I2C1 {}
18+
impl I2cTrait for device::I2C2 {}
19+
impl I2cTrait for device::I2C3 {}
20+
1321
/// Represents an I2C (Inter-Integrated Circuit) bus.
14-
pub struct I2C<'a>(&'a RegisterBlock);
22+
pub struct I2C<I: I2cTrait>(I);
1523

1624
/// Errors that can happen while accessing the I2C bus.
1725
#[derive(Debug)]
@@ -49,8 +57,8 @@ fn icr_clear_all(w: &mut i2c1::icr::W) -> &mut i2c1::icr::W {
4957
/// An active connection to a device on the I2C bus.
5058
///
5159
/// Allows reading and writing the registers of the device.
52-
pub struct I2cConnection<'a, 'i: 'a, T: RegisterType> {
53-
i2c: &'a mut I2C<'i>,
60+
pub struct I2cConnection<'a, I: I2cTrait, T: RegisterType> {
61+
i2c: &'a mut I2C<I>,
5462
device_address: Address,
5563
register_type: PhantomData<T>,
5664
}
@@ -107,7 +115,7 @@ impl RegisterType for u16 {
107115
}
108116
}
109117

110-
impl<'a, 'i: 'a, T: RegisterType> I2cConnection<'a, 'i, T> {
118+
impl<'a, I: I2cTrait, T: RegisterType> I2cConnection<'a, I, T> {
111119
fn start(&mut self, read: bool, bytes: u8) {
112120
self.i2c.0.cr2.write(|w| {
113121
w.sadd().bits(self.device_address.0); // slave_address
@@ -213,15 +221,15 @@ impl<'a, 'i: 'a, T: RegisterType> I2cConnection<'a, 'i, T> {
213221
}
214222
}
215223

216-
impl<'a> I2C<'a> {
224+
impl<I: I2cTrait> I2C<I> {
217225
/// Connects to the specified device and run the closure `f` with the connection as argument.
218226
///
219227
/// This function takes an exclusive reference to the `I2C` type because it blocks the I2C
220228
/// bus. The connection is active until the closure `f` returns.
221229
pub fn connect<T, F>(&mut self, device_address: Address, f: F) -> Result<(), Error>
222230
where
223231
T: RegisterType,
224-
F: FnOnce(I2cConnection<T>) -> Result<(), Error>,
232+
F: FnOnce(I2cConnection<I, T>) -> Result<(), Error>,
225233
{
226234
{
227235
let conn = I2cConnection {
@@ -384,29 +392,29 @@ impl<'a> I2C<'a> {
384392
}
385393
}
386394

387-
impl<'a> embedded_hal::blocking::i2c::Read for I2C<'a> {
395+
impl<I: I2cTrait> embedded_hal::blocking::i2c::Read for I2C<I> {
388396
type Error = Error;
389397

390398
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
391399
self.connect(
392400
Address::bits_7(address),
393-
|mut connection: I2cConnection<u8>| connection.read_bytes_raw(buffer.iter_mut()),
401+
|mut connection: I2cConnection<I, u8>| connection.read_bytes_raw(buffer.iter_mut()),
394402
)
395403
}
396404
}
397405

398-
impl<'a> embedded_hal::blocking::i2c::Write for I2C<'a> {
406+
impl<I: I2cTrait> embedded_hal::blocking::i2c::Write for I2C<I> {
399407
type Error = Error;
400408

401409
fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
402410
self.connect(
403411
Address::bits_7(address),
404-
|mut connection: I2cConnection<u8>| connection.write_bytes(bytes.iter().map(|b| *b)),
412+
|mut connection: I2cConnection<I, u8>| connection.write_bytes(bytes.iter().map(|b| *b)),
405413
)
406414
}
407415
}
408416

409-
impl<'a> embedded_hal::blocking::i2c::WriteRead for I2C<'a> {
417+
impl<I: I2cTrait> embedded_hal::blocking::i2c::WriteRead for I2C<I> {
410418
type Error = Error;
411419

412420
fn write_read(
@@ -417,7 +425,7 @@ impl<'a> embedded_hal::blocking::i2c::WriteRead for I2C<'a> {
417425
) -> Result<(), Self::Error> {
418426
self.connect(
419427
Address::bits_7(address),
420-
|mut connection: I2cConnection<u8>| {
428+
|mut connection: I2cConnection<I, u8>| {
421429
connection.write_bytes(bytes.iter().map(|b| *b))?;
422430
connection.read_bytes_raw(buffer.iter_mut())
423431
},
@@ -426,12 +434,7 @@ impl<'a> embedded_hal::blocking::i2c::WriteRead for I2C<'a> {
426434
}
427435

428436
/// 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.
434-
pub fn init<'a>(i2c: &'a RegisterBlock, rcc: &mut RCC) -> I2C<'a> {
437+
pub fn init<I: I2cTrait>(i2c: I, rcc: &mut RCC) -> I2C<I> {
435438
// enable clocks
436439
rcc.apb1enr.modify(|_, w| w.i2c3en().enabled());
437440

src/init/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! Provides various hardware initialization functions.
22
3-
use crate::i2c::{self, I2C};
3+
use crate::i2c::{self, I2C, I2cTrait};
44
use crate::lcd::{self, Lcd};
55
use crate::system_clock;
6-
use stm32f7::stm32f7x6::{i2c1, FLASH, FMC, LTDC, PWR, RCC, SAI2, SYST};
6+
use stm32f7::stm32f7x6::{self as device, i2c1, FLASH, FMC, LTDC, PWR, RCC, SAI2, SYST};
77

88
pub use self::pins::init as pins;
99

@@ -298,7 +298,7 @@ pub fn init_lcd<'a>(ltdc: &'a mut LTDC, rcc: &mut RCC) -> Lcd<'a> {
298298
/// Initializes the I2C3 bus.
299299
///
300300
/// This function is equivalent to [`i2c::init`](crate::i2c::init).
301-
pub fn init_i2c_3<'a>(i2c: &'a i2c1::RegisterBlock, rcc: &mut RCC) -> I2C<'a> {
301+
pub fn init_i2c_3(i2c: device::I2C3, rcc: &mut RCC) -> I2C<device::I2C3> {
302302
i2c::init(i2c, rcc)
303303
}
304304

@@ -525,7 +525,7 @@ const WM8994_ADDRESS: i2c::Address = i2c::Address::bits_7(0b0011010);
525525
/// Initializes the WM8994 audio controller.
526526
///
527527
/// Required for audio input.
528-
pub fn init_wm8994(i2c_3: &mut i2c::I2C) -> Result<(), i2c::Error> {
528+
pub fn init_wm8994(i2c_3: &mut i2c::I2C<device::I2C3>) -> Result<(), i2c::Error> {
529529
i2c_3.connect::<u16, _>(WM8994_ADDRESS, |mut conn| {
530530
// read and check device family ID
531531
assert_eq!(conn.read(0).ok(), Some(0x8994));

src/touch.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use crate::i2c::{self, I2C};
44
use arrayvec::ArrayVec;
5+
use stm32f7::stm32f7x6 as device;
56

67
const FT5336_ADDRESS: i2c::Address = i2c::Address::bits_7(0b0111000);
78
const FT5336_FAMILY_ID_REGISTER: u8 = 0xA8;
@@ -11,7 +12,7 @@ const FT5336_STATUS_REGISTER: u8 = 0x02;
1112
const FT5336_DATA_REGISTERS: [u8; 5] = [0x03, 0x09, 0x0F, 0x15, 0x1B];
1213

1314
/// Checks the whether the device familiy ID register contains the expected value.
14-
pub fn check_family_id(i2c_3: &mut I2C) -> Result<(), i2c::Error> {
15+
pub fn check_family_id(i2c_3: &mut I2C<device::I2C3>) -> Result<(), i2c::Error> {
1516
i2c_3.connect::<u8, _>(FT5336_ADDRESS, |mut conn| {
1617
// read and check device family ID
1718
assert_eq!(conn.read(FT5336_FAMILY_ID_REGISTER).ok(), Some(0x51));
@@ -27,7 +28,7 @@ pub struct Touch {
2728
}
2829

2930
/// Returns a list of active touch points.
30-
pub fn touches(i2c_3: &mut I2C) -> Result<ArrayVec<[Touch; 5]>, i2c::Error> {
31+
pub fn touches(i2c_3: &mut I2C<device::I2C3>) -> Result<ArrayVec<[Touch; 5]>, i2c::Error> {
3132
let mut touches = ArrayVec::new();
3233
i2c_3.connect::<u8, _>(FT5336_ADDRESS, |mut conn| {
3334
let status = conn.read(FT5336_STATUS_REGISTER)?;

0 commit comments

Comments
 (0)