Skip to content

Commit 35ddeef

Browse files
committed
NOT TESTED - impl eh-async::digital::Wait for awating pins
1 parent 889ebde commit 35ddeef

File tree

6 files changed

+336
-30
lines changed

6 files changed

+336
-30
lines changed

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ embedded-hal = "1.0.0"
7676
defmt = { version = "1.0.0", optional = true }
7777
paste = "1.0.15"
7878
log = { version = "0.4.20", optional = true}
79-
futures-util = { version = "0.3", default-features = false, features = ["async-await-macro"], optional = true}
79+
futures-util = { version = "0.3", default-features = false, features = ["async-await-macro"], optional = true }
8080
stm32-usbd = "0.8.0"
81+
embedded-hal-async = "1.0.0"
8182

8283
[dev-dependencies]
8384
log = { version = "0.4.20"}
@@ -95,6 +96,7 @@ panic-probe = "0.3.2"
9596
panic-semihosting = "0.6"
9697
usbd-serial = "0.2.2"
9798
usb-device = { version = "0.3.2", features = ["defmt", "log"] }
99+
rtic = { version = "2.2", features = ["thumbv8main-backend"] }
98100

99101
[profile.release]
100102
codegen-units = 1 # better optimizations
@@ -116,3 +118,7 @@ required-features = ["stm32h503"]
116118
[[example]]
117119
name = "i2c_target_manual_ack"
118120
required-features = ["stm32h503"]
121+
122+
[[example]]
123+
name = "await-pins"
124+
required-features = ["futures"]

examples/await-pins.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#![deny(warnings)]
2+
#![no_main]
3+
#![no_std]
4+
5+
mod utilities;
6+
use embedded_hal_async::digital::Wait;
7+
use stm32h5xx_hal::{
8+
gpio::{ExtiExt, ExtiPin},
9+
pac,
10+
prelude::*,
11+
};
12+
use utilities::logger::info;
13+
14+
#[rtic::app(device = pac, dispatchers = [USART1, USART2], peripherals = true)]
15+
mod app {
16+
use stm32h5xx_hal::gpio;
17+
18+
use super::*;
19+
20+
#[shared]
21+
struct Shared {}
22+
23+
#[local]
24+
struct Local {
25+
pin: gpio::PA5<gpio::Input, true>,
26+
}
27+
28+
#[init]
29+
fn init(ctx: init::Context) -> (Shared, Local) {
30+
let dp = ctx.device;
31+
32+
let pwr = dp.PWR.constrain();
33+
let pwrcfg = pwr.vos0().freeze();
34+
35+
// Constrain and Freeze clock
36+
let rcc = dp.RCC.constrain();
37+
let ccdr = rcc.sys_ck(250.MHz()).freeze(pwrcfg, &dp.SBS);
38+
39+
let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA);
40+
41+
let (mut exti, exti_channels) = dp.EXTI.split();
42+
43+
let pin = gpioa
44+
.pa5
45+
.into_input()
46+
.make_interrupt_source(exti_channels.ch5, &mut exti);
47+
48+
(Shared {}, Local { pin })
49+
}
50+
51+
#[task(local = [pin])]
52+
async fn foo(ctx: foo::Context) {
53+
loop {
54+
ctx.local.pin.wait_for_high().await.unwrap();
55+
info!("On");
56+
ctx.local.pin.wait_for_low().await.unwrap();
57+
info!("Off");
58+
}
59+
}
60+
}

src/gpio.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ mod convert;
5858
mod dynamic;
5959
mod erased;
6060
mod exti;
61+
62+
#[cfg(feature = "futures")]
63+
mod future;
6164
mod gpio_def;
6265
mod hal;
6366
mod partially_erased;
@@ -71,7 +74,7 @@ pub use dynamic::{Dynamic, DynamicPin};
7174
pub use embedded_hal::digital::PinState;
7275

7376
pub use erased::{EPin, ErasedPin};
74-
pub use exti::ExtiPin;
77+
pub use exti::{ExtiExt, ExtiPin, ExtiedPin};
7578
pub use gpio_def::*;
7679
pub use partially_erased::{PEPin, PartiallyErasedPin};
7780

