aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/dma/dma.rs6
-rw-r--r--embassy-stm32/src/spi/mod.rs4
-rw-r--r--embassy-stm32/src/spi/v3.rs98
-rw-r--r--examples/stm32h7/src/bin/spi.rs112
-rw-r--r--examples/stm32h7/src/bin/spi_dma.rs109
5 files changed, 318 insertions, 11 deletions
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index 9ac6df159..72502043d 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -88,7 +88,11 @@ pub(crate) unsafe fn do_transfer(
88 w.set_dir(dir); 88 w.set_dir(dir);
89 w.set_msize(vals::Size::BITS8); 89 w.set_msize(vals::Size::BITS8);
90 w.set_psize(vals::Size::BITS8); 90 w.set_psize(vals::Size::BITS8);
91 w.set_minc(vals::Inc::INCREMENTED); 91 if incr_mem {
92 w.set_minc(vals::Inc::INCREMENTED);
93 } else {
94 w.set_minc(vals::Inc::FIXED);
95 }
92 w.set_pinc(vals::Inc::FIXED); 96 w.set_pinc(vals::Inc::FIXED);
93 w.set_teie(true); 97 w.set_teie(true);
94 w.set_tcie(true); 98 w.set_tcie(true);
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 9bb5a729c..9c259715d 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -1,7 +1,7 @@
1#![macro_use] 1#![macro_use]
2 2
3#[cfg_attr(spi_v1, path = "v1.rs")] 3//#[cfg_attr(spi_v1, path = "v1.rs")]
4#[cfg_attr(spi_v2, path = "v2.rs")] 4//#[cfg_attr(spi_v2, path = "v2.rs")]
5#[cfg_attr(spi_v3, path = "v3.rs")] 5#[cfg_attr(spi_v3, path = "v3.rs")]
6mod _version; 6mod _version;
7use crate::{dma, peripherals, rcc::RccPeripheral}; 7use crate::{dma, peripherals, rcc::RccPeripheral};
diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs
index fb2a46f3e..2d6f4a28f 100644
--- a/embassy-stm32/src/spi/v3.rs
+++ b/embassy-stm32/src/spi/v3.rs
@@ -18,7 +18,7 @@ use embassy_extras::unborrow;
18use embassy_traits::spi as traits; 18use embassy_traits::spi as traits;
19pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 19pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
20 20
21use futures::future::join; 21use futures::future::join3;
22 22
23impl WordSize { 23impl WordSize {
24 fn dsize(&self) -> u8 { 24 fn dsize(&self) -> u8 {
@@ -110,7 +110,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
110 w.set_crcen(false); 110 w.set_crcen(false);
111 w.set_mbr(spi::vals::Mbr(br)); 111 w.set_mbr(spi::vals::Mbr(br));
112 w.set_dsize(WordSize::EightBit.dsize()); 112 w.set_dsize(WordSize::EightBit.dsize());
113 //w.set_fthlv(WordSize::EightBit.frxth());
114 }); 113 });
115 T::regs().cr2().modify(|w| { 114 T::regs().cr2().modify(|w| {
116 w.set_tsize(0); 115 w.set_tsize(0);
@@ -182,16 +181,40 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
182 where 181 where
183 Tx: TxDmaChannel<T>, 182 Tx: TxDmaChannel<T>,
184 { 183 {
184 Self::set_word_size(WordSize::EightBit);
185 unsafe {
186 T::regs().cr1().modify(|w| {
187 w.set_spe(false);
188 });
189 }
190
185 let request = self.txdma.request(); 191 let request = self.txdma.request();
186 let dst = T::regs().txdr().ptr() as *mut u8; 192 let dst = T::regs().txdr().ptr() as *mut u8;
187 let f = self.txdma.write(request, write, dst); 193 let f = self.txdma.write(request, write, dst);
194
188 unsafe { 195 unsafe {
189 T::regs().cfg1().modify(|reg| { 196 T::regs().cfg1().modify(|reg| {
190 reg.set_txdmaen(true); 197 reg.set_txdmaen(true);
191 }); 198 });
199 T::regs().cr1().modify(|w| {
200 w.set_spe(true);
201 });
202 T::regs().cr1().modify(|w| {
203 w.set_cstart(true);
204 });
192 } 205 }
193 206
194 f.await; 207 f.await;
208 unsafe {
209 T::regs().cfg1().modify(|reg| {
210 reg.set_rxdmaen(false);
211 reg.set_txdmaen(false);
212 });
213 T::regs().cr1().modify(|w| {
214 w.set_spe(false);
215 });
216 }
217
195 Ok(()) 218 Ok(())
196 } 219 }
197 220
@@ -201,6 +224,16 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
201 Tx: TxDmaChannel<T>, 224 Tx: TxDmaChannel<T>,
202 Rx: RxDmaChannel<T>, 225 Rx: RxDmaChannel<T>,
203 { 226 {
227 Self::set_word_size(WordSize::EightBit);
228 unsafe {
229 T::regs().cr1().modify(|w| {
230 w.set_spe(false);
231 });
232 T::regs().cfg1().modify(|reg| {
233 reg.set_rxdmaen(true);
234 });
235 }
236
204 let clock_byte_count = read.len(); 237 let clock_byte_count = read.len();
205 238
206 let rx_request = self.rxdma.request(); 239 let rx_request = self.rxdma.request();
@@ -217,11 +250,25 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
217 unsafe { 250 unsafe {
218 T::regs().cfg1().modify(|reg| { 251 T::regs().cfg1().modify(|reg| {
219 reg.set_txdmaen(true); 252 reg.set_txdmaen(true);
220 reg.set_rxdmaen(true); 253 });
254 T::regs().cr1().modify(|w| {
255 w.set_spe(true);
256 });
257 T::regs().cr1().modify(|w| {
258 w.set_cstart(true);
221 }); 259 });
222 } 260 }
223 261
224 let r = join(tx_f, rx_f).await; 262 join3(tx_f, rx_f, Self::wait_for_idle()).await;
263 unsafe {
264 T::regs().cfg1().modify(|reg| {
265 reg.set_rxdmaen(false);
266 reg.set_txdmaen(false);
267 });
268 T::regs().cr1().modify(|w| {
269 w.set_spe(false);
270 });
271 }
225 Ok(()) 272 Ok(())
226 } 273 }
227 274
@@ -231,11 +278,21 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
231 Tx: TxDmaChannel<T>, 278 Tx: TxDmaChannel<T>,
232 Rx: RxDmaChannel<T>, 279 Rx: RxDmaChannel<T>,
233 { 280 {
234 let clock_byte_count = read.len(); 281 Self::set_word_size(WordSize::EightBit);
282 unsafe {
283 T::regs().cr1().modify(|w| {
284 w.set_spe(false);
285 });
286 T::regs().cfg1().modify(|reg| {
287 reg.set_rxdmaen(true);
288 });
289 }
235 290
236 let rx_request = self.rxdma.request(); 291 let rx_request = self.rxdma.request();
237 let rx_src = T::regs().rxdr().ptr() as *mut u8; 292 let rx_src = T::regs().rxdr().ptr() as *mut u8;
238 let rx_f = self.rxdma.read(rx_request, rx_src, read); 293 let rx_f = self
294 .rxdma
295 .read(rx_request, rx_src, &mut read[0..write.len()]);
239 296
240 let tx_request = self.txdma.request(); 297 let tx_request = self.txdma.request();
241 let tx_dst = T::regs().txdr().ptr() as *mut u8; 298 let tx_dst = T::regs().txdr().ptr() as *mut u8;
@@ -244,13 +301,38 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
244 unsafe { 301 unsafe {
245 T::regs().cfg1().modify(|reg| { 302 T::regs().cfg1().modify(|reg| {
246 reg.set_txdmaen(true); 303 reg.set_txdmaen(true);
247 reg.set_rxdmaen(true); 304 });
305 T::regs().cr1().modify(|w| {
306 w.set_spe(true);
307 });
308 T::regs().cr1().modify(|w| {
309 w.set_cstart(true);
248 }); 310 });
249 } 311 }
250 312
251 let r = join(tx_f, rx_f).await; 313 join3(tx_f, rx_f, Self::wait_for_idle()).await;
314 unsafe {
315 T::regs().cfg1().modify(|reg| {
316 reg.set_rxdmaen(false);
317 reg.set_txdmaen(false);
318 });
319 T::regs().cr1().modify(|w| {
320 w.set_spe(false);
321 });
322 }
252 Ok(()) 323 Ok(())
253 } 324 }
325
326 async fn wait_for_idle() {
327 unsafe {
328 while !T::regs().sr().read().txc() {
329 // spin
330 }
331 while T::regs().sr().read().rxplvl().0 > 0 {
332 // spin
333 }
334 }
335 }
254} 336}
255 337
256impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { 338impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
new file mode 100644
index 000000000..ac483a311
--- /dev/null
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -0,0 +1,112 @@
1#![no_std]
2#![no_main]
3#![feature(trait_alias)]
4#![feature(min_type_alias_impl_trait)]
5#![feature(impl_trait_in_bindings)]
6#![feature(type_alias_impl_trait)]
7#![allow(incomplete_features)]
8
9#[path = "../example_common.rs"]
10mod example_common;
11
12use core::fmt::Write;
13use embassy::executor::Executor;
14use embassy::time::Clock;
15use embassy::util::Forever;
16use embassy_stm32::dma::NoDma;
17use example_common::*;
18use embedded_hal::blocking::spi::Transfer;
19
20use hal::prelude::*;
21use stm32h7xx_hal as hal;
22
23use cortex_m_rt::entry;
24use stm32h7::stm32h743 as pac;
25use heapless::String;
26use embassy_stm32::spi::{Spi, Config};
27use embassy_stm32::time::Hertz;
28
29#[embassy::task]
30async fn main_task() {
31 let p = embassy_stm32::init(Default::default());
32
33 let mut spi = Spi::new(
34 p.SPI3,
35 p.PB3,
36 p.PB5,
37 p.PB4,
38 NoDma,
39 NoDma,
40 Hertz(1_000_000),
41 Config::default(),
42 );
43
44 for n in 0u32.. {
45 let mut write: String<128> = String::new();
46 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
47 unsafe {
48 let result = spi.transfer(write.as_bytes_mut());
49 if let Err(_) = result {
50 defmt::panic!("crap");
51 }
52 }
53 info!("read via spi: {}", write.as_bytes());
54 }
55}
56
57struct ZeroClock;
58
59impl Clock for ZeroClock {
60 fn now(&self) -> u64 {
61 0
62 }
63}
64
65static EXECUTOR: Forever<Executor> = Forever::new();
66
67#[entry]
68fn main() -> ! {
69 info!("Hello World!");
70
71 let pp = pac::Peripherals::take().unwrap();
72
73 let pwrcfg = pp.PWR.constrain().freeze();
74
75 let rcc = pp.RCC.constrain();
76
77 rcc.sys_ck(96.mhz())
78 .pclk1(48.mhz())
79 .pclk2(48.mhz())
80 .pclk3(48.mhz())
81 .pclk4(48.mhz())
82 .pll1_q_ck(48.mhz())
83 .freeze(pwrcfg, &pp.SYSCFG);
84
85 let pp = unsafe { pac::Peripherals::steal() };
86
87 pp.DBGMCU.cr.modify(|_, w| {
88 w.dbgsleep_d1().set_bit();
89 w.dbgstby_d1().set_bit();
90 w.dbgstop_d1().set_bit();
91 w.d1dbgcken().set_bit();
92 w
93 });
94
95 pp.RCC.ahb4enr.modify(|_, w| {
96 w.gpioaen().set_bit();
97 w.gpioben().set_bit();
98 w.gpiocen().set_bit();
99 w.gpioden().set_bit();
100 w.gpioeen().set_bit();
101 w.gpiofen().set_bit();
102 w
103 });
104
105 unsafe { embassy::time::set_clock(&ZeroClock) };
106
107 let executor = EXECUTOR.put(Executor::new());
108
109 executor.run(|spawner| {
110 unwrap!(spawner.spawn(main_task()));
111 })
112}
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs
new file mode 100644
index 000000000..9dbfd0960
--- /dev/null
+++ b/examples/stm32h7/src/bin/spi_dma.rs
@@ -0,0 +1,109 @@
1#![no_std]
2#![no_main]
3#![feature(trait_alias)]
4#![feature(min_type_alias_impl_trait)]
5#![feature(impl_trait_in_bindings)]
6#![feature(type_alias_impl_trait)]
7#![allow(incomplete_features)]
8
9#[path = "../example_common.rs"]
10mod example_common;
11use core::fmt::Write;
12use embassy::executor::Executor;
13use embassy::time::Clock;
14use embassy::util::Forever;
15use example_common::*;
16use embassy_traits::spi::FullDuplex;
17
18use hal::prelude::*;
19use stm32h7xx_hal as hal;
20
21use cortex_m_rt::entry;
22use stm32h7::stm32h743 as pac;
23use heapless::String;
24use embassy_stm32::spi::{Spi, Config};
25use embassy_stm32::time::Hertz;
26use core::str::from_utf8;
27
28#[embassy::task]
29async fn main_task() {
30 let p = embassy_stm32::init(Default::default());
31
32 let mut spi = Spi::new(
33 p.SPI3,
34 p.PB3,
35 p.PB5,
36 p.PB4,
37 p.DMA1_CH3,
38 p.DMA1_CH4,
39 Hertz(1_000_000),
40 Config::default(),
41 );
42
43 for n in 0u32.. {
44 let mut write: String<128> = String::new();
45 let mut read = [0;128];
46 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
47 // read_write will slice the &mut read down to &write's actual length.
48 spi.read_write(&mut read, write.as_bytes()).await.ok();
49 info!("read via spi+dma: {}", from_utf8(&read).unwrap());
50 }
51
52}
53
54struct ZeroClock;
55
56impl Clock for ZeroClock {
57 fn now(&self) -> u64 {
58 0
59 }
60}
61
62static EXECUTOR: Forever<Executor> = Forever::new();
63
64#[entry]
65fn main() -> ! {
66 info!("Hello World!");
67
68 let pp = pac::Peripherals::take().unwrap();
69
70 let pwrcfg = pp.PWR.constrain().freeze();
71
72 let rcc = pp.RCC.constrain();
73
74 rcc.sys_ck(96.mhz())
75 .pclk1(48.mhz())
76 .pclk2(48.mhz())
77 .pclk3(48.mhz())
78 .pclk4(48.mhz())
79 .pll1_q_ck(48.mhz())
80 .freeze(pwrcfg, &pp.SYSCFG);
81
82 let pp = unsafe { pac::Peripherals::steal() };
83
84 pp.DBGMCU.cr.modify(|_, w| {
85 w.dbgsleep_d1().set_bit();
86 w.dbgstby_d1().set_bit();
87 w.dbgstop_d1().set_bit();
88 w.d1dbgcken().set_bit();
89 w
90 });
91
92 pp.RCC.ahb4enr.modify(|_, w| {
93 w.gpioaen().set_bit();
94 w.gpioben().set_bit();
95 w.gpiocen().set_bit();
96 w.gpioden().set_bit();
97 w.gpioeen().set_bit();
98 w.gpiofen().set_bit();
99 w
100 });
101
102 unsafe { embassy::time::set_clock(&ZeroClock) };
103
104 let executor = EXECUTOR.put(Executor::new());
105
106 executor.run(|spawner| {
107 unwrap!(spawner.spawn(main_task()));
108 })
109}