aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2021-03-17 19:49:21 -0500
committerGitHub <[email protected]>2021-03-17 19:49:21 -0500
commit4a38e7eb2b71cc721ad16fdb814c1aeb3c2c5e79 (patch)
tree8f0aa72b498f2b4033a6625bad2ace2cf25f45ba
parentf248bb17ad2840a87a6e4858e72d52fd067609ec (diff)
parent71ac582d68a242d89e9053d681bfa2dab16eb6f7 (diff)
Merge pull request #69 from michaelbeaumont/stm32l0
Add stm32l0 support for ExtiPin futures
-rw-r--r--Cargo.toml1
-rwxr-xr-xci.sh5
-rw-r--r--embassy-stm32l0/Cargo.toml26
-rw-r--r--embassy-stm32l0/src/exti.rs224
-rw-r--r--embassy-stm32l0/src/fmt.rs119
-rw-r--r--embassy-stm32l0/src/interrupt.rs162
-rw-r--r--embassy-stm32l0/src/lib.rs29
7 files changed, 566 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 069437317..31fe26476 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,6 +5,7 @@ members = [
5 "embassy-traits", 5 "embassy-traits",
6 "embassy-nrf", 6 "embassy-nrf",
7 "embassy-stm32f4", 7 "embassy-stm32f4",
8 "embassy-stm32l0",
8 "embassy-nrf-examples", 9 "embassy-nrf-examples",
9 "embassy-stm32f4-examples", 10 "embassy-stm32f4-examples",
10 "embassy-macros", 11 "embassy-macros",
diff --git a/ci.sh b/ci.sh
index b6036cacf..f1f6a52e5 100755
--- a/ci.sh
+++ b/ci.sh
@@ -29,3 +29,8 @@ set -euxo pipefail
29(cd embassy-stm32f4-examples; cargo build --target thumbv7em-none-eabi --bins) 29(cd embassy-stm32f4-examples; cargo build --target thumbv7em-none-eabi --bins)
30(cd embassy-stm32f4; cargo build --target thumbv7em-none-eabi --features stm32f405) 30(cd embassy-stm32f4; cargo build --target thumbv7em-none-eabi --features stm32f405)
31(cd embassy-stm32f4; cargo build --target thumbv7em-none-eabi --features stm32f405,defmt) 31(cd embassy-stm32f4; cargo build --target thumbv7em-none-eabi --features stm32f405,defmt)
32
33# embassy-stm32l0
34
35(cd embassy-stm32l0; cargo build --target thumbv6m-none-eabi --features stm32l0x2)
36(cd embassy-stm32l0; cargo build --target thumbv6m-none-eabi --features stm32l0x2,defmt)
diff --git a/embassy-stm32l0/Cargo.toml b/embassy-stm32l0/Cargo.toml
new file mode 100644
index 000000000..70aa431c9
--- /dev/null
+++ b/embassy-stm32l0/Cargo.toml
@@ -0,0 +1,26 @@
1[package]
2name = "embassy-stm32l0"
3version = "0.1.0"
4authors = ["Michael Beaumont <[email protected]>"]
5edition = "2018"
6
7[features]
8defmt-trace = [ ]
9defmt-debug = [ ]
10defmt-info = [ ]
11defmt-warn = [ ]
12defmt-error = [ ]
13
14stm32l0x1 = ["stm32l0xx-hal/stm32l0x1"]
15stm32l0x2 = ["stm32l0xx-hal/stm32l0x2"]
16stm32l0x3 = ["stm32l0xx-hal/stm32l0x3"]
17
18[dependencies]
19embassy = { version = "0.1.0", path = "../embassy" }
20defmt = { version = "0.2.0", optional = true }
21log = { version = "0.4.11", optional = true }
22cortex-m-rt = "0.6.13"
23cortex-m = "0.7.1"
24embedded-hal = { version = "0.2.4" }
25embedded-dma = { version = "0.1.2" }
26stm32l0xx-hal = { version = "0.7.0", features = ["rt"], git = "https://github.com/stm32-rs/stm32l0xx-hal.git"}
diff --git a/embassy-stm32l0/src/exti.rs b/embassy-stm32l0/src/exti.rs
new file mode 100644
index 000000000..c93d213ef
--- /dev/null
+++ b/embassy-stm32l0/src/exti.rs
@@ -0,0 +1,224 @@
1use core::future::Future;
2use core::mem;
3use core::pin::Pin;
4
5use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge};
6use embassy::util::InterruptFuture;
7
8use crate::hal::{
9 exti::{Exti, ExtiLine, GpioLine, TriggerEdge},
10 gpio,
11 syscfg::SYSCFG,
12};
13use crate::interrupt;
14use crate::pac::EXTI;
15
16pub struct ExtiManager {
17 syscfg: SYSCFG,
18}
19
20impl<'a> ExtiManager {
21 pub fn new(_exti: Exti, syscfg: SYSCFG) -> Self {
22 Self { syscfg }
23 }
24
25 pub fn new_pin<T>(&'static mut self, pin: T, interrupt: T::Interrupt) -> ExtiPin<T>
26 where
27 T: PinWithInterrupt,
28 {
29 ExtiPin {
30 pin,
31 interrupt,
32 mgr: self,
33 }
34 }
35}
36
37pub struct ExtiPin<T: PinWithInterrupt> {
38 pin: T,
39 interrupt: T::Interrupt,
40 mgr: &'static ExtiManager,
41}
42
43impl<T: PinWithInterrupt + 'static> ExtiPin<T> {
44 fn wait_for_edge<'a>(
45 self: Pin<&'a mut Self>,
46 edge: TriggerEdge,
47 ) -> impl Future<Output = ()> + 'a {
48 let line = self.pin.line();
49 let s = unsafe { self.get_unchecked_mut() };
50
51 Exti::unpend(line);
52
53 async move {
54 let exti: EXTI = unsafe { mem::transmute(()) };
55 let mut exti = Exti::new(exti);
56
57 let fut = InterruptFuture::new(&mut s.interrupt);
58
59 let port = s.pin.port();
60 let syscfg = &s.mgr.syscfg as *const _ as *mut SYSCFG;
61 cortex_m::interrupt::free(|_| {
62 let syscfg = unsafe { &mut *syscfg };
63 exti.listen_gpio(syscfg, port, line, edge);
64 });
65
66 fut.await;
67
68 Exti::unpend(line);
69 }
70 }
71}
72
73impl<T: PinWithInterrupt + 'static> WaitForRisingEdge for ExtiPin<T> {
74 type Future<'a> = impl Future<Output = ()> + 'a;
75
76 fn wait_for_rising_edge<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> {
77 self.wait_for_edge(TriggerEdge::Rising)
78 }
79}
80
81impl<T: PinWithInterrupt + 'static> WaitForFallingEdge for ExtiPin<T> {
82 type Future<'a> = impl Future<Output = ()> + 'a;
83
84 fn wait_for_falling_edge<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> {
85 self.wait_for_edge(TriggerEdge::Falling)
86 }
87}
88
89impl<T: PinWithInterrupt + 'static> WaitForAnyEdge for ExtiPin<T> {
90 type Future<'a> = impl Future<Output = ()> + 'a;
91
92 fn wait_for_any_edge<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> {
93 self.wait_for_edge(TriggerEdge::Both)
94 }
95}
96
97mod private {
98 pub trait Sealed {}
99}
100
101pub trait PinWithInterrupt: private::Sealed {
102 type Interrupt: interrupt::Interrupt;
103 fn port(&self) -> gpio::Port;
104 fn line(&self) -> GpioLine;
105}
106
107macro_rules! exti {
108 ($($PER:ident => ($set:ident, $pin:ident),)+) => {
109 $(
110 impl<T> private::Sealed for gpio::$set::$pin<T> {}
111 impl<T> PinWithInterrupt for gpio::$set::$pin<T> {
112 type Interrupt = interrupt::$PER;
113 fn port(&self) -> gpio::Port {
114 self.port()
115 }
116 fn line(&self) -> GpioLine {
117 GpioLine::from_raw_line(self.pin_number()).unwrap()
118 }
119 }
120 )+
121 }
122}
123
124exti! {
125 EXTI0_1 => (gpioa, PA0),
126 EXTI0_1 => (gpioa, PA1),
127 EXTI2_3 => (gpioa, PA2),
128 EXTI2_3 => (gpioa, PA3),
129 EXTI4_15 => (gpioa, PA4),
130 EXTI4_15 => (gpioa, PA5),
131 EXTI4_15 => (gpioa, PA6),
132 EXTI4_15 => (gpioa, PA7),
133 EXTI4_15 => (gpioa, PA8),
134 EXTI4_15 => (gpioa, PA9),
135 EXTI4_15 => (gpioa, PA10),
136 EXTI4_15 => (gpioa, PA11),
137 EXTI4_15 => (gpioa, PA12),
138 EXTI4_15 => (gpioa, PA13),
139 EXTI4_15 => (gpioa, PA14),
140 EXTI4_15 => (gpioa, PA15),
141}
142
143exti! {
144 EXTI0_1 => (gpiob, PB0),
145 EXTI0_1 => (gpiob, PB1),
146 EXTI2_3 => (gpiob, PB2),
147 EXTI2_3 => (gpiob, PB3),
148 EXTI4_15 => (gpiob, PB4),
149 EXTI4_15 => (gpiob, PB5),
150 EXTI4_15 => (gpiob, PB6),
151 EXTI4_15 => (gpiob, PB7),
152 EXTI4_15 => (gpiob, PB8),
153 EXTI4_15 => (gpiob, PB9),
154 EXTI4_15 => (gpiob, PB10),
155 EXTI4_15 => (gpiob, PB11),
156 EXTI4_15 => (gpiob, PB12),
157 EXTI4_15 => (gpiob, PB13),
158 EXTI4_15 => (gpiob, PB14),
159 EXTI4_15 => (gpiob, PB15),
160}
161
162exti! {
163 EXTI0_1 => (gpioc, PC0),
164 EXTI0_1 => (gpioc, PC1),
165 EXTI2_3 => (gpioc, PC2),
166 EXTI2_3 => (gpioc, PC3),
167 EXTI4_15 => (gpioc, PC4),
168 EXTI4_15 => (gpioc, PC5),
169 EXTI4_15 => (gpioc, PC6),
170 EXTI4_15 => (gpioc, PC7),
171 EXTI4_15 => (gpioc, PC8),
172 EXTI4_15 => (gpioc, PC9),
173 EXTI4_15 => (gpioc, PC10),
174 EXTI4_15 => (gpioc, PC11),
175 EXTI4_15 => (gpioc, PC12),
176 EXTI4_15 => (gpioc, PC13),
177 EXTI4_15 => (gpioc, PC14),
178 EXTI4_15 => (gpioc, PC15),
179}
180
181exti! {
182 EXTI0_1 => (gpiod, PD0),
183 EXTI0_1 => (gpiod, PD1),
184 EXTI2_3 => (gpiod, PD2),
185 EXTI2_3 => (gpiod, PD3),
186 EXTI4_15 => (gpiod, PD4),
187 EXTI4_15 => (gpiod, PD5),
188 EXTI4_15 => (gpiod, PD6),
189 EXTI4_15 => (gpiod, PD7),
190 EXTI4_15 => (gpiod, PD8),
191 EXTI4_15 => (gpiod, PD9),
192 EXTI4_15 => (gpiod, PD10),
193 EXTI4_15 => (gpiod, PD11),
194 EXTI4_15 => (gpiod, PD12),
195 EXTI4_15 => (gpiod, PD13),
196 EXTI4_15 => (gpiod, PD14),
197 EXTI4_15 => (gpiod, PD15),
198}
199
200exti! {
201 EXTI0_1 => (gpioe, PE0),
202 EXTI0_1 => (gpioe, PE1),
203 EXTI2_3 => (gpioe, PE2),
204 EXTI2_3 => (gpioe, PE3),
205 EXTI4_15 => (gpioe, PE4),
206 EXTI4_15 => (gpioe, PE5),
207 EXTI4_15 => (gpioe, PE6),
208 EXTI4_15 => (gpioe, PE7),
209 EXTI4_15 => (gpioe, PE8),
210 EXTI4_15 => (gpioe, PE9),
211 EXTI4_15 => (gpioe, PE10),
212 EXTI4_15 => (gpioe, PE11),
213 EXTI4_15 => (gpioe, PE12),
214 EXTI4_15 => (gpioe, PE13),
215 EXTI4_15 => (gpioe, PE14),
216 EXTI4_15 => (gpioe, PE15),
217}
218
219exti! {
220 EXTI0_1 => (gpioh, PH0),
221 EXTI0_1 => (gpioh, PH1),
222 EXTI4_15 => (gpioh, PH9),
223 EXTI4_15 => (gpioh, PH10),
224}
diff --git a/embassy-stm32l0/src/fmt.rs b/embassy-stm32l0/src/fmt.rs
new file mode 100644
index 000000000..1be1057a7
--- /dev/null
+++ b/embassy-stm32l0/src/fmt.rs
@@ -0,0 +1,119 @@
1#![macro_use]
2#![allow(clippy::module_inception)]
3
4#[cfg(all(feature = "defmt", feature = "log"))]
5compile_error!("You may not enable both `defmt` and `log` features.");
6
7pub use fmt::*;
8
9#[cfg(feature = "defmt")]
10mod fmt {
11 pub use defmt::{
12 assert, assert_eq, assert_ne, debug, debug_assert, debug_assert_eq, debug_assert_ne, error,
13 info, panic, todo, trace, unreachable, unwrap, warn,
14 };
15}
16
17#[cfg(feature = "log")]
18mod fmt {
19 pub use core::{
20 assert, assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, panic, todo,
21 unreachable,
22 };
23 pub use log::{debug, error, info, trace, warn};
24}
25
26#[cfg(not(any(feature = "defmt", feature = "log")))]
27mod fmt {
28 #![macro_use]
29
30 pub use core::{
31 assert, assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, panic, todo,
32 unreachable,
33 };
34
35 #[macro_export]
36 macro_rules! trace {
37 ($($msg:expr),+ $(,)?) => {
38 ()
39 };
40 }
41
42 #[macro_export]
43 macro_rules! debug {
44 ($($msg:expr),+ $(,)?) => {
45 ()
46 };
47 }
48
49 #[macro_export]
50 macro_rules! info {
51 ($($msg:expr),+ $(,)?) => {
52 ()
53 };
54 }
55
56 #[macro_export]
57 macro_rules! warn {
58 ($($msg:expr),+ $(,)?) => {
59 ()
60 };
61 }
62
63 #[macro_export]
64 macro_rules! error {
65 ($($msg:expr),+ $(,)?) => {
66 ()
67 };
68 }
69}
70
71#[cfg(not(feature = "defmt"))]
72#[macro_export]
73macro_rules! unwrap {
74 ($arg:expr) => {
75 match $crate::fmt::Try::into_result($arg) {
76 ::core::result::Result::Ok(t) => t,
77 ::core::result::Result::Err(e) => {
78 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
79 }
80 }
81 };
82 ($arg:expr, $($msg:expr),+ $(,)? ) => {
83 match $crate::fmt::Try::into_result($arg) {
84 ::core::result::Result::Ok(t) => t,
85 ::core::result::Result::Err(e) => {
86 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
87 }
88 }
89 }
90}
91
92#[derive(Debug, Copy, Clone, Eq, PartialEq)]
93pub struct NoneError;
94
95pub trait Try {
96 type Ok;
97 type Error;
98 fn into_result(self) -> Result<Self::Ok, Self::Error>;
99}
100
101impl<T> Try for Option<T> {
102 type Ok = T;
103 type Error = NoneError;
104
105 #[inline]
106 fn into_result(self) -> Result<T, NoneError> {
107 self.ok_or(NoneError)
108 }
109}
110
111impl<T, E> Try for Result<T, E> {
112 type Ok = T;
113 type Error = E;
114
115 #[inline]
116 fn into_result(self) -> Self {
117 self
118 }
119}
diff --git a/embassy-stm32l0/src/interrupt.rs b/embassy-stm32l0/src/interrupt.rs
new file mode 100644
index 000000000..499f3f275
--- /dev/null
+++ b/embassy-stm32l0/src/interrupt.rs
@@ -0,0 +1,162 @@
1//! Interrupt management
2use crate::pac::NVIC_PRIO_BITS;
3
4// Re-exports
5pub use cortex_m::interrupt::{CriticalSection, Mutex};
6pub use embassy::interrupt::{declare, take, Interrupt};
7
8#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
9#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10#[repr(u8)]
11pub enum Priority {
12 Level0 = 0,
13 Level1 = 1,
14 Level2 = 2,
15 Level3 = 3,
16 Level4 = 4,
17 Level5 = 5,
18 Level6 = 6,
19 Level7 = 7,
20 Level8 = 8,
21 Level9 = 9,
22 Level10 = 10,
23 Level11 = 11,
24 Level12 = 12,
25 Level13 = 13,
26 Level14 = 14,
27 Level15 = 15,
28}
29
30impl From<u8> for Priority {
31 fn from(priority: u8) -> Self {
32 match priority >> (8 - NVIC_PRIO_BITS) {
33 0 => Self::Level0,
34 1 => Self::Level1,
35 2 => Self::Level2,
36 3 => Self::Level3,
37 4 => Self::Level4,
38 5 => Self::Level5,
39 6 => Self::Level6,
40 7 => Self::Level7,
41 8 => Self::Level8,
42 9 => Self::Level9,
43 10 => Self::Level10,
44 11 => Self::Level11,
45 12 => Self::Level12,
46 13 => Self::Level13,
47 14 => Self::Level14,
48 15 => Self::Level15,
49 _ => unreachable!(),
50 }
51 }
52}
53
54impl From<Priority> for u8 {
55 fn from(p: Priority) -> Self {
56 (p as u8) << (8 - NVIC_PRIO_BITS)
57 }
58}
59
60#[cfg(feature = "stm32l0x1")]
61mod irqs {
62 use super::*;
63 declare!(WWDG);
64 declare!(PVD);
65 declare!(RTC);
66 declare!(FLASH);
67 declare!(RCC);
68 declare!(EXTI0_1);
69 declare!(EXTI2_3);
70 declare!(EXTI4_15);
71 declare!(DMA1_CHANNEL1);
72 declare!(DMA1_CHANNEL2_3);
73 declare!(DMA1_CHANNEL4_7);
74 declare!(ADC_COMP);
75 declare!(LPTIM1);
76 declare!(USART4_USART5);
77 declare!(TIM2);
78 declare!(TIM3);
79 declare!(TIM6);
80 declare!(TIM7);
81 declare!(TIM21);
82 declare!(I2C3);
83 declare!(TIM22);
84 declare!(I2C1);
85 declare!(I2C2);
86 declare!(SPI1);
87 declare!(SPI2);
88 declare!(USART1);
89 declare!(USART2);
90 declare!(AES_RNG_LPUART1);
91}
92
93#[cfg(feature = "stm32l0x2")]
94mod irqs {
95 use super::*;
96 declare!(WWDG);
97 declare!(PVD);
98 declare!(RTC);
99 declare!(RCC);
100 declare!(EXTI0_1);
101 declare!(EXTI2_3);
102 declare!(EXTI4_15);
103 declare!(TSC);
104 declare!(DMA1_CHANNEL1);
105 declare!(DMA1_CHANNEL2_3);
106 declare!(DMA1_CHANNEL4_7);
107 declare!(ADC_COMP);
108 declare!(LPTIM1);
109 declare!(USART4_USART5);
110 declare!(TIM2);
111 declare!(TIM3);
112 declare!(TIM6_DAC);
113 declare!(TIM7);
114 declare!(TIM21);
115 declare!(I2C3);
116 declare!(TIM22);
117 declare!(I2C1);
118 declare!(I2C2);
119 declare!(SPI1);
120 declare!(SPI2);
121 declare!(USART1);
122 declare!(USART2);
123 declare!(AES_RNG_LPUART1);
124 declare!(USB);
125}
126
127#[cfg(feature = "stm32l0x3")]
128mod irqs {
129 use super::*;
130 declare!(WWDG);
131 declare!(PVD);
132 declare!(RTC);
133 declare!(RCC);
134 declare!(EXTI0_1);
135 declare!(EXTI2_3);
136 declare!(EXTI4_15);
137 declare!(TSC);
138 declare!(DMA1_CHANNEL1);
139 declare!(DMA1_CHANNEL2_3);
140 declare!(DMA1_CHANNEL4_7);
141 declare!(ADC_COMP);
142 declare!(LPTIM1);
143 declare!(USART4_USART5);
144 declare!(TIM2);
145 declare!(TIM3);
146 declare!(TIM6_DAC);
147 declare!(TIM7);
148 declare!(TIM21);
149 declare!(I2C3);
150 declare!(TIM22);
151 declare!(I2C1);
152 declare!(I2C2);
153 declare!(SPI1);
154 declare!(SPI2);
155 declare!(USART1);
156 declare!(USART2);
157 declare!(AES_RNG_LPUART1);
158 declare!(LCD);
159 declare!(USB);
160}
161
162pub use irqs::*;
diff --git a/embassy-stm32l0/src/lib.rs b/embassy-stm32l0/src/lib.rs
new file mode 100644
index 000000000..d030713ca
--- /dev/null
+++ b/embassy-stm32l0/src/lib.rs
@@ -0,0 +1,29 @@
1#![no_std]
2#![feature(generic_associated_types)]
3#![feature(asm)]
4#![feature(type_alias_impl_trait)]
5#![feature(min_type_alias_impl_trait)]
6#![allow(incomplete_features)]
7
8#[cfg(not(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",)))]
9compile_error!(
10 "No chip feature activated. You must activate exactly one of the following features: "
11);
12
13#[cfg(any(
14 all(feature = "stm32l0x1", feature = "stm32l0x2"),
15 all(feature = "stm32l0x1", feature = "stm32l0x3"),
16 all(feature = "stm32l0x2", feature = "stm32l0x3"),
17))]
18compile_error!(
19 "Multile chip features activated. You must activate exactly one of the following features: "
20);
21
22pub use stm32l0xx_hal as hal;
23pub use stm32l0xx_hal::pac;
24
25// This mod MUST go first, so that the others see its macros.
26pub(crate) mod fmt;
27
28pub mod exti;
29pub mod interrupt;