Skip to content

Commit 7e5f345

Browse files
d3zd3zcfriedt
authored andcommitted
zephyr: gpio: Simplify usage
The gpio driver's 'token' to ensure uniqueness doesn't really help with correctness (as C code can use the gpio device as well). Short of re-defining the gpio interfaces, remove this token entirely, and make only the `get_instance` of gpio unsafe, to indicate that the safety of GPIO operations is dependent on the underlying controller. This should improve the hygeine of the GPIO API significantly, and allow uses, such as waiting on multiple pins, to be possible. Signed-off-by: David Brown <[email protected]>
1 parent f869f71 commit 7e5f345

File tree

2 files changed

+24
-69
lines changed

2 files changed

+24
-69
lines changed

samples/blinky/src/lib.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use log::warn;
1212

13-
use zephyr::raw::GPIO_OUTPUT_ACTIVE;
13+
use zephyr::raw::ZR_GPIO_OUTPUT_ACTIVE;
1414
use zephyr::time::{sleep, Duration};
1515

1616
#[no_mangle]
@@ -29,21 +29,16 @@ fn do_blink() {
2929
warn!("Inside of blinky");
3030

3131
let mut led0 = zephyr::devicetree::aliases::led0::get_instance().unwrap();
32-
let mut gpio_token = unsafe { zephyr::device::gpio::GpioToken::get_instance().unwrap() };
3332

3433
if !led0.is_ready() {
3534
warn!("LED is not ready");
3635
loop {}
3736
}
3837

39-
unsafe {
40-
led0.configure(&mut gpio_token, GPIO_OUTPUT_ACTIVE);
41-
}
38+
led0.configure(ZR_GPIO_OUTPUT_ACTIVE);
4239
let duration = Duration::millis_at_least(500);
4340
loop {
44-
unsafe {
45-
led0.toggle_pin(&mut gpio_token);
46-
}
41+
led0.toggle_pin();
4742
sleep(duration);
4843
}
4944
}

zephyr/src/device/gpio.rs

