mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2025-01-11 13:01:30 +11:00
Concentrate the unsafe register constructs
This moves almost all of the unsafe stuff together. The last remaining bit is going to need a PAC fix.
This commit is contained in:
parent
8290368c10
commit
eaea9ae1ed
|
@ -63,21 +63,6 @@ pub enum OutputSlewRate {
|
||||||
Fast,
|
Fast,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Magic numbers from the datasheet
|
|
||||||
// Order is important! Do not rearrange these
|
|
||||||
#[allow(dead_code)]
|
|
||||||
enum GpioFunction {
|
|
||||||
Spi = 1,
|
|
||||||
Uart,
|
|
||||||
I2c,
|
|
||||||
Pwn,
|
|
||||||
Sio,
|
|
||||||
Pio0,
|
|
||||||
Pio1,
|
|
||||||
Clock,
|
|
||||||
Usb,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! gpio {
|
macro_rules! gpio {
|
||||||
($GPIOX:ident, $gpiox:ident, $PADSX:ident, $padsx:ident, $gpioxs:expr, [
|
($GPIOX:ident, $gpiox:ident, $PADSX:ident, $padsx:ident, $gpioxs:expr, [
|
||||||
$($PXi:ident: ($pxi:ident, $i:expr, $is:expr),)+
|
$($PXi:ident: ($pxi:ident, $i:expr, $is:expr),)+
|
||||||
|
@ -125,12 +110,6 @@ macro_rules! gpio {
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_gpio_function(gpios: &pac::$gpiox::RegisterBlock, index: usize, function: GpioFunction) {
|
|
||||||
gpios.gpio[index]
|
|
||||||
.gpio_ctrl
|
|
||||||
.write_with_zero(|x| unsafe { x.funcsel().bits(function as _) });
|
|
||||||
}
|
|
||||||
|
|
||||||
type PacDriveStrength = pac::$padsx::gpio::DRIVE_A;
|
type PacDriveStrength = pac::$padsx::gpio::DRIVE_A;
|
||||||
|
|
||||||
$(
|
$(
|
||||||
|
@ -140,41 +119,47 @@ macro_rules! gpio {
|
||||||
_mode: PhantomData<MODE>,
|
_mode: PhantomData<MODE>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safety: We own our $i slice of padsx, gpiox, and sio because the
|
|
||||||
// construction of Parts assumes ownership of all 3 and will not release
|
|
||||||
// them. Thus several of the methods below will reconstruct these objects
|
|
||||||
// as-needed
|
|
||||||
|
|
||||||
impl<MODE> $PXi<MODE> {
|
impl<MODE> $PXi<MODE> {
|
||||||
|
// This is safe because Parts owns the pads, and each pin is responsible
|
||||||
|
// for its own pad
|
||||||
|
fn pad(&self) -> &pac::$padsx::GPIO {
|
||||||
|
unsafe {
|
||||||
|
&(*pac::$PADSX::ptr()).gpio[$i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is safe because Parts owns the SIO. But callers must only touch their
|
||||||
|
// own pin
|
||||||
|
fn sio(&self) -> &pac::sio::RegisterBlock {
|
||||||
|
unsafe {
|
||||||
|
&(*pac::SIO::ptr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is safe because Parts owns the bank, and each pin is responsible
|
||||||
|
// for its own slice of the bank
|
||||||
|
fn gpio_ctrl(&self) -> &pac::$gpiox::gpio::GPIO_CTRL {
|
||||||
|
unsafe {
|
||||||
|
&(*pac::$GPIOX::ptr()).gpio[$i].gpio_ctrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[doc = "Configure this pin as an output"]
|
#[doc = "Configure this pin as an output"]
|
||||||
pub fn into_output(
|
pub fn into_output(self)-> $PXi<Output> {
|
||||||
self,
|
self.pad().reset();
|
||||||
) -> $PXi<Output> {
|
self.gpio_ctrl().write_with_zero(|x| { x.funcsel().sio_0() });
|
||||||
unsafe {
|
// TODO: Can we update the PAC to give us a safe register field
|
||||||
(*pac::$PADSX::ptr()).gpio[$i].reset();
|
// instead of `bits`?
|
||||||
}
|
self.sio().gpio_oe_set.write(|x| unsafe { x.bits(1 << $i) });
|
||||||
unsafe {
|
|
||||||
set_gpio_function(&*pac::$GPIOX::ptr(), $i, GpioFunction::Sio);
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
(*pac::SIO::ptr()).gpio_oe_set.write(|x| { x.bits(1 << $i) });
|
|
||||||
}
|
|
||||||
$PXi { _mode: PhantomData }
|
$PXi { _mode: PhantomData }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "Configure this pin as an input"]
|
#[doc = "Configure this pin as an input"]
|
||||||
pub fn into_input(
|
pub fn into_input(self) -> $PXi<Input> {
|
||||||
self,
|
self.pad().reset();
|
||||||
) -> $PXi<Input> {
|
self.gpio_ctrl().write_with_zero(|x| { x.funcsel().sio_0() });
|
||||||
unsafe {
|
self.sio().gpio_oe_clr.write(|x| unsafe { x.bits(1 << $i) });
|
||||||
(*pac::$PADSX::ptr()).gpio[$i].reset();
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
set_gpio_function(&*pac::$GPIOX::ptr(), $i, GpioFunction::Sio);
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
(*pac::SIO::ptr()).gpio_oe_clr.write(|x| { x.bits(1 << $i) });
|
|
||||||
}
|
|
||||||
$PXi { _mode: PhantomData }
|
$PXi { _mode: PhantomData }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,16 +168,12 @@ macro_rules! gpio {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||||
unsafe {
|
self.sio().gpio_out_clr.write(|x| unsafe { x.bits(1 << $i) });
|
||||||
(*pac::SIO::ptr()).gpio_out_clr.write(|x| x.bits(1 << $i));
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||||
unsafe {
|
self.sio().gpio_out_set.write(|x| unsafe { x.bits(1 << $i) });
|
||||||
(*pac::SIO::ptr()).gpio_out_set.write(|x| x.bits(1 << $i));
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,9 +184,7 @@ macro_rules! gpio {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
||||||
unsafe {
|
Ok(self.sio().gpio_out.read().bits() & (1 << $i) != 0)
|
||||||
Ok((*pac::SIO::ptr()).gpio_out.read().bits() & (1 << $i) != 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,9 +198,7 @@ macro_rules! gpio {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_high(&self) -> Result<bool, Self::Error> {
|
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||||
unsafe {
|
Ok(self.sio().gpio_in.read().bits() & (1 << $i) != 0)
|
||||||
Ok((*pac::SIO::ptr()).gpio_in.read().bits() & (1 << $i) != 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -239,17 +216,13 @@ macro_rules! gpio {
|
||||||
OutputDriveStrength::EightMilliAmps => PacDriveStrength::_8MA,
|
OutputDriveStrength::EightMilliAmps => PacDriveStrength::_8MA,
|
||||||
OutputDriveStrength::TwelveMilliAmps => PacDriveStrength::_12MA,
|
OutputDriveStrength::TwelveMilliAmps => PacDriveStrength::_12MA,
|
||||||
};
|
};
|
||||||
unsafe {
|
self.pad().modify(|_, w| w.drive().variant(converted));
|
||||||
(*pac::$PADSX::ptr()).gpio[$i].modify(|_, w| w.drive().variant(converted));
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "Configure the slew rate for this output pin"]
|
#[doc = "Configure the slew rate for this output pin"]
|
||||||
pub fn slew_rate(self, slew_rate: OutputSlewRate) -> Self {
|
pub fn slew_rate(self, slew_rate: OutputSlewRate) -> Self {
|
||||||
unsafe {
|
self.pad().modify(|_, w| w.slewfast().bit(slew_rate == OutputSlewRate::Fast));
|
||||||
(*pac::$PADSX::ptr()).gpio[$i].modify(|_, w| w.slewfast().bit(slew_rate == OutputSlewRate::Fast));
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,41 +230,31 @@ macro_rules! gpio {
|
||||||
impl $PXi<Input> {
|
impl $PXi<Input> {
|
||||||
#[doc = "Pull this input pin high using internal resistors"]
|
#[doc = "Pull this input pin high using internal resistors"]
|
||||||
pub fn pull_up(self) -> Self {
|
pub fn pull_up(self) -> Self {
|
||||||
unsafe {
|
self.pad().modify(|_, w| w.pue().set_bit().pde().clear_bit());
|
||||||
(*pac::$PADSX::ptr()).gpio[$i].modify(|_, w| w.pue().set_bit().pde().clear_bit());
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "Pull this input pin low using internal resistors"]
|
#[doc = "Pull this input pin low using internal resistors"]
|
||||||
pub fn pull_down(self) -> Self {
|
pub fn pull_down(self) -> Self {
|
||||||
unsafe {
|
self.pad().modify(|_, w| w.pue().clear_bit().pde().set_bit());
|
||||||
(*pac::$PADSX::ptr()).gpio[$i].modify(|_, w| w.pue().clear_bit().pde().set_bit());
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "Allow this input pin to float (i.e. don't pull it high or low)"]
|
#[doc = "Allow this input pin to float (i.e. don't pull it high or low)"]
|
||||||
pub fn float(self) -> Self {
|
pub fn float(self) -> Self {
|
||||||
unsafe {
|
self.pad().modify(|_, w| w.pue().clear_bit().pde().clear_bit());
|
||||||
(*pac::$PADSX::ptr()).gpio[$i].modify(|_, w| w.pue().clear_bit().pde().clear_bit());
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "Enable the schmitt trigger for this input pin"]
|
#[doc = "Enable the schmitt trigger for this input pin"]
|
||||||
pub fn enable_schmitt_trigger(self) -> Self {
|
pub fn enable_schmitt_trigger(self) -> Self {
|
||||||
unsafe {
|
self.pad().modify(|_, w| w.schmitt().set_bit());
|
||||||
(*pac::$PADSX::ptr()).gpio[$i].modify(|_, w| w.schmitt().set_bit());
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "Disable the schmitt trigger for this input pin"]
|
#[doc = "Disable the schmitt trigger for this input pin"]
|
||||||
pub fn disable_schmitt_trigger(self) -> Self {
|
pub fn disable_schmitt_trigger(self) -> Self {
|
||||||
unsafe {
|
self.pad().modify(|_, w| w.schmitt().clear_bit());
|
||||||
(*pac::$PADSX::ptr()).gpio[$i].modify(|_, w| w.schmitt().clear_bit());
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue