aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/i2c/mod.rs85
-rw-r--r--embassy-stm32/src/i2c/v2.rs307
2 files changed, 339 insertions, 53 deletions
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index daf7e31e8..2c42ec0e9 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -1,9 +1,11 @@
1#![macro_use] 1#![macro_use]
2 2
3use embassy::interrupt::Interrupt;
4
3#[cfg_attr(i2c_v1, path = "v1.rs")] 5#[cfg_attr(i2c_v1, path = "v1.rs")]
4#[cfg_attr(i2c_v2, path = "v2.rs")] 6#[cfg_attr(i2c_v2, path = "v2.rs")]
5mod _version; 7mod _version;
6use crate::peripherals; 8use crate::{dma, peripherals};
7pub use _version::*; 9pub use _version::*;
8 10
9#[cfg_attr(feature = "defmt", derive(defmt::Format))] 11#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -18,11 +20,14 @@ pub enum Error {
18} 20}
19 21
20pub(crate) mod sealed { 22pub(crate) mod sealed {
23 use super::dma;
21 use crate::gpio::Pin; 24 use crate::gpio::Pin;
22 use crate::rcc::RccPeripheral; 25 use crate::rcc::RccPeripheral;
23 26
24 pub trait Instance: RccPeripheral { 27 pub trait Instance: RccPeripheral {
25 fn regs() -> &'static crate::pac::i2c::I2c; 28 fn regs() -> &'static crate::pac::i2c::I2c;
29
30 fn state_number() -> usize;
26 } 31 }
27 32
28 pub trait SclPin<T: Instance>: Pin { 33 pub trait SclPin<T: Instance>: Pin {
@@ -32,23 +37,61 @@ pub(crate) mod sealed {
32 pub trait SdaPin<T: Instance>: Pin { 37 pub trait SdaPin<T: Instance>: Pin {
33 fn af_num(&self) -> u8; 38 fn af_num(&self) -> u8;
34 } 39 }
40
41 pub trait RxDma<T: Instance> {
42 fn request(&self) -> dma::Request;
43 }
44
45 pub trait TxDma<T: Instance> {
46 fn request(&self) -> dma::Request;
47 }
35} 48}
36 49
37pub trait Instance: sealed::Instance + 'static {} 50pub trait Instance: sealed::Instance + 'static {
51 type Interrupt: Interrupt;
52}
38 53
39pub trait SclPin<T: Instance>: sealed::SclPin<T> + 'static {} 54pub trait SclPin<T: Instance>: sealed::SclPin<T> + 'static {}
40 55
41pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + 'static {} 56pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + 'static {}
42 57
58pub trait RxDma<T: Instance>: sealed::RxDma<T> + dma::Channel {}
59
60pub trait TxDma<T: Instance>: sealed::TxDma<T> + dma::Channel {}
61
62macro_rules! i2c_state {
63 (I2C1) => {
64 0
65 };
66 (I2C2) => {
67 1
68 };
69 (I2C3) => {
70 2
71 };
72 (I2C4) => {
73 3
74 };
75 (I2C5) => {
76 4
77 };
78}
79
43crate::pac::peripherals!( 80crate::pac::peripherals!(
44 (i2c, $inst:ident) => { 81 (i2c, $inst:ident) => {
45 impl sealed::Instance for peripherals::$inst { 82 impl sealed::Instance for peripherals::$inst {
46 fn regs() -> &'static crate::pac::i2c::I2c { 83 fn regs() -> &'static crate::pac::i2c::I2c {
47 &crate::pac::$inst 84 &crate::pac::$inst
48 } 85 }
86
87 fn state_number() -> usize {
88 i2c_state!($inst)
89 }
49 } 90 }
50 91
51 impl Instance for peripherals::$inst {} 92 impl Instance for peripherals::$inst {
93 type Interrupt = crate::interrupt::$inst;
94 }
52 95
53 }; 96 };
54); 97);
@@ -74,3 +117,39 @@ crate::pac::peripheral_pins!(
74 impl_pin!($inst, $pin, SclPin, $af); 117 impl_pin!($inst, $pin, SclPin, $af);
75 }; 118 };
76); 119);
120
121macro_rules! impl_dma {
122 ($inst:ident, {dmamux: $dmamux:ident}, $signal:ident, $request:expr) => {
123 impl<T> sealed::$signal<peripherals::$inst> for T
124 where
125 T: crate::dma::MuxChannel<Mux = crate::dma::$dmamux>,
126 {
127 fn request(&self) -> dma::Request {
128 $request
129 }
130 }
131
132 impl<T> $signal<peripherals::$inst> for T where
133 T: crate::dma::MuxChannel<Mux = crate::dma::$dmamux>
134 {
135 }
136 };
137 ($inst:ident, {channel: $channel:ident}, $signal:ident, $request:expr) => {
138 impl sealed::$signal<peripherals::$inst> for peripherals::$channel {
139 fn request(&self) -> dma::Request {
140 $request
141 }
142 }
143
144 impl $signal<peripherals::$inst> for peripherals::$channel {}
145 };
146}
147
148crate::pac::peripheral_dma_channels! {
149 ($peri:ident, i2c, $kind:ident, RX, $channel:tt, $request:expr) => {
150 impl_dma!($peri, $channel, RxDma, $request);
151 };
152 ($peri:ident, i2c, $kind:ident, TX, $channel:tt, $request:expr) => {
153 impl_dma!($peri, $channel, TxDma, $request);
154 };
155}
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 9f7206107..9a1513cf1 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -1,32 +1,66 @@
1use core::cmp; 1use core::cmp;
2use core::marker::PhantomData; 2use core::marker::PhantomData;
3use embassy::util::Unborrow; 3use core::task::Poll;
4use embassy_hal_common::unborrow; 4
5use atomic_polyfill::{AtomicUsize, Ordering};
6use embassy::interrupt::InterruptExt;
7use embassy::util::{AtomicWaker, OnDrop, Unborrow};
8use embassy_extras::unborrow;
5use embedded_hal::blocking::i2c::Read; 9use embedded_hal::blocking::i2c::Read;
6use embedded_hal::blocking::i2c::Write; 10use embedded_hal::blocking::i2c::Write;
7use embedded_hal::blocking::i2c::WriteRead; 11use embedded_hal::blocking::i2c::WriteRead;
12use futures::future::poll_fn;
8 13
14use crate::dma::NoDma;
9use crate::i2c::{Error, Instance, SclPin, SdaPin}; 15use crate::i2c::{Error, Instance, SclPin, SdaPin};
16use crate::pac;
10use crate::pac::gpio::vals::{Afr, Moder, Ot}; 17use crate::pac::gpio::vals::{Afr, Moder, Ot};
11use crate::pac::gpio::Gpio; 18use crate::pac::gpio::Gpio;
12use crate::pac::i2c; 19use crate::pac::i2c;
13use crate::time::Hertz; 20use crate::time::Hertz;
14 21
15pub struct I2c<'d, T: Instance> { 22const I2C_COUNT: usize = pac::peripheral_count!(i2c);
23
24pub struct State {
25 waker: [AtomicWaker; I2C_COUNT],
26 chunks_transferred: [AtomicUsize; I2C_COUNT],
27}
28
29impl State {
30 const fn new() -> Self {
31 const AW: AtomicWaker = AtomicWaker::new();
32 const CT: AtomicUsize = AtomicUsize::new(0);
33
34 Self {
35 waker: [AW; I2C_COUNT],
36 chunks_transferred: [CT; I2C_COUNT],
37 }
38 }
39}
40
41static STATE: State = State::new();
42
43pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
16 phantom: PhantomData<&'d mut T>, 44 phantom: PhantomData<&'d mut T>,
45 tx_dma: TXDMA,
46 #[allow(dead_code)]
47 rx_dma: RXDMA,
17} 48}
18 49
19impl<'d, T: Instance> I2c<'d, T> { 50impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
20 pub fn new<F>( 51 pub fn new<F>(
21 _peri: impl Unborrow<Target = T> + 'd, 52 _peri: impl Unborrow<Target = T> + 'd,
22 scl: impl Unborrow<Target = impl SclPin<T>>, 53 scl: impl Unborrow<Target = impl SclPin<T>> + 'd,
23 sda: impl Unborrow<Target = impl SdaPin<T>>, 54 sda: impl Unborrow<Target = impl SdaPin<T>> + 'd,
55 irq: impl Unborrow<Target = T::Interrupt> + 'd,
56 tx_dma: impl Unborrow<Target = TXDMA> + 'd,
57 rx_dma: impl Unborrow<Target = RXDMA> + 'd,
24 freq: F, 58 freq: F,
25 ) -> Self 59 ) -> Self
26 where 60 where
27 F: Into<Hertz>, 61 F: Into<Hertz>,
28 { 62 {
29 unborrow!(scl, sda); 63 unborrow!(irq, scl, sda, tx_dma, rx_dma);
30 64
31 T::enable(); 65 T::enable();
32 66
@@ -60,9 +94,31 @@ impl<'d, T: Instance> I2c<'d, T> {
60 }); 94 });
61 } 95 }
62 96
97 irq.set_handler(Self::on_interrupt);
98 irq.unpend();
99 irq.enable();
100
63 Self { 101 Self {
64 phantom: PhantomData, 102 phantom: PhantomData,
103 tx_dma,
104 rx_dma,
105 }
106 }
107
108 unsafe fn on_interrupt(_: *mut ()) {
109 let regs = T::regs();
110 let isr = regs.isr().read();
111
112 if isr.tcr() || isr.tc() {
113 let n = T::state_number();
114 STATE.chunks_transferred[n].fetch_add(1, Ordering::Relaxed);
115 STATE.waker[n].wake();
65 } 116 }
117 // The flag can only be cleared by writting to nbytes, we won't do that here, so disable
118 // the interrupt
119 critical_section::with(|_| {
120 regs.cr1().modify(|w| w.set_tcie(false));
121 });
66 } 122 }
67 123
68 unsafe fn configure_pin(block: Gpio, pin: usize, af_num: u8) { 124 unsafe fn configure_pin(block: Gpio, pin: usize, af_num: u8) {
@@ -114,13 +170,13 @@ impl<'d, T: Instance> I2c<'d, T> {
114 } 170 }
115 } 171 }
116 172
117 fn master_write(&mut self, address: u8, length: usize, stop: Stop, reload: bool) { 173 unsafe fn master_write(address: u8, length: usize, stop: Stop, reload: bool) {
118 assert!(length < 256 && length > 0); 174 assert!(length < 256 && length > 0);
119 175
120 // Wait for any previous address sequence to end 176 // Wait for any previous address sequence to end
121 // automatically. This could be up to 50% of a bus 177 // automatically. This could be up to 50% of a bus
122 // cycle (ie. up to 0.5/freq) 178 // cycle (ie. up to 0.5/freq)
123 while unsafe { T::regs().cr2().read().start() == i2c::vals::Start::START } {} 179 while T::regs().cr2().read().start() == i2c::vals::Start::START {}
124 180
125 let reload = if reload { 181 let reload = if reload {
126 i2c::vals::Reload::NOTCOMPLETED 182 i2c::vals::Reload::NOTCOMPLETED
@@ -131,23 +187,21 @@ impl<'d, T: Instance> I2c<'d, T> {
131 // Set START and prepare to send `bytes`. The 187 // Set START and prepare to send `bytes`. The
132 // START bit can be set even if the bus is BUSY or 188 // START bit can be set even if the bus is BUSY or
133 // I2C is in slave mode. 189 // I2C is in slave mode.
134 unsafe { 190 T::regs().cr2().modify(|w| {
135 T::regs().cr2().modify(|w| { 191 w.set_sadd((address << 1 | 0) as u16);
136 w.set_sadd((address << 1 | 0) as u16); 192 w.set_add10(i2c::vals::Add::BIT7);
137 w.set_add10(i2c::vals::Add::BIT7); 193 w.set_rd_wrn(i2c::vals::RdWrn::WRITE);
138 w.set_rd_wrn(i2c::vals::RdWrn::WRITE); 194 w.set_nbytes(length as u8);
139 w.set_nbytes(length as u8); 195 w.set_start(i2c::vals::Start::START);
140 w.set_start(i2c::vals::Start::START); 196 w.set_autoend(stop.autoend());
141 w.set_autoend(stop.autoend()); 197 w.set_reload(reload);
142 w.set_reload(reload); 198 });
143 });
144 }
145 } 199 }
146 200
147 fn master_continue(&mut self, length: usize, reload: bool) { 201 unsafe fn master_continue(length: usize, reload: bool) {
148 assert!(length < 256 && length > 0); 202 assert!(length < 256 && length > 0);
149 203
150 while unsafe { !T::regs().isr().read().tcr() } {} 204 while !T::regs().isr().read().tcr() {}
151 205
152 let reload = if reload { 206 let reload = if reload {
153 i2c::vals::Reload::NOTCOMPLETED 207 i2c::vals::Reload::NOTCOMPLETED
@@ -155,12 +209,10 @@ impl<'d, T: Instance> I2c<'d, T> {
155 i2c::vals::Reload::COMPLETED 209 i2c::vals::Reload::COMPLETED
156 }; 210 };
157 211
158 unsafe { 212 T::regs().cr2().modify(|w| {
159 T::regs().cr2().modify(|w| { 213 w.set_nbytes(length as u8);
160 w.set_nbytes(length as u8); 214 w.set_reload(reload);
161 w.set_reload(reload); 215 });
162 });
163 }
164 } 216 }
165 217
166 fn flush_txdr(&self) { 218 fn flush_txdr(&self) {
@@ -265,7 +317,10 @@ impl<'d, T: Instance> I2c<'d, T> {
265 317
266 for (number, chunk) in buffer.chunks_mut(255).enumerate() { 318 for (number, chunk) in buffer.chunks_mut(255).enumerate() {
267 if number != 0 { 319 if number != 0 {
268 self.master_continue(chunk.len(), number != last_chunk_idx); 320 // NOTE(unsafe) We have &mut self
321 unsafe {
322 Self::master_continue(chunk.len(), number != last_chunk_idx);
323 }
269 } 324 }
270 325
271 for byte in chunk { 326 for byte in chunk {
@@ -292,16 +347,22 @@ impl<'d, T: Instance> I2c<'d, T> {
292 // I2C start 347 // I2C start
293 // 348 //
294 // ST SAD+W 349 // ST SAD+W
295 self.master_write( 350 // NOTE(unsafe) We have &mut self
296 address, 351 unsafe {
297 bytes.len().min(255), 352 Self::master_write(
298 Stop::Software, 353 address,
299 last_chunk_idx != 0, 354 bytes.len().min(255),
300 ); 355 Stop::Software,
356 last_chunk_idx != 0,
357 );
358 }
301 359
302 for (number, chunk) in bytes.chunks(255).enumerate() { 360 for (number, chunk) in bytes.chunks(255).enumerate() {
303 if number != 0 { 361 if number != 0 {
304 self.master_continue(chunk.len(), number != last_chunk_idx); 362 // NOTE(unsafe) We have &mut self
363 unsafe {
364 Self::master_continue(chunk.len(), number != last_chunk_idx);
365 }
305 } 366 }
306 367
307 for byte in chunk { 368 for byte in chunk {
@@ -324,6 +385,143 @@ impl<'d, T: Instance> I2c<'d, T> {
324 Ok(()) 385 Ok(())
325 } 386 }
326 387
388 async fn write_dma_internal(
389 &mut self,
390 address: u8,
391 bytes: &[u8],
392 first_slice: bool,
393 last_slice: bool,
394 next_slice_len: usize,
395 next_is_last: bool,
396 ) -> Result<(), Error>
397 where
398 TXDMA: crate::i2c::TxDma<T>,
399 {
400 let total_len = bytes.len();
401 let completed_chunks = total_len / 255;
402 let total_chunks = if completed_chunks * 255 == total_len {
403 completed_chunks
404 } else {
405 completed_chunks + 1
406 };
407
408 let dma_transfer = unsafe {
409 let regs = T::regs();
410 regs.cr1().modify(|w| {
411 w.set_txdmaen(true);
412 w.set_tcie(true);
413 });
414 let dst = regs.txdr().ptr() as *mut u8;
415
416 let ch = &mut self.tx_dma;
417 ch.write(ch.request(), bytes, dst)
418 };
419
420 let state_number = T::state_number();
421 STATE.chunks_transferred[state_number].store(0, Ordering::Relaxed);
422 let mut remaining_len = total_len;
423
424 let _on_drop = OnDrop::new(|| {
425 let regs = T::regs();
426 unsafe {
427 regs.cr1().modify(|w| {
428 if last_slice {
429 w.set_txdmaen(false);
430 }
431 w.set_tcie(false);
432 })
433 }
434 });
435
436 // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers
437 if first_slice {
438 unsafe {
439 Self::master_write(
440 address,
441 total_len.min(255),
442 Stop::Software,
443 (total_chunks != 1) || !last_slice,
444 );
445 }
446 }
447
448 poll_fn(|cx| {
449 STATE.waker[state_number].register(cx.waker());
450 let chunks_transferred = STATE.chunks_transferred[state_number].load(Ordering::Relaxed);
451
452 if chunks_transferred == total_chunks {
453 if !last_slice {
454 // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers
455 unsafe {
456 Self::master_continue(
457 next_slice_len.min(255),
458 (next_slice_len > 255) || !next_is_last,
459 );
460 T::regs().cr1().modify(|w| w.set_tcie(true));
461 }
462 }
463
464 return Poll::Ready(());
465 } else if chunks_transferred != 0 {
466 remaining_len = remaining_len.saturating_sub(255);
467 let last_piece = (chunks_transferred + 1 == total_chunks) && last_slice;
468
469 // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers
470 unsafe {
471 Self::master_continue(remaining_len.min(255), !last_piece);
472 T::regs().cr1().modify(|w| w.set_tcie(true));
473 }
474 }
475 Poll::Pending
476 })
477 .await;
478
479 dma_transfer.await;
480
481 if last_slice {
482 // This should be done already
483 self.wait_tc()?;
484 self.master_stop();
485 }
486 Ok(())
487 }
488
489 pub async fn write_dma(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error>
490 where
491 TXDMA: crate::i2c::TxDma<T>,
492 {
493 self.write_dma_internal(address, bytes, true, true, 0, true)
494 .await
495 }
496
497 pub async fn write_dma_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error>
498 where
499 TXDMA: crate::i2c::TxDma<T>,
500 {
501 if bytes.is_empty() {
502 return Err(Error::ZeroLengthTransfer);
503 }
504 let mut iter = bytes.iter().peekable();
505
506 let mut first = true;
507 let mut current = iter.next();
508 while let Some(c) = current {
509 let next = iter.next();
510 let (next_len, is_last) = if let Some(next) = next {
511 (next.len(), false)
512 } else {
513 (0, true)
514 };
515 let next_is_last = iter.peek().is_none();
516
517 self.write_dma_internal(address, c, first, is_last, next_len, next_is_last)
518 .await?;
519 first = false;
520 current = next;
521 }
522 Ok(())
523 }
524
327 pub fn write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> { 525 pub fn write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> {
328 if bytes.is_empty() { 526 if bytes.is_empty() {
329 return Err(Error::ZeroLengthTransfer); 527 return Err(Error::ZeroLengthTransfer);
@@ -331,12 +529,15 @@ impl<'d, T: Instance> I2c<'d, T> {
331 let first_length = bytes[0].len(); 529 let first_length = bytes[0].len();
332 let last_slice_index = bytes.len() - 1; 530 let last_slice_index = bytes.len() - 1;
333 531
334 self.master_write( 532 // NOTE(unsafe) We have &mut self
335 address, 533 unsafe {
336 first_length.min(255), 534 Self::master_write(
337 Stop::Software, 535 address,
338 (first_length > 255) || (last_slice_index != 0), 536 first_length.min(255),
339 ); 537 Stop::Software,
538 (first_length > 255) || (last_slice_index != 0),
539 );
540 }
340 541
341 for (idx, slice) in bytes.iter().enumerate() { 542 for (idx, slice) in bytes.iter().enumerate() {
342 let slice_len = slice.len(); 543 let slice_len = slice.len();
@@ -349,18 +550,24 @@ impl<'d, T: Instance> I2c<'d, T> {
349 let last_chunk_idx = total_chunks.saturating_sub(1); 550 let last_chunk_idx = total_chunks.saturating_sub(1);
350 551
351 if idx != 0 { 552 if idx != 0 {
352 self.master_continue( 553 // NOTE(unsafe) We have &mut self
353 slice_len.min(255), 554 unsafe {
354 (idx != last_slice_index) || (slice_len > 255), 555 Self::master_continue(
355 ); 556 slice_len.min(255),
557 (idx != last_slice_index) || (slice_len > 255),
558 );
559 }
356 } 560 }
357 561
358 for (number, chunk) in slice.chunks(255).enumerate() { 562 for (number, chunk) in slice.chunks(255).enumerate() {
359 if number != 0 { 563 if number != 0 {
360 self.master_continue( 564 // NOTE(unsafe) We have &mut self
361 chunk.len(), 565 unsafe {
362 (number != last_chunk_idx) || (idx != last_slice_index), 566 Self::master_continue(
363 ); 567 chunk.len(),
568 (number != last_chunk_idx) || (idx != last_slice_index),
569 );
570 }
364 } 571 }
365 572
366 for byte in chunk { 573 for byte in chunk {