Skip to content

Commit

Permalink
Add gpio::last_write() for stateful output GPIOs
Browse files Browse the repository at this point in the history
  • Loading branch information
ia0 committed Feb 12, 2024
1 parent 67e3440 commit 58801ec
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 1 deletion.
1 change: 1 addition & 0 deletions crates/api-desc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Minor

- Add `gpio::last_write()` function
- Add `uart::{start,stop}()` and `uart::set_baudrate()` functions
- Rename `clock` module to `timer`
- Make all API functions return `isize`
Expand Down
10 changes: 10 additions & 0 deletions crates/api-desc/src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ pub(crate) fn new() -> Item {
val: usize,
} -> ()
},
item! {
/// Returns the last logical value written to a GPIO.
///
/// The initial output value counts as a write and would be returned if `write()` was
/// not called since last `configure()`.
fn last_write "gl" {
/// Index of the GPIO to query (must be configured as output).
gpio: usize,
} -> bool
},
];
Item::Mod(Mod { docs, name, items })
}
1 change: 1 addition & 0 deletions crates/board/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Major

- Add `gpio::Api::last_write()` for stateful output GPIOs
- Add `uart::Api` functions to start, stop, and set the baudrate
- Remove `Unsupported` and `UnsupportedCrypto` implementations
- Change `syscall` return type to `Option<Result<u31, Error>>`
Expand Down
3 changes: 3 additions & 0 deletions crates/board/src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,7 @@ pub trait Api: Support<usize> + Send {

/// Writes to a GPIO (must be configured as output).
fn write(gpio: Id<Self>, value: bool) -> Result<(), Error>;

/// Returns the last logical value written to a GPIO (must be configured as output).
fn last_write(gpio: Id<Self>) -> Result<bool, Error>;
}
1 change: 1 addition & 0 deletions crates/prelude/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

### Minor

- Add `gpio::Gpio::{last_write,toggle}()` for stateful output GPIOs
- Add `uart::UartBuilder` and `uart::Uart::new()` to configure a UART
- Add `serial::DelimitedReader` to read delimited frames from serial
- Add `serial::Listener` to listen for serial events
Expand Down
16 changes: 16 additions & 0 deletions crates/prelude/src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ pub fn write(gpio: usize, value: bool) {
convert_unit(unsafe { api::write(params) }).unwrap();
}

/// Returns the last logical value written to a GPIO (must be configured as output).
pub fn last_write(gpio: usize) -> bool {
let params = api::last_write::Params { gpio };
convert_bool(unsafe { api::last_write(params) }).unwrap()
}

/// GPIO that disconnects on drop.
pub struct Gpio(usize);

Expand All @@ -116,4 +122,14 @@ impl Gpio {
pub fn write(&self, value: bool) {
write(self.0, value)
}

/// Returns the last logical value written to a GPIO (must be configured as output).
pub fn last_write(&self) -> bool {
last_write(self.0)
}

/// Toggles the logical value of a GPIO (must be configured as output).
pub fn toggle(&self) {
self.write(!self.last_write());
}
}
18 changes: 17 additions & 1 deletion crates/runner-nordic/src/board/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use embedded_hal::digital::v2::{InputPin, OutputPin, PinState};
use embedded_hal::digital::v2::{InputPin, OutputPin, PinState, StatefulOutputPin as _};
use nrf52840_hal::gpio::{
Disconnected, Floating, Input, Level, OpenDrain, OpenDrainConfig, OpenDrainIO, Output, Pin,
PullDown, PullUp, PushPull,
Expand Down Expand Up @@ -83,6 +83,22 @@ impl Api for Impl {
.map_err(|_| Error::world(0))
})
}

fn last_write(gpio: Id<Self>) -> Result<bool, Error> {
with_state(|state| {
match &mut state.gpios[*gpio].state {
State::Invalid => unreachable!(),
State::Disconnected(_)
| State::InputFloating(_)
| State::InputPullDown(_)
| State::InputPullUp(_) => return Err(Error::user(Code::InvalidState)),
State::OutputPushPull(x) => x.is_set_high(),
State::OutputOpenDrain(x) => x.is_set_high(),
State::OutputOpenDrainIO(x) => x.is_set_high(),
}
.map_err(|_| Error::world(0))
})
}
}

pub fn syscall(x: u32, y: u32, z: u32) -> Result<u32, Error> {
Expand Down
1 change: 1 addition & 0 deletions crates/scheduler/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

### Minor

- Support `gpio::last_write()` function
- Support `uart::{start,stop,set_baudrate}()` functions
- Migrate `clock` module to `timer`
- Remove unstable `software-crypto` feature
Expand Down
11 changes: 11 additions & 0 deletions crates/scheduler/src/call/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub fn process<B: Board>(call: Api<DispatchSchedulerCall<B>>) {
Api::Configure(call) => or_trap!("board-api-gpio", configure(call)),
Api::Read(call) => or_trap!("board-api-gpio", read(call)),
Api::Write(call) => or_trap!("board-api-gpio", write(call)),
Api::LastWrite(call) => or_trap!("board-api-gpio", last_write(call)),
}
}

Expand Down Expand Up @@ -76,3 +77,13 @@ fn write<B: Board>(call: SchedulerCall<B, api::write::Sig>) {
};
call.reply(result);
}

#[cfg(feature = "board-api-gpio")]
fn last_write<B: Board>(call: SchedulerCall<B, api::last_write::Sig>) {
let api::last_write::Params { gpio } = call.read();
let result = try {
let gpio = Id::new(*gpio as usize).ok_or(Trap)?;
board::Gpio::<B>::last_write(gpio)
};
call.reply(result);
}
10 changes: 10 additions & 0 deletions examples/assemblyscript/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,16 @@
// Logical value (0 or 1).
val: usize,
): i32

// Returns the last logical value written to a GPIO.
//
// The initial output value counts as a write and would be returned if `write()` was
// not called since last `configure()`.
@external("env", "gl")
export declare function gpio_last_write(
// Index of the GPIO to query (must be configured as output).
gpio: usize,
): i32
// END OF MODULE gpio

// START OF MODULE led
Expand Down

0 comments on commit 58801ec

Please sign in to comment.