feat: Add rpi4 support to GPIO

This commit is contained in:
Berkus Decker 2022-01-22 02:13:41 +02:00
parent e5a3ea6998
commit 0234f2136e
1 changed files with 66 additions and 37 deletions

View File

@ -7,36 +7,18 @@
use { use {
super::BcmHost, super::BcmHost,
crate::{arch::loop_delay, platform::MMIODerefWrapper}, crate::platform::MMIODerefWrapper,
core::marker::PhantomData, core::marker::PhantomData,
tock_registers::{ tock_registers::{
fields::FieldValue, fields::FieldValue,
interfaces::{ReadWriteable, Readable, Writeable}, interfaces::{ReadWriteable, Readable, Writeable},
register_bitfields, register_structs, register_structs,
registers::{ReadOnly, ReadWrite, WriteOnly}, registers::{ReadOnly, ReadWrite, WriteOnly},
}, },
}; };
// Descriptions taken from // Descriptions taken from
// https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf // https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf
register_bitfields! {
u32,
/// GPIO Pull-up/down Clock Register 0
PUDCLK0 [
/// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [
NoEffect = 0,
AssertClock = 1
],
/// Pin 14
PUDCLK14 OFFSET(14) NUMBITS(1) [
NoEffect = 0,
AssertClock = 1
]
]
}
/// Generates `pub enums` with no variants for each `ident` passed in. /// Generates `pub enums` with no variants for each `ident` passed in.
macro states($($name:ident),*) { macro states($($name:ident),*) {
@ -76,11 +58,15 @@ register_structs! {
(0x84 => __reserved_10), (0x84 => __reserved_10),
(0x88 => pub AFEN: [ReadWrite<u32>; 2]), (0x88 => pub AFEN: [ReadWrite<u32>; 2]),
(0x90 => __reserved_11), (0x90 => __reserved_11),
#[cfg(feature = "rpi3")]
(0x94 => pub PUD: ReadWrite<u32>), // pull up down (0x94 => pub PUD: ReadWrite<u32>), // pull up down
(0x98 => pub PUDCLK: [ReadWrite<u32, PUDCLK0::Register>; 2]), // 0x98-0x9C -- TODO: remove this register? #[cfg(feature = "rpi3")]
// (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>), -- ?? (0x98 => pub PUDCLK: [ReadWrite<u32>; 2]),
#[cfg(feature = "rpi3")]
(0xa0 => __reserved_12), (0xa0 => __reserved_12),
(0xE8 => @END), #[cfg(feature = "rpi4")]
(0xe4 => PullUpDownControl: [ReadWrite<u32>; 4]),
(0xf4 => @END),
} }
} }
@ -116,21 +102,10 @@ impl GPIO {
unsafe { Pin::new(pin, self.registers.base_addr) } unsafe { Pin::new(pin, self.registers.base_addr) }
} }
pub fn enable_uart_pins(&self) { #[cfg(feature = "rpi3")]
self.registers.PUD.set(0);
loop_delay(2000);
// enable pins 14 and 15
self.registers.PUDCLK[0]
.write(PUDCLK0::PUDCLK14::AssertClock + PUDCLK0::PUDCLK15::AssertClock);
loop_delay(2000);
self.registers.PUDCLK[0].set(0);
}
pub fn power_off(&self) { pub fn power_off(&self) {
use crate::arch::loop_delay;
// power off gpio pins (but not VCC pins) // power off gpio pins (but not VCC pins)
for bank in 0..5 { for bank in 0..5 {
self.registers.FSEL[bank].set(0); self.registers.FSEL[bank].set(0);
@ -149,6 +124,11 @@ impl GPIO {
self.registers.PUDCLK[0].set(0); self.registers.PUDCLK[0].set(0);
self.registers.PUDCLK[1].set(0); self.registers.PUDCLK[1].set(0);
} }
#[cfg(feature = "rpi4")]
pub fn power_off(&self) {
todo!()
}
} }
/// An alternative GPIO function. /// An alternative GPIO function.
@ -170,6 +150,21 @@ impl ::core::convert::From<Function> for u32 {
} }
} }
/// Pull up/down resistor setup.
#[repr(u8)]
#[derive(PartialEq)]
pub enum PullUpDown {
None = 0b00,
Up = 0b01,
Down = 0b10,
}
impl ::core::convert::From<PullUpDown> for u32 {
fn from(p: PullUpDown) -> Self {
p as u32
}
}
/// A GPIO pin in state `State`. /// A GPIO pin in state `State`.
/// ///
/// The `State` generic always corresponds to an un-instantiable type that is /// The `State` generic always corresponds to an un-instantiable type that is
@ -195,6 +190,40 @@ impl<State> Pin<State> {
_state: PhantomData, _state: PhantomData,
} }
} }
#[cfg(feature = "rpi3")]
pub fn set_pull_up_down(&self, pull: PullUpDown) {
use crate::arch::loop_delay;
let bank = self.pin / 32;
let off = self.pin % 32;
self.registers.PUD.set(0);
loop_delay(2000);
self.registers.PUDCLK[bank].modify(FieldValue::<u32, ()>::new(
0b1,
off,
if pull == PullUpDown::Up { 1 } else { 0 },
));
loop_delay(2000);
self.registers.PUD.set(0);
self.registers.PUDCLK[bank].set(0);
}
#[cfg(feature = "rpi4")]
pub fn set_pull_up_down(&self, pull: PullUpDown) {
let bank = self.pin / 16;
let off = self.pin % 16;
self.registers.PullUpDownControl[bank].modify(FieldValue::<u32, ()>::new(
0b11,
off * 2,
pull.into(),
));
}
} }
impl Pin<Uninitialized> { impl Pin<Uninitialized> {