@@ -41,10 +41,36 @@ pub mod gpio {
41
41
//! devices. We want to have stronger typing in the Zephyr interfaces, so most of these types
42
42
//! will be wrapped in another structure. This wraps a Gpio device, and provides methods to
43
43
//! most of the operations on gpios.
44
+ //!
45
+ //! Safey: In general, even just using gpio pins is unsafe in Zephyr. The gpio drivers are used
46
+ //! pervasively throughout Zephyr device drivers. As such, most of the calls in this module are
47
+ //! unsafe.
44
48
45
49
use crate :: raw;
46
50
use super :: Unique ;
47
51
52
+ /// Global instance to help make gpio in Rust slightly safer.
53
+ ///
54
+ /// To help with safety, the rust types use a global instance of a gpio-token. Methods will
55
+ /// take a mutable reference to this, which will require either a single thread in the
56
+ /// application code, or something like a mutex or critical section to manage. The operation
57
+ /// methods are still unsafe, because we have no control over what happens with the gpio
58
+ /// operations outside of Rust code, but this will help make the Rust usage at least better.
59
+ pub struct GpioToken ( ( ) ) ;
60
+
61
+ static GPIO_TOKEN : Unique = Unique :: new ( ) ;
62
+
63
+ impl GpioToken {
64
+ /// Retrieves the gpio token. This is unsafe because lots of code in zephyr operates on the
65
+ /// gpio drivers.
66
+ pub unsafe fn get_instance ( ) -> Option < GpioToken > {
67
+ if !GPIO_TOKEN . once ( ) {
68
+ return None ;
69
+ }
70
+ Some ( GpioToken ( ( ) ) )
71
+ }
72
+ }
73
+
48
74
/// A single instance of a zephyr device to manage a gpio controller. A gpio controller
49
75
/// represents a set of gpio pins, that are generally operated on by the same hardware block.
50
76
pub struct Gpio {
@@ -73,8 +99,11 @@ pub mod gpio {
73
99
}
74
100
}
75
101
76
- /// A GpioPin represents a single pin on a gpio device. This is a lightweight wrapper around
77
- /// the Zephyr `gpio_dt_spec` structure.
102
+ /// A GpioPin represents a single pin on a gpio device.
103
+ ///
104
+ /// This is a lightweight wrapper around the Zephyr `gpio_dt_spec` structure. Note that
105
+ /// multiple pins may share a gpio controller, and as such, all methods on this are both unsafe,
106
+ /// and require a mutable reference to the [`GpioToken`].
78
107
#[ allow( dead_code) ]
79
108
pub struct GpioPin {
80
109
pub ( crate ) pin : raw:: gpio_dt_spec ,
@@ -111,7 +140,7 @@ pub mod gpio {
111
140
}
112
141
113
142
/// Configure a single pin.
114
- pub fn configure ( & mut self , extra_flags : raw:: gpio_flags_t ) {
143
+ pub unsafe fn configure ( & mut self , _token : & mut GpioToken , extra_flags : raw:: gpio_flags_t ) {
115
144
// TODO: Error?
116
145
unsafe {
117
146
raw:: gpio_pin_configure ( self . pin . port ,
@@ -121,7 +150,7 @@ pub mod gpio {
121
150
}
122
151
123
152
/// Toggle pin level.
124
- pub fn toggle_pin ( & mut self ) {
153
+ pub unsafe fn toggle_pin ( & mut self , _token : & mut GpioToken ) {
125
154
// TODO: Error?
126
155
unsafe {
127
156
raw:: gpio_pin_toggle_dt ( & self . pin ) ;
0 commit comments