add active low/high for gpio open-drain mode
diff --git a/target/ast10x0/peripherals/gpio/mod.rs b/target/ast10x0/peripherals/gpio/mod.rs index e0d7e3d..a0d31ac 100644 --- a/target/ast10x0/peripherals/gpio/mod.rs +++ b/target/ast10x0/peripherals/gpio/mod.rs
@@ -12,8 +12,8 @@ pub use registers::GpioRegisters; pub use types::{ - Floating, GpioError, GpioExt, Input, InputMode, InterruptMode, OpenDrain, OpenDrainMode, - Output, OutputMode, PullDown, PullUp, PushPull, Tristate, + ActiveHigh, ActiveLow, Floating, GpioError, GpioExt, Input, InputMode, InterruptMode, + OpenDrain, OpenDrainMode, Output, OutputMode, PullDown, PullUp, PushPull, Tristate, }; macro_rules! gpio_macro { @@ -137,8 +137,14 @@ { let p = unsafe { &*device::Gpio::ptr() }; p.$data_val_reg().modify(|r, w| unsafe { - w.bits(r.bits() & !(1u32 << ($pos + $i))) + let mask = 1u32 << ($pos + $i); + w.bits(if ODM::ACTIVE_HIGH { + r.bits() | mask + } else { + r.bits() & !mask + }) }); + // Start released in the inactive state. p.$dir_reg().modify(|r, w| unsafe { w.bits(r.bits() & !(1u32 << ($pos + $i))) }); @@ -197,7 +203,9 @@ { fn is_set_high(&mut self) -> Result<bool, Self::Error> { let p = unsafe { &*device::Gpio::ptr() }; - Ok((p.$dir_reg().read().bits() & (1u32 << ($pos + $i))) == 0) + let is_output = + (p.$dir_reg().read().bits() & (1u32 << ($pos + $i))) != 0; + Ok(is_output == ODM::ACTIVE_HIGH) } fn is_set_low(&mut self) -> Result<bool, Self::Error> { @@ -212,7 +220,12 @@ fn set_high(&mut self) -> Result<(), Self::Error> { let p = unsafe { &*device::Gpio::ptr() }; p.$dir_reg().modify(|r, w| unsafe { - w.bits(r.bits() & !(1u32 << ($pos + $i))) + let mask = 1u32 << ($pos + $i); + w.bits(if ODM::ACTIVE_HIGH { + r.bits() | mask + } else { + r.bits() & !mask + }) }); Ok(()) } @@ -220,7 +233,12 @@ fn set_low(&mut self) -> Result<(), Self::Error> { let p = unsafe { &*device::Gpio::ptr() }; p.$dir_reg().modify(|r, w| unsafe { - w.bits(r.bits() | (1u32 << ($pos + $i))) + let mask = 1u32 << ($pos + $i); + w.bits(if ODM::ACTIVE_HIGH { + r.bits() & !mask + } else { + r.bits() | mask + }) }); Ok(()) }
diff --git a/target/ast10x0/peripherals/gpio/types.rs b/target/ast10x0/peripherals/gpio/types.rs index bd054bf..50e90b5 100644 --- a/target/ast10x0/peripherals/gpio/types.rs +++ b/target/ast10x0/peripherals/gpio/types.rs
@@ -13,8 +13,20 @@ /// `OpenDrain` modes implement this trait. pub trait OpenDrainMode { - /// Returns whether pull-up is enabled. - fn pup() -> bool; + /// Whether the actively driven level is high. + const ACTIVE_HIGH: bool; +} + +/// Active-low open-drain mode: output drives low and input releases high. +pub struct ActiveLow; +impl OpenDrainMode for ActiveLow { + const ACTIVE_HIGH: bool = false; +} + +/// Active-high open-drain mode: output drives high and input releases low. +pub struct ActiveHigh; +impl OpenDrainMode for ActiveHigh { + const ACTIVE_HIGH: bool = true; } /// Input mode (type state). @@ -28,11 +40,6 @@ /// Sub-mode of Input: Floating input (type state). pub struct Floating; impl InputMode for Floating {} -impl OpenDrainMode for Floating { - fn pup() -> bool { - false - } -} /// Sub-mode of Input: Pulled down input (type state). pub struct PullDown; @@ -41,11 +48,6 @@ /// Sub-mode of Input: Pulled up input (type state). pub struct PullUp; impl InputMode for PullUp {} -impl OpenDrainMode for PullUp { - fn pup() -> bool { - true - } -} /// Tri-state mode (type state). pub struct Tristate; @@ -69,7 +71,7 @@ where ODM: OpenDrainMode, { - pub(super) _pull: PhantomData<ODM>, + pub(super) _mode: PhantomData<ODM>, } impl<ODM> OutputMode for OpenDrain<ODM> where ODM: OpenDrainMode {}
diff --git a/target/ast10x0/tests/peripherals/gpio/gpio_smoke/target.rs b/target/ast10x0/tests/peripherals/gpio/gpio_smoke/target.rs index 75270c7..b69ed08 100644 --- a/target/ast10x0/tests/peripherals/gpio/gpio_smoke/target.rs +++ b/target/ast10x0/tests/peripherals/gpio/gpio_smoke/target.rs
@@ -6,7 +6,7 @@ #![no_std] #![no_main] -use ast10x0_peripherals::gpio::{gpioa, Floating, GpioExt}; +use ast10x0_peripherals::gpio::{gpioa, ActiveLow, GpioExt}; use ast10x0_peripherals::scu::{pinctrl, ScuRegisters}; use console_backend::console_backend_write_all; use embedded_hal::digital::{InputPin, OutputPin, StatefulOutputPin}; @@ -41,7 +41,7 @@ } pw_log::info!("GPIOA1 pull-up input read high"); - let mut pa3 = gpioa.pa3.into_open_drain_output::<Floating>(); + let mut pa3 = gpioa.pa3.into_open_drain_output::<ActiveLow>(); if pa3.set_low().is_err() || !pa3.is_set_low().unwrap_or(false) { pw_log::error!("GPIOA3 open-drain output did not latch low"); return false;