Skip to content

Commit 29809cc

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

File tree

6 files changed

+331
-29
lines changed

6 files changed

+331
-29
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ paste = "1.0.15"
7878
log = { version = "0.4.20", optional = true}
7979
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

examples/exti.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+
led: 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 led = gpioa
44+
.pa5
45+
.into_input()
46+
.make_interrupt_source(exti_channels.ch5, &mut exti);
47+
48+
(Shared {}, Local { led })
49+
}
50+
51+
#[task(local = [led])]
52+
async fn foo(ctx: foo::Context) {
53+
loop {
54+
ctx.local.led.wait_for_high().await.unwrap();
55+
info!("On");
56+
ctx.local.led.wait_for_low().await.unwrap();
57+
info!("Off");
58+
}
59+
}
60+
}

src/gpio.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ mod convert;
5858
mod dynamic;
5959
mod erased;
6060
mod exti;
61+
mod future;
6162
mod gpio_def;
6263
mod hal;
6364
mod partially_erased;
@@ -71,7 +72,7 @@ pub use dynamic::{Dynamic, DynamicPin};
7172
pub use embedded_hal::digital::PinState;
7273

7374
pub use erased::{EPin, ErasedPin};
74-
pub use exti::ExtiPin;
75+
pub use exti::{ExtiExt, ExtiPin, ExtiedPin};
7576
pub use gpio_def::*;
7677
pub use partially_erased::{PEPin, PartiallyErasedPin};
7778

@@ -264,10 +265,16 @@ pub type AF15<Otype = PushPull> = Alternate<15, Otype>;
264265
/// - `MODE` is one of the pin modes (see [Modes](crate::gpio#modes) section).
265266
/// - `P` is port name: `A` for GPIOA, `B` for GPIOB, etc.
266267
/// - `N` is pin number: from `0` to `15`.
267-
pub struct Pin<const P: char, const N: u8, MODE = Analog> {
268+
/// - `INT` is true of the pin is configured for EXTI interrupt
269+
pub struct Pin<
270+
const P: char,
271+
const N: u8,
272+
MODE = Analog,
273+
const INT: bool = false,
274+
> {
268275
_mode: PhantomData<MODE>,
269276
}
270-
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
277+
impl<const P: char, const N: u8, MODE, const INT: bool> Pin<P, N, MODE, INT> {
271278
const fn new() -> Self {
272279
Self { _mode: PhantomData }
273280
}
@@ -412,7 +419,7 @@ impl<const P: char, const N: u8, MODE> From<Pin<P, N, MODE>>
412419
}
413420
}
414421

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

src/gpio/exti.rs

Lines changed: 110 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,40 @@ 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+
marker::Interruptable
102+
{
103+
fn make_interrupt_source(
104+
self,
105+
_ch: ExtiChannel<N>,
106+
ch: &mut Exti,
107+
) -> Pin<P, N, M, true>;
108+
}
109+
110+
// TODO: Find better name
111+
/// Only available on pins where interrupts have been enabled by the user
112+
pub trait ExtiedPin<const N: u8> {
113+
fn trigger_on_edge(&mut self, exti: &mut Exti, level: Edge);
114+
fn enable_event(&mut self, exti: &mut Exti);
115+
fn disable_event(&mut self, exti: &mut Exti);
116+
fn enable_interrupt(&mut self, exti: &mut Exti);
117+
fn disable_interrupt(&mut self, exti: &mut Exti);
40118
fn clear_interrupt_pending_bit(&mut self, edge: Edge);
41119
fn check_interrupt(&self, edge: Edge) -> bool;
42120
}
43121

44-
impl<PIN> ExtiPin for PIN
122+
impl<const P: char, const N: u8, M> ExtiPin<P, N, M>
123+
for gpio::Pin<P, N, M, false>
45124
where
46-
PIN: PinExt,
47-
PIN::Mode: marker::Interruptable,
125+
Self: marker::Interruptable,
48126
{
49127
/// Make corresponding EXTI line sensitive to this pin
50128
#[inline(always)]
51-
fn make_interrupt_source(&mut self, exti: &mut EXTI) {
129+
fn make_interrupt_source(
130+
self,
131+
_ch: ExtiChannel<N>,
132+
exti: &mut Exti,
133+
) -> Pin<P, N, M, true> {
52134
let i = self.pin_id();
53135
let port = self.port_id() as u32;
54136
let offset = 8 * (i % 4);
@@ -75,12 +157,16 @@ where
75157
}
76158
_ => unreachable!(),
77159
}
160+
161+
Pin { _mode: PhantomData }
78162
}
163+
}
79164

165+
impl<const P: char, const N: u8, M> ExtiedPin<N> for gpio::Pin<P, N, M, true> {
80166
/// Generate interrupt on rising edge, falling edge or both
81167
#[inline(always)]
82-
fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) {
83-
let i = self.pin_id();
168+
fn trigger_on_edge(&mut self, exti: &mut Exti, edge: Edge) {
169+
let i = N;
84170
match edge {
85171
Edge::Rising => {
86172
exti.rtsr1()
@@ -105,30 +191,30 @@ where
105191

106192
/// Enable external interrupts from this pin.
107193
#[inline(always)]
108-
fn enable_event(&mut self, exti: &mut EXTI) {
194+
fn enable_event(&mut self, exti: &mut Exti) {
109195
exti.emr1()
110-
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.pin_id())) });
196+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << N)) });
111197
}
112198

113199
/// Disable external interrupts from this pin
114200
#[inline(always)]
115-
fn disable_event(&mut self, exti: &mut EXTI) {
201+
fn disable_event(&mut self, exti: &mut Exti) {
116202
exti.emr1()
117-
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin_id())) });
203+
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << N)) });
118204
}
119205

120206
/// Enable external interrupts from this pin.
121207
#[inline(always)]
122-
fn enable_interrupt(&mut self, exti: &mut EXTI) {
208+
fn enable_interrupt(&mut self, exti: &mut Exti) {
123209
exti.imr1()
124-
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.pin_id())) });
210+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << N)) });
125211
}
126212

127213
/// Disable external interrupts from this pin
128214
#[inline(always)]
129-
fn disable_interrupt(&mut self, exti: &mut EXTI) {
215+
fn disable_interrupt(&mut self, exti: &mut Exti) {
130216
exti.imr1()
131-
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin_id())) });
217+
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << N)) });
132218
}
133219

134220
/// Clear the interrupt pending bit for this pin
@@ -137,7 +223,7 @@ where
137223
unsafe {
138224
let exti = &(*EXTI::ptr());
139225

140-
let mask = 1 << self.pin_id();
226+
let mask = 1 << N;
141227
match edge {
142228
Edge::Rising => exti.rpr1().write(|w| w.bits(mask)),
143229
Edge::Falling => exti.fpr1().write(|w| w.bits(mask)),
@@ -158,7 +244,7 @@ where
158244
_ => panic!("Must choose a rising or falling edge"),
159245
};
160246

161-
bits & (1 << self.pin_id()) != 0
247+
bits & (1 << N) != 0
162248
}
163249
}
164250
}

0 commit comments

Comments
 (0)