aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob McWhirter <[email protected]>2021-07-01 13:28:33 -0400
committerGitHub <[email protected]>2021-07-01 13:28:33 -0400
commite7a4a72977c068682748e85ea522dc66c7cf6146 (patch)
tree65b9a3a3021f9c3f5102d0487239f8a45e5cc311
parente55c89f890d6ca6eaf568e1f701643525c999ebc (diff)
parent8f94123ca4a61240555c9724060c415a51fd95cb (diff)
Merge pull request #264 from bobmcwhirter/usartv3
Add USARTv3 support.
-rw-r--r--embassy-stm32/src/dma/mod.rs2
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/usart/mod.rs82
-rw-r--r--embassy-stm32/src/usart/v1.rs45
-rw-r--r--embassy-stm32/src/usart/v3.rs121
-rw-r--r--examples/stm32h7/src/bin/usart.rs99
-rw-r--r--examples/stm32l4/src/bin/usart.rs97
m---------stm32-data0
-rw-r--r--stm32-metapac/gen/src/lib.rs1
9 files changed, 398 insertions, 51 deletions
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 371741ffd..466cfa033 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -1,9 +1,11 @@
1#![macro_use] 1#![macro_use]
2 2
3#[cfg(dma)]
3#[cfg_attr(dma_v1, path = "v1.rs")] 4#[cfg_attr(dma_v1, path = "v1.rs")]
4#[cfg_attr(dma_v2, path = "v2.rs")] 5#[cfg_attr(dma_v2, path = "v2.rs")]
5mod _version; 6mod _version;
6 7
8#[cfg(dma)]
7#[allow(unused)] 9#[allow(unused)]
8pub use _version::*; 10pub use _version::*;
9 11
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 9ba7bbe4c..76a6ecd88 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -26,7 +26,7 @@ pub mod adc;
26pub mod clock; 26pub mod clock;
27#[cfg(dac)] 27#[cfg(dac)]
28pub mod dac; 28pub mod dac;
29#[cfg(dma)] 29#[cfg(any(dma, dmamux))]
30pub mod dma; 30pub mod dma;
31#[cfg(all(eth, feature = "net"))] 31#[cfg(all(eth, feature = "net"))]
32pub mod eth; 32pub mod eth;
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index a75793f84..2fa758ecc 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -2,6 +2,7 @@
2 2
3#[cfg_attr(usart_v1, path = "v1.rs")] 3#[cfg_attr(usart_v1, path = "v1.rs")]
4#[cfg_attr(usart_v2, path = "v2.rs")] 4#[cfg_attr(usart_v2, path = "v2.rs")]
5#[cfg_attr(usart_v3, path = "v3.rs")]
5mod _version; 6mod _version;
6use crate::peripherals; 7use crate::peripherals;
7pub use _version::*; 8pub use _version::*;
@@ -10,6 +11,51 @@ use crate::gpio::Pin;
10use crate::pac::usart::Usart; 11use crate::pac::usart::Usart;
11use crate::rcc::RccPeripheral; 12use crate::rcc::RccPeripheral;
12 13
14#[derive(Clone, Copy, PartialEq, Eq, Debug)]
15pub enum DataBits {
16 DataBits8,
17 DataBits9,
18}
19
20#[derive(Clone, Copy, PartialEq, Eq, Debug)]
21pub enum Parity {
22 ParityNone,
23 ParityEven,
24 ParityOdd,
25}
26
27#[derive(Clone, Copy, PartialEq, Eq, Debug)]
28pub enum StopBits {
29 #[doc = "1 stop bit"]
30 STOP1,
31 #[doc = "0.5 stop bits"]
32 STOP0P5,
33 #[doc = "2 stop bits"]
34 STOP2,
35 #[doc = "1.5 stop bits"]
36 STOP1P5,
37}
38
39#[non_exhaustive]
40#[derive(Clone, Copy, PartialEq, Eq, Debug)]
41pub struct Config {
42 pub baudrate: u32,
43 pub data_bits: DataBits,
44 pub stop_bits: StopBits,
45 pub parity: Parity,
46}
47
48impl Default for Config {
49 fn default() -> Self {
50 Self {
51 baudrate: 115200,
52 data_bits: DataBits::DataBits8,
53 stop_bits: StopBits::STOP1,
54 parity: Parity::ParityNone,
55 }
56 }
57}
58
13/// Serial error 59/// Serial error
14#[derive(Debug, Eq, PartialEq, Copy, Clone)] 60#[derive(Debug, Eq, PartialEq, Copy, Clone)]
15#[non_exhaustive] 61#[non_exhaustive]
@@ -27,7 +73,7 @@ pub enum Error {
27pub(crate) mod sealed { 73pub(crate) mod sealed {
28 use super::*; 74 use super::*;
29 75
30 #[cfg(dma)] 76 #[cfg(any(dma, dmamux))]
31 use crate::dma::WriteDma; 77 use crate::dma::WriteDma;
32 78
33 pub trait Instance { 79 pub trait Instance {
@@ -49,10 +95,10 @@ pub(crate) mod sealed {
49 fn af_num(&self) -> u8; 95 fn af_num(&self) -> u8;
50 } 96 }
51 97
52 #[cfg(dma)] 98 #[cfg(any(dma, dmamux))]
53 pub trait RxDma<T: Instance> {} 99 pub trait RxDma<T: Instance> {}
54 100
55 #[cfg(dma)] 101 #[cfg(any(dma, dmamux))]
56 pub trait TxDma<T: Instance>: WriteDma<T> {} 102 pub trait TxDma<T: Instance>: WriteDma<T> {}
57} 103}
58 104
@@ -63,9 +109,10 @@ pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {}
63pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {} 109pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {}
64pub trait CkPin<T: Instance>: sealed::CkPin<T> {} 110pub trait CkPin<T: Instance>: sealed::CkPin<T> {}
65 111
66#[cfg(dma)] 112#[cfg(any(dma, dmamux))]
67pub trait RxDma<T: Instance>: sealed::RxDma<T> {} 113pub trait RxDma<T: Instance>: sealed::RxDma<T> {}
68#[cfg(dma)] 114
115#[cfg(any(dma, dmamux))]
69pub trait TxDma<T: Instance>: sealed::TxDma<T> {} 116pub trait TxDma<T: Instance>: sealed::TxDma<T> {}
70 117
71crate::pac::peripherals!( 118crate::pac::peripherals!(
@@ -93,6 +140,9 @@ macro_rules! impl_pin {
93} 140}
94 141
95crate::pac::peripheral_pins!( 142crate::pac::peripheral_pins!(
143
144 // USART
145
96 ($inst:ident, usart, USART, $pin:ident, TX, $af:expr) => { 146 ($inst:ident, usart, USART, $pin:ident, TX, $af:expr) => {
97 impl_pin!($inst, $pin, TxPin, $af); 147 impl_pin!($inst, $pin, TxPin, $af);
98 }; 148 };
@@ -112,4 +162,26 @@ crate::pac::peripheral_pins!(
112 ($inst:ident, usart, USART, $pin:ident, CK, $af:expr) => { 162 ($inst:ident, usart, USART, $pin:ident, CK, $af:expr) => {
113 impl_pin!($inst, $pin, CkPin, $af); 163 impl_pin!($inst, $pin, CkPin, $af);
114 }; 164 };
165
166 // UART
167
168 ($inst:ident, uart, UART, $pin:ident, TX, $af:expr) => {
169 impl_pin!($inst, $pin, TxPin, $af);
170 };
171
172 ($inst:ident, uart, UART, $pin:ident, RX, $af:expr) => {
173 impl_pin!($inst, $pin, RxPin, $af);
174 };
175
176 ($inst:ident, uart, UART, $pin:ident, CTS, $af:expr) => {
177 impl_pin!($inst, $pin, CtsPin, $af);
178 };
179
180 ($inst:ident, uart, UART, $pin:ident, RTS, $af:expr) => {
181 impl_pin!($inst, $pin, RtsPin, $af);
182 };
183
184 ($inst:ident, uart, UART, $pin:ident, CK, $af:expr) => {
185 impl_pin!($inst, $pin, CkPin, $af);
186 };
115); 187);
diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs
index 6c5a12441..169938952 100644
--- a/embassy-stm32/src/usart/v1.rs
+++ b/embassy-stm32/src/usart/v1.rs
@@ -7,51 +7,6 @@ use crate::pac::usart::{regs, vals};
7 7
8use super::*; 8use super::*;
9 9
10#[derive(Clone, Copy, PartialEq, Eq, Debug)]
11pub enum DataBits {
12 DataBits8,
13 DataBits9,
14}
15
16#[derive(Clone, Copy, PartialEq, Eq, Debug)]
17pub enum Parity {
18 ParityNone,
19 ParityEven,
20 ParityOdd,
21}
22
23#[derive(Clone, Copy, PartialEq, Eq, Debug)]
24pub enum StopBits {
25 #[doc = "1 stop bit"]
26 STOP1,
27 #[doc = "0.5 stop bits"]
28 STOP0P5,
29 #[doc = "2 stop bits"]
30 STOP2,
31 #[doc = "1.5 stop bits"]
32 STOP1P5,
33}
34
35#[non_exhaustive]
36#[derive(Clone, Copy, PartialEq, Eq, Debug)]
37pub struct Config {
38 pub baudrate: u32,
39 pub data_bits: DataBits,
40 pub stop_bits: StopBits,
41 pub parity: Parity,
42}
43
44impl Default for Config {
45 fn default() -> Self {
46 Self {
47 baudrate: 115200,
48 data_bits: DataBits::DataBits8,
49 stop_bits: StopBits::STOP1,
50 parity: Parity::ParityNone,
51 }
52 }
53}
54
55pub struct Uart<'d, T: Instance> { 10pub struct Uart<'d, T: Instance> {
56 inner: T, 11 inner: T,
57 phantom: PhantomData<&'d mut T>, 12 phantom: PhantomData<&'d mut T>,
diff --git a/embassy-stm32/src/usart/v3.rs b/embassy-stm32/src/usart/v3.rs
new file mode 100644
index 000000000..1e9051443
--- /dev/null
+++ b/embassy-stm32/src/usart/v3.rs
@@ -0,0 +1,121 @@
1use core::marker::PhantomData;
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 / 2)) / 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_m(0, vals::M0::BIT8);
43 w.set_pce(config.parity != Parity::ParityNone);
44 w.set_ps(match config.parity {
45 Parity::ParityOdd => vals::Ps::ODD,
46 Parity::ParityEven => vals::Ps::EVEN,
47 _ => vals::Ps::EVEN,
48 });
49 });
50 r.cr2().write(|_w| {});
51 r.cr3().write(|_w| {});
52 }
53
54 Self {
55 inner,
56 phantom: PhantomData,
57 }
58 }
59
60 #[cfg(dma)]
61 pub async fn write_dma(&mut self, ch: &mut impl TxDma<T>, buffer: &[u8]) -> Result<(), Error> {
62 unsafe {
63 self.inner.regs().cr3().modify(|reg| {
64 reg.set_dmat(true);
65 });
66 }
67 let r = self.inner.regs();
68 let dst = r.tdr().ptr() as *mut u8;
69 ch.transfer(buffer, dst).await;
70 Ok(())
71 }
72
73 pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
74 unsafe {
75 let r = self.inner.regs();
76 for b in buffer {
77 loop {
78 let sr = r.isr().read();
79 if sr.pe() {
80 r.rdr().read();
81 return Err(Error::Parity);
82 } else if sr.fe() {
83 r.rdr().read();
84 return Err(Error::Framing);
85 } else if sr.ne() {
86 r.rdr().read();
87 return Err(Error::Noise);
88 } else if sr.ore() {
89 r.rdr().read();
90 return Err(Error::Overrun);
91 } else if sr.rxne() {
92 break;
93 }
94 }
95 *b = r.rdr().read().0 as u8;
96 }
97 }
98 Ok(())
99 }
100}
101
102impl<'d, T: Instance> embedded_hal::blocking::serial::Write<u8> for Uart<'d, T> {
103 type Error = Error;
104 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
105 unsafe {
106 let r = self.inner.regs();
107 for &b in buffer {
108 while !r.isr().read().txe() {}
109 r.tdr().write_value(regs::Tdr(b as u32))
110 }
111 }
112 Ok(())
113 }
114 fn bflush(&mut self) -> Result<(), Self::Error> {
115 unsafe {
116 let r = self.inner.regs();
117 while !r.isr().read().tc() {}
118 }
119 Ok(())
120 }
121}
diff --git a/examples/stm32h7/src/bin/usart.rs b/examples/stm32h7/src/bin/usart.rs
new file mode 100644
index 000000000..b8524f2c0
--- /dev/null
+++ b/examples/stm32h7/src/bin/usart.rs
@@ -0,0 +1,99 @@
1
2#![no_std]
3#![no_main]
4#![feature(trait_alias)]
5#![feature(min_type_alias_impl_trait)]
6#![feature(impl_trait_in_bindings)]
7#![feature(type_alias_impl_trait)]
8#![allow(incomplete_features)]
9
10#[path = "../example_common.rs"]
11mod example_common;
12use cortex_m::prelude::_embedded_hal_blocking_serial_Write;
13use embassy::executor::Executor;
14use embassy::time::Clock;
15use embassy::util::Forever;
16use embassy_stm32::usart::{Config, Uart};
17use example_common::*;
18
19use stm32h7xx_hal as hal;
20use hal::prelude::*;
21
22use cortex_m_rt::entry;
23use stm32h7::stm32h743 as pac;
24
25#[embassy::task]
26async fn main_task() {
27 let p = embassy_stm32::init(Default::default());
28
29 let config = Config::default();
30 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, config);
31
32 usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap();
33 info!("wrote Hello, starting echo");
34
35 let mut buf = [0u8; 1];
36 loop {
37 usart.read(&mut buf).unwrap();
38 usart.bwrite_all(&buf).unwrap();
39 }
40}
41
42struct ZeroClock;
43
44impl Clock for ZeroClock {
45 fn now(&self) -> u64 {
46 0
47 }
48}
49
50static EXECUTOR: Forever<Executor> = Forever::new();
51
52#[entry]
53fn main() -> ! {
54 info!("Hello World!");
55
56 let pp = pac::Peripherals::take().unwrap();
57
58 let pwrcfg = pp.PWR.constrain().freeze();
59
60 let rcc = pp.RCC.constrain();
61
62 let ccdr = rcc
63 .sys_ck(96.mhz())
64 .pclk1(48.mhz())
65 .pclk2(48.mhz())
66 .pclk3(48.mhz())
67 .pclk4(48.mhz())
68 .pll1_q_ck(48.mhz())
69 .freeze(pwrcfg, &pp.SYSCFG);
70
71 let pp = unsafe { pac::Peripherals::steal() };
72
73 pp.DBGMCU.cr.modify(|_, w| {
74 w.dbgsleep_d1().set_bit();
75 w.dbgstby_d1().set_bit();
76 w.dbgstop_d1().set_bit();
77 w.d1dbgcken().set_bit();
78 w
79 });
80
81 pp.RCC.ahb4enr.modify(|_, w| {
82 w.gpioaen().set_bit();
83 w.gpioben().set_bit();
84 w.gpiocen().set_bit();
85 w.gpioden().set_bit();
86 w.gpioeen().set_bit();
87 w.gpiofen().set_bit();
88 w
89 });
90
91
92 unsafe { embassy::time::set_clock(&ZeroClock) };
93
94 let executor = EXECUTOR.put(Executor::new());
95
96 executor.run(|spawner| {
97 unwrap!(spawner.spawn(main_task()));
98 })
99} \ No newline at end of file
diff --git a/examples/stm32l4/src/bin/usart.rs b/examples/stm32l4/src/bin/usart.rs
new file mode 100644
index 000000000..5b6d9eaa1
--- /dev/null
+++ b/examples/stm32l4/src/bin/usart.rs
@@ -0,0 +1,97 @@
1
2#![no_std]
3#![no_main]
4#![feature(trait_alias)]
5#![feature(min_type_alias_impl_trait)]
6#![feature(impl_trait_in_bindings)]
7#![feature(type_alias_impl_trait)]
8#![allow(incomplete_features)]
9
10#[path = "../example_common.rs"]
11mod example_common;
12use cortex_m::prelude::_embedded_hal_blocking_serial_Write;
13use embassy::executor::Executor;
14use embassy::time::Clock;
15use embassy::util::Forever;
16use embassy_stm32::usart::{Config, Uart};
17use example_common::*;
18
19use cortex_m_rt::entry;
20use stm32l4::stm32l4x5 as pac;
21
22#[embassy::task]
23async fn main_task() {
24 let p = embassy_stm32::init(Default::default());
25
26 let config = Config::default();
27 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, config);
28
29 usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap();
30 info!("wrote Hello, starting echo");
31
32 let mut buf = [0u8; 1];
33 loop {
34 usart.read(&mut buf).unwrap();
35 usart.bwrite_all(&buf).unwrap();
36 }
37}
38
39struct ZeroClock;
40
41impl Clock for ZeroClock {
42 fn now(&self) -> u64 {
43 0
44 }
45}
46
47static EXECUTOR: Forever<Executor> = Forever::new();
48
49#[entry]
50fn main() -> ! {
51 info!("Hello World!");
52
53 let pp = pac::Peripherals::take().unwrap();
54
55 pp.DBGMCU.cr.modify(|_, w| {
56 w.dbg_sleep().set_bit();
57 w.dbg_standby().set_bit();
58 w.dbg_stop().set_bit()
59 });
60
61 pp.RCC.ahb1enr.modify(|_, w| {
62 w.dma1en().set_bit();
63 w
64 });
65
66 pp.RCC.ahb2enr.modify(|_, w| {
67 w.gpioaen().set_bit();
68 w.gpioben().set_bit();
69 w.gpiocen().set_bit();
70 w.gpioden().set_bit();
71 w.gpioeen().set_bit();
72 w.gpiofen().set_bit();
73 w
74 });
75
76 pp.RCC.apb1enr1.modify(|_, w| {
77 w.uart4en().set_bit();
78 w
79 });
80
81 pp.RCC.apb2enr.modify(|_, w| {
82 w.syscfgen().set_bit();
83 w
84 });
85 //pp.RCC.apb1enr.modify(|_, w| {
86 //w.usart3en().enabled();
87 //w
88 //});
89
90 unsafe { embassy::time::set_clock(&ZeroClock) };
91
92 let executor = EXECUTOR.put(Executor::new());
93
94 executor.run(|spawner| {
95 unwrap!(spawner.spawn(main_task()));
96 })
97} \ No newline at end of file
diff --git a/stm32-data b/stm32-data
Subproject f0a6585b4806b1f7c6836126d063eaaf970cc5a Subproject 0877c27cb1332237e65d74700b7bfb768996ca6
diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs
index a552c8cea..8eae49111 100644
--- a/stm32-metapac/gen/src/lib.rs
+++ b/stm32-metapac/gen/src/lib.rs
@@ -311,6 +311,7 @@ pub fn gen(options: Options) {
311 311
312 for dma_request in &p.dma_requests { 312 for dma_request in &p.dma_requests {
313 let mut row = Vec::new(); 313 let mut row = Vec::new();
314 row.push(bi.module.clone());
314 row.push(name.clone()); 315 row.push(name.clone());
315 row.push(dma_request.0.clone()); 316 row.push(dma_request.0.clone());
316 row.push(dma_request.1.to_string()); 317 row.push(dma_request.1.to_string());