GPIO: Fix RPi4 driver init

The RPi4 GPIO pull-up/pull down sequence is done differently than on the
RPi3. Switch to using the correct way.

Also, configure pull-ups for both UART pins.

Fixes #81
pull/84/head
Andre Richter 4 years ago
parent bb7800cf77
commit 163e2010ab
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

@ -183,13 +183,14 @@ diff -uNr 05_safe_globals/Makefile 06_drivers_gpio_uart/Makefile
diff -uNr 05_safe_globals/src/_arch/aarch64/cpu.rs 06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs diff -uNr 05_safe_globals/src/_arch/aarch64/cpu.rs 06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs
--- 05_safe_globals/src/_arch/aarch64/cpu.rs --- 05_safe_globals/src/_arch/aarch64/cpu.rs
+++ 06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs +++ 06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs
@@ -37,6 +37,16 @@ @@ -37,6 +37,17 @@
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
+pub use asm::nop; +pub use asm::nop;
+ +
+/// Spin for `n` cycles. +/// Spin for `n` cycles.
+#[cfg(feature = "bsp_rpi3")]
+#[inline(always)] +#[inline(always)]
+pub fn spin_for_cycles(n: usize) { +pub fn spin_for_cycles(n: usize) {
+ for _ in 0..n { + for _ in 0..n {
@ -204,7 +205,7 @@ diff -uNr 05_safe_globals/src/_arch/aarch64/cpu.rs 06_drivers_gpio_uart/src/_arc
diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
--- 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs --- 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
+++ 06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ 06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
@@ -0,0 +1,161 @@ @@ -0,0 +1,222 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0 +// SPDX-License-Identifier: MIT OR Apache-2.0
+// +//
+// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
@ -212,7 +213,7 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_g
+//! GPIO Driver. +//! GPIO Driver.
+ +
+use crate::{ +use crate::{
+ bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
+ synchronization::NullLock, + synchronization::NullLock,
+}; +};
+use register::{mmio::*, register_bitfields, register_structs}; +use register::{mmio::*, register_bitfields, register_structs};
@ -224,7 +225,8 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_g
+// GPIO registers. +// GPIO registers.
+// +//
+// 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
+// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
+register_bitfields! { +register_bitfields! {
+ u32, + u32,
+ +
@ -246,7 +248,21 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_g
+ ] + ]
+ ], + ],
+ +
+ /// GPIO Pull-up/down Register
+ ///
+ /// BCM2837 only.
+ GPPUD [
+ /// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
+ PUD OFFSET(0) NUMBITS(2) [
+ Off = 0b00,
+ PullDown = 0b01,
+ PullUp = 0b10
+ ]
+ ],
+
+ /// GPIO Pull-up/down Clock Register 0 + /// GPIO Pull-up/down Clock Register 0
+ ///
+ /// BCM2837 only.
+ GPPUDCLK0 [ + GPPUDCLK0 [
+ /// Pin 15 + /// Pin 15
+ PUDCLK15 OFFSET(15) NUMBITS(1) [ + PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -259,23 +275,37 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_g
+ NoEffect = 0, + NoEffect = 0,
+ AssertClock = 1 + AssertClock = 1
+ ] + ]
+ ],
+
+ /// GPIO Pull-up / Pull-down Register 0
+ ///
+ /// BCM2711 only.
+ GPIO_PUP_PDN_CNTRL_REG0 [
+ /// Pin 15
+ GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
+ NoResistor = 0b00,
+ PullUp = 0b01
+ ],
+
+ /// Pin 14
+ GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
+ NoResistor = 0b00,
+ PullUp = 0b01
+ ]
+ ] + ]
+} +}
+ +
+register_structs! { +register_structs! {
+ #[allow(non_snake_case)] + #[allow(non_snake_case)]
+ RegisterBlock { + RegisterBlock {
+ (0x00 => GPFSEL0: ReadWrite<u32>), + (0x00 => _reserved1),
+ (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), + (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
+ (0x08 => GPFSEL2: ReadWrite<u32>), + (0x08 => _reserved2),
+ (0x0C => GPFSEL3: ReadWrite<u32>), + (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
+ (0x10 => GPFSEL4: ReadWrite<u32>),
+ (0x14 => GPFSEL5: ReadWrite<u32>),
+ (0x18 => _reserved1),
+ (0x94 => GPPUD: ReadWrite<u32>),
+ (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), + (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
+ (0x9C => GPPUDCLK1: ReadWrite<u32>), + (0x9C => _reserved3),
+ (0xA0 => @END), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
+ (0xE8 => @END),
+ } + }
+} +}
+ +
@ -314,26 +344,58 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_g
+ } + }
+ } + }
+ +
+ /// Disable pull-up/down on pins 14 and 15.
+ #[cfg(feature = "bsp_rpi3")]
+ fn disable_pud_14_15_bcm2837(&mut self) {
+ use crate::cpu;
+
+ // Make an educated guess for a good delay value (Sequence described in the BCM2837
+ // peripherals PDF).
+ //
+ // - According to Wikipedia, the fastest Pi3 clocks around 1.4 GHz.
+ // - The Linux 2837 GPIO driver waits 1 µs between the steps.
+ //
+ // So lets try to be on the safe side and default to 2000 cycles, which would equal 1 µs
+ // would the CPU be clocked at 2 GHz.
+ const DELAY: usize = 2000;
+
+ self.registers.GPPUD.write(GPPUD::PUD::Off);
+ cpu::spin_for_cycles(DELAY);
+
+ self.registers
+ .GPPUDCLK0
+ .write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
+ cpu::spin_for_cycles(DELAY);
+
+ self.registers.GPPUD.write(GPPUD::PUD::Off);
+ self.registers.GPPUDCLK0.set(0);
+ }
+
+ /// Disable pull-up/down on pins 14 and 15.
+ #[cfg(feature = "bsp_rpi4")]
+ fn disable_pud_14_15_bcm2711(&mut self) {
+ self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ + GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
+ );
+ }
+
+ /// Map PL011 UART as standard output. + /// Map PL011 UART as standard output.
+ /// + ///
+ /// TX to pin 14 + /// TX to pin 14
+ /// RX to pin 15 + /// RX to pin 15
+ pub fn map_pl011_uart(&mut self) { + pub fn map_pl011_uart(&mut self) {
+ // Map to pins. + // Select the UART on pins 14 and 15.
+ self.registers + self.registers
+ .GPFSEL1 + .GPFSEL1
+ .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
+ +
+ // Enable pins 14 and 15. + // Disable pull-up/down on pins 14 and 15.
+ self.registers.GPPUD.set(0); + #[cfg(feature = "bsp_rpi3")]
+ cpu::spin_for_cycles(150); + self.disable_pud_14_15_bcm2837();
+ +
+ self.registers + #[cfg(feature = "bsp_rpi4")]
+ .GPPUDCLK0 + self.disable_pud_14_15_bcm2711();
+ .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
+ cpu::spin_for_cycles(150);
+
+ self.registers.GPPUDCLK0.set(0);
+ } + }
+} +}
+ +

