diff --git a/06_drivers_gpio_uart/README.md b/06_drivers_gpio_uart/README.md index e89ef1c6..ec28b067 100644 --- a/06_drivers_gpio_uart/README.md +++ b/06_drivers_gpio_uart/README.md @@ -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 --- 05_safe_globals/src/_arch/aarch64/cpu.rs +++ 06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs -@@ -37,6 +37,16 @@ +@@ -37,6 +37,17 @@ // Public Code //-------------------------------------------------------------------------------------------------- +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 { @@ -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 --- 05_safe_globals/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 +// +// Copyright (c) 2018-2020 Andre Richter @@ -212,7 +213,7 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_g +//! GPIO Driver. + +use crate::{ -+ bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, ++ bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, + synchronization::NullLock, +}; +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. +// +// 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! { + 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 ++ /// ++ /// BCM2837 only. + GPPUDCLK0 [ + /// Pin 15 + 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, + 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! { + #[allow(non_snake_case)] + RegisterBlock { -+ (0x00 => GPFSEL0: ReadWrite), ++ (0x00 => _reserved1), + (0x04 => GPFSEL1: ReadWrite), -+ (0x08 => GPFSEL2: ReadWrite), -+ (0x0C => GPFSEL3: ReadWrite), -+ (0x10 => GPFSEL4: ReadWrite), -+ (0x14 => GPFSEL5: ReadWrite), -+ (0x18 => _reserved1), -+ (0x94 => GPPUD: ReadWrite), ++ (0x08 => _reserved2), ++ (0x94 => GPPUD: ReadWrite), + (0x98 => GPPUDCLK0: ReadWrite), -+ (0x9C => GPPUDCLK1: ReadWrite), -+ (0xA0 => @END), ++ (0x9C => _reserved3), ++ (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), ++ (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. + /// + /// TX to pin 14 + /// RX to pin 15 + pub fn map_pl011_uart(&mut self) { -+ // Map to pins. ++ // Select the UART on pins 14 and 15. + self.registers + .GPFSEL1 -+ .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); ++ .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); + -+ // Enable pins 14 and 15. -+ self.registers.GPPUD.set(0); -+ cpu::spin_for_cycles(150); ++ // Disable pull-up/down on pins 14 and 15. ++ #[cfg(feature = "bsp_rpi3")] ++ self.disable_pud_14_15_bcm2837(); + -+ self.registers -+ .GPPUDCLK0 -+ .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); -+ cpu::spin_for_cycles(150); -+ -+ self.registers.GPPUDCLK0.set(0); ++ #[cfg(feature = "bsp_rpi4")] ++ self.disable_pud_14_15_bcm2711(); + } +} + diff --git a/06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs b/06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs index 9b2da60d..53f131f8 100644 --- a/06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs +++ b/06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs @@ -40,6 +40,7 @@ pub unsafe fn _start() -> ! { 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 { diff --git a/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 0b01db4b..974ed70f 100644 --- a/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -5,7 +5,7 @@ //! GPIO Driver. use crate::{ - bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, synchronization::NullLock, }; use register::{mmio::*, register_bitfields, register_structs}; @@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs}; // GPIO registers. // // 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! { 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 + /// + /// BCM2837 only. GPPUDCLK0 [ /// Pin 15 PUDCLK15 OFFSET(15) NUMBITS(1) [ @@ -52,23 +67,37 @@ register_bitfields! { NoEffect = 0, 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! { #[allow(non_snake_case)] RegisterBlock { - (0x00 => GPFSEL0: ReadWrite), + (0x00 => _reserved1), (0x04 => GPFSEL1: ReadWrite), - (0x08 => GPFSEL2: ReadWrite), - (0x0C => GPFSEL3: ReadWrite), - (0x10 => GPFSEL4: ReadWrite), - (0x14 => GPFSEL5: ReadWrite), - (0x18 => _reserved1), - (0x94 => GPPUD: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), (0x98 => GPPUDCLK0: ReadWrite), - (0x9C => GPPUDCLK1: ReadWrite), - (0xA0 => @END), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (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. /// /// TX to pin 14 /// RX to pin 15 pub fn map_pl011_uart(&mut self) { - // Map to pins. + // Select the UART on pins 14 and 15. self.registers .GPFSEL1 - .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); - // Enable pins 14 and 15. - self.registers.GPPUD.set(0); - cpu::spin_for_cycles(150); + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); - self.registers - .GPPUDCLK0 - .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); - cpu::spin_for_cycles(150); - - self.registers.GPPUDCLK0.set(0); + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); } } diff --git a/07_uart_chainloader/README.md b/07_uart_chainloader/README.md index 663bad83..efb9e008 100644 --- a/07_uart_chainloader/README.md +++ b/07_uart_chainloader/README.md @@ -194,7 +194,7 @@ diff -uNr 06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs 07_uart_chainloader/src/ } else { // If not core0, infinitely wait for events. wait_forever() -@@ -54,3 +54,19 @@ +@@ -55,3 +55,19 @@ asm::wfe() } } diff --git a/07_uart_chainloader/demo_payload_rpi3.img b/07_uart_chainloader/demo_payload_rpi3.img index 0e353b7d..9adf8152 100755 Binary files a/07_uart_chainloader/demo_payload_rpi3.img and b/07_uart_chainloader/demo_payload_rpi3.img differ diff --git a/07_uart_chainloader/demo_payload_rpi4.img b/07_uart_chainloader/demo_payload_rpi4.img index 4cf8cb9f..c3b1ede6 100755 Binary files a/07_uart_chainloader/demo_payload_rpi4.img and b/07_uart_chainloader/demo_payload_rpi4.img differ diff --git a/07_uart_chainloader/src/_arch/aarch64/cpu.rs b/07_uart_chainloader/src/_arch/aarch64/cpu.rs index 34cf2ab9..3121e75e 100644 --- a/07_uart_chainloader/src/_arch/aarch64/cpu.rs +++ b/07_uart_chainloader/src/_arch/aarch64/cpu.rs @@ -40,6 +40,7 @@ pub unsafe fn _start() -> ! { 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 { diff --git a/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 0b01db4b..974ed70f 100644 --- a/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -5,7 +5,7 @@ //! GPIO Driver. use crate::{ - bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, synchronization::NullLock, }; use register::{mmio::*, register_bitfields, register_structs}; @@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs}; // GPIO registers. // // 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! { 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 + /// + /// BCM2837 only. GPPUDCLK0 [ /// Pin 15 PUDCLK15 OFFSET(15) NUMBITS(1) [ @@ -52,23 +67,37 @@ register_bitfields! { NoEffect = 0, 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! { #[allow(non_snake_case)] RegisterBlock { - (0x00 => GPFSEL0: ReadWrite), + (0x00 => _reserved1), (0x04 => GPFSEL1: ReadWrite), - (0x08 => GPFSEL2: ReadWrite), - (0x0C => GPFSEL3: ReadWrite), - (0x10 => GPFSEL4: ReadWrite), - (0x14 => GPFSEL5: ReadWrite), - (0x18 => _reserved1), - (0x94 => GPPUD: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), (0x98 => GPPUDCLK0: ReadWrite), - (0x9C => GPPUDCLK1: ReadWrite), - (0xA0 => @END), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (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. /// /// TX to pin 14 /// RX to pin 15 pub fn map_pl011_uart(&mut self) { - // Map to pins. + // Select the UART on pins 14 and 15. self.registers .GPFSEL1 - .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); - // Enable pins 14 and 15. - self.registers.GPPUD.set(0); - cpu::spin_for_cycles(150); + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); - self.registers - .GPPUDCLK0 - .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); - cpu::spin_for_cycles(150); - - self.registers.GPPUDCLK0.set(0); + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); } } diff --git a/08_timestamps/README.md b/08_timestamps/README.md index e812e05b..73684f44 100644 --- a/08_timestamps/README.md +++ b/08_timestamps/README.md @@ -130,7 +130,23 @@ diff -uNr 07_uart_chainloader/src/_arch/aarch64/cpu.rs 08_timestamps/src/_arch/a } else { // If not core0, infinitely wait for events. 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() } } @@ -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 --- 07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ 08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs diff --git a/08_timestamps/src/_arch/aarch64/cpu.rs b/08_timestamps/src/_arch/aarch64/cpu.rs index 9b2da60d..3f502ee0 100644 --- a/08_timestamps/src/_arch/aarch64/cpu.rs +++ b/08_timestamps/src/_arch/aarch64/cpu.rs @@ -39,14 +39,6 @@ pub unsafe fn _start() -> ! { 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. #[inline(always)] pub fn wait_forever() -> ! { diff --git a/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 0b01db4b..e06cbc7f 100644 --- a/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -5,7 +5,7 @@ //! GPIO Driver. use crate::{ - bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, synchronization::NullLock, }; use register::{mmio::*, register_bitfields, register_structs}; @@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs}; // GPIO registers. // // 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! { 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 + /// + /// BCM2837 only. GPPUDCLK0 [ /// Pin 15 PUDCLK15 OFFSET(15) NUMBITS(1) [ @@ -52,23 +67,37 @@ register_bitfields! { NoEffect = 0, 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! { #[allow(non_snake_case)] RegisterBlock { - (0x00 => GPFSEL0: ReadWrite), + (0x00 => _reserved1), (0x04 => GPFSEL1: ReadWrite), - (0x08 => GPFSEL2: ReadWrite), - (0x0C => GPFSEL3: ReadWrite), - (0x10 => GPFSEL4: ReadWrite), - (0x14 => GPFSEL5: ReadWrite), - (0x18 => _reserved1), - (0x94 => GPPUD: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), (0x98 => GPPUDCLK0: ReadWrite), - (0x9C => GPPUDCLK1: ReadWrite), - (0xA0 => @END), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (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. /// /// TX to pin 14 /// RX to pin 15 pub fn map_pl011_uart(&mut self) { - // Map to pins. + // Select the UART on pins 14 and 15. self.registers .GPFSEL1 - .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); - // Enable pins 14 and 15. - self.registers.GPPUD.set(0); - cpu::spin_for_cycles(150); + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); - self.registers - .GPPUDCLK0 - .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); - cpu::spin_for_cycles(150); - - self.registers.GPPUDCLK0.set(0); + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); } } diff --git a/09_hw_debug_JTAG/src/_arch/aarch64/cpu.rs b/09_hw_debug_JTAG/src/_arch/aarch64/cpu.rs index 9b2da60d..3f502ee0 100644 --- a/09_hw_debug_JTAG/src/_arch/aarch64/cpu.rs +++ b/09_hw_debug_JTAG/src/_arch/aarch64/cpu.rs @@ -39,14 +39,6 @@ pub unsafe fn _start() -> ! { 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. #[inline(always)] pub fn wait_forever() -> ! { diff --git a/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 0b01db4b..e06cbc7f 100644 --- a/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -5,7 +5,7 @@ //! GPIO Driver. use crate::{ - bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, synchronization::NullLock, }; use register::{mmio::*, register_bitfields, register_structs}; @@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs}; // GPIO registers. // // 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! { 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 + /// + /// BCM2837 only. GPPUDCLK0 [ /// Pin 15 PUDCLK15 OFFSET(15) NUMBITS(1) [ @@ -52,23 +67,37 @@ register_bitfields! { NoEffect = 0, 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! { #[allow(non_snake_case)] RegisterBlock { - (0x00 => GPFSEL0: ReadWrite), + (0x00 => _reserved1), (0x04 => GPFSEL1: ReadWrite), - (0x08 => GPFSEL2: ReadWrite), - (0x0C => GPFSEL3: ReadWrite), - (0x10 => GPFSEL4: ReadWrite), - (0x14 => GPFSEL5: ReadWrite), - (0x18 => _reserved1), - (0x94 => GPPUD: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), (0x98 => GPPUDCLK0: ReadWrite), - (0x9C => GPPUDCLK1: ReadWrite), - (0xA0 => @END), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (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. /// /// TX to pin 14 /// RX to pin 15 pub fn map_pl011_uart(&mut self) { - // Map to pins. + // Select the UART on pins 14 and 15. self.registers .GPFSEL1 - .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); - // Enable pins 14 and 15. - self.registers.GPPUD.set(0); - cpu::spin_for_cycles(150); + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); - self.registers - .GPPUDCLK0 - .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); - cpu::spin_for_cycles(150); - - self.registers.GPPUDCLK0.set(0); + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); } } diff --git a/10_privilege_level/src/_arch/aarch64/cpu.rs b/10_privilege_level/src/_arch/aarch64/cpu.rs index ab7c6047..3e5e5753 100644 --- a/10_privilege_level/src/_arch/aarch64/cpu.rs +++ b/10_privilege_level/src/_arch/aarch64/cpu.rs @@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! { 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. #[inline(always)] pub fn wait_forever() -> ! { diff --git a/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 0b01db4b..e06cbc7f 100644 --- a/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -5,7 +5,7 @@ //! GPIO Driver. use crate::{ - bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, synchronization::NullLock, }; use register::{mmio::*, register_bitfields, register_structs}; @@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs}; // GPIO registers. // // 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! { 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 + /// + /// BCM2837 only. GPPUDCLK0 [ /// Pin 15 PUDCLK15 OFFSET(15) NUMBITS(1) [ @@ -52,23 +67,37 @@ register_bitfields! { NoEffect = 0, 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! { #[allow(non_snake_case)] RegisterBlock { - (0x00 => GPFSEL0: ReadWrite), + (0x00 => _reserved1), (0x04 => GPFSEL1: ReadWrite), - (0x08 => GPFSEL2: ReadWrite), - (0x0C => GPFSEL3: ReadWrite), - (0x10 => GPFSEL4: ReadWrite), - (0x14 => GPFSEL5: ReadWrite), - (0x18 => _reserved1), - (0x94 => GPPUD: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), (0x98 => GPPUDCLK0: ReadWrite), - (0x9C => GPPUDCLK1: ReadWrite), - (0xA0 => @END), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (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. /// /// TX to pin 14 /// RX to pin 15 pub fn map_pl011_uart(&mut self) { - // Map to pins. + // Select the UART on pins 14 and 15. self.registers .GPFSEL1 - .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); - // Enable pins 14 and 15. - self.registers.GPPUD.set(0); - cpu::spin_for_cycles(150); + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); - self.registers - .GPPUDCLK0 - .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); - cpu::spin_for_cycles(150); - - self.registers.GPPUDCLK0.set(0); + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); } } diff --git a/11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/cpu.rs b/11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/cpu.rs index ab7c6047..3e5e5753 100644 --- a/11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/cpu.rs +++ b/11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/cpu.rs @@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! { 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. #[inline(always)] pub fn wait_forever() -> ! { diff --git a/11_virtual_mem_part1_identity_mapping/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/11_virtual_mem_part1_identity_mapping/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 0b01db4b..e06cbc7f 100644 --- a/11_virtual_mem_part1_identity_mapping/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/11_virtual_mem_part1_identity_mapping/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -5,7 +5,7 @@ //! GPIO Driver. use crate::{ - bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, synchronization::NullLock, }; use register::{mmio::*, register_bitfields, register_structs}; @@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs}; // GPIO registers. // // 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! { 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 + /// + /// BCM2837 only. GPPUDCLK0 [ /// Pin 15 PUDCLK15 OFFSET(15) NUMBITS(1) [ @@ -52,23 +67,37 @@ register_bitfields! { NoEffect = 0, 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! { #[allow(non_snake_case)] RegisterBlock { - (0x00 => GPFSEL0: ReadWrite), + (0x00 => _reserved1), (0x04 => GPFSEL1: ReadWrite), - (0x08 => GPFSEL2: ReadWrite), - (0x0C => GPFSEL3: ReadWrite), - (0x10 => GPFSEL4: ReadWrite), - (0x14 => GPFSEL5: ReadWrite), - (0x18 => _reserved1), - (0x94 => GPPUD: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), (0x98 => GPPUDCLK0: ReadWrite), - (0x9C => GPPUDCLK1: ReadWrite), - (0xA0 => @END), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (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. /// /// TX to pin 14 /// RX to pin 15 pub fn map_pl011_uart(&mut self) { - // Map to pins. + // Select the UART on pins 14 and 15. self.registers .GPFSEL1 - .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); - // Enable pins 14 and 15. - self.registers.GPPUD.set(0); - cpu::spin_for_cycles(150); + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); - self.registers - .GPPUDCLK0 - .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); - cpu::spin_for_cycles(150); - - self.registers.GPPUDCLK0.set(0); + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); } } diff --git a/12_exceptions_part1_groundwork/src/_arch/aarch64/cpu.rs b/12_exceptions_part1_groundwork/src/_arch/aarch64/cpu.rs index ab7c6047..3e5e5753 100644 --- a/12_exceptions_part1_groundwork/src/_arch/aarch64/cpu.rs +++ b/12_exceptions_part1_groundwork/src/_arch/aarch64/cpu.rs @@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! { 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. #[inline(always)] pub fn wait_forever() -> ! { diff --git a/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 0b01db4b..e06cbc7f 100644 --- a/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -5,7 +5,7 @@ //! GPIO Driver. use crate::{ - bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, synchronization::NullLock, }; use register::{mmio::*, register_bitfields, register_structs}; @@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs}; // GPIO registers. // // 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! { 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 + /// + /// BCM2837 only. GPPUDCLK0 [ /// Pin 15 PUDCLK15 OFFSET(15) NUMBITS(1) [ @@ -52,23 +67,37 @@ register_bitfields! { NoEffect = 0, 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! { #[allow(non_snake_case)] RegisterBlock { - (0x00 => GPFSEL0: ReadWrite), + (0x00 => _reserved1), (0x04 => GPFSEL1: ReadWrite), - (0x08 => GPFSEL2: ReadWrite), - (0x0C => GPFSEL3: ReadWrite), - (0x10 => GPFSEL4: ReadWrite), - (0x14 => GPFSEL5: ReadWrite), - (0x18 => _reserved1), - (0x94 => GPPUD: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), (0x98 => GPPUDCLK0: ReadWrite), - (0x9C => GPPUDCLK1: ReadWrite), - (0xA0 => @END), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (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. /// /// TX to pin 14 /// RX to pin 15 pub fn map_pl011_uart(&mut self) { - // Map to pins. + // Select the UART on pins 14 and 15. self.registers .GPFSEL1 - .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); - // Enable pins 14 and 15. - self.registers.GPPUD.set(0); - cpu::spin_for_cycles(150); + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); - self.registers - .GPPUDCLK0 - .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); - cpu::spin_for_cycles(150); - - self.registers.GPPUDCLK0.set(0); + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); } } diff --git a/13_integrated_testing/README.md b/13_integrated_testing/README.md index 68460d7b..50b9436b 100644 --- a/13_integrated_testing/README.md +++ b/13_integrated_testing/README.md @@ -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 --- 12_exceptions_part1_groundwork/src/_arch/aarch64/cpu.rs +++ 13_integrated_testing/src/_arch/aarch64/cpu.rs -@@ -95,3 +95,20 @@ +@@ -87,3 +87,20 @@ asm::wfe() } } diff --git a/13_integrated_testing/src/_arch/aarch64/cpu.rs b/13_integrated_testing/src/_arch/aarch64/cpu.rs index e7fe1711..7d146d23 100644 --- a/13_integrated_testing/src/_arch/aarch64/cpu.rs +++ b/13_integrated_testing/src/_arch/aarch64/cpu.rs @@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! { 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. #[inline(always)] pub fn wait_forever() -> ! { diff --git a/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 0b01db4b..e06cbc7f 100644 --- a/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -5,7 +5,7 @@ //! GPIO Driver. use crate::{ - bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, synchronization::NullLock, }; use register::{mmio::*, register_bitfields, register_structs}; @@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs}; // GPIO registers. // // 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! { 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 + /// + /// BCM2837 only. GPPUDCLK0 [ /// Pin 15 PUDCLK15 OFFSET(15) NUMBITS(1) [ @@ -52,23 +67,37 @@ register_bitfields! { NoEffect = 0, 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! { #[allow(non_snake_case)] RegisterBlock { - (0x00 => GPFSEL0: ReadWrite), + (0x00 => _reserved1), (0x04 => GPFSEL1: ReadWrite), - (0x08 => GPFSEL2: ReadWrite), - (0x0C => GPFSEL3: ReadWrite), - (0x10 => GPFSEL4: ReadWrite), - (0x14 => GPFSEL5: ReadWrite), - (0x18 => _reserved1), - (0x94 => GPPUD: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), (0x98 => GPPUDCLK0: ReadWrite), - (0x9C => GPPUDCLK1: ReadWrite), - (0xA0 => @END), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (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. /// /// TX to pin 14 /// RX to pin 15 pub fn map_pl011_uart(&mut self) { - // Map to pins. + // Select the UART on pins 14 and 15. self.registers .GPFSEL1 - .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); - // Enable pins 14 and 15. - self.registers.GPPUD.set(0); - cpu::spin_for_cycles(150); + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); - self.registers - .GPPUDCLK0 - .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); - cpu::spin_for_cycles(150); - - self.registers.GPPUDCLK0.set(0); + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); } } diff --git a/14_exceptions_part2_peripheral_IRQs/README.md b/14_exceptions_part2_peripheral_IRQs/README.md index d15542d8..23f50fcd 100644 --- a/14_exceptions_part2_peripheral_IRQs/README.md +++ b/14_exceptions_part2_peripheral_IRQs/README.md @@ -1462,13 +1462,13 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 14_exc @@ -6,7 +6,7 @@ use crate::{ - bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, - synchronization::NullLock, + synchronization::IRQSafeNullLock, }; use register::{mmio::*, register_bitfields, register_structs}; -@@ -88,7 +88,7 @@ +@@ -117,7 +117,7 @@ /// Representation of the GPIO HW. 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. pub const unsafe fn new(mmio_start_addr: usize) -> Self { Self { diff --git a/14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/cpu.rs b/14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/cpu.rs index e7fe1711..7d146d23 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/cpu.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/cpu.rs @@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! { 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. #[inline(always)] pub fn wait_forever() -> ! { diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 761dea0b..54b7133f 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -5,7 +5,7 @@ //! GPIO Driver. use crate::{ - bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, synchronization::IRQSafeNullLock, }; use register::{mmio::*, register_bitfields, register_structs}; @@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs}; // GPIO registers. // // 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! { 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 + /// + /// BCM2837 only. GPPUDCLK0 [ /// Pin 15 PUDCLK15 OFFSET(15) NUMBITS(1) [ @@ -52,23 +67,37 @@ register_bitfields! { NoEffect = 0, 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! { #[allow(non_snake_case)] RegisterBlock { - (0x00 => GPFSEL0: ReadWrite), + (0x00 => _reserved1), (0x04 => GPFSEL1: ReadWrite), - (0x08 => GPFSEL2: ReadWrite), - (0x0C => GPFSEL3: ReadWrite), - (0x10 => GPFSEL4: ReadWrite), - (0x14 => GPFSEL5: ReadWrite), - (0x18 => _reserved1), - (0x94 => GPPUD: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), (0x98 => GPPUDCLK0: ReadWrite), - (0x9C => GPPUDCLK1: ReadWrite), - (0xA0 => @END), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (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. /// /// TX to pin 14 /// RX to pin 15 pub fn map_pl011_uart(&mut self) { - // Map to pins. + // Select the UART on pins 14 and 15. self.registers .GPFSEL1 - .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); - // Enable pins 14 and 15. - self.registers.GPPUD.set(0); - cpu::spin_for_cycles(150); + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); - self.registers - .GPPUDCLK0 - .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); - cpu::spin_for_cycles(150); - - self.registers.GPPUDCLK0.set(0); + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); } } diff --git a/15_virtual_mem_part2_mmio_remap/README.md b/15_virtual_mem_part2_mmio_remap/README.md index 0b60f8c5..e82c93ac 100644 --- a/15_virtual_mem_part2_mmio_remap/README.md +++ b/15_virtual_mem_part2_mmio_remap/README.md @@ -1052,16 +1052,16 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_ //! GPIO Driver. use crate::{ -- bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, +- bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, - 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, }; +use core::sync::atomic::{AtomicUsize, Ordering}; use register::{mmio::*, register_bitfields, register_structs}; //-------------------------------------------------------------------------------------------------- -@@ -88,6 +89,8 @@ +@@ -117,6 +118,8 @@ /// Representation of the GPIO HW. pub struct GPIO { @@ -1070,7 +1070,7 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_ inner: IRQSafeNullLock, } -@@ -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(()) + } + - /// Map PL011 UART as standard output. - /// - /// TX to pin 14 -@@ -135,10 +151,14 @@ + /// Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + fn disable_pud_14_15_bcm2837(&mut self) { +@@ -190,10 +206,14 @@ /// /// # 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 { "BCM GPIO" } diff --git a/15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/cpu.rs b/15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/cpu.rs index 59840838..c68f1817 100644 --- a/15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/cpu.rs +++ b/15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/cpu.rs @@ -80,14 +80,6 @@ unsafe fn el2_to_el1_transition() -> ! { 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. #[inline(always)] pub fn wait_forever() -> ! { diff --git a/15_virtual_mem_part2_mmio_remap/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/15_virtual_mem_part2_mmio_remap/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index b9fc3c8b..e5fb0439 100644 --- a/15_virtual_mem_part2_mmio_remap/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/15_virtual_mem_part2_mmio_remap/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -5,7 +5,7 @@ //! GPIO Driver. 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, }; use core::sync::atomic::{AtomicUsize, Ordering}; @@ -18,7 +18,8 @@ use register::{mmio::*, register_bitfields, register_structs}; // GPIO registers. // // 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! { 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 + /// + /// BCM2837 only. GPPUDCLK0 [ /// Pin 15 PUDCLK15 OFFSET(15) NUMBITS(1) [ @@ -53,23 +68,37 @@ register_bitfields! { NoEffect = 0, 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! { #[allow(non_snake_case)] RegisterBlock { - (0x00 => GPFSEL0: ReadWrite), + (0x00 => _reserved1), (0x04 => GPFSEL1: ReadWrite), - (0x08 => GPFSEL2: ReadWrite), - (0x0C => GPFSEL3: ReadWrite), - (0x10 => GPFSEL4: ReadWrite), - (0x14 => GPFSEL5: ReadWrite), - (0x18 => _reserved1), - (0x94 => GPPUD: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), (0x98 => GPPUDCLK0: ReadWrite), - (0x9C => GPPUDCLK1: ReadWrite), - (0xA0 => @END), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (0xE8 => @END), } } @@ -123,26 +152,52 @@ impl GPIOInner { 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. /// /// TX to pin 14 /// RX to pin 15 pub fn map_pl011_uart(&mut self) { - // Map to pins. + // Select the UART on pins 14 and 15. self.registers .GPFSEL1 - .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); - // Enable pins 14 and 15. - self.registers.GPPUD.set(0); - cpu::spin_for_cycles(150); + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); - self.registers - .GPPUDCLK0 - .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); - cpu::spin_for_cycles(150); - - self.registers.GPPUDCLK0.set(0); + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); } } diff --git a/X1_JTAG_boot/jtag_boot_rpi3.img b/X1_JTAG_boot/jtag_boot_rpi3.img index 086b01ae..88b5a6b4 100755 Binary files a/X1_JTAG_boot/jtag_boot_rpi3.img and b/X1_JTAG_boot/jtag_boot_rpi3.img differ diff --git a/X1_JTAG_boot/jtag_boot_rpi4.img b/X1_JTAG_boot/jtag_boot_rpi4.img index 1e3c185b..5b4fc45d 100755 Binary files a/X1_JTAG_boot/jtag_boot_rpi4.img and b/X1_JTAG_boot/jtag_boot_rpi4.img differ diff --git a/X1_JTAG_boot/src/_arch/aarch64/cpu.rs b/X1_JTAG_boot/src/_arch/aarch64/cpu.rs index f2d96678..3f502ee0 100644 --- a/X1_JTAG_boot/src/_arch/aarch64/cpu.rs +++ b/X1_JTAG_boot/src/_arch/aarch64/cpu.rs @@ -20,7 +20,7 @@ use cortex_a::{asm, regs::*}; /// - Linker script must ensure to place this function at `0x80_000`. #[naked] #[no_mangle] -pub unsafe extern "C" fn _start() -> ! { +pub unsafe fn _start() -> ! { use crate::runtime_init; // Expect the boot core to start in EL2. @@ -39,14 +39,6 @@ pub unsafe extern "C" fn _start() -> ! { 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. #[inline(always)] pub fn wait_forever() -> ! { diff --git a/X1_JTAG_boot/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/X1_JTAG_boot/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 0b01db4b..e06cbc7f 100644 --- a/X1_JTAG_boot/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/X1_JTAG_boot/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -5,7 +5,7 @@ //! GPIO Driver. use crate::{ - bsp::device_driver::common::MMIODerefWrapper, cpu, driver, synchronization, + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, synchronization::NullLock, }; use register::{mmio::*, register_bitfields, register_structs}; @@ -17,7 +17,8 @@ use register::{mmio::*, register_bitfields, register_structs}; // GPIO registers. // // 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! { 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 + /// + /// BCM2837 only. GPPUDCLK0 [ /// Pin 15 PUDCLK15 OFFSET(15) NUMBITS(1) [ @@ -52,23 +67,37 @@ register_bitfields! { NoEffect = 0, 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! { #[allow(non_snake_case)] RegisterBlock { - (0x00 => GPFSEL0: ReadWrite), + (0x00 => _reserved1), (0x04 => GPFSEL1: ReadWrite), - (0x08 => GPFSEL2: ReadWrite), - (0x0C => GPFSEL3: ReadWrite), - (0x10 => GPFSEL4: ReadWrite), - (0x14 => GPFSEL5: ReadWrite), - (0x18 => _reserved1), - (0x94 => GPPUD: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), (0x98 => GPPUDCLK0: ReadWrite), - (0x9C => GPPUDCLK1: ReadWrite), - (0xA0 => @END), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (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. /// /// TX to pin 14 /// RX to pin 15 pub fn map_pl011_uart(&mut self) { - // Map to pins. + // Select the UART on pins 14 and 15. self.registers .GPFSEL1 - .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); - // Enable pins 14 and 15. - self.registers.GPPUD.set(0); - cpu::spin_for_cycles(150); + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); - self.registers - .GPPUDCLK0 - .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); - cpu::spin_for_cycles(150); - - self.registers.GPPUDCLK0.set(0); + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); } }