@@ -264,10 +267,16 @@ pub type AF15<Otype = PushPull> = Alternate<15, Otype>;
264267
/// - `MODE` is one of the pin modes (see [Modes](crate::gpio#modes) section).
265268
/// - `P` is port name: `A` for GPIOA, `B` for GPIOB, etc.
266269
/// - `N` is pin number: from `0` to `15`.
267-
pub struct Pin<const P: char, const N: u8, MODE = Analog> {
270+
/// - `INT` is true of the pin is configured for EXTI interrupt
271+
pub struct Pin<
272+
const P: char,
273+
const N: u8,
274+
MODE = Analog,
275+
const INT: bool = false,
276+
> {
268277
_mode: PhantomData<MODE>,
269278
}
270-
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
279+
impl<const P: char, const N: u8, MODE, const INT: bool> Pin<P, N, MODE, INT> {
271280
const fn new() -> Self {
272281
Self { _mode: PhantomData }
273282
}
@@ -412,7 +421,7 @@ impl<const P: char, const N: u8, MODE> From<Pin<P, N, MODE>>
412421
}
413422
}
414423

415-
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
424+
impl<const P: char, const N: u8, MODE, const INT: bool> Pin<P, N, MODE, INT> {
416425
/// Set the output of the pin regardless of its mode.
417426
/// Primarily used to set the output value of the pin
418427
/// before changing its mode to an output to avoid

src/gpio/exti.rs

Lines changed: 108 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,72 @@
1+
use core::{marker::PhantomData, ops::Deref};
2+
13
use super::{marker, Edge, Pin, PinExt};
2-
use crate::pac::{Interrupt, EXTI};
4+
use crate::{
5+
gpio,
6+
pac::{Interrupt, EXTI},
7+
};
8+
9+
pub trait ExtiExt {
10+
fn split(self) -> (Exti, ExtiChannels);
11+
}
12+
13+
impl ExtiExt for EXTI {
14+
fn split(self) -> (Exti, ExtiChannels) {
15+
(
16+
Exti(self),
17+
ExtiChannels {
18+
ch0: ExtiChannel,
19+
ch1: ExtiChannel,
20+
ch2: ExtiChannel,
21+
ch3: ExtiChannel,
22+
ch4: ExtiChannel,
23+
ch5: ExtiChannel,
24+
ch6: ExtiChannel,
25+
ch7: ExtiChannel,
26+
ch8: ExtiChannel,
27+
ch9: ExtiChannel,
28+
ch10: ExtiChannel,
29+
ch11: ExtiChannel,
30+
ch12: ExtiChannel,
31+
ch13: ExtiChannel,
32+
ch14: ExtiChannel,
33+
ch15: ExtiChannel,
34+
},
35+
)
36+
}
37+
}
38+
39+
pub struct Exti(pub(crate) EXTI);
40+
41+
impl Deref for Exti {
42+
type Target = EXTI;
43+
44+
fn deref(&self) -> &Self::Target {
45+
&self.0
46+
}
47+
}
48+
49+
#[non_exhaustive]
50+
pub struct ExtiChannel<const N: u8>;
51+
52+
pub struct ExtiChannels {
53+
pub ch0: ExtiChannel<0>,
54+
pub ch1: ExtiChannel<1>,
55+
pub ch2: ExtiChannel<2>,
56+
pub ch3: ExtiChannel<3>,
57+
pub ch4: ExtiChannel<4>,
58+
pub ch5: ExtiChannel<5>,
59+
pub ch6: ExtiChannel<6>,
60+
pub ch7: ExtiChannel<7>,
61+
pub ch8: ExtiChannel<8>,
62+
pub ch9: ExtiChannel<9>,
63+
pub ch10: ExtiChannel<10>,
64+
pub ch11: ExtiChannel<11>,
65+
pub ch12: ExtiChannel<12>,
66+
pub ch13: ExtiChannel<13>,
67+
pub ch14: ExtiChannel<14>,
68+
pub ch15: ExtiChannel<15>,
69+
}
370

471
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
572
/// NVIC interrupt number of interrupt from this pin
@@ -30,25 +97,38 @@ impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
3097
}
3198