@ -40,6 +40,7 @@ pub unsafe fn _start() -> ! {
pub use asm::nop; pub use asm::nop;
/// Spin for `n` cycles. /// Spin for `n` cycles.
#[cfg(feature = "bsp_rpi3")]
#[inline(always)] #[inline(always)]
pub fn spin_for_cycles(n: usize) { pub fn spin_for_cycles(n: usize) {
for _ in 0..n { for _ in 0..n {

@ -5,7 +5,7 @@
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
synchronization::NullLock, synchronization::NullLock,
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs};
// GPIO registers. // GPIO registers.
// //
// 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
// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
register_bitfields! { register_bitfields! {
u32, u32,
@ -39,7 +40,21 @@ register_bitfields! {
] ]
], ],
/// GPIO Pull-up/down Register
///
/// BCM2837 only.
GPPUD [
/// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
PUD OFFSET(0) NUMBITS(2) [
Off = 0b00,
PullDown = 0b01,
PullUp = 0b10
]
],
/// GPIO Pull-up/down Clock Register 0 /// GPIO Pull-up/down Clock Register 0
///
/// BCM2837 only.
GPPUDCLK0 [ GPPUDCLK0 [
/// Pin 15 /// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [ PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -52,23 +67,37 @@ register_bitfields! {
NoEffect = 0, NoEffect = 0,
AssertClock = 1 AssertClock = 1
] ]
],
/// GPIO Pull-up / Pull-down Register 0
///
/// BCM2711 only.
GPIO_PUP_PDN_CNTRL_REG0 [
/// Pin 15
GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
],
/// Pin 14
GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
]
] ]
} }
register_structs! { register_structs! {
#[allow(non_snake_case)] #[allow(non_snake_case)]
RegisterBlock { RegisterBlock {
(0x00 => GPFSEL0: ReadWrite<u32>), (0x00 => _reserved1),
(0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
(0x08 => GPFSEL2: ReadWrite<u32>), (0x08 => _reserved2),
(0x0C => GPFSEL3: ReadWrite<u32>), (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
(0x10 => GPFSEL4: ReadWrite<u32>),
(0x14 => GPFSEL5: ReadWrite<u32>),
(0x18 => _reserved1),
(0x94 => GPPUD: ReadWrite<u32>),
(0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
(0x9C => GPPUDCLK1: ReadWrite<u32>), (0x9C => _reserved3),
(0xA0 => @END), (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
(0xE8 => @END),
} }
} }
@ -107,26 +136,58 @@ impl GPIOInner {
} }
} }
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
use crate::cpu;
// Make an educated guess for a good delay value (Sequence described in the BCM2837
// peripherals PDF).
//
// - According to Wikipedia, the fastest Pi3 clocks around 1.4 GHz.
// - The Linux 2837 GPIO driver waits 1 µs between the steps.
//
// So lets try to be on the safe side and default to 2000 cycles, which would equal 1 µs
// would the CPU be clocked at 2 GHz.
const DELAY: usize = 2000;
self.registers.GPPUD.write(GPPUD::PUD::Off);
cpu::spin_for_cycles(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
cpu::spin_for_cycles(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
}
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi4")]
fn disable_pud_14_15_bcm2711(&mut self) {
self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
);
}
/// Map PL011 UART as standard output. /// Map PL011 UART as standard output.
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&mut self) { pub fn map_pl011_uart(&mut self) {
// Map to pins. // Select the UART on pins 14 and 15.
self.registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
// Enable pins 14 and 15. // Disable pull-up/down on pins 14 and 15.
self.registers.GPPUD.set(0); #[cfg(feature = "bsp_rpi3")]
cpu::spin_for_cycles(150); self.disable_pud_14_15_bcm2837();
self.registers #[cfg(feature = "bsp_rpi4")]
.GPPUDCLK0 self.disable_pud_14_15_bcm2711();
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
self.registers.GPPUDCLK0.set(0);
} }
} }

@ -194,7 +194,7 @@ diff -uNr 06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs 07_uart_chainloader/src/
} else { } else {
// If not core0, infinitely wait for events. // If not core0, infinitely wait for events.
wait_forever() wait_forever()
@@ -54,3 +54,19 @@ @@ -55,3 +55,19 @@
asm::wfe() asm::wfe()
} }
} }

@ -40,6 +40,7 @@ pub unsafe fn _start() -> ! {
pub use asm::nop; pub use asm::nop;
/// Spin for `n` cycles. /// Spin for `n` cycles.
#[cfg(feature = "bsp_rpi3")]
#[inline(always)] #[inline(always)]
pub fn spin_for_cycles(n: usize) { pub fn spin_for_cycles(n: usize) {
for _ in 0..n { for _ in 0..n {

@ -5,7 +5,7 @@
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
synchronization::NullLock, synchronization::NullLock,
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs};
// GPIO registers. // GPIO registers.
// //
// 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
// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
register_bitfields! { register_bitfields! {
u32, u32,
@ -39,7 +40,21 @@ register_bitfields! {
] ]
], ],
/// GPIO Pull-up/down Register
///
/// BCM2837 only.
GPPUD [
/// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
PUD OFFSET(0) NUMBITS(2) [
Off = 0b00,
PullDown = 0b01,
PullUp = 0b10
]
],
/// GPIO Pull-up/down Clock Register 0 /// GPIO Pull-up/down Clock Register 0
///
/// BCM2837 only.
GPPUDCLK0 [ GPPUDCLK0 [
/// Pin 15 /// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [ PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -52,23 +67,37 @@ register_bitfields! {
NoEffect = 0, NoEffect = 0,
AssertClock = 1 AssertClock = 1
] ]
],
/// GPIO Pull-up / Pull-down Register 0
///
/// BCM2711 only.
GPIO_PUP_PDN_CNTRL_REG0 [
/// Pin 15
GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
],
/// Pin 14
GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
]
] ]
} }
register_structs! { register_structs! {
#[allow(non_snake_case)] #[allow(non_snake_case)]
RegisterBlock { RegisterBlock {
(0x00 => GPFSEL0: ReadWrite<u32>), (0x00 => _reserved1),
(0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
(0x08 => GPFSEL2: ReadWrite<u32>), (0x08 => _reserved2),
(0x0C => GPFSEL3: ReadWrite<u32>), (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
(0x10 => GPFSEL4: ReadWrite<u32>),
(0x14 => GPFSEL5: ReadWrite<u32>),
(0x18 => _reserved1),
(0x94 => GPPUD: ReadWrite<u32>),
(0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
(0x9C => GPPUDCLK1: ReadWrite<u32>), (0x9C => _reserved3),
(0xA0 => @END), (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
(0xE8 => @END),
} }
} }
@ -107,26 +136,58 @@ impl GPIOInner {
} }
} }
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
use crate::cpu;
// Make an educated guess for a good delay value (Sequence described in the BCM2837
// peripherals PDF).
//
// - According to Wikipedia, the fastest Pi3 clocks around 1.4 GHz.
// - The Linux 2837 GPIO driver waits 1 µs between the steps.
//
// So lets try to be on the safe side and default to 2000 cycles, which would equal 1 µs
// would the CPU be clocked at 2 GHz.
const DELAY: usize = 2000;
self.registers.GPPUD.write(GPPUD::PUD::Off);
cpu::spin_for_cycles(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
cpu::spin_for_cycles(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
}
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi4")]
fn disable_pud_14_15_bcm2711(&mut self) {
self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
);
}
/// Map PL011 UART as standard output. /// Map PL011 UART as standard output.
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&mut self) { pub fn map_pl011_uart(&mut self) {
// Map to pins. // Select the UART on pins 14 and 15.
self.registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
// Enable pins 14 and 15. // Disable pull-up/down on pins 14 and 15.
self.registers.GPPUD.set(0); #[cfg(feature = "bsp_rpi3")]
cpu::spin_for_cycles(150); self.disable_pud_14_15_bcm2837();
self.registers #[cfg(feature = "bsp_rpi4")]
.GPPUDCLK0 self.disable_pud_14_15_bcm2711();
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
self.registers.GPPUDCLK0.set(0);
} }
} }