Lines changed: 21 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ mod async_io {
3737

3838
use crate::sync::atomic::{AtomicBool, AtomicU32};
3939

40-
use super::{GpioPin, GpioToken};
40+
use super::GpioPin;
4141

4242
pub(crate) struct GpioStatic {
4343
/// The wakers for each of the gpios.
@@ -158,26 +158,17 @@ mod async_io {
158158
///
159159
/// # Safety
160160
///
161-
/// The `_token` enforces single use of gpios. Note that this makes it impossible to wait for
162-
/// more than one GPIO.
163-
///
164-
pub unsafe fn wait_for_high(
165-
&mut self,
166-
_token: &mut GpioToken,
167-
) -> impl Future<Output = ()> + use<'_> {
161+
/// Safety of multiple GPIOs depends on the underlying controller.
162+
pub unsafe fn wait_for_high(&mut self) -> impl Future<Output = ()> + use<'_> {
168163
GpioWait::new(self, 1)
169164
}
170165

171166
/// Asynchronously wait for a gpio pin to become low.
172167
///
173168
/// # Safety
174169
///
175-
/// The `_token` enforces single use of gpios. Note that this makes it impossible to wait
176-
/// for more than one GPIO.
177-
pub unsafe fn wait_for_low(
178-
&mut self,
179-
_token: &mut GpioToken,
180-
) -> impl Future<Output = ()> + use<'_> {
170+
/// Safety of multiple GPIOs depends on the underlying controller.
171+
pub unsafe fn wait_for_low(&mut self) -> impl Future<Output = ()> + use<'_> {
181172
GpioWait::new(self, 0)
182173
}
183174
}
@@ -245,35 +236,6 @@ mod async_io {
245236

246237
pub(crate) use async_io::*;
247238

248-
/// Global instance to help make gpio in Rust slightly safer.
249-
///
250-
/// # Safety
251-
///
252-
/// To help with safety, the rust types use a global instance of a gpio-token. Methods will
253-
/// take a mutable reference to this, which will require either a single thread in the
254-
/// application code, or something like a mutex or critical section to manage. The operation
255-
/// methods are still unsafe, because we have no control over what happens with the gpio
256-
/// operations outside of Rust code, but this will help make the Rust usage at least better.
257-
pub struct GpioToken(());
258-
259-
static GPIO_TOKEN: Unique = Unique::new();
260-
261-
impl GpioToken {
262-
/// Retrieves the gpio token.
263-
///
264-
/// # Safety
265-
/// This is unsafe because lots of code in zephyr operates on the gpio drivers. The user of the
266-
/// gpio subsystem, in general should either coordinate all gpio access across the system (the
267-
/// token coordinates this only within Rust code), or verify that the particular gpio driver and
268-
/// methods are thread safe.
269-
pub unsafe fn get_instance() -> Option<GpioToken> {
270-
if !GPIO_TOKEN.once() {
271-
return None;
272-
}
273-
Some(GpioToken(()))
274-
}
275-
}
276-
277239
/// A single instance of a zephyr device to manage a gpio controller. A gpio controller
278240
/// represents a set of gpio pins, that are generally operated on by the same hardware block.
279241
pub struct Gpio {
@@ -312,9 +274,7 @@ impl Gpio {
312274

313275
/// A GpioPin represents a single pin on a gpio device.
314276
///
315-
/// This is a lightweight wrapper around the Zephyr `gpio_dt_spec` structure. Note that
316-
/// multiple pins may share a gpio controller, and as such, all methods on this are both unsafe,
317-
/// and require a mutable reference to the [`GpioToken`].
277+
/// This is a lightweight wrapper around the Zephyr `gpio_dt_spec` structure.
318278
#[allow(dead_code)]
319279
pub struct GpioPin {
320280
pub(crate) pin: raw::gpio_dt_spec,
@@ -366,10 +326,8 @@ impl GpioPin {
366326
///
367327
/// # Safety
368328
///
369-
/// The `_token` enforces single threaded use of gpios from Rust code. However, many drivers
370-
/// within Zephyr use GPIOs, and to use gpios safely, the caller must ensure that there is
371-
/// either not simultaneous use, or the gpio driver in question is thread safe.
372-
pub unsafe fn configure(&mut self, _token: &mut GpioToken, extra_flags: raw::gpio_flags_t) {
329+
/// Concurrency safety is determined by the underlying driver.
330+
pub fn configure(&mut self, extra_flags: raw::gpio_flags_t) {
373331
// TODO: Error?
374332
unsafe {
375333
raw::gpio_pin_configure(
@@ -384,27 +342,29 @@ impl GpioPin {
384342
///
385343
/// # Safety
386344
///
387-
/// The `_token` enforces single threaded use of gpios from Rust code. However, many drivers
388-
/// within Zephyr use GPIOs, and to use gpios safely, the caller must ensure that there is
389-
/// either not simultaneous use, or the gpio driver in question is thread safe.
390-
pub unsafe fn toggle_pin(&mut self, _token: &mut GpioToken) {
345+
/// Concurrency safety is determined by the underlying driver.
346+
pub fn toggle_pin(&mut self) {
391347
// TODO: Error?
392348
unsafe {
393349
raw::gpio_pin_toggle_dt(&self.pin);
394350
}
395351
}
396352

397353
/// Set the logical level of the pin.
398-
pub unsafe fn set(&mut self, _token: &mut GpioToken, value: bool) {
399-
raw::gpio_pin_set_dt(&self.pin, value as c_int);
354+
pub fn set(&mut self, value: bool) {
355+
unsafe {
356+
raw::gpio_pin_set_dt(&self.pin, value as c_int);
357+
}
400358
}
401359

402360
/// Read the logical level of the pin.
403-
pub unsafe fn get(&mut self, _token: &mut GpioToken) -> bool {
404-
match raw::gpio_pin_get_dt(&self.pin) {
405-
0 => false,
406-
1 => true,
407-
_ => panic!("TODO: Handle gpio get error"),
361+
pub fn get(&mut self) -> bool {
362+
unsafe {
363+
match raw::gpio_pin_get_dt(&self.pin) {
364+
0 => false,
365+
1 => true,
366+
_ => panic!("TODO: Handle gpio get error"),
367+
}
408368
}
409369
}
410370
}

0 commit comments

Comments
 (0)