Skip to content

Commit e44b853

Browse files
committed
Add DMA support for serial receive and transmit
1 parent eaddb81 commit e44b853

File tree

2 files changed

+116
-72
lines changed

2 files changed

+116
-72
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ targets = ["thumbv7em-none-eabihf"]
1919
travis-ci = { repository = "stm32-rs/stm32f3xx-hal" }
2020

2121
[dependencies]
22+
as-slice = "0.1"
2223
cortex-m = "0.6"
2324
cortex-m-rt = "0.6"
2425
embedded-hal = "0.2"

src/serial.rs

Lines changed: 115 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,15 @@
11
//! Serial
22
3-
use core::convert::Infallible;
4-
use core::marker::PhantomData;
5-
use core::ptr;
6-
7-
use crate::hal::blocking::serial::write::Default;
8-
use crate::hal::serial;
9-
use crate::pac::{USART1, USART2, USART3};
3+
use crate::{
4+
gpio::{gpioa, gpiob, gpioc, AF7},
5+
hal::{blocking, serial},
6+
pac::{USART1, USART2, USART3},
7+
rcc::{Clocks, APB1, APB2},
8+
time::Bps,
9+
};
10+
use core::{convert::Infallible, marker::PhantomData, ptr};
1011
use nb;
1112

12-
use crate::gpio::gpioa::{PA10, PA2, PA3, PA9};
13-
#[cfg(any(
14-
feature = "stm32f301",
15-
feature = "stm32f318",
16-
feature = "stm32f302",
17-
feature = "stm32f303",
18-
feature = "stm32f334",
19-
feature = "stm32f328",
20-
feature = "stm32f358",
21-
feature = "stm32f398"
22-
))]
23-
use crate::gpio::gpiob::PB11;
24-
use crate::gpio::gpiob::{PB10, PB6, PB7};
25-
use crate::gpio::gpioc::{PC10, PC11, PC4, PC5};
2613
#[cfg(any(
2714
feature = "stm32f302",
2815
feature = "stm32f303xb",
@@ -36,24 +23,20 @@ use crate::gpio::gpioc::{PC10, PC11, PC4, PC5};
3623
feature = "stm32f358",
3724
feature = "stm32f398"
3825
))]
39-
use crate::gpio::gpiod::{PD5, PD6, PD8, PD9};
40-
#[cfg(any(
41-
feature = "stm32f302",
42-
feature = "stm32f303xb",
43-
feature = "stm32f303xc",
44-
feature = "stm32f303xd",
45-
feature = "stm32f303xe",
46-
feature = "stm32f373",
47-
feature = "stm32f378",
48-
feature = "stm32f328",
49-
feature = "stm32f358",
50-
feature = "stm32f398"
51-
))]
52-
use crate::gpio::gpioe::{PE0, PE1, PE15};
26+
use crate::gpio::{gpiod, gpioe};
27+
28+
#[cfg(feature = "stm32f303")]
29+
mod dma_imports {
30+
pub use crate::dma;
31+
pub use as_slice::{AsMutSlice, AsSlice};
32+
pub use core::{
33+
ops::{Deref, DerefMut},
34+
pin::Pin,
35+
};
36+
}
5337

54-
use crate::gpio::AF7;
55-
use crate::rcc::{Clocks, APB1, APB2};
56-
use crate::time::Bps;
38+
#[cfg(feature = "stm32f303")]
39+
use dma_imports::*;
5740

5841
/// Interrupt event
5942
pub enum Event {
@@ -85,9 +68,9 @@ pub unsafe trait TxPin<USART> {}
8568
/// RX pin - DO NOT IMPLEMENT THIS TRAIT
8669
pub unsafe trait RxPin<USART> {}
8770

88-
unsafe impl TxPin<USART1> for PA9<AF7> {}
89-
unsafe impl TxPin<USART1> for PB6<AF7> {}
90-
unsafe impl TxPin<USART1> for PC4<AF7> {}
71+
unsafe impl TxPin<USART1> for gpioa::PA9<AF7> {}
72+
unsafe impl TxPin<USART1> for gpiob::PB6<AF7> {}
73+
unsafe impl TxPin<USART1> for gpioc::PC4<AF7> {}
9174
#[cfg(any(
9275
feature = "stm32f302",
9376
feature = "stm32f303xb",
@@ -100,11 +83,11 @@ unsafe impl TxPin<USART1> for PC4<AF7> {}
10083
feature = "stm32f358",
10184
feature = "stm32f398"
10285
))]
103-
unsafe impl TxPin<USART1> for PE0<AF7> {}
86+
unsafe impl TxPin<USART1> for gpioe::PE0<AF7> {}
10487