3299
/// External Interrupt Pin
33-
pub trait ExtiPin {
34-
fn make_interrupt_source(&mut self, exti: &mut EXTI);
35-
fn trigger_on_edge(&mut self, exti: &mut EXTI, level: Edge);
36-
fn enable_event(&mut self, exti: &mut EXTI);
37-
fn disable_event(&mut self, exti: &mut EXTI);
38-
fn enable_interrupt(&mut self, exti: &mut EXTI);
39-
fn disable_interrupt(&mut self, exti: &mut EXTI);
100+
pub trait ExtiPin<const P: char, const N: u8, M> {
101+
fn make_interrupt_source(
102+
self,
103+
_ch: ExtiChannel<N>,
104+
ch: &mut Exti,
105+
) -> Pin<P, N, M, true>;
106+
}
107+
108+
// TODO: Find better name
109+
/// Only available on pins where interrupts have been enabled by the user
110+
pub trait ExtiedPin<const N: u8> {
111+
fn trigger_on_edge(&mut self, exti: &mut Exti, level: Edge);
112+
fn enable_event(&mut self, exti: &mut Exti);
113+
fn disable_event(&mut self, exti: &mut Exti);
114+
fn enable_interrupt(&mut self, exti: &mut Exti);
115+
fn disable_interrupt(&mut self, exti: &mut Exti);
40116
fn clear_interrupt_pending_bit(&mut self, edge: Edge);
41117
fn check_interrupt(&self, edge: Edge) -> bool;
42118
}
43119

44-
impl<PIN> ExtiPin for PIN
120+
impl<const P: char, const N: u8, M> ExtiPin<P, N, M>
121+
for gpio::Pin<P, N, M, false>
45122
where
46-
PIN: PinExt,
47-
PIN::Mode: marker::Interruptable,
123+
M: marker::Interruptable,
48124
{
49125
/// Make corresponding EXTI line sensitive to this pin
50126
#[inline(always)]
51-
fn make_interrupt_source(&mut self, exti: &mut EXTI) {
127+
fn make_interrupt_source(
128+
self,
129+
_ch: ExtiChannel<N>,
130+
exti: &mut Exti,
131+
) -> Pin<P, N, M, true> {
52132
let i = self.pin_id();
53133
let port = self.port_id() as u32;
54134
let offset = 8 * (i % 4);
@@ -75,12 +155,16 @@ where
75155
}
76156
_ => unreachable!(),
77157
}
158+
159+
Pin { _mode: PhantomData }
78160
}
161+
}
79162

163+
impl<const P: char, const N: u8, M> ExtiedPin<N> for gpio::Pin<P, N, M, true> {
80164
/// Generate interrupt on rising edge, falling edge or both
81165
#[inline(always)]
82-
fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) {
83-
let i = self.pin_id();
166+
fn trigger_on_edge(&mut self, exti: &mut Exti, edge: Edge) {
167+
let i = N;
84168
match edge {
85169
Edge::Rising => {
86170
exti.rtsr1()
@@ -105,30 +189,30 @@ where
105189

106190
/// Enable external interrupts from this pin.
107191
#[inline(always)]
108-
fn enable_event(&mut self, exti: &mut EXTI) {
192+
fn enable_event(&mut self, exti: &mut Exti) {
109193
exti.emr1()
110-
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.pin_id())) });
194+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << N)) });
111195
}
112196

113197
/// Disable external interrupts from this pin
114198
#[inline(always)]
115-
fn disable_event(&mut self, exti: &mut EXTI) {
199+
fn disable_event(&mut self, exti: &mut Exti) {
116200
exti.emr1()
117-
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin_id())) });
201+
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << N)) });
118202
}
119203

120204
/// Enable external interrupts from this pin.
121205
#[inline(always)]
122-
fn enable_interrupt(&mut self, exti: &mut EXTI) {
206+
fn enable_interrupt(&mut self, exti: &mut Exti) {
123207
exti.imr1()
124-
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.pin_id())) });
208+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << N)) });
125209
}
126210

127211
/// Disable external interrupts from this pin
128212
#[inline(always)]
129-
fn disable_interrupt(&mut self, exti: &mut EXTI) {
213+
fn disable_interrupt(&mut self, exti: &mut Exti) {
130214
exti.imr1()
131-
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin_id())) });
215+
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << N)) });
132216
}
133217

134218
/// Clear the interrupt pending bit for this pin
@@ -137,7 +221,7 @@ where
137221
unsafe {
138222
let exti = &(*EXTI::ptr());
139223

140-
let mask = 1 << self.pin_id();
224+
let mask = 1 << N;
141225
match edge {
142226
Edge::Rising => exti.rpr1().write(|w| w.bits(mask)),
143227
Edge::Falling => exti.fpr1().write(|w| w.bits(mask)),
@@ -158,7 +242,7 @@ where
158242
_ => panic!("Must choose a rising or falling edge"),
159243
};
160244

161-
bits & (1 << self.pin_id()) != 0
245+
bits & (1 << N) != 0
162246
}
163247
}
164248
}

0 commit comments

Comments
 (0)