diff --git a/nrf52840-hal-tests/Cargo.toml b/nrf52840-hal-tests/Cargo.toml index 42a847fb..f5636dab 100644 --- a/nrf52840-hal-tests/Cargo.toml +++ b/nrf52840-hal-tests/Cargo.toml @@ -20,6 +20,10 @@ harness = false name = "gpio-output-open-drain" harness = false +[[test]] +name = "gpio-output-open-drain-io" +harness = false + [[test]] name = "nvmc" harness = false diff --git a/nrf52840-hal-tests/tests/gpio-output-open-drain-io.rs b/nrf52840-hal-tests/tests/gpio-output-open-drain-io.rs new file mode 100644 index 00000000..8151efe7 --- /dev/null +++ b/nrf52840-hal-tests/tests/gpio-output-open-drain-io.rs @@ -0,0 +1,93 @@ +// Required connections: +// +// - P0.28 <-> P0.29 + +#![deny(warnings)] +#![no_std] +#![no_main] + +use defmt_rtt as _; +use nrf52840_hal as _; +use panic_probe as _; + +use nrf52840_hal::gpio::{Input, OpenDrainIO, Output, Pin, PullUp}; + +struct State { + input_pin: Option>>, + output_pin: Pin>, +} + +#[defmt_test::tests] +mod tests { + use cortex_m::asm; + use defmt::{assert, unwrap}; + use nrf52840_hal::{ + gpio::{p0, Level, OpenDrainConfig}, + pac, + prelude::*, + }; + + use super::State; + + #[init] + fn init() -> State { + let p = unwrap!(pac::Peripherals::take()); + let port0 = p0::Parts::new(p.P0); + + let input_pin = Some(port0.p0_28.into_pullup_input().degrade()); + let output_pin = port0 + .p0_29 + .into_open_drain_input_output(OpenDrainConfig::Standard0Disconnect1, Level::High) + .degrade(); + + State { + input_pin, + output_pin, + } + } + + #[test] + fn set_low_is_low(state: &mut State) { + state.output_pin.set_low().unwrap(); + // GPIO operations are not instantaneous so a delay is needed + asm::delay(100); + assert!(state.input_pin.as_ref().unwrap().is_low().unwrap()); + } + + #[test] + fn set_high_is_open(state: &mut State) { + state.output_pin.set_high().unwrap(); + // GPIO operations are not instantaneous so a delay is needed + asm::delay(100); + assert!(state.input_pin.as_ref().unwrap().is_high().unwrap()); + + let pulled_down_input_pin = state.input_pin.take().unwrap().into_pulldown_input(); + // GPIO operations are not instantaneous so a delay is needed + asm::delay(100); + assert!(pulled_down_input_pin.is_low().unwrap()); + + // Restore original input pin state + state.input_pin = Some(pulled_down_input_pin.into_pullup_input()); + } + + #[test] + fn open_pullup_reads_high(state: &mut State) { + state.output_pin.set_high().unwrap(); + // GPIO operations are not instantaneous so a delay is needed + asm::delay(100); + assert!(state.output_pin.is_high().unwrap()); + } + + #[test] + fn open_pulldown_reads_low(state: &mut State) { + state.output_pin.set_high().unwrap(); + + let pulled_down_input_pin = state.input_pin.take().unwrap().into_pulldown_input(); + // GPIO operations are not instantaneous so a delay is needed + asm::delay(100); + assert!(pulled_down_input_pin.is_low().unwrap()); + + // Restore original input pin state + state.input_pin = Some(pulled_down_input_pin.into_pullup_input()); + } +} diff --git a/nrf52840-hal-tests/tests/gpio-output-open-drain.rs b/nrf52840-hal-tests/tests/gpio-output-open-drain.rs index 0760d03f..84ee8796 100644 --- a/nrf52840-hal-tests/tests/gpio-output-open-drain.rs +++ b/nrf52840-hal-tests/tests/gpio-output-open-drain.rs @@ -10,15 +10,16 @@ use defmt_rtt as _; use nrf52840_hal as _; use panic_probe as _; -use nrf52840_hal::gpio::{Floating, Input, OpenDrain, Output, Pin}; +use nrf52840_hal::gpio::{Input, OpenDrain, Output, Pin, PullUp}; struct State { - input_pin: Pin>, + input_pin: Option>>, output_pin: Pin>, } #[defmt_test::tests] mod tests { + use cortex_m::asm; use defmt::{assert, unwrap}; use nrf52840_hal::{ gpio::{p0, Level, OpenDrainConfig}, @@ -33,7 +34,7 @@ mod tests { let p = unwrap!(pac::Peripherals::take()); let port0 = p0::Parts::new(p.P0); - let input_pin = port0.p0_28.into_floating_input().degrade(); + let input_pin = Some(port0.p0_28.into_pullup_input().degrade()); let output_pin = port0 .p0_29 .into_open_drain_output(OpenDrainConfig::Standard0Disconnect1, Level::High) @@ -48,15 +49,24 @@ mod tests { #[test] fn set_low_is_low(state: &mut State) { state.output_pin.set_low().unwrap(); - assert!(state.input_pin.is_low().unwrap()); + // GPIO operations are not instantaneous so a delay is needed + asm::delay(100); + assert!(state.input_pin.as_ref().unwrap().is_low().unwrap()); } - // with the current API we cannot test this w/o an _external_ pull-up - /* #[test] - fn set_high_is_high(state: &mut State) { + fn set_high_is_open(state: &mut State) { state.output_pin.set_high().unwrap(); - assert!(state.input_pin.is_high().unwrap()); + // GPIO operations are not instantaneous so a delay is needed + asm::delay(100); + assert!(state.input_pin.as_ref().unwrap().is_high().unwrap()); + + let pulled_down_input_pin = state.input_pin.take().unwrap().into_pulldown_input(); + // GPIO operations are not instantaneous so a delay is needed + asm::delay(100); + assert!(pulled_down_input_pin.is_low().unwrap()); + + // Restore original input pin state + state.input_pin = Some(pulled_down_input_pin.into_pullup_input()); } - */ }