Skip to content
This repository was archived by the owner on Aug 9, 2022. It is now read-only.

Commit e978d80

Browse files
committed
refactor to support multiple devices on one i2c line
1 parent 27bf6e6 commit e978d80

File tree

2 files changed

+90
-125
lines changed

2 files changed

+90
-125
lines changed

examples/i2c.rs

Lines changed: 84 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,32 @@
11
#![no_std]
22
#![no_main]
33

4-
use esp32_hal as hal;
5-
6-
use {
7-
core::panic::PanicInfo,
8-
embedded_graphics::{
9-
fonts::{Font8x16, Text},
10-
pixelcolor::BinaryColor,
11-
prelude::*,
12-
style::TextStyle,
13-
},
14-
hal::{
15-
clock_control::{self, sleep, CPUSource, ClockControl, ClockControlConfig},
16-
dport::Split,
17-
dprintln, i2c,
18-
prelude::*,
19-
timer::Timer,
20-
},
21-
// mpu6050::Mpu6050,
22-
ssd1306::{prelude::*, Builder},
4+
use core::panic::PanicInfo;
5+
use embedded_graphics::{
6+
fonts::{Font8x16, Text},
7+
pixelcolor::BinaryColor,
8+
prelude::*,
9+
style::TextStyle,
2310
};
11+
use embedded_hal::blocking::i2c::{Write, WriteRead};
12+
use esp32_hal::{
13+
clock_control::{self, sleep, CPUSource, ClockControl},
14+
delay::Delay,
15+
dport::Split,
16+
dprintln,
17+
interrupt::{self, Interrupt},
18+
i2c::{self, Error, I2C},
19+
prelude::*,
20+
target::{I2C0, Peripherals},
21+
timer::Timer,
22+
};
23+
use mpu6050::Mpu6050;
24+
use ssd1306::{prelude::*, Builder};
25+
use xtensa_lx::mutex::SpinLockMutex;
2426

2527
#[entry]
2628
fn main() -> ! {
27-
let dp = esp32::Peripherals::take().unwrap();
29+
let dp = Peripherals::take().unwrap();
2830

2931
let (mut dport, dport_clock_control) = dp.DPORT.split();
3032

@@ -58,102 +60,101 @@ fn main() -> ! {
5860
let (.., mut watchdog1) = Timer::new(dp.TIMG1, clkcntrl_config);
5961
watchdog0.disable();
6062
watchdog1.disable();
63+
dprintln!("Watchdogs disabled");
64+
sleep(2.s());
65+
66+
interrupt::enable(Interrupt::I2C_EXT0_INTR).unwrap();
6167

6268
let pins = dp.GPIO.split();
69+
let i2c0 = i2c::I2C::new(
70+
dp.I2C0,
71+
i2c::Pins {
72+
sda: pins.gpio4,
73+
scl: pins.gpio15,
74+
},
75+
400_000,
76+
&mut dport,
77+
);
78+
let i2c0 = SpinLockMutex::new(i2c0);
6379

6480
// Display
6581
let mut display = {
66-
let i2c0 = i2c::I2C::new(
67-
dp.I2C0,
68-
i2c::Pins {
69-
sda: pins.gpio4,
70-
scl: pins.gpio15,
71-
},
72-
400_000,
73-
&mut dport,
74-
);
75-
76-
let mut display: GraphicsMode<_> = Builder::new().connect_i2c(i2c0).into();
82+
let i2c_wrapper = I2CWrapper::new(&i2c0);
83+
let mut display: GraphicsMode<_> = Builder::new().connect_i2c(i2c_wrapper).into();
7784

7885
let mut rst = pins.gpio16.into_push_pull_output();
7986
rst.set_low().unwrap();
8087
sleep(10.ms());
8188
rst.set_high().unwrap();
8289

90+
dprintln!("starting display init");
8391
display.init().unwrap();
92+
dprintln!("finished display init");
8493
display.clear();
8594
display.flush().unwrap();
8695

8796
display
8897
};
98+
dprintln!("Set up display");
8999

90-
/*// IMU
100+
// IMU
91101
let mut imu = {
92-
let i2c1 = i2c::I2C::new(
93-
dp.I2C1,
94-
i2c::Pins {
95-
sda: pins.gpio22,
96-
scl: pins.gpio23,
97-
},
98-
200_000,
99-
&mut dport,
100-
);
101-
102-
let mut imu = Mpu6050::new(i2c1, Delay);
103-
104-
imu.verify().unwrap();
105-
106-
imu.init().unwrap();
107-
imu.soft_calib(mpu6050::Steps(100)).unwrap();
108-
imu.calc_variance(mpu6050::Steps(50)).unwrap();
102+
let i2c_wrapper = I2CWrapper::new(&i2c0);
103+
let mut imu = Mpu6050::new(i2c_wrapper);
109104

105+
let mut delay = Delay::new();
106+
imu.init(&mut delay).unwrap();
110107
imu
111108
};
112-
113-
let temp = imu.get_temp().unwrap();
114-
let gyro = imu.get_gyro().unwrap();
115-
let acc = imu.get_acc().unwrap();
116-
dprintln!("temp: {}, gyro: {:?}, acc: {:?}", temp, gyro, acc);*/
117-
118-
// let mut sensor = {
119-
// let i2c1 = i2c::I2C::new(
120-
// dp.I2C1,
121-
// i2c::Pins {
122-
// sda: pins.gpio22,
123-
// scl: pins.gpio23,
124-
// },
125-
// 200_000,
126-
// &mut dport,
127-
// );
128-
//
129-
// let mut sensor = sgp30::Sgp30::new(i2c1, 0x58, Delay);
130-
//
131-
// dprintln!("serial: {:?}", sensor.serial().unwrap());
132-
//
133-
// sensor
134-
// };
109+
dprintln!("Set up IMU");
135110

136111
Text::new("Hello world!", Point::new(2, 28))
137112
.into_styled(TextStyle::new(Font8x16, BinaryColor::On))
138113
.draw(&mut display)
139114
.unwrap();
140115
display.flush().unwrap();
141-
loop {}
116+
dprintln!("Wrote to display");
117+
118+
sleep(3.s());
119+
120+
loop {
121+
let temp = imu.get_temp().unwrap();
122+
let gyro = imu.get_gyro().unwrap();
123+
let acc = imu.get_acc().unwrap();
124+
dprintln!("temp: {}, gyro: {:?}, acc: {:?}", temp, gyro, acc);
125+
sleep(1.s());
126+
}
142127
}
143128

144-
#[panic_handler]
145-
fn panic(info: &PanicInfo) -> ! {
146-
// park the other core
147-
unsafe { ClockControlConfig {}.park_core(esp32_hal::get_other_core()) };
129+
struct I2CWrapper<'a> {
130+
i2c: &'a SpinLockMutex<I2C<I2C0>>,
131+
}
148132

149-
// print panic message
150-
dprintln!("\n\n*** {:?}", info);
133+
impl<'a> I2CWrapper<'a> {
134+
fn new(i2c: &'a SpinLockMutex<I2C<I2C0>>) -> Self {
135+
Self { i2c }
136+
}
137+
}
151138

152-
// park this core
153-
unsafe { ClockControlConfig {}.park_core(esp32_hal::get_core()) };
139+
impl<'a> Write for I2CWrapper<'a> {
140+
type Error = Error;
141+
142+
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
143+
self.i2c.lock(|x| x.write(addr, bytes))
144+
}
145+
}
154146

155-
dprintln!("Not reached because core is parked.");
147+
impl<'a> WriteRead for I2CWrapper<'a> {
148+
type Error = Error;
156149

157-
// this statement will not be reached, but is needed to make this a diverging function
150+
fn write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
151+
self.i2c.lock(|x| x.write_read(address, bytes, buffer))
152+
}
153+
}
154+
155+
#[panic_handler]
156+
fn panic(info: &PanicInfo) -> ! {
157+
dprintln!("----- PANIC -----");
158+
dprintln!("{:?}", info);
158159
loop {}
159160
}

src/i2c.rs

Lines changed: 6 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
1-
use {
2-
crate::{
3-
dflush,
4-
dprintln,
5-
gpio::{InputPin, InputSignal, OutputPin, OutputSignal},
6-
target::{i2c, DPORT, I2C0, I2C1},
7-
},
8-
core::{ops::Deref, ptr},
9-
};
1+
use crate::gpio::{InputPin, InputSignal, OutputPin, OutputSignal};
2+
use crate::target::{i2c, DPORT, I2C0, I2C1};
3+
use core::{ops::Deref, ptr};
104

115
const DPORT_BASE_ADDR: u32 = 0x3FF4_0000;
126
const AHB_BASE_ADDR: u32 = 0x6000_0000;
@@ -20,7 +14,6 @@ const DPORT_I2C1_ADDR: u32 = DPORT_BASE_ADDR + I2C1_OFFSET;
2014
const AHB_I2C0_ADDR: u32 = AHB_BASE_ADDR + I2C0_OFFSET;
2115
const AHB_I2C1_ADDR: u32 = AHB_BASE_ADDR + I2C1_OFFSET;
2216

23-
2417
pub struct I2C<T>(T);
2518

2619
impl<T> I2C<T>
@@ -234,7 +227,6 @@ where
234227

235228
// TODO: Enable ACK checks and return error if ACK check fails
236229
pub fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
237-
dprintln!("starting write");
238230
// Reset FIFO
239231
self.reset_fifo();
240232