105-
unsafe impl RxPin<USART1> for PA10<AF7> {}
106-
unsafe impl RxPin<USART1> for PB7<AF7> {}
107-
unsafe impl RxPin<USART1> for PC5<AF7> {}
88+
unsafe impl RxPin<USART1> for gpioa::PA10<AF7> {}
89+
unsafe impl RxPin<USART1> for gpiob::PB7<AF7> {}
90+
unsafe impl RxPin<USART1> for gpioc::PC5<AF7> {}
10891
#[cfg(any(
10992
feature = "stm32f302",
11093
feature = "stm32f303xb",
@@ -117,11 +100,11 @@ unsafe impl RxPin<USART1> for PC5<AF7> {}
117100
feature = "stm32f358",
118101
feature = "stm32f398"
119102
))]
120-
unsafe impl RxPin<USART1> for PE1<AF7> {}
103+
unsafe impl RxPin<USART1> for gpioe::PE1<AF7> {}
121104

122-
unsafe impl TxPin<USART2> for PA2<AF7> {}
123-
// unsafe impl TxPin<USART2> for PA14<AF7> {}
124-
// unsafe impl TxPin<USART2> for PB3<AF7> {}
105+
unsafe impl TxPin<USART2> for gpioa::PA2<AF7> {}
106+
// unsafe impl TxPin<USART2> for gpioa::PA14<AF7> {}
107+
// unsafe impl TxPin<USART2> for gpiob::PB3<AF7> {}
125108
#[cfg(any(
126109
feature = "stm32f302",
127110
feature = "stm32f303xb",
@@ -135,11 +118,11 @@ unsafe impl TxPin<USART2> for PA2<AF7> {}
135118
feature = "stm32f358",
136119
feature = "stm32f398"
137120
))]
138-
unsafe impl TxPin<USART2> for PD5<AF7> {}
121+
unsafe impl TxPin<USART2> for gpiod::PD5<AF7> {}
139122

140-
unsafe impl RxPin<USART2> for PA3<AF7> {}
141-
// unsafe impl RxPin<USART2> for PA15<AF7> {}
142-
// unsafe impl RxPin<USART2> for PB4<AF7> {}
123+
unsafe impl RxPin<USART2> for gpioa::PA3<AF7> {}
124+
// unsafe impl RxPin<USART2> for gpioa::PA15<AF7> {}
125+
// unsafe impl RxPin<USART2> for gpiob::PB4<AF7> {}
143126
#[cfg(any(
144127
feature = "stm32f302",
145128
feature = "stm32f303xb",
@@ -153,10 +136,10 @@ unsafe impl RxPin<USART2> for PA3<AF7> {}
153136
feature = "stm32f358",
154137
feature = "stm32f398"
155138
))]
156-
unsafe impl RxPin<USART2> for PD6<AF7> {}
139+
unsafe impl RxPin<USART2> for gpiod::PD6<AF7> {}
157140

158-
unsafe impl TxPin<USART3> for PB10<AF7> {}
159-
unsafe impl TxPin<USART3> for PC10<AF7> {}
141+
unsafe impl TxPin<USART3> for gpiob::PB10<AF7> {}
142+
unsafe impl TxPin<USART3> for gpioc::PC10<AF7> {}
160143
#[cfg(any(
161144
feature = "stm32f302",
162145
feature = "stm32f303xb",
@@ -170,7 +153,7 @@ unsafe impl TxPin<USART3> for PC10<AF7> {}
170153
feature = "stm32f358",
171154
feature = "stm32f398"
172155
))]
173-
unsafe impl TxPin<USART3> for PD8<AF7> {}
156+
unsafe impl TxPin<USART3> for gpiod::PD8<AF7> {}
174157

175158
#[cfg(any(
176159
feature = "stm32f301",
@@ -182,8 +165,8 @@ unsafe impl TxPin<USART3> for PD8<AF7> {}
182165
feature = "stm32f358",
183166
feature = "stm32f398"
184167
))]
185-
unsafe impl RxPin<USART3> for PB11<AF7> {}
186-
unsafe impl RxPin<USART3> for PC11<AF7> {}
168+
unsafe impl RxPin<USART3> for gpiob::PB11<AF7> {}
169+
unsafe impl RxPin<USART3> for gpioc::PC11<AF7> {}
187170
#[cfg(any(
188171
feature = "stm32f302",
189172
feature = "stm32f303xb",
@@ -197,7 +180,7 @@ unsafe impl RxPin<USART3> for PC11<AF7> {}
197180
feature = "stm32f358",
198181
feature = "stm32f398"
199182
))]
200-
unsafe impl RxPin<USART3> for PD9<AF7> {}
183+
unsafe impl RxPin<USART3> for gpiod::PD9<AF7> {}
201184
#[cfg(any(
202185
feature = "stm32f302",
203186
feature = "stm32f303xb",
@@ -210,7 +193,7 @@ unsafe impl RxPin<USART3> for PD9<AF7> {}
210193
feature = "stm32f358",
211194
feature = "stm32f398"
212195
))]
213-
unsafe impl RxPin<USART3> for PE15<AF7> {}
196+
unsafe impl RxPin<USART3> for gpioe::PE15<AF7> {}
214197