@ -130,7 +130,23 @@ diff -uNr 07_uart_chainloader/src/_arch/aarch64/cpu.rs 08_timestamps/src/_arch/a
} else { } else {
// If not core0, infinitely wait for events. // If not core0, infinitely wait for events.
wait_forever() wait_forever()
@@ -54,19 +54,3 @@ @@ -39,15 +39,6 @@
pub use asm::nop;
-/// Spin for `n` cycles.
-#[cfg(feature = "bsp_rpi3")]
-#[inline(always)]
-pub fn spin_for_cycles(n: usize) {
- for _ in 0..n {
- asm::nop();
- }
-}
-
/// Pause execution on the core.
#[inline(always)]
pub fn wait_forever() -> ! {
@@ -55,19 +46,3 @@
asm::wfe() asm::wfe()
} }
} }
@ -254,6 +270,42 @@ diff -uNr 07_uart_chainloader/src/_arch/aarch64/time.rs 08_timestamps/src/_arch/
+ } + }
+} +}
diff -uNr 07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
--- 07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
+++ 08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
@@ -139,25 +139,19 @@
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
- use crate::cpu;
+ use crate::{time, time::interface::TimeManager};
+ use core::time::Duration;
- // Make an educated guess for a good delay value (Sequence described in the BCM2837
- // peripherals PDF).
- //
- // - According to Wikipedia, the fastest Pi3 clocks around 1.4 GHz.
- // - The Linux 2837 GPIO driver waits 1 µs between the steps.
- //
- // So lets try to be on the safe side and default to 2000 cycles, which would equal 1 µs
- // would the CPU be clocked at 2 GHz.
- const DELAY: usize = 2000;
+ // The Linux 2837 GPIO driver waits 1 µs between the steps.
+ const DELAY: Duration = Duration::from_micros(1);
self.registers.GPPUD.write(GPPUD::PUD::Off);
- cpu::spin_for_cycles(DELAY);
+ time::time_manager().spin_for(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
- cpu::spin_for_cycles(DELAY);
+ time::time_manager().spin_for(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
diff -uNr 07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs diff -uNr 07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
--- 07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs --- 07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
+++ 08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ 08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs

@ -39,14 +39,6 @@ pub unsafe fn _start() -> ! {
pub use asm::nop; pub use asm::nop;
/// Spin for `n` cycles.
#[inline(always)]
pub fn spin_for_cycles(n: usize) {
for _ in 0..n {
asm::nop();
}
}
/// Pause execution on the core. /// Pause execution on the core.
#[inline(always)] #[inline(always)]
pub fn wait_forever() -> ! { pub fn wait_forever() -> ! {

@ -5,7 +5,7 @@
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
synchronization::NullLock, synchronization::NullLock,
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs};
// GPIO registers. // GPIO registers.
// //
// 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
// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
register_bitfields! { register_bitfields! {
u32, u32,
@ -39,7 +40,21 @@ register_bitfields! {
] ]
], ],
/// GPIO Pull-up/down Register
///
/// BCM2837 only.
GPPUD [
/// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
PUD OFFSET(0) NUMBITS(2) [
Off = 0b00,
PullDown = 0b01,
PullUp = 0b10
]
],
/// GPIO Pull-up/down Clock Register 0 /// GPIO Pull-up/down Clock Register 0
///
/// BCM2837 only.
GPPUDCLK0 [ GPPUDCLK0 [
/// Pin 15 /// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [ PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -52,23 +67,37 @@ register_bitfields! {
NoEffect = 0, NoEffect = 0,
AssertClock = 1 AssertClock = 1
] ]
],
/// GPIO Pull-up / Pull-down Register 0
///
/// BCM2711 only.
GPIO_PUP_PDN_CNTRL_REG0 [
/// Pin 15
GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
],
/// Pin 14
GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
]
] ]
} }
register_structs! { register_structs! {
#[allow(non_snake_case)] #[allow(non_snake_case)]
RegisterBlock { RegisterBlock {
(0x00 => GPFSEL0: ReadWrite<u32>), (0x00 => _reserved1),
(0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
(0x08 => GPFSEL2: ReadWrite<u32>), (0x08 => _reserved2),
(0x0C => GPFSEL3: ReadWrite<u32>), (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
(0x10 => GPFSEL4: ReadWrite<u32>),
(0x14 => GPFSEL5: ReadWrite<u32>),
(0x18 => _reserved1),
(0x94 => GPPUD: ReadWrite<u32>),
(0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
(0x9C => GPPUDCLK1: ReadWrite<u32>), (0x9C => _reserved3),
(0xA0 => @END), (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
(0xE8 => @END),
} }
} }
@ -107,26 +136,52 @@ impl GPIOInner {
} }
} }
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
use crate::{time, time::interface::TimeManager};
use core::time::Duration;
// The Linux 2837 GPIO driver waits 1 µs between the steps.
const DELAY: Duration = Duration::from_micros(1);
self.registers.GPPUD.write(GPPUD::PUD::Off);
time::time_manager().spin_for(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
time::time_manager().spin_for(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
}
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi4")]
fn disable_pud_14_15_bcm2711(&mut self) {
self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
);
}
/// Map PL011 UART as standard output. /// Map PL011 UART as standard output.
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&mut self) { pub fn map_pl011_uart(&mut self) {
// Map to pins. // Select the UART on pins 14 and 15.
self.registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
// Enable pins 14 and 15. // Disable pull-up/down on pins 14 and 15.
self.registers.GPPUD.set(0); #[cfg(feature = "bsp_rpi3")]
cpu::spin_for_cycles(150); self.disable_pud_14_15_bcm2837();
self.registers #[cfg(feature = "bsp_rpi4")]
.GPPUDCLK0 self.disable_pud_14_15_bcm2711();
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
self.registers.GPPUDCLK0.set(0);
} }
} }

@ -39,14 +39,6 @@ pub unsafe fn _start() -> ! {
pub use asm::nop; pub use asm::nop;
/// Spin for `n` cycles.
#[inline(always)]
pub fn spin_for_cycles(n: usize) {
for _ in 0..n {
asm::nop();
}
}
/// Pause execution on the core. /// Pause execution on the core.
#[inline(always)] #[inline(always)]
pub fn wait_forever() -> ! { pub fn wait_forever() -> ! {

@ -5,7 +5,7 @@
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
synchronization::NullLock, synchronization::NullLock,
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs};
// GPIO registers. // GPIO registers.
// //
// 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
// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
register_bitfields! { register_bitfields! {
u32, u32,
@ -39,7 +40,21 @@ register_bitfields! {
] ]
], ],
/// GPIO Pull-up/down Register
///
/// BCM2837 only.
GPPUD [
/// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
PUD OFFSET(0) NUMBITS(2) [
Off = 0b00,
PullDown = 0b01,
PullUp = 0b10
]
],
/// GPIO Pull-up/down Clock Register 0 /// GPIO Pull-up/down Clock Register 0
///
/// BCM2837 only.
GPPUDCLK0 [ GPPUDCLK0 [
/// Pin 15 /// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [ PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -52,23 +67,37 @@ register_bitfields! {
NoEffect = 0, NoEffect = 0,
AssertClock = 1 AssertClock = 1
] ]
],
/// GPIO Pull-up / Pull-down Register 0
///
/// BCM2711 only.
GPIO_PUP_PDN_CNTRL_REG0 [
/// Pin 15
GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
],
/// Pin 14
GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
]
] ]
} }
register_structs! { register_structs! {
#[allow(non_snake_case)] #[allow(non_snake_case)]
RegisterBlock { RegisterBlock {
(0x00 => GPFSEL0: ReadWrite<u32>), (0x00 => _reserved1),
(0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
(0x08 => GPFSEL2: ReadWrite<u32>), (0x08 => _reserved2),
(0x0C => GPFSEL3: ReadWrite<u32>), (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
(0x10 => GPFSEL4: ReadWrite<u32>),
(0x14 => GPFSEL5: ReadWrite<u32>),
(0x18 => _reserved1),
(0x94 => GPPUD: ReadWrite<u32>),
(0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
(0x9C => GPPUDCLK1: ReadWrite<u32>), (0x9C => _reserved3),
(0xA0 => @END), (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
(0xE8 => @END),
} }
} }
@ -107,26 +136,52 @@ impl GPIOInner {
} }
} }
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
use crate::{time, time::interface::TimeManager};
use core::time::Duration;
// The Linux 2837 GPIO driver waits 1 µs between the steps.
const DELAY: Duration = Duration::from_micros(1);
self.registers.GPPUD.write(GPPUD::PUD::Off);
time::time_manager().spin_for(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
time::time_manager().spin_for(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
}
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi4")]
fn disable_pud_14_15_bcm2711(&mut self) {
self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
);
}
/// Map PL011 UART as standard output. /// Map PL011 UART as standard output.
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&mut self) { pub fn map_pl011_uart(&mut self) {
// Map to pins. // Select the UART on pins 14 and 15.
self.registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
// Enable pins 14 and 15. // Disable pull-up/down on pins 14 and 15.
self.registers.GPPUD.set(0); #[cfg(feature = "bsp_rpi3")]
cpu::spin_for_cycles(150); self.disable_pud_14_15_bcm2837();
self.registers #[cfg(feature = "bsp_rpi4")]
.GPPUDCLK0 self.disable_pud_14_15_bcm2711();
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
self.registers.GPPUDCLK0.set(0);
} }
} }

@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! {
pub use asm::nop; pub use asm::nop;
/// Spin for `n` cycles.
#[inline(always)]
pub fn spin_for_cycles(n: usize) {
for _ in 0..n {
asm::nop();
}
}
/// Pause execution on the core. /// Pause execution on the core.
#[inline(always)] #[inline(always)]
pub fn wait_forever() -> ! { pub fn wait_forever() -> ! {

@ -5,7 +5,7 @@
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
synchronization::NullLock, synchronization::NullLock,
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs};
// GPIO registers. // GPIO registers.
// //
// 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
// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
register_bitfields! { register_bitfields! {
u32, u32,
@ -39,7 +40,21 @@ register_bitfields! {
] ]
], ],
/// GPIO Pull-up/down Register
///
/// BCM2837 only.
GPPUD [
/// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
PUD OFFSET(0) NUMBITS(2) [
Off = 0b00,
PullDown = 0b01,
PullUp = 0b10
]
],
/// GPIO Pull-up/down Clock Register 0 /// GPIO Pull-up/down Clock Register 0
///
/// BCM2837 only.
GPPUDCLK0 [ GPPUDCLK0 [
/// Pin 15 /// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [ PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -52,23 +67,37 @@ register_bitfields! {
NoEffect = 0, NoEffect = 0,
AssertClock = 1 AssertClock = 1
] ]
],
/// GPIO Pull-up / Pull-down Register 0
///
/// BCM2711 only.
GPIO_PUP_PDN_CNTRL_REG0 [
/// Pin 15
GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
],
/// Pin 14
GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
]
] ]
} }
register_structs! { register_structs! {
#[allow(non_snake_case)] #[allow(non_snake_case)]
RegisterBlock { RegisterBlock {
(0x00 => GPFSEL0: ReadWrite<u32>), (0x00 => _reserved1),
(0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
(0x08 => GPFSEL2: ReadWrite<u32>), (0x08 => _reserved2),
(0x0C => GPFSEL3: ReadWrite<u32>), (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
(0x10 => GPFSEL4: ReadWrite<u32>),
(0x14 => GPFSEL5: ReadWrite<u32>),
(0x18 => _reserved1),
(0x94 => GPPUD: ReadWrite<u32>),
(0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
(0x9C => GPPUDCLK1: ReadWrite<u32>), (0x9C => _reserved3),
(0xA0 => @END), (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
(0xE8 => @END),
} }
} }
@ -107,26 +136,52 @@ impl GPIOInner {
} }
} }
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
use crate::{time, time::interface::TimeManager};
use core::time::Duration;
// The Linux 2837 GPIO driver waits 1 µs between the steps.
const DELAY: Duration = Duration::from_micros(1);
self.registers.GPPUD.write(GPPUD::PUD::Off);
time::time_manager().spin_for(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
time::time_manager().spin_for(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
}
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi4")]
fn disable_pud_14_15_bcm2711(&mut self) {
self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
);
}
/// Map PL011 UART as standard output. /// Map PL011 UART as standard output.
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&mut self) { pub fn map_pl011_uart(&mut self) {
// Map to pins. // Select the UART on pins 14 and 15.
self.registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
// Enable pins 14 and 15. // Disable pull-up/down on pins 14 and 15.
self.registers.GPPUD.set(0); #[cfg(feature = "bsp_rpi3")]
cpu::spin_for_cycles(150); self.disable_pud_14_15_bcm2837();
self.registers #[cfg(feature = "bsp_rpi4")]
.GPPUDCLK0 self.disable_pud_14_15_bcm2711();
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
self.registers.GPPUDCLK0.set(0);
} }
} }