@@ -279,19 +271,14 @@ where
279271

280272
// Busy wait for all three commands to be marked as done
281273
while self.0.comd0.read().command0_done().bit() != true {}
282-
dprintln!("start done");
283274
while self.0.comd1.read().command1_done().bit() != true {}
284-
dprintln!("write done");
285275
while self.0.comd2.read().command2_done().bit() != true {}
286-
dprintln!("stop done");
287276

288277
Ok(())
289278
}
290279

291280
// TODO: Enable ACK checks and return error if ACK check fails
292281
pub fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
293-
dprintln!("starting I2C read");
294-
295282
// Reset FIFO
296283
self.reset_fifo();
297284

@@ -352,51 +339,35 @@ where
352339
// Start transmission
353340
self.0.ctr.modify(|_, w| w.trans_start().set_bit());
354341

355-
// Busy wait for all three commands to be marked as done
342+
// Busy wait for all commands to be marked as done
356343
while self.0.comd0.read().command0_done().bit() != true {}
357344
while self.0.comd1.read().command1_done().bit() != true {}
358-
dprintln!("write addr done");
359345

360346
if buffer.len() > 1 {
361347
while self.0.comd2.read().command2_done().bit() != true {}
362-
dprintln!("read bytes [..^1] done");
363-
dflush!();
364348
while self.0.comd3.read().command3_done().bit() != true {}
365-
dprintln!("read bytes [^1] done");
366-
dflush!();
367349
while self.0.comd4.read().command4_done().bit() != true {}
368-
dprintln!("stop done");
369-
dflush!();
370350
} else {
371351
while self.0.comd2.read().command2_done().bit() != true {}
372-
dprintln!("read byte done");
373-
dflush!();
374352
while self.0.comd3.read().command3_done().bit() != true {}
375-
dprintln!("stop done");
376-
dflush!();
377353
}
378354

379355

380356
// Read bytes from FIFO
381-
dprintln!("rxfifo: {:?}", self.0.sr.read().rxfifo_cnt().bits());
382-
dflush!();
383357
for byte in buffer.iter_mut() {
384358
*byte = unsafe { ptr::read_volatile(fifo_addr) };
385359
}
386-
dprintln!("{:x?}", &buffer);
387-
dflush!();
388360

389361
Ok(())
390362
}
391363

392364
// TODO: Enable ACK checks and return error if ACK check fails
393-
pub fn write_then_read(
365+
pub fn write_read(
394366
&mut self,
395367
addr: u8,
396368
bytes: &[u8],
397369
buffer: &mut [u8],
398370
) -> Result<(), Error> {
399-
dprintln!("starting write then read");
400371
// Reset FIFO
401372
self.reset_fifo();
402373

@@ -484,20 +455,13 @@ where
484455

485456
// Busy wait for all commands to be marked as done
486457
while self.0.comd0.read().command0_done().bit() != true {}
487-
dprintln!("comd0");
488458
while self.0.comd1.read().command1_done().bit() != true {}
489-
dprintln!("comd1");
490459
while self.0.comd2.read().command2_done().bit() != true {}
491-
dprintln!("comd2");
492460
while self.0.comd3.read().command3_done().bit() != true {}
493-
dprintln!("comd3");
494461
while self.0.comd4.read().command4_done().bit() != true {}
495-
dprintln!("comd4");
496462
while self.0.comd5.read().command5_done().bit() != true {}
497-
dprintln!("comd5");
498463
if buffer.len() > 1 {
499464
while self.0.comd6.read().command6_done().bit() != true {}
500-
dprintln!("comd6");
501465
}
502466

503467
// read bytes from FIFO
@@ -551,7 +515,7 @@ where
551515
bytes: &'w [u8],
552516
buffer: &'w mut [u8],
553517
) -> Result<(), Error> {
554-
self.write_then_read(addr, bytes, buffer)
518+
self.write_read(addr, bytes, buffer)
555519
}
556520
}
557521

0 commit comments

Comments
 (0)