-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
zephyr: device: Split gpio and flash to own files
Move this code out of the device.rs file, and into separate files for each module. Signed-off-by: David Brown <[email protected]>
- Loading branch information
Showing
3 changed files
with
180 additions
and
183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
//! Device wrappers for flash controllers, and flash partitions. | ||
|
||
use crate::raw; | ||
use super::Unique; | ||
|
||
/// A flash controller | ||
/// | ||
/// This is a wrapper around the `struct device` in Zephyr that represents a flash controller. | ||
/// Using the flash controller allows flash operations on the entire device. See | ||
/// [`FlashPartition`] for a wrapper that limits the operation to a partition as defined in the | ||
/// DT. | ||
#[allow(dead_code)] | ||
pub struct FlashController { | ||
pub(crate) device: *const raw::device, | ||
} | ||
|
||
impl FlashController { | ||
/// Constructor, intended to be called by devicetree generated code. | ||
pub(crate) unsafe fn new(unique: &Unique, device: *const raw::device) -> Option<FlashController> { | ||
if !unique.once() { | ||
return None; | ||
} | ||
|
||
Some(FlashController { device }) | ||
} | ||
} | ||
|
||
/// A wrapper for flash partitions. There is no Zephyr struct that corresponds with this | ||
/// information, which is typically used in a more direct underlying manner. | ||
#[allow(dead_code)] | ||
pub struct FlashPartition { | ||
/// The underlying controller. | ||
#[allow(dead_code)] | ||
pub(crate) controller: FlashController, | ||
#[allow(dead_code)] | ||
pub(crate) offset: u32, | ||
#[allow(dead_code)] | ||
pub(crate) size: u32, | ||
} | ||
|
||
impl FlashPartition { | ||
/// Constructor, intended to be called by devicetree generated code. | ||
pub(crate) unsafe fn new(unique: &Unique, device: *const raw::device, offset: u32, size: u32) -> Option<FlashPartition> { | ||
if !unique.once() { | ||
return None; | ||
} | ||
|
||
// The `get_instance` on the flash controller would try to guarantee a unique instance, | ||
// but in this case, we need one for each device, so just construct it here. | ||
// TODO: This is not actually safe. | ||
let controller = FlashController { device }; | ||
Some(FlashPartition { controller, offset, size }) | ||
} | ||
} | ||
|
||
// Note that currently, the flash partition shares the controller, so the underlying operations | ||
// are not actually safe. Need to rethink how to manage this. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
//! Most devices in Zephyr operate on a `struct device`. This provides untyped access to | ||
//! devices. We want to have stronger typing in the Zephyr interfaces, so most of these types | ||
//! will be wrapped in another structure. This wraps a Gpio device, and provides methods to | ||
//! most of the operations on gpios. | ||
//! | ||
//! Safey: In general, even just using gpio pins is unsafe in Zephyr. The gpio drivers are used | ||
//! pervasively throughout Zephyr device drivers. As such, most of the calls in this module are | ||
//! unsafe. | ||
|
||
use crate::raw; | ||
use super::Unique; | ||
|
||
/// Global instance to help make gpio in Rust slightly safer. | ||
/// | ||
/// To help with safety, the rust types use a global instance of a gpio-token. Methods will | ||
/// take a mutable reference to this, which will require either a single thread in the | ||
/// application code, or something like a mutex or critical section to manage. The operation | ||
/// methods are still unsafe, because we have no control over what happens with the gpio | ||
/// operations outside of Rust code, but this will help make the Rust usage at least better. | ||
pub struct GpioToken(()); | ||
|
||
static GPIO_TOKEN: Unique = Unique::new(); | ||
|
||
impl GpioToken { | ||
/// Retrieves the gpio token. This is unsafe because lots of code in zephyr operates on the | ||
/// gpio drivers. | ||
pub unsafe fn get_instance() -> Option<GpioToken> { | ||
if !GPIO_TOKEN.once() { | ||
return None; | ||
} | ||
Some(GpioToken(())) | ||
} | ||
} | ||
|
||
/// A single instance of a zephyr device to manage a gpio controller. A gpio controller | ||
/// represents a set of gpio pins, that are generally operated on by the same hardware block. | ||
pub struct Gpio { | ||
/// The underlying device itself. | ||
#[allow(dead_code)] | ||
pub(crate) device: *const raw::device, | ||
} | ||
|
||
impl Gpio { | ||
/// Constructor, used by the devicetree generated code. | ||
/// | ||
/// TODO: Guarantee single instancing. | ||
pub(crate) unsafe fn new(unique: &Unique, device: *const raw::device) -> Option<Gpio> { | ||
if !unique.once() { | ||
return None; | ||
} | ||
Some(Gpio { device }) | ||
} | ||
|
||
/// Verify that the device is ready for use. At a minimum, this means the device has been | ||
/// successfully initialized. | ||
pub fn is_ready(&self) -> bool { | ||
unsafe { | ||
raw::device_is_ready(self.device) | ||
} | ||
} | ||
} | ||
|
||
/// A GpioPin represents a single pin on a gpio device. | ||
/// | ||
/// This is a lightweight wrapper around the Zephyr `gpio_dt_spec` structure. Note that | ||
/// multiple pins may share a gpio controller, and as such, all methods on this are both unsafe, | ||
/// and require a mutable reference to the [`GpioToken`]. | ||
#[allow(dead_code)] | ||
pub struct GpioPin { | ||
pub(crate) pin: raw::gpio_dt_spec, | ||
} | ||
|
||
impl GpioPin { | ||
/// Constructor, used by the devicetree generated code. | ||
/// | ||
/// TODO: Guarantee single instancing. | ||
pub(crate) unsafe fn new(unique: &Unique, device: *const raw::device, pin: u32, dt_flags: u32) -> Option<GpioPin> { | ||
if !unique.once() { | ||
return None; | ||
} | ||
Some(GpioPin { | ||
pin: raw::gpio_dt_spec { | ||
port: device, | ||
pin: pin as raw::gpio_pin_t, | ||
dt_flags: dt_flags as raw::gpio_dt_flags_t, | ||
} | ||
}) | ||
} | ||
|
||
/// Verify that the device is ready for use. At a minimum, this means the device has been | ||
/// successfully initialized. | ||
pub fn is_ready(&self) -> bool { | ||
self.get_gpio().is_ready() | ||
} | ||
|
||
/// Get the underlying Gpio device. | ||
pub fn get_gpio(&self) -> Gpio { | ||
Gpio { | ||
device: self.pin.port, | ||
} | ||
} | ||
|
||
/// Configure a single pin. | ||
pub unsafe fn configure(&mut self, _token: &mut GpioToken, extra_flags: raw::gpio_flags_t) { | ||
// TODO: Error? | ||
unsafe { | ||
raw::gpio_pin_configure(self.pin.port, | ||
self.pin.pin, | ||
self.pin.dt_flags as raw::gpio_flags_t | extra_flags); | ||
} | ||
} | ||
|
||
/// Toggle pin level. | ||
pub unsafe fn toggle_pin(&mut self, _token: &mut GpioToken) { | ||
// TODO: Error? | ||
unsafe { | ||
raw::gpio_pin_toggle_dt(&self.pin); | ||
} | ||
} | ||
} |