@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! {
pub use asm::nop; pub use asm::nop;
/// Spin for `n` cycles.
#[inline(always)]
pub fn spin_for_cycles(n: usize) {
for _ in 0..n {
asm::nop();
}
}
/// Pause execution on the core. /// Pause execution on the core.
#[inline(always)] #[inline(always)]
pub fn wait_forever() -> ! { pub fn wait_forever() -> ! {

@ -5,7 +5,7 @@
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
synchronization::NullLock, synchronization::NullLock,
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs};
// GPIO registers. // GPIO registers.
// //
// 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
// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
register_bitfields! { register_bitfields! {
u32, u32,
@ -39,7 +40,21 @@ register_bitfields! {
] ]
], ],
/// GPIO Pull-up/down Register
///
/// BCM2837 only.
GPPUD [
/// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
PUD OFFSET(0) NUMBITS(2) [
Off = 0b00,
PullDown = 0b01,
PullUp = 0b10
]
],
/// GPIO Pull-up/down Clock Register 0 /// GPIO Pull-up/down Clock Register 0
///
/// BCM2837 only.
GPPUDCLK0 [ GPPUDCLK0 [
/// Pin 15 /// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [ PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -52,23 +67,37 @@ register_bitfields! {
NoEffect = 0, NoEffect = 0,
AssertClock = 1 AssertClock = 1
] ]
],
/// GPIO Pull-up / Pull-down Register 0
///
/// BCM2711 only.
GPIO_PUP_PDN_CNTRL_REG0 [
/// Pin 15
GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
],
/// Pin 14
GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
]
] ]
} }
register_structs! { register_structs! {
#[allow(non_snake_case)] #[allow(non_snake_case)]
RegisterBlock { RegisterBlock {
(0x00 => GPFSEL0: ReadWrite<u32>), (0x00 => _reserved1),
(0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
(0x08 => GPFSEL2: ReadWrite<u32>), (0x08 => _reserved2),
(0x0C => GPFSEL3: ReadWrite<u32>), (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
(0x10 => GPFSEL4: ReadWrite<u32>),
(0x14 => GPFSEL5: ReadWrite<u32>),
(0x18 => _reserved1),
(0x94 => GPPUD: ReadWrite<u32>),
(0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
(0x9C => GPPUDCLK1: ReadWrite<u32>), (0x9C => _reserved3),
(0xA0 => @END), (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
(0xE8 => @END),
} }
} }
@ -107,26 +136,52 @@ impl GPIOInner {
} }
} }
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
use crate::{time, time::interface::TimeManager};
use core::time::Duration;
// The Linux 2837 GPIO driver waits 1 µs between the steps.
const DELAY: Duration = Duration::from_micros(1);
self.registers.GPPUD.write(GPPUD::PUD::Off);
time::time_manager().spin_for(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
time::time_manager().spin_for(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
}
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi4")]
fn disable_pud_14_15_bcm2711(&mut self) {
self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
);
}
/// Map PL011 UART as standard output. /// Map PL011 UART as standard output.
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&mut self) { pub fn map_pl011_uart(&mut self) {
// Map to pins. // Select the UART on pins 14 and 15.
self.registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
// Enable pins 14 and 15. // Disable pull-up/down on pins 14 and 15.
self.registers.GPPUD.set(0); #[cfg(feature = "bsp_rpi3")]
cpu::spin_for_cycles(150); self.disable_pud_14_15_bcm2837();
self.registers #[cfg(feature = "bsp_rpi4")]
.GPPUDCLK0 self.disable_pud_14_15_bcm2711();
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
self.registers.GPPUDCLK0.set(0);
} }
} }

@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! {
pub use asm::nop; pub use asm::nop;
/// Spin for `n` cycles.
#[inline(always)]
pub fn spin_for_cycles(n: usize) {
for _ in 0..n {
asm::nop();
}
}
/// Pause execution on the core. /// Pause execution on the core.
#[inline(always)] #[inline(always)]
pub fn wait_forever() -> ! { pub fn wait_forever() -> ! {

@ -5,7 +5,7 @@
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
synchronization::NullLock, synchronization::NullLock,
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs};
// GPIO registers. // GPIO registers.
// //
// 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
// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
register_bitfields! { register_bitfields! {
u32, u32,
@ -39,7 +40,21 @@ register_bitfields! {
] ]
], ],
/// GPIO Pull-up/down Register
///
/// BCM2837 only.
GPPUD [
/// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
PUD OFFSET(0) NUMBITS(2) [
Off = 0b00,
PullDown = 0b01,
PullUp = 0b10
]
],
/// GPIO Pull-up/down Clock Register 0 /// GPIO Pull-up/down Clock Register 0
///
/// BCM2837 only.
GPPUDCLK0 [ GPPUDCLK0 [
/// Pin 15 /// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [ PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -52,23 +67,37 @@ register_bitfields! {
NoEffect = 0, NoEffect = 0,
AssertClock = 1 AssertClock = 1
] ]
],
/// GPIO Pull-up / Pull-down Register 0
///
/// BCM2711 only.
GPIO_PUP_PDN_CNTRL_REG0 [
/// Pin 15
GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
],
/// Pin 14
GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
]
] ]
} }
register_structs! { register_structs! {
#[allow(non_snake_case)] #[allow(non_snake_case)]
RegisterBlock { RegisterBlock {
(0x00 => GPFSEL0: ReadWrite<u32>), (0x00 => _reserved1),
(0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
(0x08 => GPFSEL2: ReadWrite<u32>), (0x08 => _reserved2),
(0x0C => GPFSEL3: ReadWrite<u32>), (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
(0x10 => GPFSEL4: ReadWrite<u32>),
(0x14 => GPFSEL5: ReadWrite<u32>),
(0x18 => _reserved1),
(0x94 => GPPUD: ReadWrite<u32>),
(0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
(0x9C => GPPUDCLK1: ReadWrite<u32>), (0x9C => _reserved3),
(0xA0 => @END), (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
(0xE8 => @END),
} }
} }
@ -107,26 +136,52 @@ impl GPIOInner {
} }
} }
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
use crate::{time, time::interface::TimeManager};
use core::time::Duration;
// The Linux 2837 GPIO driver waits 1 µs between the steps.
const DELAY: Duration = Duration::from_micros(1);
self.registers.GPPUD.write(GPPUD::PUD::Off);
time::time_manager().spin_for(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
time::time_manager().spin_for(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
}
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi4")]
fn disable_pud_14_15_bcm2711(&mut self) {
self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
);
}
/// Map PL011 UART as standard output. /// Map PL011 UART as standard output.
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&mut self) { pub fn map_pl011_uart(&mut self) {
// Map to pins. // Select the UART on pins 14 and 15.
self.registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
// Enable pins 14 and 15. // Disable pull-up/down on pins 14 and 15.
self.registers.GPPUD.set(0); #[cfg(feature = "bsp_rpi3")]
cpu::spin_for_cycles(150); self.disable_pud_14_15_bcm2837();
self.registers #[cfg(feature = "bsp_rpi4")]
.GPPUDCLK0 self.disable_pud_14_15_bcm2711();
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
self.registers.GPPUDCLK0.set(0);
} }
} }

