aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-04-15 21:45:08 +0000
committerGitHub <[email protected]>2024-04-15 21:45:08 +0000
commit76bf3f733dd735296553b9c44640bb8a1575fda7 (patch)
tree45dfaa958f46d2f6f55e46cccd269366c2fe6df3
parentd66c054aae616616377c7bcee47f5de8a312d085 (diff)
parent913bb19a34b88e996972c6666679b2b99ae01ce0 (diff)
Merge pull request #2820 from embassy-rs/i2c-nodma
stm32/i2c: remove DMA generic params.
-rw-r--r--embassy-stm32/src/dma/mod.rs3
-rw-r--r--embassy-stm32/src/dma/util.rs60
-rw-r--r--embassy-stm32/src/i2c/mod.rs61
-rw-r--r--embassy-stm32/src/i2c/v1.rs50
-rw-r--r--embassy-stm32/src/i2c/v2.rs276
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/macros.rs (renamed from embassy-stm32/src/traits.rs)7
-rw-r--r--embassy-stm32/src/spi/mod.rs76
-rw-r--r--examples/stm32f4/src/bin/i2c.rs18
-rw-r--r--examples/stm32l4/src/bin/i2c.rs18
-rw-r--r--examples/stm32l4/src/bin/i2c_blocking_async.rs18
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs2
-rw-r--r--examples/stm32u5/src/bin/i2c.rs18
13 files changed, 294 insertions, 315 deletions
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 7e3681469..8766d0a60 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -16,6 +16,9 @@ mod dmamux;
16#[cfg(dmamux)] 16#[cfg(dmamux)]
17pub use dmamux::*; 17pub use dmamux::*;
18 18
19mod util;
20pub(crate) use util::*;
21
19pub(crate) mod ringbuffer; 22pub(crate) mod ringbuffer;
20pub mod word; 23pub mod word;
21 24
diff --git a/embassy-stm32/src/dma/util.rs b/embassy-stm32/src/dma/util.rs
new file mode 100644
index 000000000..962ea2501
--- /dev/null
+++ b/embassy-stm32/src/dma/util.rs
@@ -0,0 +1,60 @@
1use embassy_hal_internal::PeripheralRef;
2
3use super::word::Word;
4use super::{AnyChannel, Request, Transfer, TransferOptions};
5
6/// Convenience wrapper, contains a channel and a request number.
7///
8/// Commonly used in peripheral drivers that own DMA channels.
9pub(crate) struct ChannelAndRequest<'d> {
10 pub channel: PeripheralRef<'d, AnyChannel>,
11 pub request: Request,
12}
13
14impl<'d> ChannelAndRequest<'d> {
15 pub unsafe fn read<'a, W: Word>(
16 &'a mut self,
17 peri_addr: *mut W,
18 buf: &'a mut [W],
19 options: TransferOptions,
20 ) -> Transfer<'a> {
21 Transfer::new_read(&mut self.channel, self.request, peri_addr, buf, options)
22 }
23
24 pub unsafe fn read_raw<'a, W: Word>(
25 &'a mut self,
26 peri_addr: *mut W,
27 buf: *mut [W],
28 options: TransferOptions,
29 ) -> Transfer<'a> {
30 Transfer::new_read_raw(&mut self.channel, self.request, peri_addr, buf, options)
31 }
32
33 pub unsafe fn write<'a, W: Word>(
34 &'a mut self,
35 buf: &'a [W],
36 peri_addr: *mut W,
37 options: TransferOptions,
38 ) -> Transfer<'a> {
39 Transfer::new_write(&mut self.channel, self.request, buf, peri_addr, options)
40 }
41
42 pub unsafe fn write_raw<'a, W: Word>(
43 &'a mut self,
44 buf: *const [W],
45 peri_addr: *mut W,
46 options: TransferOptions,
47 ) -> Transfer<'a> {
48 Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options)
49 }
50
51 pub unsafe fn write_repeated<'a, W: Word>(
52 &'a mut self,
53 repeated: &'a W,
54 count: usize,
55 peri_addr: *mut W,
56 options: TransferOptions,
57 ) -> Transfer<'a> {
58 Transfer::new_write_repeated(&mut self.channel, self.request, repeated, count, peri_addr, options)
59 }
60}
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index a46061d54..ccbea9831 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -14,9 +14,10 @@ use embassy_sync::waitqueue::AtomicWaker;
14#[cfg(feature = "time")] 14#[cfg(feature = "time")]
15use embassy_time::{Duration, Instant}; 15use embassy_time::{Duration, Instant};
16 16
17use crate::dma::NoDma; 17use crate::dma::ChannelAndRequest;
18use crate::gpio::{AFType, Pull}; 18use crate::gpio::{AFType, Pull};
19use crate::interrupt::typelevel::Interrupt; 19use crate::interrupt::typelevel::Interrupt;
20use crate::mode::{Async, Blocking, Mode};
20use crate::time::Hertz; 21use crate::time::Hertz;
21use crate::{interrupt, peripherals}; 22use crate::{interrupt, peripherals};
22 23
@@ -71,17 +72,16 @@ impl Default for Config {
71} 72}
72 73
73/// I2C driver. 74/// I2C driver.
74pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> { 75pub struct I2c<'d, T: Instance, M: Mode> {
75 _peri: PeripheralRef<'d, T>, 76 _peri: PeripheralRef<'d, T>,
76 #[allow(dead_code)] 77 tx_dma: Option<ChannelAndRequest<'d>>,
77 tx_dma: PeripheralRef<'d, TXDMA>, 78 rx_dma: Option<ChannelAndRequest<'d>>,
78 #[allow(dead_code)]
79 rx_dma: PeripheralRef<'d, RXDMA>,
80 #[cfg(feature = "time")] 79 #[cfg(feature = "time")]
81 timeout: Duration, 80 timeout: Duration,
81 _phantom: PhantomData<M>,
82} 82}
83 83
84impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { 84impl<'d, T: Instance> I2c<'d, T, Async> {
85 /// Create a new I2C driver. 85 /// Create a new I2C driver.
86 pub fn new( 86 pub fn new(
87 peri: impl Peripheral<P = T> + 'd, 87 peri: impl Peripheral<P = T> + 'd,
@@ -90,12 +90,40 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
90 _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>> 90 _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
91 + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>> 91 + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
92 + 'd, 92 + 'd,
93 tx_dma: impl Peripheral<P = TXDMA> + 'd, 93 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
94 rx_dma: impl Peripheral<P = RXDMA> + 'd, 94 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
95 freq: Hertz, 95 freq: Hertz,
96 config: Config, 96 config: Config,
97 ) -> Self { 97 ) -> Self {
98 into_ref!(peri, scl, sda, tx_dma, rx_dma); 98 Self::new_inner(peri, scl, sda, new_dma!(tx_dma), new_dma!(rx_dma), freq, config)
99 }
100}
101
102impl<'d, T: Instance> I2c<'d, T, Blocking> {
103 /// Create a new blocking I2C driver.
104 pub fn new_blocking(
105 peri: impl Peripheral<P = T> + 'd,
106 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
107 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
108 freq: Hertz,
109 config: Config,
110 ) -> Self {
111 Self::new_inner(peri, scl, sda, None, None, freq, config)
112 }
113}
114
115impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
116 /// Create a new I2C driver.
117 fn new_inner(
118 peri: impl Peripheral<P = T> + 'd,
119 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
120 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
121 tx_dma: Option<ChannelAndRequest<'d>>,
122 rx_dma: Option<ChannelAndRequest<'d>>,
123 freq: Hertz,
124 config: Config,
125 ) -> Self {
126 into_ref!(peri, scl, sda);
99 127
100 T::enable_and_reset(); 128 T::enable_and_reset();
101 129
@@ -125,6 +153,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
125 rx_dma, 153 rx_dma,
126 #[cfg(feature = "time")] 154 #[cfg(feature = "time")]
127 timeout: config.timeout, 155 timeout: config.timeout,
156 _phantom: PhantomData,
128 }; 157 };
129 158
130 this.init(freq, config); 159 this.init(freq, config);
@@ -249,7 +278,7 @@ foreach_peripheral!(
249 }; 278 };
250); 279);
251 280
252impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> { 281impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, T, M> {
253 type Error = Error; 282 type Error = Error;
254 283
255 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { 284 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
@@ -257,7 +286,7 @@ impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> {
257 } 286 }
258} 287}
259 288
260impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Write for I2c<'d, T> { 289impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, T, M> {
261 type Error = Error; 290 type Error = Error;
262 291
263 fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { 292 fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
@@ -265,7 +294,7 @@ impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Write for I2c<'d, T> {
265 } 294 }
266} 295}
267 296
268impl<'d, T: Instance> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T> { 297impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T, M> {
269 type Error = Error; 298 type Error = Error;
270 299
271 fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { 300 fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
@@ -289,11 +318,11 @@ impl embedded_hal_1::i2c::Error for Error {
289 } 318 }
290} 319}
291 320
292impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for I2c<'d, T, TXDMA, RXDMA> { 321impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, T, M> {
293 type Error = Error; 322 type Error = Error;
294} 323}
295 324
296impl<'d, T: Instance> embedded_hal_1::i2c::I2c for I2c<'d, T, NoDma, NoDma> { 325impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, T, M> {
297 fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { 326 fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
298 self.blocking_read(address, read) 327 self.blocking_read(address, read)
299 } 328 }
@@ -315,7 +344,7 @@ impl<'d, T: Instance> embedded_hal_1::i2c::I2c for I2c<'d, T, NoDma, NoDma> {
315 } 344 }
316} 345}
317 346
318impl<'d, T: Instance, TXDMA: TxDma<T>, RXDMA: RxDma<T>> embedded_hal_async::i2c::I2c for I2c<'d, T, TXDMA, RXDMA> { 347impl<'d, T: Instance> embedded_hal_async::i2c::I2c for I2c<'d, T, Async> {
319 async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { 348 async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
320 self.read(address, read).await 349 self.read(address, read).await
321 } 350 }
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index d45c48b24..13a473344 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -13,7 +13,7 @@ use embassy_hal_internal::drop::OnDrop;
13use embedded_hal_1::i2c::Operation; 13use embedded_hal_1::i2c::Operation;
14 14
15use super::*; 15use super::*;
16use crate::dma::Transfer; 16use crate::mode::Mode as PeriMode;
17use crate::pac::i2c; 17use crate::pac::i2c;
18 18
19// /!\ /!\ 19// /!\ /!\
@@ -41,7 +41,7 @@ pub unsafe fn on_interrupt<T: Instance>() {
41 }); 41 });
42} 42}
43 43
44impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { 44impl<'d, T: Instance, M: PeriMode> I2c<'d, T, M> {
45 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { 45 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
46 T::regs().cr1().modify(|reg| { 46 T::regs().cr1().modify(|reg| {
47 reg.set_pe(false); 47 reg.set_pe(false);
@@ -326,11 +326,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
326 w.set_itevten(true); 326 w.set_itevten(true);
327 }); 327 });
328 } 328 }
329}
329 330
330 async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> 331impl<'d, T: Instance> I2c<'d, T, Async> {
331 where 332 async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> {
332 TXDMA: crate::i2c::TxDma<T>,
333 {
334 T::regs().cr2().modify(|w| { 333 T::regs().cr2().modify(|w| {
335 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for 334 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
336 // reception. 335 // reception.
@@ -415,9 +414,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
415 // this address from the memory after each TxE event. 414 // this address from the memory after each TxE event.
416 let dst = T::regs().dr().as_ptr() as *mut u8; 415 let dst = T::regs().dr().as_ptr() as *mut u8;
417 416
418 let ch = &mut self.tx_dma; 417 self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
419 let request = ch.request();
420 Transfer::new_write(ch, request, write, dst, Default::default())
421 }; 418 };
422 419
423 // Wait for bytes to be sent, or an error to occur. 420 // Wait for bytes to be sent, or an error to occur.
@@ -479,10 +476,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
479 } 476 }
480 477
481 /// Write. 478 /// Write.
482 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> 479 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
483 where
484 TXDMA: crate::i2c::TxDma<T>,
485 {
486 self.write_frame(address, write, FrameOptions::FirstAndLastFrame) 480 self.write_frame(address, write, FrameOptions::FirstAndLastFrame)
487 .await?; 481 .await?;
488 482
@@ -490,20 +484,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
490 } 484 }
491 485
492 /// Read. 486 /// Read.
493 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> 487 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
494 where
495 RXDMA: crate::i2c::RxDma<T>,
496 {
497 self.read_frame(address, buffer, FrameOptions::FirstAndLastFrame) 488 self.read_frame(address, buffer, FrameOptions::FirstAndLastFrame)
498 .await?; 489 .await?;
499 490
500 Ok(()) 491 Ok(())
501 } 492 }
502 493
503 async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error> 494 async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error> {
504 where
505 RXDMA: crate::i2c::RxDma<T>,
506 {
507 if buffer.is_empty() { 495 if buffer.is_empty() {
508 return Err(Error::Overrun); 496 return Err(Error::Overrun);
509 } 497 }
@@ -623,9 +611,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
623 // from this address from the memory after each RxE event. 611 // from this address from the memory after each RxE event.
624 let src = T::regs().dr().as_ptr() as *mut u8; 612 let src = T::regs().dr().as_ptr() as *mut u8;
625 613
626 let ch = &mut self.rx_dma; 614 self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
627 let request = ch.request();
628 Transfer::new_read(ch, request, src, buffer, Default::default())
629 }; 615 };
630 616
631 // Wait for bytes to be received, or an error to occur. 617 // Wait for bytes to be received, or an error to occur.
@@ -664,11 +650,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
664 } 650 }
665 651
666 /// Write, restart, read. 652 /// Write, restart, read.
667 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> 653 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
668 where
669 RXDMA: crate::i2c::RxDma<T>,
670 TXDMA: crate::i2c::TxDma<T>,
671 {
672 // Check empty read buffer before starting transaction. Otherwise, we would not generate the 654 // Check empty read buffer before starting transaction. Otherwise, we would not generate the
673 // stop condition below. 655 // stop condition below.
674 if read.is_empty() { 656 if read.is_empty() {
@@ -684,11 +666,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
684 /// Consecutive operations of same type are merged. See [transaction contract] for details. 666 /// Consecutive operations of same type are merged. See [transaction contract] for details.
685 /// 667 ///
686 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 668 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
687 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> 669 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
688 where
689 RXDMA: crate::i2c::RxDma<T>,
690 TXDMA: crate::i2c::TxDma<T>,
691 {
692 for (op, frame) in operation_frames(operations)? { 670 for (op, frame) in operation_frames(operations)? {
693 match op { 671 match op {
694 Operation::Read(read) => self.read_frame(addr, read, frame).await?, 672 Operation::Read(read) => self.read_frame(addr, read, frame).await?,
@@ -700,7 +678,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
700 } 678 }
701} 679}
702 680
703impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> { 681impl<'d, T: Instance, M: PeriMode> Drop for I2c<'d, T, M> {
704 fn drop(&mut self) { 682 fn drop(&mut self) {
705 T::disable(); 683 T::disable();
706 } 684 }
@@ -806,7 +784,7 @@ impl Timings {
806 } 784 }
807} 785}
808 786
809impl<'d, T: Instance> SetConfig for I2c<'d, T> { 787impl<'d, T: Instance, M: PeriMode> SetConfig for I2c<'d, T, M> {
810 type Config = Hertz; 788 type Config = Hertz;
811 type ConfigError = (); 789 type ConfigError = ();
812 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { 790 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index da3b0ee30..12df98534 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -7,7 +7,6 @@ use embassy_hal_internal::drop::OnDrop;
7use embedded_hal_1::i2c::Operation; 7use embedded_hal_1::i2c::Operation;
8 8
9use super::*; 9use super::*;
10use crate::dma::Transfer;
11use crate::pac::i2c; 10use crate::pac::i2c;
12 11
13pub(crate) unsafe fn on_interrupt<T: Instance>() { 12pub(crate) unsafe fn on_interrupt<T: Instance>() {
@@ -24,7 +23,7 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
24 }); 23 });
25} 24}
26 25
27impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { 26impl<'d, T: Instance, M: Mode> I2c<'d, T, M> {
28 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { 27 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
29 T::regs().cr1().modify(|reg| { 28 T::regs().cr1().modify(|reg| {
30 reg.set_pe(false); 29 reg.set_pe(false);
@@ -302,6 +301,119 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
302 result 301 result
303 } 302 }
304 303
304 // =========================
305 // Blocking public API
306
307 /// Blocking read.
308 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
309 self.read_internal(address, read, false, self.timeout())
310 // Automatic Stop
311 }
312
313 /// Blocking write.
314 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
315 self.write_internal(address, write, true, self.timeout())
316 }
317
318 /// Blocking write, restart, read.
319 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
320 let timeout = self.timeout();
321 self.write_internal(address, write, false, timeout)?;
322 self.read_internal(address, read, true, timeout)
323 // Automatic Stop
324 }
325
326 /// Blocking transaction with operations.
327 ///
328 /// Consecutive operations of same type are merged. See [transaction contract] for details.
329 ///
330 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
331 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
332 let _ = addr;
333 let _ = operations;
334 todo!()
335 }
336
337 /// Blocking write multiple buffers.
338 ///
339 /// The buffers are concatenated in a single write transaction.
340 pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
341 if write.is_empty() {
342 return Err(Error::ZeroLengthTransfer);
343 }
344
345 let timeout = self.timeout();
346
347 let first_length = write[0].len();
348 let last_slice_index = write.len() - 1;
349
350 if let Err(err) = Self::master_write(
351 address,
352 first_length.min(255),
353 Stop::Software,
354 (first_length > 255) || (last_slice_index != 0),
355 timeout,
356 ) {
357 self.master_stop();
358 return Err(err);
359 }
360
361 for (idx, slice) in write.iter().enumerate() {
362 let slice_len = slice.len();
363 let completed_chunks = slice_len / 255;
364 let total_chunks = if completed_chunks * 255 == slice_len {
365 completed_chunks
366 } else {
367 completed_chunks + 1
368 };
369 let last_chunk_idx = total_chunks.saturating_sub(1);
370
371 if idx != 0 {
372 if let Err(err) = Self::master_continue(
373 slice_len.min(255),
374 (idx != last_slice_index) || (slice_len > 255),
375 timeout,
376 ) {
377 self.master_stop();
378 return Err(err);
379 }
380 }
381
382 for (number, chunk) in slice.chunks(255).enumerate() {
383 if number != 0 {
384 if let Err(err) = Self::master_continue(
385 chunk.len(),
386 (number != last_chunk_idx) || (idx != last_slice_index),
387 timeout,
388 ) {
389 self.master_stop();
390 return Err(err);
391 }
392 }
393
394 for byte in chunk {
395 // Wait until we are allowed to send data
396 // (START has been ACKed or last byte when
397 // through)
398 if let Err(err) = self.wait_txe(timeout) {
399 self.master_stop();
400 return Err(err);
401 }
402
403 // Put byte on the wire
404 //self.i2c.txdr.write(|w| w.txdata().bits(*byte));
405 T::regs().txdr().write(|w| w.set_txdata(*byte));
406 }
407 }
408 }
409 // Wait until the write finishes
410 let result = self.wait_tc(timeout);
411 self.master_stop();
412 result
413 }
414}
415
416impl<'d, T: Instance> I2c<'d, T, Async> {
305 async fn write_dma_internal( 417 async fn write_dma_internal(
306 &mut self, 418 &mut self,
307 address: u8, 419 address: u8,
@@ -309,10 +421,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
309 first_slice: bool, 421 first_slice: bool,
310 last_slice: bool, 422 last_slice: bool,
311 timeout: Timeout, 423 timeout: Timeout,
312 ) -> Result<(), Error> 424 ) -> Result<(), Error> {
313 where
314 TXDMA: crate::i2c::TxDma<T>,
315 {
316 let total_len = write.len(); 425 let total_len = write.len();
317 426
318 let dma_transfer = unsafe { 427 let dma_transfer = unsafe {
@@ -325,9 +434,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
325 }); 434 });
326 let dst = regs.txdr().as_ptr() as *mut u8; 435 let dst = regs.txdr().as_ptr() as *mut u8;
327 436
328 let ch = &mut self.tx_dma; 437 self.tx_dma.as_mut().unwrap().write(write, dst, Default::default())
329 let request = ch.request();
330 Transfer::new_write(ch, request, write, dst, Default::default())
331 }; 438 };
332 439
333 let state = T::state(); 440 let state = T::state();
@@ -398,10 +505,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
398 buffer: &mut [u8], 505 buffer: &mut [u8],
399 restart: bool, 506 restart: bool,
400 timeout: Timeout, 507 timeout: Timeout,
401 ) -> Result<(), Error> 508 ) -> Result<(), Error> {
402 where
403 RXDMA: crate::i2c::RxDma<T>,
404 {
405 let total_len = buffer.len(); 509 let total_len = buffer.len();
406 510
407 let dma_transfer = unsafe { 511 let dma_transfer = unsafe {
@@ -412,9 +516,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
412 }); 516 });
413 let src = regs.rxdr().as_ptr() as *mut u8; 517 let src = regs.rxdr().as_ptr() as *mut u8;
414 518
415 let ch = &mut self.rx_dma; 519 self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
416 let request = ch.request();
417 Transfer::new_read(ch, request, src, buffer, Default::default())
418 }; 520 };
419 521
420 let state = T::state(); 522 let state = T::state();
@@ -475,10 +577,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
475 // Async public API 577 // Async public API
476 578
477 /// Write. 579 /// Write.
478 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> 580 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
479 where
480 TXDMA: crate::i2c::TxDma<T>,
481 {
482 let timeout = self.timeout(); 581 let timeout = self.timeout();
483 if write.is_empty() { 582 if write.is_empty() {
484 self.write_internal(address, write, true, timeout) 583 self.write_internal(address, write, true, timeout)
@@ -492,10 +591,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
492 /// Write multiple buffers. 591 /// Write multiple buffers.
493 /// 592 ///
494 /// The buffers are concatenated in a single write transaction. 593 /// The buffers are concatenated in a single write transaction.
495 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> 594 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
496 where
497 TXDMA: crate::i2c::TxDma<T>,
498 {
499 let timeout = self.timeout(); 595 let timeout = self.timeout();
500 596
501 if write.is_empty() { 597 if write.is_empty() {
@@ -518,10 +614,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
518 } 614 }
519 615
520 /// Read. 616 /// Read.
521 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> 617 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
522 where
523 RXDMA: crate::i2c::RxDma<T>,
524 {
525 let timeout = self.timeout(); 618 let timeout = self.timeout();
526 619
527 if buffer.is_empty() { 620 if buffer.is_empty() {
@@ -533,11 +626,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
533 } 626 }
534 627
535 /// Write, restart, read. 628 /// Write, restart, read.
536 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> 629 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
537 where
538 TXDMA: super::TxDma<T>,
539 RXDMA: super::RxDma<T>,
540 {
541 let timeout = self.timeout(); 630 let timeout = self.timeout();
542 631
543 if write.is_empty() { 632 if write.is_empty() {
@@ -562,129 +651,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
562 /// Consecutive operations of same type are merged. See [transaction contract] for details. 651 /// Consecutive operations of same type are merged. See [transaction contract] for details.
563 /// 652 ///
564 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 653 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
565 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> 654 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
566 where
567 RXDMA: crate::i2c::RxDma<T>,
568 TXDMA: crate::i2c::TxDma<T>,
569 {
570 let _ = addr;
571 let _ = operations;
572 todo!()
573 }
574
575 // =========================
576 // Blocking public API
577
578 /// Blocking read.
579 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
580 self.read_internal(address, read, false, self.timeout())
581 // Automatic Stop
582 }
583
584 /// Blocking write.
585 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
586 self.write_internal(address, write, true, self.timeout())
587 }
588
589 /// Blocking write, restart, read.
590 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
591 let timeout = self.timeout();
592 self.write_internal(address, write, false, timeout)?;
593 self.read_internal(address, read, true, timeout)
594 // Automatic Stop
595 }
596
597 /// Blocking transaction with operations.
598 ///
599 /// Consecutive operations of same type are merged. See [transaction contract] for details.
600 ///
601 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
602 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
603 let _ = addr; 655 let _ = addr;
604 let _ = operations; 656 let _ = operations;
605 todo!() 657 todo!()
606 } 658 }
607
608 /// Blocking write multiple buffers.
609 ///
610 /// The buffers are concatenated in a single write transaction.
611 pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
612 if write.is_empty() {
613 return Err(Error::ZeroLengthTransfer);
614 }
615
616 let timeout = self.timeout();
617
618 let first_length = write[0].len();
619 let last_slice_index = write.len() - 1;
620
621 if let Err(err) = Self::master_write(
622 address,
623 first_length.min(255),
624 Stop::Software,
625 (first_length > 255) || (last_slice_index != 0),
626 timeout,
627 ) {
628 self.master_stop();
629 return Err(err);
630 }
631
632 for (idx, slice) in write.iter().enumerate() {
633 let slice_len = slice.len();
634 let completed_chunks = slice_len / 255;
635 let total_chunks = if completed_chunks * 255 == slice_len {
636 completed_chunks
637 } else {
638 completed_chunks + 1
639 };
640 let last_chunk_idx = total_chunks.saturating_sub(1);
641
642 if idx != 0 {
643 if let Err(err) = Self::master_continue(
644 slice_len.min(255),
645 (idx != last_slice_index) || (slice_len > 255),
646 timeout,
647 ) {
648 self.master_stop();
649 return Err(err);
650 }
651 }
652
653 for (number, chunk) in slice.chunks(255).enumerate() {
654 if number != 0 {
655 if let Err(err) = Self::master_continue(
656 chunk.len(),
657 (number != last_chunk_idx) || (idx != last_slice_index),
658 timeout,
659 ) {
660 self.master_stop();
661 return Err(err);
662 }
663 }
664
665 for byte in chunk {
666 // Wait until we are allowed to send data
667 // (START has been ACKed or last byte when
668 // through)
669 if let Err(err) = self.wait_txe(timeout) {
670 self.master_stop();
671 return Err(err);
672 }
673
674 // Put byte on the wire
675 //self.i2c.txdr.write(|w| w.txdata().bits(*byte));
676 T::regs().txdr().write(|w| w.set_txdata(*byte));
677 }
678 }
679 }
680 // Wait until the write finishes
681 let result = self.wait_tc(timeout);
682 self.master_stop();
683 result
684 }
685} 659}
686 660
687impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> { 661impl<'d, T: Instance, M: Mode> Drop for I2c<'d, T, M> {
688 fn drop(&mut self) { 662 fn drop(&mut self) {
689 T::disable(); 663 T::disable();
690 } 664 }
@@ -814,7 +788,7 @@ impl Timings {
814 } 788 }
815} 789}
816 790
817impl<'d, T: Instance> SetConfig for I2c<'d, T> { 791impl<'d, T: Instance, M: Mode> SetConfig for I2c<'d, T, M> {
818 type Config = Hertz; 792 type Config = Hertz;
819 type ConfigError = (); 793 type ConfigError = ();
820 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { 794 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 1f0f85936..7d2b49ff4 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -15,8 +15,8 @@ mod fmt;
15include!(concat!(env!("OUT_DIR"), "/_macros.rs")); 15include!(concat!(env!("OUT_DIR"), "/_macros.rs"));
16 16
17// Utilities 17// Utilities
18mod macros;
18pub mod time; 19pub mod time;
19mod traits;
20/// Operating modes for peripherals. 20/// Operating modes for peripherals.
21pub mod mode { 21pub mod mode {
22 trait SealedMode {} 22 trait SealedMode {}
diff --git a/embassy-stm32/src/traits.rs b/embassy-stm32/src/macros.rs
index 539302c49..f603f661f 100644
--- a/embassy-stm32/src/traits.rs
+++ b/embassy-stm32/src/macros.rs
@@ -73,8 +73,11 @@ macro_rules! dma_trait_impl {
73macro_rules! new_dma { 73macro_rules! new_dma {
74 ($name:ident) => {{ 74 ($name:ident) => {{
75 let dma = $name.into_ref(); 75 let dma = $name.into_ref();
76 let req = dma.request(); 76 let request = dma.request();
77 Some((dma.map_into(), req)) 77 Some(crate::dma::ChannelAndRequest {
78 channel: dma.map_into(),
79 request,
80 })
78 }}; 81 }};
79} 82}
80 83
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index a4465e289..c39ef1913 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -9,7 +9,7 @@ use embassy_futures::join::join;
9use embassy_hal_internal::{into_ref, PeripheralRef}; 9use embassy_hal_internal::{into_ref, PeripheralRef};
10pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 10pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
11 11
12use crate::dma::{slice_ptr_parts, word, AnyChannel, Request, Transfer}; 12use crate::dma::{slice_ptr_parts, word, ChannelAndRequest};
13use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed}; 13use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
14use crate::mode::{Async, Blocking, Mode as PeriMode}; 14use crate::mode::{Async, Blocking, Mode as PeriMode};
15use crate::pac::spi::{regs, vals, Spi as Regs}; 15use crate::pac::spi::{regs, vals, Spi as Regs};
@@ -97,8 +97,8 @@ pub struct Spi<'d, T: Instance, M: PeriMode> {
97 sck: Option<PeripheralRef<'d, AnyPin>>, 97 sck: Option<PeripheralRef<'d, AnyPin>>,
98 mosi: Option<PeripheralRef<'d, AnyPin>>, 98 mosi: Option<PeripheralRef<'d, AnyPin>>,
99 miso: Option<PeripheralRef<'d, AnyPin>>, 99 miso: Option<PeripheralRef<'d, AnyPin>>,
100 txdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>, 100 tx_dma: Option<ChannelAndRequest<'d>>,
101 rxdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>, 101 rx_dma: Option<ChannelAndRequest<'d>>,
102 _phantom: PhantomData<M>, 102 _phantom: PhantomData<M>,
103 current_word_size: word_impl::Config, 103 current_word_size: word_impl::Config,
104} 104}
@@ -109,8 +109,8 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
109 sck: Option<PeripheralRef<'d, AnyPin>>, 109 sck: Option<PeripheralRef<'d, AnyPin>>,
110 mosi: Option<PeripheralRef<'d, AnyPin>>, 110 mosi: Option<PeripheralRef<'d, AnyPin>>,
111 miso: Option<PeripheralRef<'d, AnyPin>>, 111 miso: Option<PeripheralRef<'d, AnyPin>>,
112 txdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>, 112 tx_dma: Option<ChannelAndRequest<'d>>,
113 rxdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>, 113 rx_dma: Option<ChannelAndRequest<'d>>,
114 config: Config, 114 config: Config,
115 ) -> Self { 115 ) -> Self {
116 into_ref!(peri); 116 into_ref!(peri);
@@ -209,8 +209,8 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> {
209 sck, 209 sck,
210 mosi, 210 mosi,
211 miso, 211 miso,
212 txdma, 212 tx_dma,
213 rxdma, 213 rx_dma,
214 current_word_size: <u8 as SealedWord>::CONFIG, 214 current_word_size: <u8 as SealedWord>::CONFIG,
215 _phantom: PhantomData, 215 _phantom: PhantomData,
216 } 216 }
@@ -479,8 +479,8 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
479 sck: impl Peripheral<P = impl SckPin<T>> + 'd, 479 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
480 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd, 480 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
481 miso: impl Peripheral<P = impl MisoPin<T>> + 'd, 481 miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
482 txdma: impl Peripheral<P = impl TxDma<T>> + 'd, 482 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
483 rxdma: impl Peripheral<P = impl RxDma<T>> + 'd, 483 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
484 config: Config, 484 config: Config,
485 ) -> Self { 485 ) -> Self {
486 Self::new_inner( 486 Self::new_inner(
@@ -488,8 +488,8 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
488 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()), 488 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
489 new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh), 489 new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
490 new_pin!(miso, AFType::Input, Speed::VeryHigh), 490 new_pin!(miso, AFType::Input, Speed::VeryHigh),
491 new_dma!(txdma), 491 new_dma!(tx_dma),
492 new_dma!(rxdma), 492 new_dma!(rx_dma),
493 config, 493 config,
494 ) 494 )
495 } 495 }
@@ -499,7 +499,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
499 peri: impl Peripheral<P = T> + 'd, 499 peri: impl Peripheral<P = T> + 'd,
500 sck: impl Peripheral<P = impl SckPin<T>> + 'd, 500 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
501 miso: impl Peripheral<P = impl MisoPin<T>> + 'd, 501 miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
502 rxdma: impl Peripheral<P = impl RxDma<T>> + 'd, 502 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
503 config: Config, 503 config: Config,
504 ) -> Self { 504 ) -> Self {
505 Self::new_inner( 505 Self::new_inner(
@@ -508,7 +508,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
508 None, 508 None,
509 new_pin!(miso, AFType::Input, Speed::VeryHigh), 509 new_pin!(miso, AFType::Input, Speed::VeryHigh),
510 None, 510 None,
511 new_dma!(rxdma), 511 new_dma!(rx_dma),
512 config, 512 config,
513 ) 513 )
514 } 514 }
@@ -518,7 +518,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
518 peri: impl Peripheral<P = T> + 'd, 518 peri: impl Peripheral<P = T> + 'd,
519 sck: impl Peripheral<P = impl SckPin<T>> + 'd, 519 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
520 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd, 520 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
521 txdma: impl Peripheral<P = impl TxDma<T>> + 'd, 521 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
522 config: Config, 522 config: Config,
523 ) -> Self { 523 ) -> Self {
524 Self::new_inner( 524 Self::new_inner(
@@ -526,7 +526,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
526 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()), 526 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
527 new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh), 527 new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
528 None, 528 None,
529 new_dma!(txdma), 529 new_dma!(tx_dma),
530 None, 530 None,
531 config, 531 config,
532 ) 532 )
@@ -538,7 +538,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
538 pub fn new_txonly_nosck( 538 pub fn new_txonly_nosck(
539 peri: impl Peripheral<P = T> + 'd, 539 peri: impl Peripheral<P = T> + 'd,
540 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd, 540 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
541 txdma: impl Peripheral<P = impl TxDma<T>> + 'd, 541 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
542 config: Config, 542 config: Config,
543 ) -> Self { 543 ) -> Self {
544 Self::new_inner( 544 Self::new_inner(
@@ -546,7 +546,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
546 None, 546 None,
547 new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh), 547 new_pin!(mosi, AFType::OutputPushPull, Speed::VeryHigh),
548 None, 548 None,
549 new_dma!(txdma), 549 new_dma!(tx_dma),
550 None, 550 None,
551 config, 551 config,
552 ) 552 )
@@ -556,8 +556,8 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
556 /// Useful for on chip peripherals like SUBGHZ which are hardwired. 556 /// Useful for on chip peripherals like SUBGHZ which are hardwired.
557 pub fn new_subghz( 557 pub fn new_subghz(
558 peri: impl Peripheral<P = T> + 'd, 558 peri: impl Peripheral<P = T> + 'd,
559 txdma: impl Peripheral<P = impl TxDma<T>> + 'd, 559 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
560 rxdma: impl Peripheral<P = impl RxDma<T>> + 'd, 560 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
561 ) -> Self { 561 ) -> Self {
562 // see RM0453 rev 1 section 7.2.13 page 291 562 // see RM0453 rev 1 section 7.2.13 page 291
563 // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two. 563 // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two.
@@ -569,17 +569,17 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
569 config.bit_order = BitOrder::MsbFirst; 569 config.bit_order = BitOrder::MsbFirst;
570 config.frequency = freq; 570 config.frequency = freq;
571 571
572 Self::new_inner(peri, None, None, None, new_dma!(txdma), new_dma!(rxdma), config) 572 Self::new_inner(peri, None, None, None, new_dma!(tx_dma), new_dma!(rx_dma), config)
573 } 573 }
574 574
575 #[allow(dead_code)] 575 #[allow(dead_code)]
576 pub(crate) fn new_internal( 576 pub(crate) fn new_internal(
577 peri: impl Peripheral<P = T> + 'd, 577 peri: impl Peripheral<P = T> + 'd,
578 txdma: impl Peripheral<P = impl TxDma<T>> + 'd, 578 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
579 rxdma: impl Peripheral<P = impl RxDma<T>> + 'd, 579 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
580 config: Config, 580 config: Config,
581 ) -> Self { 581 ) -> Self {
582 Self::new_inner(peri, None, None, None, new_dma!(txdma), new_dma!(rxdma), config) 582 Self::new_inner(peri, None, None, None, new_dma!(tx_dma), new_dma!(rx_dma), config)
583 } 583 }
584 584
585 /// SPI write, using DMA. 585 /// SPI write, using DMA.
@@ -593,9 +593,8 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
593 w.set_spe(false); 593 w.set_spe(false);
594 }); 594 });
595 595
596 let (txdma, tx_request) = self.txdma.as_mut().unwrap();
597 let tx_dst = T::REGS.tx_ptr(); 596 let tx_dst = T::REGS.tx_ptr();
598 let tx_f = unsafe { Transfer::new_write(txdma, *tx_request, data, tx_dst, Default::default()) }; 597 let tx_f = unsafe { self.tx_dma.as_mut().unwrap().write(data, tx_dst, Default::default()) };
599 598
600 set_txdmaen(T::REGS, true); 599 set_txdmaen(T::REGS, true);
601 T::REGS.cr1().modify(|w| { 600 T::REGS.cr1().modify(|w| {
@@ -632,22 +631,16 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
632 631
633 let clock_byte_count = data.len(); 632 let clock_byte_count = data.len();
634 633
635 let (rxdma, rx_request) = self.rxdma.as_mut().unwrap();
636 let rx_src = T::REGS.rx_ptr(); 634 let rx_src = T::REGS.rx_ptr();
637 let rx_f = unsafe { Transfer::new_read(rxdma, *rx_request, rx_src, data, Default::default()) }; 635 let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read(rx_src, data, Default::default()) };
638 636
639 let (txdma, tx_request) = self.txdma.as_mut().unwrap();
640 let tx_dst = T::REGS.tx_ptr(); 637 let tx_dst = T::REGS.tx_ptr();
641 let clock_byte = 0x00u8; 638 let clock_byte = 0x00u8;
642 let tx_f = unsafe { 639 let tx_f = unsafe {
643 Transfer::new_write_repeated( 640 self.tx_dma
644 txdma, 641 .as_mut()
645 *tx_request, 642 .unwrap()
646 &clock_byte, 643 .write_repeated(&clock_byte, clock_byte_count, tx_dst, Default::default())
647 clock_byte_count,
648 tx_dst,
649 Default::default(),
650 )
651 }; 644 };
652 645
653 set_txdmaen(T::REGS, true); 646 set_txdmaen(T::REGS, true);
@@ -685,13 +678,16 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
685 678
686 set_rxdmaen(T::REGS, true); 679 set_rxdmaen(T::REGS, true);
687 680
688 let (rxdma, rx_request) = self.rxdma.as_mut().unwrap();
689 let rx_src = T::REGS.rx_ptr(); 681 let rx_src = T::REGS.rx_ptr();
690 let rx_f = unsafe { Transfer::new_read_raw(rxdma, *rx_request, rx_src, read, Default::default()) }; 682 let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) };
691 683
692 let (txdma, tx_request) = self.txdma.as_mut().unwrap();
693 let tx_dst = T::REGS.tx_ptr(); 684 let tx_dst = T::REGS.tx_ptr();
694 let tx_f = unsafe { Transfer::new_write_raw(txdma, *tx_request, write, tx_dst, Default::default()) }; 685 let tx_f = unsafe {
686 self.tx_dma
687 .as_mut()
688 .unwrap()
689 .write_raw(write, tx_dst, Default::default())
690 };
695 691
696 set_txdmaen(T::REGS, true); 692 set_txdmaen(T::REGS, true);
697 T::REGS.cr1().modify(|w| { 693 T::REGS.cr1().modify(|w| {
diff --git a/examples/stm32f4/src/bin/i2c.rs b/examples/stm32f4/src/bin/i2c.rs
index 4b5da774d..4a96357a4 100644
--- a/examples/stm32f4/src/bin/i2c.rs
+++ b/examples/stm32f4/src/bin/i2c.rs
@@ -3,35 +3,19 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dma::NoDma;
7use embassy_stm32::i2c::{Error, I2c}; 6use embassy_stm32::i2c::{Error, I2c};
8use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, i2c, peripherals};
10use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
11 9
12const ADDRESS: u8 = 0x5F; 10const ADDRESS: u8 = 0x5F;
13const WHOAMI: u8 = 0x0F; 11const WHOAMI: u8 = 0x0F;
14 12
15bind_interrupts!(struct Irqs {
16 I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
17 I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
18});
19
20#[embassy_executor::main] 13#[embassy_executor::main]
21async fn main(_spawner: Spawner) { 14async fn main(_spawner: Spawner) {
22 info!("Hello world!"); 15 info!("Hello world!");
23 let p = embassy_stm32::init(Default::default()); 16 let p = embassy_stm32::init(Default::default());
24 17
25 let mut i2c = I2c::new( 18 let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default());
26 p.I2C2,
27 p.PB10,
28 p.PB11,
29 Irqs,
30 NoDma,
31 NoDma,
32 Hertz(100_000),
33 Default::default(),
34 );
35 19
36 let mut data = [0u8; 1]; 20 let mut data = [0u8; 1];
37 21
diff --git a/examples/stm32l4/src/bin/i2c.rs b/examples/stm32l4/src/bin/i2c.rs
index f553deb82..2861bc091 100644
--- a/examples/stm32l4/src/bin/i2c.rs
+++ b/examples/stm32l4/src/bin/i2c.rs
@@ -3,33 +3,17 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dma::NoDma;
7use embassy_stm32::i2c::I2c; 6use embassy_stm32::i2c::I2c;
8use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, i2c, peripherals};
10use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
11 9
12const ADDRESS: u8 = 0x5F; 10const ADDRESS: u8 = 0x5F;
13const WHOAMI: u8 = 0x0F; 11const WHOAMI: u8 = 0x0F;
14 12
15bind_interrupts!(struct Irqs {
16 I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
17 I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
18});
19
20#[embassy_executor::main] 13#[embassy_executor::main]
21async fn main(_spawner: Spawner) { 14async fn main(_spawner: Spawner) {
22 let p = embassy_stm32::init(Default::default()); 15 let p = embassy_stm32::init(Default::default());
23 let mut i2c = I2c::new( 16 let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default());
24 p.I2C2,
25 p.PB10,
26 p.PB11,
27 Irqs,
28 NoDma,
29 NoDma,
30 Hertz(100_000),
31 Default::default(),
32 );
33 17
34 let mut data = [0u8; 1]; 18 let mut data = [0u8; 1];
35 unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data)); 19 unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data));
diff --git a/examples/stm32l4/src/bin/i2c_blocking_async.rs b/examples/stm32l4/src/bin/i2c_blocking_async.rs
index 1b8652bcc..a014b23e0 100644
--- a/examples/stm32l4/src/bin/i2c_blocking_async.rs
+++ b/examples/stm32l4/src/bin/i2c_blocking_async.rs
@@ -4,34 +4,18 @@
4use defmt::*; 4use defmt::*;
5use embassy_embedded_hal::adapter::BlockingAsync; 5use embassy_embedded_hal::adapter::BlockingAsync;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma;
8use embassy_stm32::i2c::I2c; 7use embassy_stm32::i2c::I2c;
9use embassy_stm32::time::Hertz; 8use embassy_stm32::time::Hertz;
10use embassy_stm32::{bind_interrupts, i2c, peripherals};
11use embedded_hal_async::i2c::I2c as I2cTrait; 9use embedded_hal_async::i2c::I2c as I2cTrait;
12use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
13 11
14const ADDRESS: u8 = 0x5F; 12const ADDRESS: u8 = 0x5F;
15const WHOAMI: u8 = 0x0F; 13const WHOAMI: u8 = 0x0F;
16 14
17bind_interrupts!(struct Irqs {
18 I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
19 I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
20});
21
22#[embassy_executor::main] 15#[embassy_executor::main]
23async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
24 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
25 let i2c = I2c::new( 18 let i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default());
26 p.I2C2,
27 p.PB10,
28 p.PB11,
29 Irqs,
30 NoDma,
31 NoDma,
32 Hertz(100_000),
33 Default::default(),
34 );
35 let mut i2c = BlockingAsync::new(i2c); 19 let mut i2c = BlockingAsync::new(i2c);
36 20
37 let mut data = [0u8; 1]; 21 let mut data = [0u8; 1];
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index a99d08924..694629ede 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -60,7 +60,7 @@ pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
60pub type SpeInt = exti::ExtiInput<'static>; 60pub type SpeInt = exti::ExtiInput<'static>;
61pub type SpeRst = Output<'static>; 61pub type SpeRst = Output<'static>;
62pub type Adin1110T = ADIN1110<SpeSpiCs>; 62pub type Adin1110T = ADIN1110<SpeSpiCs>;
63pub type TempSensI2c = I2c<'static, peripherals::I2C3, peripherals::DMA1_CH6, peripherals::DMA1_CH7>; 63pub type TempSensI2c = I2c<'static, peripherals::I2C3, Async>;
64 64
65static TEMP: AtomicI32 = AtomicI32::new(0); 65static TEMP: AtomicI32 = AtomicI32::new(0);
66 66
diff --git a/examples/stm32u5/src/bin/i2c.rs b/examples/stm32u5/src/bin/i2c.rs
index e376c6bc8..19a78eac9 100644
--- a/examples/stm32u5/src/bin/i2c.rs
+++ b/examples/stm32u5/src/bin/i2c.rs
@@ -3,33 +3,17 @@
3 3
4use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dma::NoDma;
7use embassy_stm32::i2c::I2c; 6use embassy_stm32::i2c::I2c;
8use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, i2c, peripherals};
10use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
11 9
12const HTS221_ADDRESS: u8 = 0x5F; 10const HTS221_ADDRESS: u8 = 0x5F;
13const WHOAMI: u8 = 0x0F; 11const WHOAMI: u8 = 0x0F;
14 12
15bind_interrupts!(struct Irqs {
16 I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
17 I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
18});
19
20#[embassy_executor::main] 13#[embassy_executor::main]
21async fn main(_spawner: Spawner) { 14async fn main(_spawner: Spawner) {
22 let p = embassy_stm32::init(Default::default()); 15 let p = embassy_stm32::init(Default::default());
23 let mut i2c = I2c::new( 16 let mut i2c = I2c::new_blocking(p.I2C2, p.PH4, p.PH5, Hertz(100_000), Default::default());
24 p.I2C2,
25 p.PH4,
26 p.PH5,
27 Irqs,
28 NoDma,
29 NoDma,
30 Hertz(100_000),
31 Default::default(),
32 );
33 17
34 let mut data = [0u8; 1]; 18 let mut data = [0u8; 1];
35 unwrap!(i2c.blocking_write_read(HTS221_ADDRESS, &[WHOAMI], &mut data)); 19 unwrap!(i2c.blocking_write_read(HTS221_ADDRESS, &[WHOAMI], &mut data));