Skip to content

Commit f18a64b

Browse files
authored
Merge pull request #253 from Sh3Rm4n/serial-events
Rework serial (interrupt) events
2 parents 598fb34 + f1e0c83 commit f18a64b

File tree

8 files changed

+920
-139
lines changed

8 files changed

+920
-139
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
features: ["rt"]
4141
include:
4242
- mcu: stm32f303xc
43-
features: rt,can,stm32-usbd
43+
features: rt,can,stm32-usbd,enumset
4444
steps:
4545
- uses: actions/checkout@v2
4646
- uses: actions-rs/toolchain@v1

CHANGELOG.md

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,45 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1919
- Readd MonoTimer. This was accidentally removed before. ([#247])
2020
- Basic serial implementation also available for UART4 and UART5 ([#246])
2121
- Implement serial DMA also for Serial ([#246])
22+
- Add [`enumset`][] as a optional dependency, which allow more ergonomic functions
23+
regarding enums. This is especially useful for status event query functions.
24+
([#253])
25+
- As serial `Error` and serial `Events` share things in common. `TryFrom<Event>`
26+
and `From<Error>` is implemented for conversions. ([#253])
27+
- Add serial character match function, with which events can be triggered for
28+
the set character. ([#253])
29+
- Add receiver timeout function, which configures the serial peripheral to
30+
trigger an event, if nothing happened after a certain time on the serial
31+
receiver line. ([#253])
32+
- Add `raw_read()` function, which does no error handling and also does not
33+
clear any `Event` by itself. Useful, if the error_handling has to be done in
34+
another context (like an interrupt rountine). ([#253])
35+
- Introduce `Toggle`, with `On` and `Off` as a convinience wrapper around `bool`
36+
for configuration purposes. ([#253])
37+
- Add an associated const to `serial::Instance` to return the corresponding
38+
`pac::Interrupt`-number, which is useful to `unmask()` interrupts.
39+
An `nvic()` function to `Serial` was also added for convinience. ([#253])
40+
- Add a `Serial::is_busy()` function to check, if the serial device is busy.
41+
Useful to block on this function, e.g. `while serial.is_busy() {}`. ([#253])
42+
- Add `BaudTable` a convinience wrapper around `Baud` to configure the `Serial`
43+
to the most commen baud rates. ([#253])
44+
- Add `Serial::detect_overrun()` function, to en- or disable the overrun
45+
detection of the `Serial`. If overrun is disabled (enabled by default), than
46+
newly arrived bytes are overwriting the current data in the read receive
47+
register without throwing any event. ([#253]).
48+
- Lift generic constraint of most `Serial` method on `TxPin` and `RxPin`.
49+
This should make it easier to generically use the `Serial` peripheral. ([#253])
50+
51+
[`enumset`]: https://crates.io/crates/enumset
2252

2353
### Changed
2454

2555
- `PXx` struct (representing a generic GPIO pin) implements `Send` and `Sync` ([#251])
2656
- Each pin aliases (`PA0`, `PA1`, ..) are defined under `gpio` module directly.
27-
Re-export from gpio port sub-modules are provided for compatibility. [#257]
57+
Re-export from gpio port sub-modules are provided for compatibility. ([#257])
58+
- The `embedded-hal` Read implementation of `Serial` does now return `WoudBlock`
59+
if the peripheral is busy. Also if an `Overrun` occured the receive data
60+
register (RDR) is flushed to have a more consistent API. ([#253])
2861

2962
### Fixed
3063

@@ -45,6 +78,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
4578
when `Serial::split` was previously called. ([#252])
4679
- Parameterized `usb::Peripheral` and `usb::UsbType` on the pin configuration
4780
used ([#255])
81+
- Add (almost) all missing serial (interrupt and status) events.
82+
Also rename all the event names to be more descriptive. ([#253])
83+
- A new serial interrupt API was introduced: ([#253])
84+
- `listen()` and `unlisten()` are renamed to `enable_interrupt()` and
85+
`disable_interrupt()`.
86+
- `is_tc()` and other non-parametrizable functions are removed.
87+
- `configure_interrupt()` was added, which can be parameterized.
88+
- `clear_event()` was added to clear specific events.
89+
- `clear_events()` was added to clear all events at once.
90+
- `is_event_triggered()` can check if an `Event` is triggered.
91+
- `triggered_events` returns an `EnumSet` of triggered events.
4892

4993
## [v0.7.0] - 2021-06-18
5094

@@ -374,6 +418,7 @@ let clocks = rcc
374418
[#259]: https://github.com/stm32-rs/stm32f3xx-hal/pull/259
375419
[#257]: https://github.com/stm32-rs/stm32f3xx-hal/pull/257
376420
[#255]: https://github.com/stm32-rs/stm32f3xx-hal/pull/255
421+
[#253]: https://github.com/stm32-rs/stm32f3xx-hal/pull/253
377422
[#252]: https://github.com/stm32-rs/stm32f3xx-hal/pull/252
378423
[#251]: https://github.com/stm32-rs/stm32f3xx-hal/pull/251
379424
[#247]: https://github.com/stm32-rs/stm32f3xx-hal/pull/247

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ stm32f3 = "0.13.2"
4747
bxcan = { version = ">=0.4, <0.6", optional = true }
4848
stm32-usbd = { version = "0.6.0", optional = true }
4949
void = { version = "1.0.2", default-features = false }
50+
enumset = { version = "1.0.6", optional = true}
5051

5152
[dev-dependencies]
5253
cortex-m = "0.7.2"
@@ -186,7 +187,7 @@ required-features = ["ld", "rt", "stm32f303"]
186187

187188
[[example]]
188189
name = "serial_echo_rtic"
189-
required-features = ["ld", "rt", "stm32f303xc"]
190+
required-features = ["ld", "rt", "stm32f303xc", "enumset"]
190191

191192
[[example]]
192193
name = "adc"

examples/serial_echo_rtic.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod app {
1212
pac,
1313
prelude::*,
1414
serial::{Event, Serial},
15+
Toggle,
1516
};
1617

1718
#[monotonic(binds = SysTick, default = true)]
@@ -65,10 +66,13 @@ mod app {
6566
pins.1.internal_pull_up(&mut gpioa.pupdr, true);
6667
let mut serial: SerialType =
6768
Serial::new(cx.device.USART1, pins, 19200.Bd(), clocks, &mut rcc.apb2);
68-
serial.listen(Event::Rxne);
69+
serial.configure_interrupt(Event::ReceiveDataRegisterNotEmpty, Toggle::On);
6970

7071
rprintln!("post init");
7172

73+
// A kick of for the infitinte loop in protocol_serial_task()
74+
nb::block!(serial.write(b'c')).unwrap();
75+
7276
task1::spawn().unwrap();
7377

7478
(Shared {}, Local { serial, dir }, init::Monotonics(mono))
@@ -79,22 +83,33 @@ mod app {
7983
let serial = cx.local.serial;
8084
let dir = cx.local.dir;
8185

82-
if serial.is_rxne() {
86+
if serial.is_event_triggered(Event::ReceiveDataRegisterNotEmpty) {
8387
dir.set_high().unwrap();
84-
serial.unlisten(Event::Rxne);
88+
serial.configure_interrupt(Event::ReceiveDataRegisterNotEmpty, Toggle::Off);
8589
match serial.read() {
8690
Ok(byte) => {
8791
serial.write(byte).unwrap();
88-
serial.listen(Event::Tc);
92+
rprintln!("{:?}", char::from_u32(byte.into()).unwrap_or('?'));
93+
serial.configure_interrupt(Event::TransmissionComplete, Toggle::On);
8994
}
9095
Err(_error) => rprintln!("irq error"),
9196
};
9297
}
9398

94-
if serial.is_tc() {
99+
// It is perfectly viable to just use `is_event_triggered` here,
100+
// but this is a showcase, to also be able to used `triggered_events`
101+
// and other functions enabled by the "enumset" feature.
102+
let events = serial.triggered_events();
103+
if events.contains(Event::TransmissionComplete) {
95104
dir.set_low().unwrap();
96-
serial.unlisten(Event::Tc);
97-
serial.listen(Event::Rxne);
105+
let interrupts = {
106+
let mut interrupts = enumset::EnumSet::new();
107+
interrupts.insert(Event::ReceiveDataRegisterNotEmpty);
108+
interrupts
109+
};
110+
serial.clear_event(Event::TransmissionComplete);
111+
// Disable all interrupts, except ReceiveDataRegisterNotEmpty.
112+
serial.configure_interrupts(interrupts);
98113
}
99114
}
100115

src/lib.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@
6969
7070
Enable USB peripherals on supported targets.
7171
72+
### `enumset`
73+
74+
Enable functions, which leverage [`enumset`](https://crates.io/crates/enumset).
75+
This is especially usefull to get all set status events at once,
76+
see for example [`serial::Serial::triggered_events()`]
77+
7278
### `defmt`
7379
7480
Currently these are only used for panicking calls, like
@@ -212,3 +218,30 @@ mod private {
212218
/// which do implement peripheral functionalities.
213219
pub trait Sealed {}
214220
}
221+
222+
/// Toggle something on or off.
223+
///
224+
/// Convenience enum and wrapper around a bool, which more explicit about the intention to enable
225+
/// or disable something, in comparison to `true` or `false`.
226+
// TODO: Maybe move to some mod like "util"?
227+
pub enum Toggle {
228+
/// Toggle something on / enable a thing.
229+
On,
230+
/// Toggle something off / disable a thing.
231+
Off,
232+
}
233+
234+
impl From<Toggle> for bool {
235+
fn from(toggle: Toggle) -> Self {
236+
matches!(toggle, Toggle::On)
237+
}
238+
}
239+
240+
impl From<bool> for Toggle {
241+
fn from(b: bool) -> Self {
242+
match b {
243+
true => Toggle::On,
244+
false => Toggle::Off,
245+
}
246+
}
247+
}

0 commit comments

Comments
 (0)