@ -935,7 +935,7 @@ diff -uNr 12_exceptions_part1_groundwork/Makefile 13_integrated_testing/Makefile
diff -uNr 12_exceptions_part1_groundwork/src/_arch/aarch64/cpu.rs 13_integrated_testing/src/_arch/aarch64/cpu.rs diff -uNr 12_exceptions_part1_groundwork/src/_arch/aarch64/cpu.rs 13_integrated_testing/src/_arch/aarch64/cpu.rs
--- 12_exceptions_part1_groundwork/src/_arch/aarch64/cpu.rs --- 12_exceptions_part1_groundwork/src/_arch/aarch64/cpu.rs
+++ 13_integrated_testing/src/_arch/aarch64/cpu.rs +++ 13_integrated_testing/src/_arch/aarch64/cpu.rs
@@ -95,3 +95,20 @@ @@ -87,3 +87,20 @@
asm::wfe() asm::wfe()
} }
} }

@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! {
pub use asm::nop; pub use asm::nop;
/// Spin for `n` cycles.
#[inline(always)]
pub fn spin_for_cycles(n: usize) {
for _ in 0..n {
asm::nop();
}
}
/// Pause execution on the core. /// Pause execution on the core.
#[inline(always)] #[inline(always)]
pub fn wait_forever() -> ! { pub fn wait_forever() -> ! {

@ -5,7 +5,7 @@
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
synchronization::NullLock, synchronization::NullLock,
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs};
// GPIO registers. // GPIO registers.
// //
// 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
// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
register_bitfields! { register_bitfields! {
u32, u32,
@ -39,7 +40,21 @@ register_bitfields! {
] ]
], ],
/// GPIO Pull-up/down Register
///
/// BCM2837 only.
GPPUD [
/// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
PUD OFFSET(0) NUMBITS(2) [
Off = 0b00,
PullDown = 0b01,
PullUp = 0b10
]
],
/// GPIO Pull-up/down Clock Register 0 /// GPIO Pull-up/down Clock Register 0
///
/// BCM2837 only.
GPPUDCLK0 [ GPPUDCLK0 [
/// Pin 15 /// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [ PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -52,23 +67,37 @@ register_bitfields! {
NoEffect = 0, NoEffect = 0,
AssertClock = 1 AssertClock = 1
] ]
],
/// GPIO Pull-up / Pull-down Register 0
///
/// BCM2711 only.
GPIO_PUP_PDN_CNTRL_REG0 [
/// Pin 15
GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
],
/// Pin 14
GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
]
] ]
} }
register_structs! { register_structs! {
#[allow(non_snake_case)] #[allow(non_snake_case)]
RegisterBlock { RegisterBlock {
(0x00 => GPFSEL0: ReadWrite<u32>), (0x00 => _reserved1),
(0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
(0x08 => GPFSEL2: ReadWrite<u32>), (0x08 => _reserved2),
(0x0C => GPFSEL3: ReadWrite<u32>), (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
(0x10 => GPFSEL4: ReadWrite<u32>),
(0x14 => GPFSEL5: ReadWrite<u32>),
(0x18 => _reserved1),
(0x94 => GPPUD: ReadWrite<u32>),
(0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
(0x9C => GPPUDCLK1: ReadWrite<u32>), (0x9C => _reserved3),
(0xA0 => @END), (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
(0xE8 => @END),
} }
} }
@ -107,26 +136,52 @@ impl GPIOInner {
} }
} }
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
use crate::{time, time::interface::TimeManager};
use core::time::Duration;
// The Linux 2837 GPIO driver waits 1 µs between the steps.
const DELAY: Duration = Duration::from_micros(1);
self.registers.GPPUD.write(GPPUD::PUD::Off);
time::time_manager().spin_for(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
time::time_manager().spin_for(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
}
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi4")]
fn disable_pud_14_15_bcm2711(&mut self) {
self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
);
}
/// Map PL011 UART as standard output. /// Map PL011 UART as standard output.
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&mut self) { pub fn map_pl011_uart(&mut self) {
// Map to pins. // Select the UART on pins 14 and 15.
self.registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
// Enable pins 14 and 15. // Disable pull-up/down on pins 14 and 15.
self.registers.GPPUD.set(0); #[cfg(feature = "bsp_rpi3")]
cpu::spin_for_cycles(150); self.disable_pud_14_15_bcm2837();
self.registers #[cfg(feature = "bsp_rpi4")]
.GPPUDCLK0 self.disable_pud_14_15_bcm2711();
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
self.registers.GPPUDCLK0.set(0);
} }
} }

@ -1462,13 +1462,13 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 14_exc
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
- synchronization::NullLock, - synchronization::NullLock,
+ synchronization::IRQSafeNullLock, + synchronization::IRQSafeNullLock,
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@@ -88,7 +88,7 @@ @@ -117,7 +117,7 @@
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -1477,7 +1477,7 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 14_exc
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -138,7 +138,7 @@ @@ -193,7 +193,7 @@
/// - The user must ensure to provide a correct MMIO start address. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {

@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! {
pub use asm::nop; pub use asm::nop;
/// Spin for `n` cycles.
#[inline(always)]
pub fn spin_for_cycles(n: usize) {
for _ in 0..n {
asm::nop();
}
}
/// Pause execution on the core. /// Pause execution on the core.
#[inline(always)] #[inline(always)]
pub fn wait_forever() -> ! { pub fn wait_forever() -> ! {

@ -5,7 +5,7 @@
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
synchronization::IRQSafeNullLock, synchronization::IRQSafeNullLock,
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs};
// GPIO registers. // GPIO registers.
// //
// 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
// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
register_bitfields! { register_bitfields! {
u32, u32,
@ -39,7 +40,21 @@ register_bitfields! {
] ]
], ],
/// GPIO Pull-up/down Register
///
/// BCM2837 only.
GPPUD [
/// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
PUD OFFSET(0) NUMBITS(2) [
Off = 0b00,
PullDown = 0b01,
PullUp = 0b10
]
],
/// GPIO Pull-up/down Clock Register 0 /// GPIO Pull-up/down Clock Register 0
///
/// BCM2837 only.
GPPUDCLK0 [ GPPUDCLK0 [
/// Pin 15 /// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [ PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -52,23 +67,37 @@ register_bitfields! {
NoEffect = 0, NoEffect = 0,
AssertClock = 1 AssertClock = 1
] ]
],
/// GPIO Pull-up / Pull-down Register 0
///
/// BCM2711 only.
GPIO_PUP_PDN_CNTRL_REG0 [
/// Pin 15
GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
],
/// Pin 14
GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
]
] ]
} }
register_structs! { register_structs! {
#[allow(non_snake_case)] #[allow(non_snake_case)]
RegisterBlock { RegisterBlock {
(0x00 => GPFSEL0: ReadWrite<u32>), (0x00 => _reserved1),
(0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
(0x08 => GPFSEL2: ReadWrite<u32>), (0x08 => _reserved2),
(0x0C => GPFSEL3: ReadWrite<u32>), (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
(0x10 => GPFSEL4: ReadWrite<u32>),
(0x14 => GPFSEL5: ReadWrite<u32>),
(0x18 => _reserved1),
(0x94 => GPPUD: ReadWrite<u32>),
(0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
(0x9C => GPPUDCLK1: ReadWrite<u32>), (0x9C => _reserved3),
(0xA0 => @END), (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
(0xE8 => @END),
} }
} }
@ -107,26 +136,52 @@ impl GPIOInner {
} }
} }
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
use crate::{time, time::interface::TimeManager};
use core::time::Duration;
// The Linux 2837 GPIO driver waits 1 µs between the steps.
const DELAY: Duration = Duration::from_micros(1);
self.registers.GPPUD.write(GPPUD::PUD::Off);
time::time_manager().spin_for(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
time::time_manager().spin_for(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
}
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi4")]
fn disable_pud_14_15_bcm2711(&mut self) {
self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
);
}
/// Map PL011 UART as standard output. /// Map PL011 UART as standard output.
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&mut self) { pub fn map_pl011_uart(&mut self) {
// Map to pins. // Select the UART on pins 14 and 15.
self.registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
// Enable pins 14 and 15. // Disable pull-up/down on pins 14 and 15.
self.registers.GPPUD.set(0); #[cfg(feature = "bsp_rpi3")]
cpu::spin_for_cycles(150); self.disable_pud_14_15_bcm2837();
self.registers #[cfg(feature = "bsp_rpi4")]
.GPPUDCLK0 self.disable_pud_14_15_bcm2711();
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
self.registers.GPPUDCLK0.set(0);
} }
} }

@ -1052,16 +1052,16 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
- bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, - bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
- synchronization::IRQSafeNullLock, - synchronization::IRQSafeNullLock,
+ bsp::device_driver::common::MMIODerefWrapper, cpu, driver, memory, memory::mmu::Physical, + bsp::device_driver::common::MMIODerefWrapper, driver, memory, memory::mmu::Physical,
+ synchronization, synchronization::IRQSafeNullLock, + synchronization, synchronization::IRQSafeNullLock,
}; };
+use core::sync::atomic::{AtomicUsize, Ordering}; +use core::sync::atomic::{AtomicUsize, Ordering};
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -88,6 +89,8 @@ @@ -117,6 +118,8 @@
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -1070,7 +1070,7 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_
inner: IRQSafeNullLock<GPIOInner>, inner: IRQSafeNullLock<GPIOInner>,
} }
@@ -107,6 +110,19 @@ @@ -136,6 +139,19 @@
} }
} }
@ -1087,10 +1087,10 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_
+ Ok(()) + Ok(())
+ } + }
+ +
/// Map PL011 UART as standard output. /// Disable pull-up/down on pins 14 and 15.
/// #[cfg(feature = "bsp_rpi3")]
/// TX to pin 14 fn disable_pud_14_15_bcm2837(&mut self) {
@@ -135,10 +151,14 @@ @@ -190,10 +206,14 @@
/// ///
/// # Safety /// # Safety
/// ///
@ -1108,7 +1108,7 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_
} }
} }
@@ -158,4 +178,27 @@ @@ -213,4 +233,27 @@
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM GPIO" "BCM GPIO"
} }

@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! {
pub use asm::nop; pub use asm::nop;
/// Spin for `n` cycles.
#[inline(always)]
pub fn spin_for_cycles(n: usize) {
for _ in 0..n {
asm::nop();
}
}
/// Pause execution on the core. /// Pause execution on the core.
#[inline(always)] #[inline(always)]
pub fn wait_forever() -> ! { pub fn wait_forever() -> ! {

@ -5,7 +5,7 @@
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, memory, memory::mmu::Physical, bsp::device_driver::common::MMIODerefWrapper, driver, memory, memory::mmu::Physical,
synchronization, synchronization::IRQSafeNullLock, synchronization, synchronization::IRQSafeNullLock,
}; };
use core::sync::atomic::{AtomicUsize, Ordering}; use core::sync::atomic::{AtomicUsize, Ordering};
@ -18,7 +18,8 @@ use register::{mmio::*, register_bitfields, register_structs};
// GPIO registers. // GPIO registers.
// //
// 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
// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
register_bitfields! { register_bitfields! {
u32, u32,
@ -40,7 +41,21 @@ register_bitfields! {
] ]
], ],
/// GPIO Pull-up/down Register
///
/// BCM2837 only.
GPPUD [
/// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
PUD OFFSET(0) NUMBITS(2) [
Off = 0b00,
PullDown = 0b01,
PullUp = 0b10
]
],
/// GPIO Pull-up/down Clock Register 0 /// GPIO Pull-up/down Clock Register 0
///
/// BCM2837 only.
GPPUDCLK0 [ GPPUDCLK0 [
/// Pin 15 /// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [ PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -53,23 +68,37 @@ register_bitfields! {
NoEffect = 0, NoEffect = 0,
AssertClock = 1 AssertClock = 1
] ]
],
/// GPIO Pull-up / Pull-down Register 0
///
/// BCM2711 only.
GPIO_PUP_PDN_CNTRL_REG0 [
/// Pin 15
GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
],
/// Pin 14
GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
]
] ]
} }
register_structs! { register_structs! {
#[allow(non_snake_case)] #[allow(non_snake_case)]
RegisterBlock { RegisterBlock {
(0x00 => GPFSEL0: ReadWrite<u32>), (0x00 => _reserved1),
(0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
(0x08 => GPFSEL2: ReadWrite<u32>), (0x08 => _reserved2),
(0x0C => GPFSEL3: ReadWrite<u32>), (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
(0x10 => GPFSEL4: ReadWrite<u32>),
(0x14 => GPFSEL5: ReadWrite<u32>),
(0x18 => _reserved1),
(0x94 => GPPUD: ReadWrite<u32>),
(0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
(0x9C => GPPUDCLK1: ReadWrite<u32>), (0x9C => _reserved3),
(0xA0 => @END), (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
(0xE8 => @END),
} }
} }
@ -123,26 +152,52 @@ impl GPIOInner {
Ok(()) Ok(())
} }
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
use crate::{time, time::interface::TimeManager};
use core::time::Duration;
// The Linux 2837 GPIO driver waits 1 µs between the steps.
const DELAY: Duration = Duration::from_micros(1);
self.registers.GPPUD.write(GPPUD::PUD::Off);
time::time_manager().spin_for(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
time::time_manager().spin_for(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
}
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi4")]
fn disable_pud_14_15_bcm2711(&mut self) {
self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
);
}
/// Map PL011 UART as standard output. /// Map PL011 UART as standard output.
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&mut self) { pub fn map_pl011_uart(&mut self) {
// Map to pins. // Select the UART on pins 14 and 15.
self.registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
// Enable pins 14 and 15. // Disable pull-up/down on pins 14 and 15.
self.registers.GPPUD.set(0); #[cfg(feature = "bsp_rpi3")]
cpu::spin_for_cycles(150); self.disable_pud_14_15_bcm2837();
self.registers #[cfg(feature = "bsp_rpi4")]
.GPPUDCLK0 self.disable_pud_14_15_bcm2711();
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
self.registers.GPPUDCLK0.set(0);
} }
} }

