aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32f4-examples/Cargo.toml4
-rw-r--r--embassy-stm32f4-examples/src/bin/serial.rs23
-rw-r--r--embassy-stm32f4/src/serial.rs214
3 files changed, 157 insertions, 84 deletions
diff --git a/embassy-stm32f4-examples/Cargo.toml b/embassy-stm32f4-examples/Cargo.toml
index 16581f4fd..94f24c75e 100644
--- a/embassy-stm32f4-examples/Cargo.toml
+++ b/embassy-stm32f4-examples/Cargo.toml
@@ -19,7 +19,7 @@ defmt-error = []
19[dependencies] 19[dependencies]
20embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] } 20embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] }
21embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] } 21embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] }
22embassy-stm32f4 = { version = "*", path = "../embassy-stm32f4", features = ["stm32f401"] } 22embassy-stm32f4 = { version = "*", path = "../embassy-stm32f4", features = ["stm32f405"] }
23 23
24defmt = "0.2.0" 24defmt = "0.2.0"
25defmt-rtt = "0.2.0" 25defmt-rtt = "0.2.0"
@@ -28,6 +28,6 @@ cortex-m = "0.7.1"
28cortex-m-rt = "0.6.13" 28cortex-m-rt = "0.6.13"
29embedded-hal = { version = "0.2.4" } 29embedded-hal = { version = "0.2.4" }
30panic-probe = "0.1.0" 30panic-probe = "0.1.0"
31stm32f4xx-hal = { version = "0.8.3", features = ["rt", "stm32f401"], git = "https://github.com/stm32-rs/stm32f4xx-hal.git"} 31stm32f4xx-hal = { version = "0.8.3", features = ["rt", "stm32f405"], git = "https://github.com/stm32-rs/stm32f4xx-hal.git"}
32futures = { version = "0.3.8", default-features = false, features = ["async-await"] } 32futures = { version = "0.3.8", default-features = false, features = ["async-await"] }
33rtt-target = { version = "0.3", features = ["cortex-m"] } 33rtt-target = { version = "0.3", features = ["cortex-m"] }
diff --git a/embassy-stm32f4-examples/src/bin/serial.rs b/embassy-stm32f4-examples/src/bin/serial.rs
index 72fd1a2f9..6351f7284 100644
--- a/embassy-stm32f4-examples/src/bin/serial.rs
+++ b/embassy-stm32f4-examples/src/bin/serial.rs
@@ -14,6 +14,7 @@ use embassy::traits::uart::Uart;
14use embassy::util::Forever; 14use embassy::util::Forever;
15use embassy_stm32f4::interrupt; 15use embassy_stm32f4::interrupt;
16use embassy_stm32f4::serial; 16use embassy_stm32f4::serial;
17use stm32f4xx_hal::dma::StreamsTuple;
17use stm32f4xx_hal::prelude::*; 18use stm32f4xx_hal::prelude::*;
18use stm32f4xx_hal::serial::config::Config; 19use stm32f4xx_hal::serial::config::Config;
19use stm32f4xx_hal::stm32; 20use stm32f4xx_hal::stm32;
@@ -38,10 +39,12 @@ async fn run(dp: stm32::Peripherals, _cp: cortex_m::Peripherals) {
38 .pclk1(24.mhz()) 39 .pclk1(24.mhz())
39 .freeze(); 40 .freeze();
40 41
42 let streams = StreamsTuple::new(dp.DMA2);
43
41 let mut serial = unsafe { 44 let mut serial = unsafe {
42 serial::Serial::new( 45 serial::Serial::new(
43 dp.USART1, 46 dp.USART1,
44 dp.DMA2, 47 (streams.7, streams.2),
45 ( 48 (
46 gpioa.pa9.into_alternate_af7(), 49 gpioa.pa9.into_alternate_af7(),
47 gpioa.pa10.into_alternate_af7(), 50 gpioa.pa10.into_alternate_af7(),
@@ -53,6 +56,24 @@ async fn run(dp: stm32::Peripherals, _cp: cortex_m::Peripherals) {
53 clocks, 56 clocks,
54 ) 57 )
55 }; 58 };
59
60 let streams = StreamsTuple::new(dp.DMA1);
61
62 let mut serial = unsafe {
63 serial::Serial::new(
64 dp.USART2,
65 (streams.6, streams.5),
66 (
67 gpioa.pa2.into_alternate_af7(),
68 gpioa.pa3.into_alternate_af7(),
69 ),
70 interrupt::take!(DMA1_STREAM6),
71 interrupt::take!(DMA1_STREAM5),
72 interrupt::take!(USART2),
73 Config::default().baudrate(9600.bps()),
74 clocks,
75 )
76 };
56 let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); 77 let buf = singleton!(: [u8; 30] = [0; 30]).unwrap();
57 78
58 buf[5] = 0x01; 79 buf[5] = 0x01;
diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs
index 8a90e9fa3..36ca5af56 100644
--- a/embassy-stm32f4/src/serial.rs
+++ b/embassy-stm32f4/src/serial.rs
@@ -8,129 +8,120 @@ use core::future::Future;
8use core::ptr; 8use core::ptr;
9use core::sync::atomic::{self, Ordering}; 9use core::sync::atomic::{self, Ordering};
10 10
11use embassy::interrupt::InterruptExt; 11use embassy::interrupt::{Interrupt, InterruptExt};
12use embassy::traits::uart::{Error, Uart}; 12use embassy::traits::uart::{Error, Uart};
13use embassy::util::Signal; 13use embassy::util::InterruptFuture;
14 14
15use crate::hal::dma;
15use crate::hal::dma::config::DmaConfig; 16use crate::hal::dma::config::DmaConfig;
16use crate::hal::dma::traits::{PeriAddress, Stream}; 17use crate::hal::dma::traits::{PeriAddress, Stream};
17use crate::hal::dma::{Stream2, Stream7, StreamsTuple, Transfer}; 18use crate::hal::dma::{MemoryToPeripheral, PeripheralToMemory, Transfer};
18use crate::hal::rcc::Clocks; 19use crate::hal::rcc::Clocks;
20use crate::hal::serial;
19use crate::hal::serial::config::{Config as SerialConfig, DmaConfig as SerialDmaConfig}; 21use crate::hal::serial::config::{Config as SerialConfig, DmaConfig as SerialDmaConfig};
20use crate::hal::serial::Pins; 22use crate::hal::serial::Pins;
21use crate::hal::serial::{Event as SerialEvent, Serial as HalSerial}; 23use crate::hal::serial::{Event as SerialEvent, Serial as HalSerial};
22use crate::interrupt; 24use crate::interrupt;
23use crate::pac::{DMA2, USART1}; 25use crate::pac;
24 26
25/// Interface to the Serial peripheral 27/// Interface to the Serial peripheral
26pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: Stream> { 28pub struct Serial<
29 USART: PeriAddress<MemSize = u8>,
30 TSTREAM: Stream,
31 RSTREAM: Stream,
32 CHANNEL: dma::traits::Channel,
33 TINT: Interrupt,
34 RINT: Interrupt,
35 UINT: Interrupt,
36> {
27 tx_stream: Option<TSTREAM>, 37 tx_stream: Option<TSTREAM>,
28 rx_stream: Option<RSTREAM>, 38 rx_stream: Option<RSTREAM>,
29 usart: Option<USART>, 39 usart: Option<USART>,
30 tx_int: interrupt::DMA2_STREAM7, 40 tx_int: TINT,
31 rx_int: interrupt::DMA2_STREAM2, 41 rx_int: RINT,
32 usart_int: interrupt::USART1, 42 usart_int: UINT,
43 channel: core::marker::PhantomData<CHANNEL>,
33} 44}
34 45
35struct State { 46// static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut();
36 tx_int: Signal<()>, 47
37 rx_int: Signal<()>, 48impl<USART, TSTREAM, RSTREAM, CHANNEL, TINT, RINT, UINT>
38} 49 Serial<USART, TSTREAM, RSTREAM, CHANNEL, TINT, RINT, UINT>
39 50where
40static STATE: State = State { 51 USART: serial::Instance
41 tx_int: Signal::new(), 52 + dma::traits::PeriAddress<MemSize = u8>
42 rx_int: Signal::new(), 53 + dma::traits::DMASet<TSTREAM, CHANNEL, MemoryToPeripheral>
43}; 54 + dma::traits::DMASet<RSTREAM, CHANNEL, PeripheralToMemory>
44 55 + WithInterrupt<Instance = UINT>,
45static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut(); 56 TSTREAM: Stream + WithInterrupt<Instance = TINT>,
46 57 RSTREAM: Stream + WithInterrupt<Instance = RINT>,
47impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { 58 CHANNEL: dma::traits::Channel,
59 TINT: Interrupt,
60 RINT: Interrupt,
61 UINT: Interrupt,
62{
48 // Leaking futures is forbidden! 63 // Leaking futures is forbidden!
49 pub unsafe fn new<PINS>( 64 pub unsafe fn new<PINS>(
50 usart: USART1, 65 usart: USART,
51 dma: DMA2, 66 streams: (TSTREAM, RSTREAM),
52 pins: PINS, 67 pins: PINS,
53 tx_int: interrupt::DMA2_STREAM7, 68 tx_int: TINT,
54 rx_int: interrupt::DMA2_STREAM2, 69 rx_int: RINT,
55 usart_int: interrupt::USART1, 70 usart_int: UINT,
56 mut config: SerialConfig, 71 mut config: SerialConfig,
57 clocks: Clocks, 72 clocks: Clocks,
58 ) -> Self 73 ) -> Self
59 where 74 where
60 PINS: Pins<USART1>, 75 PINS: Pins<USART>,
61 { 76 {
62 config.dma = SerialDmaConfig::TxRx; 77 config.dma = SerialDmaConfig::TxRx;
63 let mut serial = HalSerial::usart1(usart, pins, config, clocks).unwrap(); 78 let mut serial = HalSerial::new(usart, pins, config, clocks).unwrap();
64 79
65 serial.listen(SerialEvent::Idle); 80 serial.listen(SerialEvent::Idle);
66 // serial.listen(SerialEvent::Txe); 81 // serial.listen(SerialEvent::Txe);
67 82
68 let (usart, _) = serial.release(); 83 let (usart, _) = serial.release();
69 84
70 // Register ISR 85 let (tx_stream, rx_stream) = streams;
71 tx_int.set_handler(Self::on_tx_irq);
72 rx_int.set_handler(Self::on_rx_irq);
73 usart_int.set_handler(Self::on_rx_irq);
74 // usart_int.unpend();
75 // usart_int.enable();
76
77 let streams = StreamsTuple::new(dma);
78 86
79 Serial { 87 Serial {
80 tx_stream: Some(streams.7), 88 tx_stream: Some(tx_stream),
81 rx_stream: Some(streams.2), 89 rx_stream: Some(rx_stream),
82 usart: Some(usart), 90 usart: Some(usart),
83 tx_int: tx_int, 91 tx_int: tx_int,
84 rx_int: rx_int, 92 rx_int: rx_int,
85 usart_int: usart_int, 93 usart_int: usart_int,
94 channel: core::marker::PhantomData,
86 } 95 }
87 } 96 }
88
89 unsafe fn on_tx_irq(_ctx: *mut ()) {
90 let s = &(*INSTANCE);
91
92 s.tx_int.disable();
93
94 STATE.tx_int.signal(());
95 }
96
97 unsafe fn on_rx_irq(_ctx: *mut ()) {
98 let s = &(*INSTANCE);
99
100 atomic::compiler_fence(Ordering::Acquire);
101 s.rx_int.disable();
102 s.usart_int.disable();
103 atomic::compiler_fence(Ordering::Release);
104
105 STATE.rx_int.signal(());
106 }
107
108 unsafe fn on_usart_irq(_ctx: *mut ()) {
109 let s = &(*INSTANCE);
110
111 atomic::compiler_fence(Ordering::Acquire);
112 s.rx_int.disable();
113 s.usart_int.disable();
114 atomic::compiler_fence(Ordering::Release);
115
116 STATE.rx_int.signal(());
117 }
118} 97}
119 98
120impl Uart for Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { 99impl<USART, TSTREAM, RSTREAM, CHANNEL, TINT, RINT, UINT> Uart
100 for Serial<USART, TSTREAM, RSTREAM, CHANNEL, TINT, RINT, UINT>
101where
102 USART: serial::Instance
103 + dma::traits::PeriAddress<MemSize = u8>
104 + dma::traits::DMASet<TSTREAM, CHANNEL, MemoryToPeripheral>
105 + dma::traits::DMASet<RSTREAM, CHANNEL, PeripheralToMemory>
106 + WithInterrupt<Instance = UINT>
107 + 'static,
108 TSTREAM: Stream + WithInterrupt<Instance = TINT> + 'static,
109 RSTREAM: Stream + WithInterrupt<Instance = RINT> + 'static,
110 CHANNEL: dma::traits::Channel + 'static,
111 TINT: Interrupt + 'static,
112 RINT: Interrupt + 'static,
113 UINT: Interrupt + 'static,
114{
121 type SendFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; 115 type SendFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
122 type ReceiveFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; 116 type ReceiveFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
123 117
124 /// Sends serial data. 118 /// Sends serial data.
125 fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a> { 119 fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a> {
126 unsafe { INSTANCE = self };
127
128 #[allow(mutable_transmutes)] 120 #[allow(mutable_transmutes)]
129 let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) }; 121 let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) };
130 122
131 let tx_stream = self.tx_stream.take().unwrap(); 123 let tx_stream = self.tx_stream.take().unwrap();
132 let usart = self.usart.take().unwrap(); 124 let usart = self.usart.take().unwrap();
133 STATE.tx_int.reset();
134 125
135 async move { 126 async move {
136 let mut tx_transfer = Transfer::init( 127 let mut tx_transfer = Transfer::init(
@@ -144,11 +135,11 @@ impl Uart for Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
144 .double_buffer(false), 135 .double_buffer(false),
145 ); 136 );
146 137
147 self.tx_int.unpend(); 138 let fut = InterruptFuture::new(&mut self.tx_int);
148 self.tx_int.enable(); 139
149 tx_transfer.start(|_usart| {}); 140 tx_transfer.start(|_usart| {});
150 141
151 STATE.tx_int.wait().await; 142 fut.await;
152 143
153 let (tx_stream, usart, _buf, _) = tx_transfer.free(); 144 let (tx_stream, usart, _buf, _) = tx_transfer.free();
154 self.tx_stream.replace(tx_stream); 145 self.tx_stream.replace(tx_stream);
@@ -165,12 +156,11 @@ impl Uart for Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
165 /// unfinished transfers after a timeout to prevent lockup when no more data 156 /// unfinished transfers after a timeout to prevent lockup when no more data
166 /// is incoming. 157 /// is incoming.
167 fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> { 158 fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> {
168 unsafe { INSTANCE = self };
169
170 let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) }; 159 let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) };
160
171 let rx_stream = self.rx_stream.take().unwrap(); 161 let rx_stream = self.rx_stream.take().unwrap();
172 let usart = self.usart.take().unwrap(); 162 let usart = self.usart.take().unwrap();
173 STATE.rx_int.reset(); 163
174 async move { 164 async move {
175 let mut rx_transfer = Transfer::init( 165 let mut rx_transfer = Transfer::init(
176 rx_stream, 166 rx_stream,
@@ -182,14 +172,76 @@ impl Uart for Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
182 .memory_increment(true) 172 .memory_increment(true)
183 .double_buffer(false), 173 .double_buffer(false),
184 ); 174 );
185 self.rx_int.unpend(); 175
186 self.rx_int.enable(); 176 let fut = InterruptFuture::new(&mut self.rx_int);
177
187 rx_transfer.start(|_usart| {}); 178 rx_transfer.start(|_usart| {});
188 STATE.rx_int.wait().await; 179 fut.await;
180
189 let (rx_stream, usart, _, _) = rx_transfer.free(); 181 let (rx_stream, usart, _, _) = rx_transfer.free();
190 self.rx_stream.replace(rx_stream); 182 self.rx_stream.replace(rx_stream);
191 self.usart.replace(usart); 183 self.usart.replace(usart);
184
192 Ok(()) 185 Ok(())
193 } 186 }
194 } 187 }
195} 188}
189
190mod private {
191 pub trait Sealed {}
192}
193
194pub trait WithInterrupt: private::Sealed {
195 type Instance;
196}
197
198macro_rules! dma {
199 ($($PER:ident => ($dma:ident, $stream:ident),)+) => {
200 $(
201 impl private::Sealed for dma::$stream<pac::$dma> {}
202 impl WithInterrupt for dma::$stream<pac::$dma> {
203 type Instance = interrupt::$PER;
204 }
205 )+
206 }
207 }
208
209macro_rules! usart {
210 ($($PER:ident => ($usart:ident),)+) => {
211 $(
212 impl private::Sealed for pac::$usart {}
213 impl WithInterrupt for pac::$usart {
214 type Instance = interrupt::$PER;
215 }
216 )+
217 }
218}
219
220#[cfg(any(feature = "stm32f405",))]
221dma! {
222 DMA2_STREAM0 => (DMA2, Stream0),
223 DMA2_STREAM1 => (DMA2, Stream1),
224 DMA2_STREAM2 => (DMA2, Stream2),
225 DMA2_STREAM3 => (DMA2, Stream3),
226 DMA2_STREAM4 => (DMA2, Stream4),
227 DMA2_STREAM5 => (DMA2, Stream5),
228 DMA2_STREAM6 => (DMA2, Stream6),
229 DMA2_STREAM7 => (DMA2, Stream7),
230 DMA1_STREAM0 => (DMA1, Stream0),
231 DMA1_STREAM1 => (DMA1, Stream1),
232 DMA1_STREAM2 => (DMA1, Stream2),
233 DMA1_STREAM3 => (DMA1, Stream3),
234 DMA1_STREAM4 => (DMA1, Stream4),
235 DMA1_STREAM5 => (DMA1, Stream5),
236 DMA1_STREAM6 => (DMA1, Stream6),
237}
238
239#[cfg(any(feature = "stm32f405",))]
240usart! {
241 USART1 => (USART1),
242 USART2 => (USART2),
243 USART3 => (USART3),
244 UART4 => (UART4),
245 UART5 => (UART5),
246 USART6 => (USART6),
247}