aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml1
-rw-r--r--embassy-stm32f4/Cargo.toml40
-rw-r--r--embassy-stm32f4/src/fmt.rs118
-rw-r--r--embassy-stm32f4/src/interrupt.rs129
-rw-r--r--embassy-stm32f4/src/lib.rs316
-rw-r--r--embassy-stm32f4/src/uarte.rs561
6 files changed, 1165 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 792804046..e1a1c34b5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,7 @@
3members = [ 3members = [
4 "embassy", 4 "embassy",
5 "embassy-nrf", 5 "embassy-nrf",
6 "embassy-stm32f4",
6 "embassy-macros", 7 "embassy-macros",
7 "examples", 8 "examples",
8] 9]
diff --git a/embassy-stm32f4/Cargo.toml b/embassy-stm32f4/Cargo.toml
new file mode 100644
index 000000000..52ecba612
--- /dev/null
+++ b/embassy-stm32f4/Cargo.toml
@@ -0,0 +1,40 @@
1[package]
2name = "embassy-stm32f4"
3version = "0.1.0"
4authors = ["Dario Nieuwenhuis <[email protected]>"]
5edition = "2018"
6
7[features]
8defmt-trace = [ ]
9defmt-debug = [ ]
10defmt-info = [ ]
11defmt-warn = [ ]
12defmt-error = [ ]
13
14stm32f401 = ["stm32f4xx-hal/stm32f401"]
15stm32f405 = ["stm32f4xx-hal/stm32f405"]
16stm32f407 = ["stm32f4xx-hal/stm32f407"]
17stm32f410 = ["stm32f4xx-hal/stm32f410"]
18stm32f411 = ["stm32f4xx-hal/stm32f411"]
19stm32f412 = ["stm32f4xx-hal/stm32f412"]
20stm32f413 = ["stm32f4xx-hal/stm32f413"]
21stm32f415 = ["stm32f4xx-hal/stm32f405"]
22stm32f417 = ["stm32f4xx-hal/stm32f407"]
23stm32f423 = ["stm32f4xx-hal/stm32f413"]
24stm32f427 = ["stm32f4xx-hal/stm32f427"]
25stm32f429 = ["stm32f4xx-hal/stm32f429"]
26stm32f437 = ["stm32f4xx-hal/stm32f427"]
27stm32f439 = ["stm32f4xx-hal/stm32f429"]
28stm32f446 = ["stm32f4xx-hal/stm32f446"]
29stm32f469 = ["stm32f4xx-hal/stm32f469"]
30stm32f479 = ["stm32f4xx-hal/stm32f469"]
31
32[dependencies]
33embassy = { version = "0.1.0", path = "../embassy" }
34
35defmt = { version = "0.1.3", optional = true }
36log = { version = "0.4.11", optional = true }
37cortex-m-rt = "0.6.13"
38cortex-m = { version = "0.6.4" }
39embedded-hal = { version = "0.2.4" }
40stm32f4xx-hal = { version = "0.8.3", features = ["rt"]}
diff --git a/embassy-stm32f4/src/fmt.rs b/embassy-stm32f4/src/fmt.rs
new file mode 100644
index 000000000..4da69766c
--- /dev/null
+++ b/embassy-stm32f4/src/fmt.rs
@@ -0,0 +1,118 @@
1#![macro_use]
2
3#[cfg(all(feature = "defmt", feature = "log"))]
4compile_error!("You may not enable both `defmt` and `log` features.");
5
6pub use fmt::*;
7
8#[cfg(feature = "defmt")]
9mod fmt {
10 pub use defmt::{
11 assert, assert_eq, assert_ne, debug, debug_assert, debug_assert_eq, debug_assert_ne, error,
12 info, panic, todo, trace, unreachable, unwrap, warn,
13 };
14}
15
16#[cfg(feature = "log")]
17mod fmt {
18 pub use core::{
19 assert, assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, panic, todo,
20 unreachable,
21 };
22 pub use log::{debug, error, info, trace, warn};
23}
24
25#[cfg(not(any(feature = "defmt", feature = "log")))]
26mod fmt {
27 #![macro_use]
28
29 pub use core::{
30 assert, assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, panic, todo,
31 unreachable,
32 };
33
34 #[macro_export]
35 macro_rules! trace {
36 ($($msg:expr),+ $(,)?) => {
37 ()
38 };
39 }
40
41 #[macro_export]
42 macro_rules! debug {
43 ($($msg:expr),+ $(,)?) => {
44 ()
45 };
46 }
47
48 #[macro_export]
49 macro_rules! info {
50 ($($msg:expr),+ $(,)?) => {
51 ()
52 };
53 }
54
55 #[macro_export]
56 macro_rules! warn {
57 ($($msg:expr),+ $(,)?) => {
58 ()
59 };
60 }
61
62 #[macro_export]
63 macro_rules! error {
64 ($($msg:expr),+ $(,)?) => {
65 ()
66 };
67 }
68}
69
70#[cfg(not(feature = "defmt"))]
71#[macro_export]
72macro_rules! unwrap {
73 ($arg:expr) => {
74 match $crate::fmt::Try::into_result($arg) {
75 ::core::result::Result::Ok(t) => t,
76 ::core::result::Result::Err(e) => {
77 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
78 }
79 }
80 };
81 ($arg:expr, $($msg:expr),+ $(,)? ) => {
82 match $crate::fmt::Try::into_result($arg) {
83 ::core::result::Result::Ok(t) => t,
84 ::core::result::Result::Err(e) => {
85 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
86 }
87 }
88 }
89}
90
91#[derive(Debug, Copy, Clone, Eq, PartialEq)]
92pub struct NoneError;
93
94pub trait Try {
95 type Ok;
96 type Error;
97 fn into_result(self) -> Result<Self::Ok, Self::Error>;
98}
99
100impl<T> Try for Option<T> {
101 type Ok = T;
102 type Error = NoneError;
103
104 #[inline]
105 fn into_result(self) -> Result<T, NoneError> {
106 self.ok_or(NoneError)
107 }
108}
109
110impl<T, E> Try for Result<T, E> {
111 type Ok = T;
112 type Error = E;
113
114 #[inline]
115 fn into_result(self) -> Self {
116 self
117 }
118}
diff --git a/embassy-stm32f4/src/interrupt.rs b/embassy-stm32f4/src/interrupt.rs
new file mode 100644
index 000000000..17fc9ab34
--- /dev/null
+++ b/embassy-stm32f4/src/interrupt.rs
@@ -0,0 +1,129 @@
1//! Interrupt management
2//!
3//! This module implements an API for managing interrupts compatible with
4//! nrf_softdevice::interrupt. Intended for switching between the two at compile-time.
5
6use core::sync::atomic::{compiler_fence, Ordering};
7
8use crate::pac::{NVIC, NVIC_PRIO_BITS};
9
10// Re-exports
11pub use crate::pac::Interrupt;
12pub use crate::pac::Interrupt::*; // needed for cortex-m-rt #[interrupt]
13pub use cortex_m::interrupt::{CriticalSection, Mutex};
14
15#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17#[repr(u8)]
18pub enum Priority {
19 Level0 = 0,
20 Level1 = 1,
21 Level2 = 2,
22 Level3 = 3,
23 Level4 = 4,
24 Level5 = 5,
25 Level6 = 6,
26 Level7 = 7,
27}
28
29impl Priority {
30 #[inline]
31 fn to_nvic(self) -> u8 {
32 (self as u8) << (8 - NVIC_PRIO_BITS)
33 }
34
35 #[inline]
36 fn from_nvic(priority: u8) -> Self {
37 match priority >> (8 - NVIC_PRIO_BITS) {
38 0 => Self::Level0,
39 1 => Self::Level1,
40 2 => Self::Level2,
41 3 => Self::Level3,
42 4 => Self::Level4,
43 5 => Self::Level5,
44 6 => Self::Level6,
45 7 => Self::Level7,
46 _ => unreachable!(),
47 }
48 }
49}
50
51#[inline]
52pub fn free<F, R>(f: F) -> R
53where
54 F: FnOnce(&CriticalSection) -> R,
55{
56 unsafe {
57 // TODO: assert that we're in privileged level
58 // Needed because disabling irqs in non-privileged level is a noop, which would break safety.
59
60 let primask: u32;
61 asm!("mrs {}, PRIMASK", out(reg) primask);
62
63 asm!("cpsid i");
64
65 // Prevent compiler from reordering operations inside/outside the critical section.
66 compiler_fence(Ordering::SeqCst);
67
68 let r = f(&CriticalSection::new());
69
70 compiler_fence(Ordering::SeqCst);
71
72 if primask & 1 == 0 {
73 asm!("cpsie i");
74 }
75
76 r
77 }
78}
79
80#[inline]
81pub fn enable(irq: Interrupt) {
82 unsafe {
83 NVIC::unmask(irq);
84 }
85}
86
87#[inline]
88pub fn disable(irq: Interrupt) {
89 NVIC::mask(irq);
90}
91
92#[inline]
93pub fn is_active(irq: Interrupt) -> bool {
94 NVIC::is_active(irq)
95}
96
97#[inline]
98pub fn is_enabled(irq: Interrupt) -> bool {
99 NVIC::is_enabled(irq)
100}
101
102#[inline]
103pub fn is_pending(irq: Interrupt) -> bool {
104 NVIC::is_pending(irq)
105}
106
107#[inline]
108pub fn pend(irq: Interrupt) {
109 NVIC::pend(irq)
110}
111
112#[inline]
113pub fn unpend(irq: Interrupt) {
114 NVIC::unpend(irq)
115}
116
117#[inline]
118pub fn get_priority(irq: Interrupt) -> Priority {
119 Priority::from_nvic(NVIC::get_priority(irq))
120}
121
122#[inline]
123pub fn set_priority(irq: Interrupt, prio: Priority) {
124 unsafe {
125 cortex_m::peripheral::Peripherals::steal()
126 .NVIC
127 .set_priority(irq, prio.to_nvic())
128 }
129}
diff --git a/embassy-stm32f4/src/lib.rs b/embassy-stm32f4/src/lib.rs
new file mode 100644
index 000000000..fc4110889
--- /dev/null
+++ b/embassy-stm32f4/src/lib.rs
@@ -0,0 +1,316 @@
1#![no_std]
2#![feature(generic_associated_types)]
3#![feature(asm)]
4#![feature(type_alias_impl_trait)]
5
6#[cfg(not(any(
7 feature = "stm32f401",
8 feature = "stm32f405",
9 feature = "stm32f407",
10 feature = "stm32f410",
11 feature = "stm32f411",
12 feature = "stm32f412",
13 feature = "stm32f413",
14 feature = "stm32f415",
15 feature = "stm32f417",
16 feature = "stm32f423",
17 feature = "stm32f427",
18 feature = "stm32f429",
19 feature = "stm32f437",
20 feature = "stm32f439",
21 feature = "stm32f446",
22 feature = "stm32f469",
23 feature = "stm32f479",
24)))]
25compile_error!(
26 "No chip feature activated. You must activate exactly one of the following features: "
27);
28
29#[cfg(any(
30 all(feature = "stm32f401", feature = "stm32f405"),
31 all(feature = "stm32f401", feature = "stm32f407"),
32 all(feature = "stm32f401", feature = "stm32f410"),
33 all(feature = "stm32f401", feature = "stm32f411"),
34 all(feature = "stm32f401", feature = "stm32f412"),
35 all(feature = "stm32f401", feature = "stm32f413"),
36 all(feature = "stm32f401", feature = "stm32f415"),
37 all(feature = "stm32f401", feature = "stm32f417"),
38 all(feature = "stm32f401", feature = "stm32f423"),
39 all(feature = "stm32f401", feature = "stm32f427"),
40 all(feature = "stm32f401", feature = "stm32f429"),
41 all(feature = "stm32f401", feature = "stm32f437"),
42 all(feature = "stm32f401", feature = "stm32f439"),
43 all(feature = "stm32f401", feature = "stm32f446"),
44 all(feature = "stm32f401", feature = "stm32f469"),
45 all(feature = "stm32f401", feature = "stm32f479"),
46 all(feature = "stm32f405", feature = "stm32f401"),
47 all(feature = "stm32f405", feature = "stm32f407"),
48 all(feature = "stm32f405", feature = "stm32f410"),
49 all(feature = "stm32f405", feature = "stm32f411"),
50 all(feature = "stm32f405", feature = "stm32f412"),
51 all(feature = "stm32f405", feature = "stm32f413"),
52 all(feature = "stm32f405", feature = "stm32f415"),
53 all(feature = "stm32f405", feature = "stm32f417"),
54 all(feature = "stm32f405", feature = "stm32f423"),
55 all(feature = "stm32f405", feature = "stm32f427"),
56 all(feature = "stm32f405", feature = "stm32f429"),
57 all(feature = "stm32f405", feature = "stm32f437"),
58 all(feature = "stm32f405", feature = "stm32f439"),
59 all(feature = "stm32f405", feature = "stm32f446"),
60 all(feature = "stm32f405", feature = "stm32f469"),
61 all(feature = "stm32f405", feature = "stm32f479"),
62 all(feature = "stm32f407", feature = "stm32f401"),
63 all(feature = "stm32f407", feature = "stm32f405"),
64 all(feature = "stm32f407", feature = "stm32f410"),
65 all(feature = "stm32f407", feature = "stm32f411"),
66 all(feature = "stm32f407", feature = "stm32f412"),
67 all(feature = "stm32f407", feature = "stm32f413"),
68 all(feature = "stm32f407", feature = "stm32f415"),
69 all(feature = "stm32f407", feature = "stm32f417"),
70 all(feature = "stm32f407", feature = "stm32f423"),
71 all(feature = "stm32f407", feature = "stm32f427"),
72 all(feature = "stm32f407", feature = "stm32f429"),
73 all(feature = "stm32f407", feature = "stm32f437"),
74 all(feature = "stm32f407", feature = "stm32f439"),
75 all(feature = "stm32f407", feature = "stm32f446"),
76 all(feature = "stm32f407", feature = "stm32f469"),
77 all(feature = "stm32f407", feature = "stm32f479"),
78 all(feature = "stm32f410", feature = "stm32f401"),
79 all(feature = "stm32f410", feature = "stm32f405"),
80 all(feature = "stm32f410", feature = "stm32f407"),
81 all(feature = "stm32f410", feature = "stm32f411"),
82 all(feature = "stm32f410", feature = "stm32f412"),
83 all(feature = "stm32f410", feature = "stm32f413"),
84 all(feature = "stm32f410", feature = "stm32f415"),
85 all(feature = "stm32f410", feature = "stm32f417"),
86 all(feature = "stm32f410", feature = "stm32f423"),
87 all(feature = "stm32f410", feature = "stm32f427"),
88 all(feature = "stm32f410", feature = "stm32f429"),
89 all(feature = "stm32f410", feature = "stm32f437"),
90 all(feature = "stm32f410", feature = "stm32f439"),
91 all(feature = "stm32f410", feature = "stm32f446"),
92 all(feature = "stm32f410", feature = "stm32f469"),
93 all(feature = "stm32f410", feature = "stm32f479"),
94 all(feature = "stm32f411", feature = "stm32f401"),
95 all(feature = "stm32f411", feature = "stm32f405"),
96 all(feature = "stm32f411", feature = "stm32f407"),
97 all(feature = "stm32f411", feature = "stm32f410"),
98 all(feature = "stm32f411", feature = "stm32f412"),
99 all(feature = "stm32f411", feature = "stm32f413"),
100 all(feature = "stm32f411", feature = "stm32f415"),
101 all(feature = "stm32f411", feature = "stm32f417"),
102 all(feature = "stm32f411", feature = "stm32f423"),
103 all(feature = "stm32f411", feature = "stm32f427"),
104 all(feature = "stm32f411", feature = "stm32f429"),
105 all(feature = "stm32f411", feature = "stm32f437"),
106 all(feature = "stm32f411", feature = "stm32f439"),
107 all(feature = "stm32f411", feature = "stm32f446"),
108 all(feature = "stm32f411", feature = "stm32f469"),
109 all(feature = "stm32f411", feature = "stm32f479"),
110 all(feature = "stm32f412", feature = "stm32f401"),
111 all(feature = "stm32f412", feature = "stm32f405"),
112 all(feature = "stm32f412", feature = "stm32f407"),
113 all(feature = "stm32f412", feature = "stm32f410"),
114 all(feature = "stm32f412", feature = "stm32f411"),
115 all(feature = "stm32f412", feature = "stm32f413"),
116 all(feature = "stm32f412", feature = "stm32f415"),
117 all(feature = "stm32f412", feature = "stm32f417"),
118 all(feature = "stm32f412", feature = "stm32f423"),
119 all(feature = "stm32f412", feature = "stm32f427"),
120 all(feature = "stm32f412", feature = "stm32f429"),
121 all(feature = "stm32f412", feature = "stm32f437"),
122 all(feature = "stm32f412", feature = "stm32f439"),
123 all(feature = "stm32f412", feature = "stm32f446"),
124 all(feature = "stm32f412", feature = "stm32f469"),
125 all(feature = "stm32f412", feature = "stm32f479"),
126 all(feature = "stm32f413", feature = "stm32f401"),
127 all(feature = "stm32f413", feature = "stm32f405"),
128 all(feature = "stm32f413", feature = "stm32f407"),
129 all(feature = "stm32f413", feature = "stm32f410"),
130 all(feature = "stm32f413", feature = "stm32f411"),
131 all(feature = "stm32f413", feature = "stm32f412"),
132 all(feature = "stm32f413", feature = "stm32f415"),
133 all(feature = "stm32f413", feature = "stm32f417"),
134 all(feature = "stm32f413", feature = "stm32f423"),
135 all(feature = "stm32f413", feature = "stm32f427"),
136 all(feature = "stm32f413", feature = "stm32f429"),
137 all(feature = "stm32f413", feature = "stm32f437"),
138 all(feature = "stm32f413", feature = "stm32f439"),
139 all(feature = "stm32f413", feature = "stm32f446"),
140 all(feature = "stm32f413", feature = "stm32f469"),
141 all(feature = "stm32f413", feature = "stm32f479"),
142 all(feature = "stm32f415", feature = "stm32f401"),
143 all(feature = "stm32f415", feature = "stm32f405"),
144 all(feature = "stm32f415", feature = "stm32f407"),
145 all(feature = "stm32f415", feature = "stm32f410"),
146 all(feature = "stm32f415", feature = "stm32f411"),
147 all(feature = "stm32f415", feature = "stm32f412"),
148 all(feature = "stm32f415", feature = "stm32f413"),
149 all(feature = "stm32f415", feature = "stm32f417"),
150 all(feature = "stm32f415", feature = "stm32f423"),
151 all(feature = "stm32f415", feature = "stm32f427"),
152 all(feature = "stm32f415", feature = "stm32f429"),
153 all(feature = "stm32f415", feature = "stm32f437"),
154 all(feature = "stm32f415", feature = "stm32f439"),
155 all(feature = "stm32f415", feature = "stm32f446"),
156 all(feature = "stm32f415", feature = "stm32f469"),
157 all(feature = "stm32f415", feature = "stm32f479"),
158 all(feature = "stm32f417", feature = "stm32f401"),
159 all(feature = "stm32f417", feature = "stm32f405"),
160 all(feature = "stm32f417", feature = "stm32f407"),
161 all(feature = "stm32f417", feature = "stm32f410"),
162 all(feature = "stm32f417", feature = "stm32f411"),
163 all(feature = "stm32f417", feature = "stm32f412"),
164 all(feature = "stm32f417", feature = "stm32f413"),
165 all(feature = "stm32f417", feature = "stm32f415"),
166 all(feature = "stm32f417", feature = "stm32f423"),
167 all(feature = "stm32f417", feature = "stm32f427"),
168 all(feature = "stm32f417", feature = "stm32f429"),
169 all(feature = "stm32f417", feature = "stm32f437"),
170 all(feature = "stm32f417", feature = "stm32f439"),
171 all(feature = "stm32f417", feature = "stm32f446"),
172 all(feature = "stm32f417", feature = "stm32f469"),
173 all(feature = "stm32f417", feature = "stm32f479"),
174 all(feature = "stm32f423", feature = "stm32f401"),
175 all(feature = "stm32f423", feature = "stm32f405"),
176 all(feature = "stm32f423", feature = "stm32f407"),
177 all(feature = "stm32f423", feature = "stm32f410"),
178 all(feature = "stm32f423", feature = "stm32f411"),
179 all(feature = "stm32f423", feature = "stm32f412"),
180 all(feature = "stm32f423", feature = "stm32f413"),
181 all(feature = "stm32f423", feature = "stm32f415"),
182 all(feature = "stm32f423", feature = "stm32f417"),
183 all(feature = "stm32f423", feature = "stm32f427"),
184 all(feature = "stm32f423", feature = "stm32f429"),
185 all(feature = "stm32f423", feature = "stm32f437"),
186 all(feature = "stm32f423", feature = "stm32f439"),
187 all(feature = "stm32f423", feature = "stm32f446"),
188 all(feature = "stm32f423", feature = "stm32f469"),
189 all(feature = "stm32f423", feature = "stm32f479"),
190 all(feature = "stm32f427", feature = "stm32f401"),
191 all(feature = "stm32f427", feature = "stm32f405"),
192 all(feature = "stm32f427", feature = "stm32f407"),
193 all(feature = "stm32f427", feature = "stm32f410"),
194 all(feature = "stm32f427", feature = "stm32f411"),
195 all(feature = "stm32f427", feature = "stm32f412"),
196 all(feature = "stm32f427", feature = "stm32f413"),
197 all(feature = "stm32f427", feature = "stm32f415"),
198 all(feature = "stm32f427", feature = "stm32f417"),
199 all(feature = "stm32f427", feature = "stm32f423"),
200 all(feature = "stm32f427", feature = "stm32f429"),
201 all(feature = "stm32f427", feature = "stm32f437"),
202 all(feature = "stm32f427", feature = "stm32f439"),
203 all(feature = "stm32f427", feature = "stm32f446"),
204 all(feature = "stm32f427", feature = "stm32f469"),
205 all(feature = "stm32f427", feature = "stm32f479"),
206 all(feature = "stm32f429", feature = "stm32f401"),
207 all(feature = "stm32f429", feature = "stm32f405"),
208 all(feature = "stm32f429", feature = "stm32f407"),
209 all(feature = "stm32f429", feature = "stm32f410"),
210 all(feature = "stm32f429", feature = "stm32f411"),
211 all(feature = "stm32f429", feature = "stm32f412"),
212 all(feature = "stm32f429", feature = "stm32f413"),
213 all(feature = "stm32f429", feature = "stm32f415"),
214 all(feature = "stm32f429", feature = "stm32f417"),
215 all(feature = "stm32f429", feature = "stm32f423"),
216 all(feature = "stm32f429", feature = "stm32f427"),
217 all(feature = "stm32f429", feature = "stm32f437"),
218 all(feature = "stm32f429", feature = "stm32f439"),
219 all(feature = "stm32f429", feature = "stm32f446"),
220 all(feature = "stm32f429", feature = "stm32f469"),
221 all(feature = "stm32f429", feature = "stm32f479"),
222 all(feature = "stm32f437", feature = "stm32f401"),
223 all(feature = "stm32f437", feature = "stm32f405"),
224 all(feature = "stm32f437", feature = "stm32f407"),
225 all(feature = "stm32f437", feature = "stm32f410"),
226 all(feature = "stm32f437", feature = "stm32f411"),
227 all(feature = "stm32f437", feature = "stm32f412"),
228 all(feature = "stm32f437", feature = "stm32f413"),
229 all(feature = "stm32f437", feature = "stm32f415"),
230 all(feature = "stm32f437", feature = "stm32f417"),
231 all(feature = "stm32f437", feature = "stm32f423"),
232 all(feature = "stm32f437", feature = "stm32f427"),
233 all(feature = "stm32f437", feature = "stm32f429"),
234 all(feature = "stm32f437", feature = "stm32f439"),
235 all(feature = "stm32f437", feature = "stm32f446"),
236 all(feature = "stm32f437", feature = "stm32f469"),
237 all(feature = "stm32f437", feature = "stm32f479"),
238 all(feature = "stm32f439", feature = "stm32f401"),
239 all(feature = "stm32f439", feature = "stm32f405"),
240 all(feature = "stm32f439", feature = "stm32f407"),
241 all(feature = "stm32f439", feature = "stm32f410"),
242 all(feature = "stm32f439", feature = "stm32f411"),
243 all(feature = "stm32f439", feature = "stm32f412"),
244 all(feature = "stm32f439", feature = "stm32f413"),
245 all(feature = "stm32f439", feature = "stm32f415"),
246 all(feature = "stm32f439", feature = "stm32f417"),
247 all(feature = "stm32f439", feature = "stm32f423"),
248 all(feature = "stm32f439", feature = "stm32f427"),
249 all(feature = "stm32f439", feature = "stm32f429"),
250 all(feature = "stm32f439", feature = "stm32f437"),
251 all(feature = "stm32f439", feature = "stm32f446"),
252 all(feature = "stm32f439", feature = "stm32f469"),
253 all(feature = "stm32f439", feature = "stm32f479"),
254 all(feature = "stm32f446", feature = "stm32f401"),
255 all(feature = "stm32f446", feature = "stm32f405"),
256 all(feature = "stm32f446", feature = "stm32f407"),
257 all(feature = "stm32f446", feature = "stm32f410"),
258 all(feature = "stm32f446", feature = "stm32f411"),
259 all(feature = "stm32f446", feature = "stm32f412"),
260 all(feature = "stm32f446", feature = "stm32f413"),
261 all(feature = "stm32f446", feature = "stm32f415"),
262 all(feature = "stm32f446", feature = "stm32f417"),
263 all(feature = "stm32f446", feature = "stm32f423"),
264 all(feature = "stm32f446", feature = "stm32f427"),
265 all(feature = "stm32f446", feature = "stm32f429"),
266 all(feature = "stm32f446", feature = "stm32f437"),
267 all(feature = "stm32f446", feature = "stm32f439"),
268 all(feature = "stm32f446", feature = "stm32f469"),
269 all(feature = "stm32f446", feature = "stm32f479"),
270 all(feature = "stm32f469", feature = "stm32f401"),
271 all(feature = "stm32f469", feature = "stm32f405"),
272 all(feature = "stm32f469", feature = "stm32f407"),
273 all(feature = "stm32f469", feature = "stm32f410"),
274 all(feature = "stm32f469", feature = "stm32f411"),
275 all(feature = "stm32f469", feature = "stm32f412"),
276 all(feature = "stm32f469", feature = "stm32f413"),
277 all(feature = "stm32f469", feature = "stm32f415"),
278 all(feature = "stm32f469", feature = "stm32f417"),
279 all(feature = "stm32f469", feature = "stm32f423"),
280 all(feature = "stm32f469", feature = "stm32f427"),
281 all(feature = "stm32f469", feature = "stm32f429"),
282 all(feature = "stm32f469", feature = "stm32f437"),
283 all(feature = "stm32f469", feature = "stm32f439"),
284 all(feature = "stm32f469", feature = "stm32f446"),
285 all(feature = "stm32f469", feature = "stm32f479"),
286 all(feature = "stm32f479", feature = "stm32f401"),
287 all(feature = "stm32f479", feature = "stm32f405"),
288 all(feature = "stm32f479", feature = "stm32f407"),
289 all(feature = "stm32f479", feature = "stm32f410"),
290 all(feature = "stm32f479", feature = "stm32f411"),
291 all(feature = "stm32f479", feature = "stm32f412"),
292 all(feature = "stm32f479", feature = "stm32f413"),
293 all(feature = "stm32f479", feature = "stm32f415"),
294 all(feature = "stm32f479", feature = "stm32f417"),
295 all(feature = "stm32f479", feature = "stm32f423"),
296 all(feature = "stm32f479", feature = "stm32f427"),
297 all(feature = "stm32f479", feature = "stm32f429"),
298 all(feature = "stm32f479", feature = "stm32f437"),
299 all(feature = "stm32f479", feature = "stm32f439"),
300 all(feature = "stm32f479", feature = "stm32f446"),
301 all(feature = "stm32f479", feature = "stm32f469"),
302))]
303compile_error!(
304 "Multile chip features activated. You must activate exactly one of the following features: "
305);
306
307pub use stm32f4xx_hal as hal;
308pub use stm32f4xx_hal::stm32 as pac;
309
310// This mod MUST go first, so that the others see its macros.
311pub(crate) mod fmt;
312
313pub mod interrupt;
314pub mod uarte;
315
316pub use cortex_m_rt::interrupt;
diff --git a/embassy-stm32f4/src/uarte.rs b/embassy-stm32f4/src/uarte.rs
new file mode 100644
index 000000000..3a33e7597
--- /dev/null
+++ b/embassy-stm32f4/src/uarte.rs
@@ -0,0 +1,561 @@
1//! HAL interface to the UARTE peripheral
2//!
3//! See product specification:
4//!
5//! - nrf52832: Section 35
6//! - nrf52840: Section 6.34
7use core::cell::UnsafeCell;
8use core::cmp::min;
9use core::marker::PhantomPinned;
10use core::ops::Deref;
11use core::pin::Pin;
12use core::ptr;
13use core::sync::atomic::{compiler_fence, Ordering};
14use core::task::{Context, Poll};
15
16use embedded_hal::digital::v2::OutputPin;
17
18use crate::hal::gpio::{Floating, Input, Output, Pin as GpioPin, Port as GpioPort, PushPull};
19use crate::interrupt;
20use crate::interrupt::CriticalSection;
21#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))]
22use crate::pac::UARTE1;
23use crate::pac::{uarte0, Interrupt, UARTE0};
24
25// Re-export SVD variants to allow user to directly set values
26pub use uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
27
28use embassy::io::{AsyncBufRead, AsyncWrite, Result};
29use embassy::util::WakerStore;
30
31use crate::fmt::{assert, panic, todo, *};
32
33//use crate::trace;
34
35const RINGBUF_SIZE: usize = 512;
36struct RingBuf {
37 buf: [u8; RINGBUF_SIZE],
38 start: usize,
39 end: usize,
40 empty: bool,
41}
42
43impl RingBuf {
44 fn new() -> Self {
45 RingBuf {
46 buf: [0; RINGBUF_SIZE],
47 start: 0,
48 end: 0,
49 empty: true,
50 }
51 }
52
53 fn push_buf(&mut self) -> &mut [u8] {
54 if self.start == self.end && !self.empty {
55 trace!(" ringbuf: push_buf empty");
56 return &mut self.buf[..0];
57 }
58
59 let n = if self.start <= self.end {
60 RINGBUF_SIZE - self.end
61 } else {
62 self.start - self.end
63 };
64
65 trace!(" ringbuf: push_buf {:?}..{:?}", self.end, self.end + n);
66 &mut self.buf[self.end..self.end + n]
67 }
68
69 fn push(&mut self, n: usize) {
70 trace!(" ringbuf: push {:?}", n);
71 if n == 0 {
72 return;
73 }
74
75 self.end = Self::wrap(self.end + n);
76 self.empty = false;
77 }
78
79 fn pop_buf(&mut self) -> &mut [u8] {
80 if self.empty {
81 trace!(" ringbuf: pop_buf empty");
82 return &mut self.buf[..0];
83 }
84
85 let n = if self.end <= self.start {
86 RINGBUF_SIZE - self.start
87 } else {
88 self.end - self.start
89 };
90
91 trace!(" ringbuf: pop_buf {:?}..{:?}", self.start, self.start + n);
92 &mut self.buf[self.start..self.start + n]
93 }
94
95 fn pop(&mut self, n: usize) {
96 trace!(" ringbuf: pop {:?}", n);
97 if n == 0 {
98 return;
99 }
100
101 self.start = Self::wrap(self.start + n);
102 self.empty = self.start == self.end;
103 }
104
105 fn wrap(n: usize) -> usize {
106 assert!(n <= RINGBUF_SIZE);
107 if n == RINGBUF_SIZE {
108 0
109 } else {
110 n
111 }
112 }
113}
114
115#[derive(Copy, Clone, Debug, PartialEq)]
116enum RxState {
117 Idle,
118 Receiving,
119 ReceivingReady,
120 Stopping,
121}
122#[derive(Copy, Clone, Debug, PartialEq)]
123enum TxState {
124 Idle,
125 Transmitting(usize),
126}
127
128/// Interface to a UARTE instance
129///
130/// This is a very basic interface that comes with the following limitations:
131/// - The UARTE instances share the same address space with instances of UART.
132/// You need to make sure that conflicting instances
133/// are disabled before using `Uarte`. See product specification:
134/// - nrf52832: Section 15.2
135/// - nrf52840: Section 6.1.2
136pub struct Uarte<T: Instance> {
137 started: bool,
138 state: UnsafeCell<UarteState<T>>,
139}
140
141// public because it needs to be used in Instance::{get_state, set_state}, but
142// should not be used outside the module
143#[doc(hidden)]
144pub struct UarteState<T> {
145 inner: T,
146
147 rx: RingBuf,
148 rx_state: RxState,
149 rx_waker: WakerStore,
150
151 tx: RingBuf,
152 tx_state: TxState,
153 tx_waker: WakerStore,
154
155 _pin: PhantomPinned,
156}
157
158#[cfg(any(feature = "52833", feature = "52840"))]
159fn port_bit(port: GpioPort) -> bool {
160 match port {
161 GpioPort::Port0 => false,
162 GpioPort::Port1 => true,
163 }
164}
165
166impl<T: Instance> Uarte<T> {
167 pub fn new(uarte: T, mut pins: Pins, parity: Parity, baudrate: Baudrate) -> Self {
168 // Select pins
169 uarte.psel.rxd.write(|w| {
170 let w = unsafe { w.pin().bits(pins.rxd.pin()) };
171 #[cfg(any(feature = "52833", feature = "52840"))]
172 let w = w.port().bit(port_bit(pins.rxd.port()));
173 w.connect().connected()
174 });
175 pins.txd.set_high().unwrap();
176 uarte.psel.txd.write(|w| {
177 let w = unsafe { w.pin().bits(pins.txd.pin()) };
178 #[cfg(any(feature = "52833", feature = "52840"))]
179 let w = w.port().bit(port_bit(pins.txd.port()));
180 w.connect().connected()
181 });
182
183 // Optional pins
184 uarte.psel.cts.write(|w| {
185 if let Some(ref pin) = pins.cts {
186 let w = unsafe { w.pin().bits(pin.pin()) };
187 #[cfg(any(feature = "52833", feature = "52840"))]
188 let w = w.port().bit(port_bit(pin.port()));
189 w.connect().connected()
190 } else {
191 w.connect().disconnected()
192 }
193 });
194
195 uarte.psel.rts.write(|w| {
196 if let Some(ref pin) = pins.rts {
197 let w = unsafe { w.pin().bits(pin.pin()) };
198 #[cfg(any(feature = "52833", feature = "52840"))]
199 let w = w.port().bit(port_bit(pin.port()));
200 w.connect().connected()
201 } else {
202 w.connect().disconnected()
203 }
204 });
205
206 // Enable UARTE instance
207 uarte.enable.write(|w| w.enable().enabled());
208
209 // Enable interrupts
210 uarte.intenset.write(|w| w.endrx().set().endtx().set());
211
212 // Configure
213 let hardware_flow_control = pins.rts.is_some() && pins.cts.is_some();
214 uarte
215 .config
216 .write(|w| w.hwfc().bit(hardware_flow_control).parity().variant(parity));
217
218 // Configure frequency
219 uarte.baudrate.write(|w| w.baudrate().variant(baudrate));
220
221 Uarte {
222 started: false,
223 state: UnsafeCell::new(UarteState {
224 inner: uarte,
225
226 rx: RingBuf::new(),
227 rx_state: RxState::Idle,
228 rx_waker: WakerStore::new(),
229
230 tx: RingBuf::new(),
231 tx_state: TxState::Idle,
232 tx_waker: WakerStore::new(),
233
234 _pin: PhantomPinned,
235 }),
236 }
237 }
238
239 fn with_state<'a, R>(
240 self: Pin<&'a mut Self>,
241 f: impl FnOnce(Pin<&'a mut UarteState<T>>) -> R,
242 ) -> R {
243 let Self { state, started } = unsafe { self.get_unchecked_mut() };
244
245 interrupt::free(|cs| {
246 let ptr = state.get();
247
248 if !*started {
249 T::set_state(cs, ptr);
250
251 *started = true;
252
253 // safety: safe because critical section ensures only one *mut UartState
254 // exists at the same time.
255 unsafe { Pin::new_unchecked(&mut *ptr) }.start();
256 }
257
258 // safety: safe because critical section ensures only one *mut UartState
259 // exists at the same time.
260 f(unsafe { Pin::new_unchecked(&mut *ptr) })
261 })
262 }
263}
264
265impl<T: Instance> Drop for Uarte<T> {
266 fn drop(&mut self) {
267 // stop DMA before dropping, because DMA is using the buffer in `self`.
268 todo!()
269 }
270}
271
272impl<T: Instance> AsyncBufRead for Uarte<T> {
273 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
274 self.with_state(|s| s.poll_fill_buf(cx))
275 }
276
277 fn consume(self: Pin<&mut Self>, amt: usize) {
278 self.with_state(|s| s.consume(amt))
279 }
280}
281
282impl<T: Instance> AsyncWrite for Uarte<T> {
283 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
284 self.with_state(|s| s.poll_write(cx, buf))
285 }
286}
287
288impl<T: Instance> UarteState<T> {
289 pub fn start(self: Pin<&mut Self>) {
290 interrupt::set_priority(T::interrupt(), interrupt::Priority::Level7);
291 interrupt::enable(T::interrupt());
292 interrupt::pend(T::interrupt());
293 }
294
295 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
296 let this = unsafe { self.get_unchecked_mut() };
297
298 // Conservative compiler fence to prevent optimizations that do not
299 // take in to account actions by DMA. The fence has been placed here,
300 // before any DMA action has started
301 compiler_fence(Ordering::SeqCst);
302 trace!("poll_read");
303
304 // We have data ready in buffer? Return it.
305 let buf = this.rx.pop_buf();
306 if buf.len() != 0 {
307 trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len());
308 return Poll::Ready(Ok(buf));
309 }
310
311 trace!(" empty");
312
313 if this.rx_state == RxState::ReceivingReady {
314 trace!(" stopping");
315 this.rx_state = RxState::Stopping;
316 this.inner.tasks_stoprx.write(|w| unsafe { w.bits(1) });
317 }
318
319 this.rx_waker.store(cx.waker());
320 Poll::Pending
321 }
322
323 fn consume(self: Pin<&mut Self>, amt: usize) {
324 let this = unsafe { self.get_unchecked_mut() };
325 trace!("consume {:?}", amt);
326 this.rx.pop(amt);
327 interrupt::pend(T::interrupt());
328 }
329
330 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
331 let this = unsafe { self.get_unchecked_mut() };
332
333 trace!("poll_write: {:?}", buf.len());
334
335 let tx_buf = this.tx.push_buf();
336 if tx_buf.len() == 0 {
337 trace!("poll_write: pending");
338 this.tx_waker.store(cx.waker());
339 return Poll::Pending;
340 }
341
342 let n = min(tx_buf.len(), buf.len());
343 tx_buf[..n].copy_from_slice(&buf[..n]);
344 this.tx.push(n);
345
346 trace!("poll_write: queued {:?}", n);
347
348 // Conservative compiler fence to prevent optimizations that do not
349 // take in to account actions by DMA. The fence has been placed here,
350 // before any DMA action has started
351 compiler_fence(Ordering::SeqCst);
352
353 interrupt::pend(T::interrupt());
354
355 Poll::Ready(Ok(n))
356 }
357
358 fn on_interrupt(&mut self) {
359 trace!("irq: start");
360 let mut more_work = true;
361 while more_work {
362 more_work = false;
363 match self.rx_state {
364 RxState::Idle => {
365 trace!(" irq_rx: in state idle");
366
367 if self.inner.events_rxdrdy.read().bits() != 0 {
368 trace!(" irq_rx: rxdrdy?????");
369 self.inner.events_rxdrdy.reset();
370 }
371
372 if self.inner.events_endrx.read().bits() != 0 {
373 panic!("unexpected endrx");
374 }
375
376 let buf = self.rx.push_buf();
377 if buf.len() != 0 {
378 trace!(" irq_rx: starting {:?}", buf.len());
379 self.rx_state = RxState::Receiving;
380
381 // Set up the DMA read
382 self.inner.rxd.ptr.write(|w|
383 // The PTR field is a full 32 bits wide and accepts the full range
384 // of values.
385 unsafe { w.ptr().bits(buf.as_ptr() as u32) });
386 self.inner.rxd.maxcnt.write(|w|
387 // We're giving it the length of the buffer, so no danger of
388 // accessing invalid memory. We have verified that the length of the
389 // buffer fits in an `u8`, so the cast to `u8` is also fine.
390 //
391 // The MAXCNT field is at least 8 bits wide and accepts the full
392 // range of values.
393 unsafe { w.maxcnt().bits(buf.len() as _) });
394 trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len());
395
396 // Enable RXRDY interrupt.
397 self.inner.events_rxdrdy.reset();
398 self.inner.intenset.write(|w| w.rxdrdy().set());
399
400 // Start UARTE Receive transaction
401 self.inner.tasks_startrx.write(|w|
402 // `1` is a valid value to write to task registers.
403 unsafe { w.bits(1) });
404 }
405 }
406 RxState::Receiving => {
407 trace!(" irq_rx: in state receiving");
408 if self.inner.events_rxdrdy.read().bits() != 0 {
409 trace!(" irq_rx: rxdrdy");
410
411 // Disable the RXRDY event interrupt
412 // RXRDY is triggered for every byte, but we only care about whether we have
413 // some bytes or not. So as soon as we have at least one, disable it, to avoid
414 // wasting CPU cycles in interrupts.
415 self.inner.intenclr.write(|w| w.rxdrdy().clear());
416
417 self.inner.events_rxdrdy.reset();
418
419 self.rx_waker.wake();
420 self.rx_state = RxState::ReceivingReady;
421 more_work = true; // in case we also have endrx pending
422 }
423 }
424 RxState::ReceivingReady | RxState::Stopping => {
425 trace!(" irq_rx: in state ReceivingReady");
426
427 if self.inner.events_rxdrdy.read().bits() != 0 {
428 trace!(" irq_rx: rxdrdy");
429 self.inner.events_rxdrdy.reset();
430 }
431
432 if self.inner.events_endrx.read().bits() != 0 {
433 let n: usize = self.inner.rxd.amount.read().amount().bits() as usize;
434 trace!(" irq_rx: endrx {:?}", n);
435 self.rx.push(n);
436
437 self.inner.events_endrx.reset();
438
439 self.rx_waker.wake();
440 self.rx_state = RxState::Idle;
441 more_work = true; // start another rx if possible
442 }
443 }
444 }
445 }
446
447 more_work = true;
448 while more_work {
449 more_work = false;
450 match self.tx_state {
451 TxState::Idle => {
452 trace!(" irq_tx: in state Idle");
453 let buf = self.tx.pop_buf();
454 if buf.len() != 0 {
455 trace!(" irq_tx: starting {:?}", buf.len());
456 self.tx_state = TxState::Transmitting(buf.len());
457
458 // Set up the DMA write
459 self.inner.txd.ptr.write(|w|
460 // The PTR field is a full 32 bits wide and accepts the full range
461 // of values.
462 unsafe { w.ptr().bits(buf.as_ptr() as u32) });
463 self.inner.txd.maxcnt.write(|w|
464 // We're giving it the length of the buffer, so no danger of
465 // accessing invalid memory. We have verified that the length of the
466 // buffer fits in an `u8`, so the cast to `u8` is also fine.
467 //
468 // The MAXCNT field is 8 bits wide and accepts the full range of
469 // values.
470 unsafe { w.maxcnt().bits(buf.len() as _) });
471
472 // Start UARTE Transmit transaction
473 self.inner.tasks_starttx.write(|w|
474 // `1` is a valid value to write to task registers.
475 unsafe { w.bits(1) });
476 }
477 }
478 TxState::Transmitting(n) => {
479 trace!(" irq_tx: in state Transmitting");
480 if self.inner.events_endtx.read().bits() != 0 {
481 self.inner.events_endtx.reset();
482
483 trace!(" irq_tx: endtx {:?}", n);
484 self.tx.pop(n);
485 self.tx_waker.wake();
486 self.tx_state = TxState::Idle;
487 more_work = true; // start another tx if possible
488 }
489 }
490 }
491 }
492 trace!("irq: end");
493 }
494}
495
496pub struct Pins {
497 pub rxd: GpioPin<Input<Floating>>,
498 pub txd: GpioPin<Output<PushPull>>,
499 pub cts: Option<GpioPin<Input<Floating>>>,
500 pub rts: Option<GpioPin<Output<PushPull>>>,
501}
502
503mod private {
504 pub trait Sealed {}
505
506 impl Sealed for crate::pac::UARTE0 {}
507 #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))]
508 impl Sealed for crate::pac::UARTE1 {}
509}
510
511pub trait Instance: Deref<Target = uarte0::RegisterBlock> + Sized + private::Sealed {
512 fn interrupt() -> Interrupt;
513
514 #[doc(hidden)]
515 fn get_state(_cs: &CriticalSection) -> *mut UarteState<Self>;
516
517 #[doc(hidden)]
518 fn set_state(_cs: &CriticalSection, state: *mut UarteState<Self>);
519}
520
521#[interrupt]
522unsafe fn UARTE0_UART0() {
523 interrupt::free(|cs| UARTE0::get_state(cs).as_mut().unwrap().on_interrupt());
524}
525
526#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))]
527#[interrupt]
528unsafe fn UARTE1() {
529 interrupt::free(|cs| UARTE1::get_state(cs).as_mut().unwrap().on_interrupt());
530}
531
532static mut UARTE0_STATE: *mut UarteState<UARTE0> = ptr::null_mut();
533#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))]
534static mut UARTE1_STATE: *mut UarteState<UARTE1> = ptr::null_mut();
535
536impl Instance for UARTE0 {
537 fn interrupt() -> Interrupt {
538 Interrupt::UARTE0_UART0
539 }
540
541 fn get_state(_cs: &CriticalSection) -> *mut UarteState<Self> {
542 unsafe { UARTE0_STATE } // Safe because of CriticalSection
543 }
544 fn set_state(_cs: &CriticalSection, state: *mut UarteState<Self>) {
545 unsafe { UARTE0_STATE = state } // Safe because of CriticalSection
546 }
547}
548
549#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))]
550impl Instance for UARTE1 {
551 fn interrupt() -> Interrupt {
552 Interrupt::UARTE1
553 }
554
555 fn get_state(_cs: &CriticalSection) -> *mut UarteState<Self> {
556 unsafe { UARTE1_STATE } // Safe because of CriticalSection
557 }
558 fn set_state(_cs: &CriticalSection, state: *mut UarteState<Self>) {
559 unsafe { UARTE1_STATE = state } // Safe because of CriticalSection
560 }
561}