aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThales Fragoso <[email protected]>2021-07-04 15:40:33 -0300
committerBob McWhirter <[email protected]>2021-07-13 10:08:43 -0400
commita56ddfdc04a02d9de2dc474f5cc9dbae8cff1ab1 (patch)
tree603a7cb547663674792eb9c13907fa9c449c02df
parentf32caaeaafd77b15005612b6d8d039b101b36975 (diff)
STM: Add usart v2
-rw-r--r--embassy-stm32/src/bdma/v1.rs38
-rw-r--r--embassy-stm32/src/usart/v2.rs118
2 files changed, 143 insertions, 13 deletions
diff --git a/embassy-stm32/src/bdma/v1.rs b/embassy-stm32/src/bdma/v1.rs
index 584d531f7..13caf329b 100644
--- a/embassy-stm32/src/bdma/v1.rs
+++ b/embassy-stm32/src/bdma/v1.rs
@@ -35,13 +35,15 @@ impl State {
35static STATE: State = State::new(); 35static STATE: State = State::new();
36 36
37#[allow(unused)] 37#[allow(unused)]
38pub(crate) async unsafe fn transfer_p2m(ch: &mut impl Channel, src: *const u8, dst: &mut [u8]) { 38pub(crate) async unsafe fn transfer_p2m(
39 regs: pac::bdma::Ch,
40 state_number: usize,
41 src: *const u8,
42 dst: &mut [u8],
43) {
39 // ndtr is max 16 bits. 44 // ndtr is max 16 bits.
40 assert!(dst.len() <= 0xFFFF); 45 assert!(dst.len() <= 0xFFFF);
41 46
42 let regs: pac::bdma::Ch = ch.regs();
43 let state_number = ch.state_num();
44
45 // Reset status 47 // Reset status
46 // Generate a DMB here to flush the store buffer (M7) before enabling the DMA 48 // Generate a DMB here to flush the store buffer (M7) before enabling the DMA
47 STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release); 49 STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release);
@@ -82,13 +84,15 @@ pub(crate) async unsafe fn transfer_p2m(ch: &mut impl Channel, src: *const u8, d
82} 84}
83 85
84#[allow(unused)] 86#[allow(unused)]
85pub(crate) async unsafe fn transfer_m2p(ch: &mut impl Channel, src: &[u8], dst: *mut u8) { 87pub(crate) async unsafe fn transfer_m2p(
88 regs: pac::bdma::Ch,
89 state_number: usize,
90 src: &[u8],
91 dst: *mut u8,
92) {
86 // ndtr is max 16 bits. 93 // ndtr is max 16 bits.
87 assert!(src.len() <= 0xFFFF); 94 assert!(src.len() <= 0xFFFF);
88 95
89 let regs: pac::bdma::Ch = ch.regs();
90 let state_number = ch.state_num();
91
92 // Reset status 96 // Reset status
93 // Generate a DMB here to flush the store buffer (M7) before enabling the DMA 97 // Generate a DMB here to flush the store buffer (M7) before enabling the DMA
94 STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release); 98 STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release);
@@ -168,7 +172,7 @@ pub(crate) mod sealed {
168 } 172 }
169 173
170 pub trait Channel { 174 pub trait Channel {
171 fn dma_regs() -> &'static pac::bdma::Dma; 175 fn dma_regs() -> pac::bdma::Dma;
172 176
173 fn state_num(&self) -> usize; 177 fn state_num(&self) -> usize;
174 178
@@ -199,8 +203,8 @@ macro_rules! impl_dma_channel {
199 impl Channel for crate::peripherals::$channel_peri {} 203 impl Channel for crate::peripherals::$channel_peri {}
200 impl sealed::Channel for crate::peripherals::$channel_peri { 204 impl sealed::Channel for crate::peripherals::$channel_peri {
201 #[inline] 205 #[inline]
202 fn dma_regs() -> &'static pac::bdma::Dma { 206 fn dma_regs() -> pac::bdma::Dma {
203 &crate::pac::$dma_peri 207 crate::pac::$dma_peri
204 } 208 }
205 209
206 fn state_num(&self) -> usize { 210 fn state_num(&self) -> usize {
@@ -222,7 +226,11 @@ macro_rules! impl_dma_channel {
222 where 226 where
223 T: 'a, 227 T: 'a,
224 { 228 {
225 unsafe { transfer_m2p(self, buf, dst) } 229 use sealed::Channel as _Channel;
230
231 let state_num = self.state_num();
232 let regs = self.regs();
233 unsafe { transfer_m2p(regs, state_num, buf, dst) }
226 } 234 }
227 } 235 }
228 236
@@ -240,7 +248,11 @@ macro_rules! impl_dma_channel {
240 where 248 where
241 T: 'a, 249 T: 'a,
242 { 250 {
243 unsafe { transfer_p2m(self, src, buf) } 251 use sealed::Channel as _Channel;
252
253 let state_num = self.state_num();
254 let regs = self.regs();
255 unsafe { transfer_p2m(regs, state_num, src, buf) }
244 } 256 }
245 } 257 }
246 }; 258 };
diff --git a/embassy-stm32/src/usart/v2.rs b/embassy-stm32/src/usart/v2.rs
index 8b1378917..271eff850 100644
--- a/embassy-stm32/src/usart/v2.rs
+++ b/embassy-stm32/src/usart/v2.rs
@@ -1 +1,119 @@
1use core::marker::PhantomData;
1 2
3use embassy::util::Unborrow;
4use embassy_extras::unborrow;
5
6use crate::pac::usart::{regs, vals};
7
8use super::*;
9
10pub struct Uart<'d, T: Instance> {
11 inner: T,
12 phantom: PhantomData<&'d mut T>,
13}
14
15impl<'d, T: Instance> Uart<'d, T> {
16 pub fn new(
17 inner: impl Unborrow<Target = T>,
18 rx: impl Unborrow<Target = impl RxPin<T>>,
19 tx: impl Unborrow<Target = impl TxPin<T>>,
20 config: Config,
21 ) -> Self {
22 unborrow!(inner, rx, tx);
23
24 // Uncomment once we find all of the H7's UART clocks.
25 T::enable();
26 let pclk_freq = T::frequency();
27
28 // TODO: better calculation, including error checking and OVER8 if possible.
29 let div = pclk_freq.0 / config.baudrate;
30
31 let r = inner.regs();
32
33 unsafe {
34 rx.set_as_af(rx.af_num());
35 tx.set_as_af(tx.af_num());
36
37 r.brr().write_value(regs::Brr(div));
38 r.cr1().write(|w| {
39 w.set_ue(true);
40 w.set_te(true);
41 w.set_re(true);
42 w.set_m0(vals::M0::BIT8);
43 w.set_m1(vals::M1::M0);
44 w.set_pce(config.parity != Parity::ParityNone);
45 w.set_ps(match config.parity {
46 Parity::ParityOdd => vals::Ps::ODD,
47 Parity::ParityEven => vals::Ps::EVEN,
48 _ => vals::Ps::EVEN,
49 });
50 });
51 r.cr2().write(|_w| {});
52 r.cr3().write(|_w| {});
53 }
54
55 Self {
56 inner,
57 phantom: PhantomData,
58 }
59 }
60
61 #[cfg(dma)]
62 pub async fn write_dma(&mut self, ch: &mut impl TxDma<T>, buffer: &[u8]) -> Result<(), Error> {
63 unsafe {
64 self.inner.regs().cr3().modify(|reg| {
65 reg.set_dmat(true);
66 });
67 }
68 let r = self.inner.regs();
69 let dst = r.tdr().ptr() as *mut u8;
70 ch.transfer(buffer, dst).await;
71 Ok(())
72 }
73
74 pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
75 unsafe {
76 let r = self.inner.regs();
77 for b in buffer {
78 loop {
79 let sr = r.isr().read();
80 if sr.pe() {
81 r.rdr().read();
82 return Err(Error::Parity);
83 } else if sr.fe() {
84 r.rdr().read();
85 return Err(Error::Framing);
86 } else if sr.ore() {
87 r.rdr().read();
88 return Err(Error::Overrun);
89 } else if sr.rxne() {
90 break;
91 }
92 }
93 *b = r.rdr().read().0 as u8;
94 }
95 }
96 Ok(())
97 }
98}
99
100impl<'d, T: Instance> embedded_hal::blocking::serial::Write<u8> for Uart<'d, T> {
101 type Error = Error;
102 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
103 unsafe {
104 let r = self.inner.regs();
105 for &b in buffer {
106 while !r.isr().read().txe() {}
107 r.tdr().write(|w| w.set_dr(b as u16));
108 }
109 }
110 Ok(())
111 }
112 fn bflush(&mut self) -> Result<(), Self::Error> {
113 unsafe {
114 let r = self.inner.regs();
115 while !r.isr().read().tc() {}
116 }
117 Ok(())
118 }
119}