215198
/// Serial abstraction
216199
pub struct Serial<USART, PINS> {
@@ -251,21 +234,21 @@ macro_rules! hal {
251234
apb.rstr().modify(|_, w| w.$usartXrst().set_bit());
252235
apb.rstr().modify(|_, w| w.$usartXrst().clear_bit());
253236

254-
// disable hardware flow control
255-
// TODO enable DMA
256-
// usart.cr3.write(|w| w.rtse().clear_bit().ctse().clear_bit());
257-
258237
let brr = clocks.$pclkX().0 / baud_rate.0;
259238
assert!(brr >= 16, "impossible baud rate");
260239
// NOTE(write): uses all bits of this register.
261240
usart.brr.write(|w| unsafe { w.bits(brr) });
262241

263-
// UE: enable USART
264-
// RE: enable receiver
265-
// TE: enable transceiver
266-
usart
267-
.cr1
268-
.modify(|_, w| w.ue().set_bit().re().set_bit().te().set_bit());
242+
usart.cr3.modify(|_, w| {
243+
w.dmar().enabled(); // enable DMA for reception
244+
w.dmat().enabled() // enable DMA for transmission
245+
});
246+
247+
usart.cr1.modify(|_, w| {
248+
w.ue().enabled(); // enable USART
249+
w.re().enabled(); // enable receiver
250+
w.te().enabled() // enable transmitter
251+
});
269252

270253
Serial { usart, pins }
271254
}
@@ -380,7 +363,67 @@ macro_rules! hal {
380363
}
381364
}
382365

383-
impl Default<u8> for Tx<$USARTX> {}
366+
impl blocking::serial::write::Default<u8> for Tx<$USARTX> {}
367+
368+
#[cfg(feature = "stm32f303")]
369+
impl Rx<$USARTX> {
370+
/// Fill the buffer with received data using DMA.
371+
pub fn read_all<B, C>(
372+
self,
373+
mut buffer: Pin<B>,
374+
mut channel: C
375+
) -> dma::Transfer<B, C, Self>
376+
where
377+
Self: dma::Target<C>,
378+
B: DerefMut + 'static,
379+
B::Target: AsMutSlice<Element = u8> + Unpin,
380+
C: dma::Channel,
381+
{
382+
// NOTE(unsafe) taking the address of a register
383+
let pa = unsafe { &(*$USARTX::ptr()).rdr } as *const _ as u32;
384+
channel.set_peripheral_address(pa, dma::Increment::Disable);
385+
386+
let slice = buffer.as_mut_slice();
387+
let (ma, len) = (slice.as_mut_ptr() as u32, slice.len());
388+
channel.set_memory_address(ma, dma::Increment::Enable);
389+
channel.set_transfer_length(len);
390+
channel.set_word_size(dma::WordSize::Bits8);
391+
392+
channel.set_direction(dma::Direction::FromPeripheral);
393+
394+
unsafe { dma::Transfer::start(buffer, channel, self) }
395+
}
396+
}
397+
398+
#[cfg(feature = "stm32f303")]
399+
impl Tx<$USARTX> {
400+
/// Transmit all data in the buffer using DMA.
401+
pub fn write_all<B, C>(
402+
self,
403+
buffer: Pin<B>,
404+
mut channel: C
405+
) -> dma::Transfer<B, C, Self>
406+
where
407+
Self: dma::Target<C>,
408+
B: Deref + 'static,
409+
B::Target: AsSlice<Element = u8>,
410+
C: dma::Channel,
411+
{
412+
// NOTE(unsafe) taking the address of a register
413+
let pa = unsafe { &(*$USARTX::ptr()).tdr } as *const _ as u32;
414+
channel.set_peripheral_address(pa, dma::Increment::Disable);
415+
416+
let slice = buffer.as_slice();
417+
let (ma, len) = (slice.as_ptr() as u32, slice.len());
418+
channel.set_memory_address(ma, dma::Increment::Enable);
419+
channel.set_transfer_length(len);
420+
channel.set_word_size(dma::WordSize::Bits8);
421+
422+
channel.set_direction(dma::Direction::FromMemory);
423+
424+
unsafe { dma::Transfer::start(buffer, channel, self) }
425+
}
426+
}
384427
)+
385428
}
386429
}

0 commit comments

Comments
 (0)