Binary file not shown.

Binary file not shown.

@ -20,7 +20,7 @@ use cortex_a::{asm, regs::*};
/// - Linker script must ensure to place this function at `0x80_000`. /// - Linker script must ensure to place this function at `0x80_000`.
#[naked] #[naked]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn _start() -> ! { pub unsafe fn _start() -> ! {
use crate::runtime_init; use crate::runtime_init;
// Expect the boot core to start in EL2. // Expect the boot core to start in EL2.
@ -39,14 +39,6 @@ pub unsafe extern "C" fn _start() -> ! {
pub use asm::nop; pub use asm::nop;
/// Spin for `n` cycles.
#[inline(always)]
pub fn spin_for_cycles(n: usize) {
for _ in 0..n {
asm::nop();
}
}
/// Pause execution on the core. /// Pause execution on the core.
#[inline(always)] #[inline(always)]
pub fn wait_forever() -> ! { pub fn wait_forever() -> ! {

@ -5,7 +5,7 @@
//! GPIO Driver. //! GPIO Driver.
use crate::{ use crate::{
bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, bsp::device_driver::common::MMIODerefWrapper, driver, synchronization,
synchronization::NullLock, synchronization::NullLock,
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs};
// GPIO registers. // GPIO registers.
// //
// 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
// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
register_bitfields! { register_bitfields! {
u32, u32,
@ -39,7 +40,21 @@ register_bitfields! {
] ]
], ],
/// GPIO Pull-up/down Register
///
/// BCM2837 only.
GPPUD [
/// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins.
PUD OFFSET(0) NUMBITS(2) [
Off = 0b00,
PullDown = 0b01,
PullUp = 0b10
]
],
/// GPIO Pull-up/down Clock Register 0 /// GPIO Pull-up/down Clock Register 0
///
/// BCM2837 only.
GPPUDCLK0 [ GPPUDCLK0 [
/// Pin 15 /// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [ PUDCLK15 OFFSET(15) NUMBITS(1) [
@ -52,23 +67,37 @@ register_bitfields! {
NoEffect = 0, NoEffect = 0,
AssertClock = 1 AssertClock = 1
] ]
],
/// GPIO Pull-up / Pull-down Register 0
///
/// BCM2711 only.
GPIO_PUP_PDN_CNTRL_REG0 [
/// Pin 15
GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
],
/// Pin 14
GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [
NoResistor = 0b00,
PullUp = 0b01
]
] ]
} }
register_structs! { register_structs! {
#[allow(non_snake_case)] #[allow(non_snake_case)]
RegisterBlock { RegisterBlock {
(0x00 => GPFSEL0: ReadWrite<u32>), (0x00 => _reserved1),
(0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>), (0x04 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
(0x08 => GPFSEL2: ReadWrite<u32>), (0x08 => _reserved2),
(0x0C => GPFSEL3: ReadWrite<u32>), (0x94 => GPPUD: ReadWrite<u32, GPPUD::Register>),
(0x10 => GPFSEL4: ReadWrite<u32>),
(0x14 => GPFSEL5: ReadWrite<u32>),
(0x18 => _reserved1),
(0x94 => GPPUD: ReadWrite<u32>),
(0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>), (0x98 => GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>),
(0x9C => GPPUDCLK1: ReadWrite<u32>), (0x9C => _reserved3),
(0xA0 => @END), (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite<u32, GPIO_PUP_PDN_CNTRL_REG0::Register>),
(0xE8 => @END),
} }
} }
@ -107,26 +136,52 @@ impl GPIOInner {
} }
} }
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) {
use crate::{time, time::interface::TimeManager};
use core::time::Duration;
// The Linux 2837 GPIO driver waits 1 µs between the steps.
const DELAY: Duration = Duration::from_micros(1);
self.registers.GPPUD.write(GPPUD::PUD::Off);
time::time_manager().spin_for(DELAY);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock);
time::time_manager().spin_for(DELAY);
self.registers.GPPUD.write(GPPUD::PUD::Off);
self.registers.GPPUDCLK0.set(0);
}
/// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi4")]
fn disable_pud_14_15_bcm2711(&mut self) {
self.registers.GPIO_PUP_PDN_CNTRL_REG0.write(
GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp
+ GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp,
);
}
/// Map PL011 UART as standard output. /// Map PL011 UART as standard output.
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&mut self) { pub fn map_pl011_uart(&mut self) {
// Map to pins. // Select the UART on pins 14 and 15.
self.registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0);
// Enable pins 14 and 15. // Disable pull-up/down on pins 14 and 15.
self.registers.GPPUD.set(0); #[cfg(feature = "bsp_rpi3")]
cpu::spin_for_cycles(150); self.disable_pud_14_15_bcm2837();
self.registers #[cfg(feature = "bsp_rpi4")]
.GPPUDCLK0 self.disable_pud_14_15_bcm2711();
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
self.registers.GPPUDCLK0.set(0);
} }
} }

Loading…
Cancel
Save