From 163e2010ab2044a8194bdaf7a59204a8a0bbaa68 Mon Sep 17 00:00:00 2001 From: Andre Richter Date: Sat, 14 Nov 2020 09:57:31 +0100 Subject: [PATCH] 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 --- 06_drivers_gpio_uart/README.md | 110 ++++++++++++++---- 06_drivers_gpio_uart/src/_arch/aarch64/cpu.rs | 1 + .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 105 +++++++++++++---- 07_uart_chainloader/README.md | 2 +- 07_uart_chainloader/demo_payload_rpi3.img | Bin 6896 -> 7384 bytes 07_uart_chainloader/demo_payload_rpi4.img | Bin 6880 -> 7240 bytes 07_uart_chainloader/src/_arch/aarch64/cpu.rs | 1 + .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 105 +++++++++++++---- 08_timestamps/README.md | 54 ++++++++- 08_timestamps/src/_arch/aarch64/cpu.rs | 8 -- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 99 ++++++++++++---- 09_hw_debug_JTAG/src/_arch/aarch64/cpu.rs | 8 -- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 99 ++++++++++++---- 10_privilege_level/src/_arch/aarch64/cpu.rs | 8 -- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 99 ++++++++++++---- .../src/_arch/aarch64/cpu.rs | 8 -- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 99 ++++++++++++---- .../src/_arch/aarch64/cpu.rs | 8 -- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 99 ++++++++++++---- 13_integrated_testing/README.md | 2 +- .../src/_arch/aarch64/cpu.rs | 8 -- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 99 ++++++++++++---- 14_exceptions_part2_peripheral_IRQs/README.md | 6 +- .../src/_arch/aarch64/cpu.rs | 8 -- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 99 ++++++++++++---- 15_virtual_mem_part2_mmio_remap/README.md | 18 +-- .../src/_arch/aarch64/cpu.rs | 8 -- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 99 ++++++++++++---- X1_JTAG_boot/jtag_boot_rpi3.img | Bin 7512 -> 8992 bytes X1_JTAG_boot/jtag_boot_rpi4.img | Bin 7496 -> 7384 bytes X1_JTAG_boot/src/_arch/aarch64/cpu.rs | 10 +- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 99 ++++++++++++---- 32 files changed, 1015 insertions(+), 354 deletions(-) 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 0e353b7dc74b4fd01860d01b33bebae20dabbaab..9adf8152f7447be4c0d35ec20c96f7c67c377510 100755 GIT binary patch delta 4257 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 delta 3719 zcmZ8jeQZp^3kr4B?Qj>d(`v55VIKRw_l_%S*#Qx`c=^{e~L^b@+q_&`t^jZ0uJ!3d9%bqj`PRrj>F;;enflNnL795w+4bpD z_mSgWGpT=CO(RXhp~^>|HK$*O&KuNlM@L_0TA)Ky!z1g{2O&Q^Von?Of>TXj)Q1)` znF_wW5?&Ktx>%(SOx&mTn`6B{jI2=SQ9DEIS?R-~FtDvYmU+f0p3F_FTX zTuR$17de{2+2yKi{dh(i83nyhu%;&P-3a~=_)d1lB-f%qoL3|{xFA{McWb=$MJ9Zx z)Y+Pnih?#Kn7yukqOcv(dIAI`n-I3jTyJh%&a9bb+sxJLttJ}hiA`KWJ)@lFQCba1 z>TR!*&H(qc)OTS%pC&D&qyr?5r6eIf?3!+S3CSBqG;>lxyqTRd*9#H0WG-_J0B;9b zQ#`JqQ)%k~?lR`d^VTi^mjh@Pfqf3xUq_^Uh;$yfhk+Y80q*|1EN*O~j=KQ3hp{QI zGc~WG=Gby3oPa(@#WOyGEvJbp9VJJoVa?9xg`z?0Dw^U_IZ1&_POs1Qlxs`wHt!GI{9Jgne(fQAxdYWCT*cw(vsC^ zKJ{j8ewNf@yf>ht`%twR6qW^GxKj(j1fgpM819fe<3P9%fKxA*kRHAaKXMdktUwZo z;79;S0YF&6&`&$M*kXRxd9qQ`vK_#$CZkyZ`#6BlGY{NT(Qa8CNXXfWp7yC6=xU>h z5%T^7cFR(uXsGmfLbAl8e1rcfl9Q*HI~X$o`QZ9=(5y`DbU9mtW|}(Z065V4eo9jT zGcEBloylavoK`?bdO3gNFYe`8z>`7C+2wt~GSjFA@OB86)LSTd(6*wPfbb()=EPYT zedmkJ&-rYSffkYJz!KLFydT?o>bf$1{yM$$@9W%XB7aJ6x4aGlrRA#LOyFc;9jQZe zF7=>L%L;6PM)XB}){sR>XZ3!U)x%ZmQ41?UzX1yN*_-`<~Lxb~5J8uF#t7>rDkmDUiG!k$f ztz@qkSGn5YAOXX3k~=srRm3kzh$${Q$F9Kp5Ju%9 zzSpFpcyal3+utxTUdF_@BH80trIKJX^kvbOnnrHkFe~l9wvu{9DviI3iII6h8o5?V zQHKU*2ZSc@Z7NsV-UO2iWiUA2#{l7D@^1bc2A>a_s|brbTas*X!=U3NhE1`fvb6;K z>)`7=!xkT)4u`Y#s^kdf>-wAIV2Q2xvCYkutyhKO;K!X0jwrZ0BC@3fG7u07-|iEN zQURf8Y!Ok;U^;QfT#f(?9e1)raHght)&wWZI08-M;)}2FY#uXH_yeNJqj|J613u3j zzki~yIQhR9-!ZnWtfS)X7$%|rVGc+xFFW&zrl zVQB>{++7JbH+N|gPSUL{o!afb*^?2HFK}7z=^(Q@J03bJ7N&LzHr>-}*v0#C?>K0# zbQ~4LksjAeuS8MF{ph7bsNx>M`F6Kp8RJ-^sNw}_tP;KQ@K9$BW6pNgZFjPS)5Icn zw@VQy^vok&+NU^fXAo}$D0eW`UdC!%ZDMJLeaj__b9KLoy1ps|YE(aZARi)^VEP=| z_T5(zpAV-LZv4JRcB#Bp_!YBOtggX{a$(BgLHhJ(&+dViUHyYkHSgY|uP?gT?uupy zm1o7!!Su&o&fcu3Tia%kabeaUpZ+xaA_hIrpg(D>(FXJf>JE3E~|~E+z&l^Eibz=EMTv*PsE6e$Mc=tgHJtU1azPxD_>~H zq3oy$Z`Zm_zK0&&u$i@a6rqqUxhq!QW1|15!GXT#`Ui7%pyGD3H$8P?x10ULvm&~~ zoi&UDqCd|W>l~nAOO~I5oBQ500x;!gDLFZ}VJ9bd#E?5_e9u>AIY+X7s_3FYm^K^- zsh-wSi1J8c9bP{VlGggNR@*!|v-hrZ`(t8$Z-vET%}TL|*X?i`DuxA$dDu(d3!OZ_ q!-Lxgp5FcKmM3>T)3WR7C-h9m3^chtd<^&dQaJlEeH+uNTK)&Ai%b~+ diff --git a/07_uart_chainloader/demo_payload_rpi4.img b/07_uart_chainloader/demo_payload_rpi4.img index 4cf8cb9f0a84c805df9c41512669bf2c19f87385..c3b1ede6cc6ba9075e528da9dfaa43ef960e33ed 100755 GIT binary patch delta 4031 zcmZu!eNYtV8Gm+{K>Y*GzvHyNF%SJTXU2+3H2BI8wvZ)2qhAuL!x6iY9XDxs&36P_ooI0Eow>EZA1rr z1EtzjS(-j2k!FYN*6|{&45Z?xI zw3uqHOB6R)yh}A7AQ<*;UTR=WsIq=TO*diS>@8rP#n~v{Tt)+AM6;--9OtGSNjbv$ zxB+pbO5?tn8ze3IJ5kREjDm}e4sGrs(r+Fi?dB#ycY#y4$I_UFnhpln9W1-zviaQoWU7<*Kjwrz}q}*8Te(oHpKV2l(Bu}sdam#fAQ~g zi8B8_K^c2>DdoOfL%l17eMO=Byc^=@Wzz2RrpNb#X+M=42l)5-L?sT;SohKm@x9>b zUYZ_H3GVr}%zrhJC@}na!lOx0x+Uz@((wMRQeqeslEZCJv0mwH&QY54uUJC4(^6(6 zQ&8e}vX-W6 z;LN?SZbHh4WI)GirpskQm|c(^&Ozv{CtK_!-W7SunpW81WO3Q;qtH3Vy2KJQ=Jmy|_LsP=K#e_`4CC4-uPfh>cxV;;o2{U8XqK)i9R`L?M;q zHDVL?FqVFg8ks=D;6(m2i)yuIB%*hMJpLcDbuf4W zsW)bol)9-)RA)Vnbv4$5ztM*T8g<)fCW;zzlOwh{lLAw@G;Bq2x&;?IYj^prgTL0# z5WTe+4xU1Q;6t6$QfGOQ^Rtt-AD%7F@Tw#|GROB$SVm>{k^HmiG~)qau26tNe#`fO zx0f`+RA*!om#UQiJnZVC6~gPxm0c;k%v!RGg?84Fy~3rTt;Er6pHIG@s->}~C#i0j z>DhxaPrn;%_2L5cmjGA~JH2@n7)BmOa1pxBCIZ(${}@iV0%L+gW{i-iG3e_7pmS;JT&)U3N0W&5%Szoo z0QwLL_I4CKphEd6C|v?Td>~#0AWoAc3cQPRC$aY$t^w!4&#woZHwV0*r+7ISSju_- zE@W1Ov42cZ>h^*kxtDikIT*X((v7$iYy(3O?j$4^M&4+>;4l>6&7REh)%1(c9&*FQ z<1z(4CK^?d=>mlFaPfO|Ap{N~LC>Vo=rm{>usrq_ zJ4M@BJ}^0KE)4}A;3qFb8aFw-kZ_L3jr$vQ2{-evH#O+` zwh4Aa`cb6M9dO8AxhVG~LF{dHK6gk(!Gti9hfyr8g5zwnU^P-qMX^jv!$oM-2U<}u zT?0Or;i%ilwGPxOW2yfMO2SghoyzII2i+_I$3h7x0{K~6qyAMoX>Y-bc33flmVvrs z&pXzOH|E(zhgDJmXALEc#LP2=fNaB-6Yea z$u-izcyRow{N=d^l4Sf3Ns<4Wzg#?1z&_1io^wz(h5t%2-w(5#g1gyNL19&M5>0>K zmdc%do!fV<>g(qM!i6ShrYR1EN3;?@_DX@WHefL~lY2-H^Z9|W(Du$P!6!qVDT!dQ zx>!kJ8Ky^Tp<8vCGSDcD=ZWMxC9ARNUeDb>ZMi?x-`~-S8&*P!a?vBUSdc1w1 z?N4;9>g*48^z7WVyWGdIZ|>h&*%#{Hxw)gSZ}-m5%ASs%9eulD%$rHMOOtw9@J62? zHPdDSNSTs)e`!sACHGT&C==sJ@%<&;{2EQZ%a@qzsieZHh#hiWZ0YXY+!yNG sUAbjPUq>Z()#E+8DtmT3mJBp~RBYlaPRiee|2rs~AJIeXjiSo`0wSQZY5)KL delta 3696 zcmZWreQZzk8iOKpA650kT ztsU!Z$fl(YRJ`3(?Yd2bqHR3)i>>KI`o|iYNuy$AwCm{h$22EwlM@3Yl$N+H^?vug z=M=gpS=aZTbAIP{&OP_sd$KLvdax$ZAktWng74?2g?B&SW>&9kv8W$Pfs~8r*x2?u zB_p{~iG8#%E>X^el(a;OY>*o{aj2vS*Fyu07<=ius22Q+A&xaB7;xH-c zAB(C7G^);ScPNW@llsXKQa;%xs6H&V_xacd!m_68xLJWaWvA%f!2PsfQ=vLvLMh{x`?6=TIAeSxcIP&a>(NiSzrlq|WCN(+6fP*O@5gwDfYn zpu;iJz?d>qbSWqCYWAw=(b6XADu01W&_t~~WgC%szJRHHrl1eZ4m+CX7D}F4N+Oo0HuSup#MG=_oBmn`+28FO{Ue z!n#aN%}J4BU2eJUWj8r@y8SI&nm8d14P(7Wuw}d`gygS%VQ6wq@J_0MKob0ITt2zG%E?ILHAVKQ%K+-qM4D3Q!Ck|xk2b2E1QFq&P!F!B3~n zvaj3rhc|acPSCq>d2ry4kdnrc&o&7-YNFbKJ@0VSXL$EtB};JCdk*&R6% zI3DT6DBMqzbA6=uj>92k4t2Z{iu33p`GiTGtK+T1ymV&MM+9Ydnv`)6;f33S;>@Fd ztRQ0r8SdByLURtv1wbGG0xAfw<3%eHA+(Yr%5iM1N5n%4_mM$gSlUDQIA|5^SP zEmMD6rq|_oK(EVWP}AXc2?edU;=HA-CRt5O*3>^lLfesZJ=h1HJnqXDU!O}v%<|-@ zDcQZl?P`gbX_7B?JVTRjJCohK$iik?IFZlC_`02*>yG^N|7BLl0$48qTlY38dShr( zIs|L>Efnq2{71CN*QSAa=30Kkv-}nafEl9Fn58d|yqCP^<;(KenalL2|6JC#y=anm z^kaOB!|%EktsP)KzmAlF!)|5&iREmME!>0-s6|dzIj7sbq1z#Y;kZMyn+L`~sGdpo zXytMxymkfp@bA@hk$^m*VX!WHo%nB&?Xs^)+yxk`Y3jXxZ2rsY#&6jfWP#tZ zK?_B_MWh5IPxdVn#nN@1YJ4=Iwx1(q&pJ{HH*RvVXmve&Z*bk1h}9AjQ7-4coQPhD zcmF`@YAvl%oM<4VCV>IgTE-1NYZG=)*SrZ!~+O{j+kr z_D)#f?~XvKqm+ii?n8c7Q&!_{gM&1HXC!ZAR;o&!lRT-%SXWsh_$?Hh{8`Z#<}+V1 zzf`ta_#^wequNJ{MbX~cPK4=B&EjQK$eqlF98JP8_6x@<;Rt)jQ7t6doTJJ26LgOp z`r<)j{N8Gs+%rq<`&o1OaN>$2rf`3z0*LG*obkOlULE+4{t&whbou{yImO28G%-*n z=jISoN_350fcF7hcIPo(l1fu$o~gD!qvt=3o_|3qPhFH8k(ICyi1zFha`TE=ZvTyq zlnYWt>NI+O{t0R5QUxWPDuf+S8pqh|k=uR?Ay>+y{lAB6fM0ai%U?0%{JOY^u(-1Y z$(}L*okwwHlsWw^4#+P%$>(`C z51T3WKGDP>3z{C}Jahb|iN50E|En>MvUi*vjzeN`cB5b$B@`)g%c?7Vckp-7lcMbu zZ*Q}(ejlDRB<+=Md3q7Mcr#uO`^|pmAweA4W;%c>-XyqAZ4j)ZoNEGAJTHye#IX5v@RzacjKDDhxBRR?p=MW zcE)$lyXaoA^ zVf(7;og>CF-d2U>H>&EzDG!^is;?L^>)_v)^l>Zmd2ieLFN;1am>?+a+iEc60X(v+ z|Di{X2p+4_^-Byr)EPD7*SW4Mc-z*ETi8*r%zC}v+8Y4k5B2x;d^g@-K!JhP%W8cM zf|qUb1rlBz6sJM^9x&zwGWS?@d4XzS%oyYsjj^ETHE;@g`wjWejd9AaOGXSo)hCUG zW5z;+8fXng$wCr))gRi-@zw-&)J9(c_QrW(Gp-n9bt&Pv=-;BT&d&I~PLlx=G=z`% y*eCw8Yk9T@`?vQ!yz9PI_wRgk)y{{%qvib(gI}Sn?!?2q0;XSHznA%HR{akGbx-C1 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 086b01aeab0f5ed1e855dda06b628d2d5fe8b165..88b5a6b4081da46555c0b7b6f678fb7fe82541f7 100755 GIT binary patch delta 2917 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 b`mOwjTk{%TJ*N0&_z%>$NT>Q9m?Ki diff --git a/X1_JTAG_boot/jtag_boot_rpi4.img b/X1_JTAG_boot/jtag_boot_rpi4.img index 1e3c185ba8502dcb400bb8c97b2cdd32a6f06e7a..5b4fc45d19dfdf9a7bab6b1c2cc47391b3e10f64 100755 GIT binary patch delta 1208 zcmY*YUuauZ7(eIS+~(fQw$!vq?@gMUEN#;yGuztPVIOSlm}V8G+!kbG(v*VeCQ>@z zb1RCg`mn=Sb&o3|?hZjqRFW5$(mm7{b)asbVB#3m6qG%!Sz*`j{z-=i?mc|x`+eW< zcYgP~TN8Jlxg4c$t`AtWZ$Kogl#s6zHI>)z68@J!c&&Vt4N_)A;1%IKV@cQ)rk`Ak z@$Hn)+{SzW@zaSYXuepe9_95Dgde12HBREc5KIx0gc+aCco4oo#Cj*+!Ny&f`H_zC zZruM(#Nc;dh9xxci{mASnj$sj4+&Y#Q}Xm&T=>iMxS^j``Gu$u8se}vSweitWRyBc28@Q z-g-1fT9*)iRV3foK4Q(~^m6PZw@S?XfEaq<=8Yv=T|G(6!u?79caoX~ny(oGq_J)e&*zY;@SIkWx(xl)vQ{Z9rK!_LEjKC78DJQX_?T#NjE4=KioHaoAAcqHW-wb<8ohIOKlK_^|giQ(*aX?CJ;{ zmZm~fZJlksb&UP#(>bw6B>Jlm6xxaDy#UxZfV O0WHG)Xc*t}z~p~g6;k{F delta 1292 zcmbtUU2GIp6h8OP{><=G(x2Vw>`!M_OSijZ7f4IB8$-8X5F4X*ZNiHYHavisC={X( zJnUdFQEMXCLu2uU-57%tUN8&BeUU9~q9jDo2r=rzR(WWb2jEHTgX5XmS=7LrH<`IP z_dECdzH{%H`Em5?+^HCQ{j<2uLZf~-%>XVW%$R8W2I5x<#4pvYyr1!W9QR0v_?3QK zkS4l{hFDJetYyO2Q2xYH9Ccq`xZEciJ3(w`aM}Rl2OtRQ{rG~fz$Zg^jxvsH5VwiA zgOG3Lhs6e(?=0!~voFn;3=H~5O0F~`X(qzNlV`APuOZ#AZCiEu%uRyRt{t#RBqXzN z1OBCz-zX%)_QQbi(R{K#;PMpxX5pfjSC{tQlnGO2cde%V`Pz)nEF22;45j^0lWDD_ z&qD2Lms!wBH06hT^R_*uz+6E&^WeHpYYt(XR8DLY3X!L19%J%tg~60-`c~U?Mifc# zQ_sx(+_&HlC;zH#m!@8{?GK&Pb4cw4_T67Yu=){gcpJ=uym)!K9Ds`}t%E-`F>Z)P z5-jE3m}n-MWtX_6uzc-Z5_y`cA_FyDJZRi4=plvbvtc@hz?-g+?raW0&0=N&&A>*! zl)`g?KKF(`rW;xSQFaOm{BuK&j}@DIsIdC~d_3HSGOmAtCj*IzVoEFrVYQi*Eax`m zN=n!zYRHn`y5GQ$QUjC6!;Z&4?P2#KjAW}r8cDB12J!u1mhVgB<=~F+d{nF@wsrJ0 zcY=6DM8$ja8C2zGc_o7fn`zPrh0t+BYu7&gJ-*%Jh7!Z)170y zoWZYpauniB_bkqZK5=SwOTP9yBT0gj=j>TC{2)#tX>J&a`CvEapY zH11gRVlRY6tf}9w8I)U$kIVQ$Z#FU*Z-tHC*1W}wWetDo9btE|Q&Y8T;TCvwdjICb z(=WezEIWPFVJ+jh_LTNypoO+|+WOb9qUpRhf>*QwzB__Vt*`T7q?Jp*1b4iFTI4ZS z#>q&D$D;UsB%3=J{V!cRrjvEYGhP8+2yMCNWz0plcV6(e8y ! { +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(); } }