From 7ae506355311613434614402c85e6ee6f41aed2f Mon Sep 17 00:00:00 2001 From: Andre Richter Date: Fri, 11 Oct 2019 21:40:44 +0200 Subject: [PATCH] Defer BSP driver init to BSP code --- 05_safe_globals/README.md | 18 +- 05_safe_globals/src/bsp/rpi3.rs | 10 +- 06_drivers_gpio_uart/README.md | 247 ++++++++++-------- 06_drivers_gpio_uart/kernel | Bin 82656 -> 83112 bytes 06_drivers_gpio_uart/kernel8.img | Bin 7728 -> 7776 bytes 06_drivers_gpio_uart/src/bsp/driver.rs | 10 +- 06_drivers_gpio_uart/src/bsp/driver/bcm.rs | 11 + .../src/bsp/driver/{ => bcm}/bcm2837_gpio.rs | 34 +-- .../bsp/driver/{ => bcm}/bcm2xxx_mini_uart.rs | 59 ++--- 06_drivers_gpio_uart/src/bsp/rpi3.rs | 22 ++ 06_drivers_gpio_uart/src/main.rs | 22 +- 11 files changed, 240 insertions(+), 193 deletions(-) create mode 100644 06_drivers_gpio_uart/src/bsp/driver/bcm.rs rename 06_drivers_gpio_uart/src/bsp/driver/{ => bcm}/bcm2837_gpio.rs (88%) rename 06_drivers_gpio_uart/src/bsp/driver/{ => bcm}/bcm2xxx_mini_uart.rs (85%) diff --git a/05_safe_globals/README.md b/05_safe_globals/README.md index 04ed3aa1..fa4935b5 100644 --- a/05_safe_globals/README.md +++ b/05_safe_globals/README.md @@ -110,7 +110,7 @@ diff -uNr 04_zero_overhead_abstraction/src/arch/aarch64.rs 05_safe_globals/src/a diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/rpi3.rs --- 04_zero_overhead_abstraction/src/bsp/rpi3.rs +++ 05_safe_globals/src/bsp/rpi3.rs -@@ -4,39 +4,111 @@ +@@ -4,39 +4,115 @@ //! Board Support Package for the Raspberry Pi 3. @@ -128,8 +128,7 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r +struct QEMUOutputInner { + chars_written: usize, +} - --/// Implementing `console::Write` enables usage of the `format_args!` macros, ++ +impl QEMUOutputInner { + const fn new() -> QEMUOutputInner { + QEMUOutputInner { chars_written: 0 } @@ -142,7 +141,8 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r + } + } +} -+ + +-/// Implementing `console::Write` enables usage of the `format_args!` macros, +/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, /// which in turn are used to implement the `kernel`'s `print!` and `println!` -/// macros. @@ -176,7 +176,7 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r } //////////////////////////////////////////////////////////////////////////////// -+// OS interface implementations ++// BSP-public +//////////////////////////////////////////////////////////////////////////////// + +/// The main struct. @@ -192,6 +192,10 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r + } +} + ++//////////////////////////////////////////////////////////////////////////////// ++// OS interface implementations ++//////////////////////////////////////////////////////////////////////////////// ++ +/// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded +/// by a Mutex to serialize access. +impl interface::console::Write for QEMUOutput { @@ -201,7 +205,7 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r + // Fully qualified syntax for the call to + // `core::fmt::Write::write:fmt()` to increase readability. + let mut r = &self.inner; -+ r.lock(|i| fmt::Write::write_fmt(i, args)) ++ r.lock(|inner| fmt::Write::write_fmt(inner, args)) + } +} + @@ -212,7 +216,7 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r + use interface::sync::Mutex; + + let mut r = &self.inner; -+ r.lock(|i| i.chars_written) ++ r.lock(|inner| inner.chars_written) + } +} + diff --git a/05_safe_globals/src/bsp/rpi3.rs b/05_safe_globals/src/bsp/rpi3.rs index 0373d24c..06359a96 100644 --- a/05_safe_globals/src/bsp/rpi3.rs +++ b/05_safe_globals/src/bsp/rpi3.rs @@ -58,7 +58,7 @@ impl fmt::Write for QEMUOutputInner { } //////////////////////////////////////////////////////////////////////////////// -// OS interface implementations +// BSP-public //////////////////////////////////////////////////////////////////////////////// /// The main struct. @@ -74,6 +74,10 @@ impl QEMUOutput { } } +//////////////////////////////////////////////////////////////////////////////// +// OS interface implementations +//////////////////////////////////////////////////////////////////////////////// + /// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded /// by a Mutex to serialize access. impl interface::console::Write for QEMUOutput { @@ -83,7 +87,7 @@ impl interface::console::Write for QEMUOutput { // Fully qualified syntax for the call to // `core::fmt::Write::write:fmt()` to increase readability. let mut r = &self.inner; - r.lock(|i| fmt::Write::write_fmt(i, args)) + r.lock(|inner| fmt::Write::write_fmt(inner, args)) } } @@ -94,7 +98,7 @@ impl interface::console::Statistics for QEMUOutput { use interface::sync::Mutex; let mut r = &self.inner; - r.lock(|i| i.chars_written) + r.lock(|inner| inner.chars_written) } } diff --git a/06_drivers_gpio_uart/README.md b/06_drivers_gpio_uart/README.md index ba0e96b0..2992e906 100644 --- a/06_drivers_gpio_uart/README.md +++ b/06_drivers_gpio_uart/README.md @@ -51,9 +51,9 @@ diff -uNr 05_safe_globals/src/arch/aarch64.rs 06_drivers_gpio_uart/src/arch/aarc #[inline(always)] pub fn wait_forever() -> ! { -diff -uNr 05_safe_globals/src/bsp/driver/bcm2837_gpio.rs 06_drivers_gpio_uart/src/bsp/driver/bcm2837_gpio.rs ---- 05_safe_globals/src/bsp/driver/bcm2837_gpio.rs -+++ 06_drivers_gpio_uart/src/bsp/driver/bcm2837_gpio.rs +diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2837_gpio.rs 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2837_gpio.rs +--- 05_safe_globals/src/bsp/driver/bcm/bcm2837_gpio.rs ++++ 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2837_gpio.rs @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: MIT +// @@ -78,8 +78,7 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm2837_gpio.rs 06_drivers_gpio_uart/sr + FSEL15 OFFSET(15) NUMBITS(3) [ + Input = 0b000, + Output = 0b001, -+ RXD0 = 0b100, // UART0 - Alternate function 0 -+ RXD1 = 0b010 // Mini UART - Alternate function 5 ++ AltFunc5 = 0b010 // Mini UART RX + + ], + @@ -87,8 +86,7 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm2837_gpio.rs 06_drivers_gpio_uart/sr + FSEL14 OFFSET(12) NUMBITS(3) [ + Input = 0b000, + Output = 0b001, -+ TXD0 = 0b100, // UART0 - Alternate function 0 -+ TXD1 = 0b010 // Mini UART - Alternate function 5 ++ AltFunc5 = 0b010 // Mini UART TX + ] + ], + @@ -165,10 +163,10 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm2837_gpio.rs 06_drivers_gpio_uart/sr + /// + /// TX to pin 14 + /// RX to pin 15 -+ fn map_mini_uart(&mut self) { ++ pub fn map_mini_uart(&mut self) { + // Map to pins. + self.GPFSEL1 -+ .modify(GPFSEL1::FSEL14::TXD1 + GPFSEL1::FSEL15::RXD1); ++ .modify(GPFSEL1::FSEL14::AltFunc5 + GPFSEL1::FSEL15::AltFunc5); + + // Enable pins 14 and 15. + self.GPPUD.set(0); @@ -187,10 +185,11 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm2837_gpio.rs 06_drivers_gpio_uart/sr +} + +//////////////////////////////////////////////////////////////////////////////// -+// OS interface implementations ++// BSP-public +//////////////////////////////////////////////////////////////////////////////// ++use interface::sync::Mutex; + -+/// The driver's public data. ++/// The driver's main struct. +pub struct GPIO { + inner: NullLock, +} @@ -201,27 +200,28 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm2837_gpio.rs 06_drivers_gpio_uart/sr + inner: NullLock::new(GPIOInner::new(base_addr)), + } + } ++ ++ // Only visible to other BSP code. ++ pub fn map_mini_uart(&self) { ++ let mut r = &self.inner; ++ r.lock(|inner| inner.map_mini_uart()); ++ } +} + ++//////////////////////////////////////////////////////////////////////////////// ++// OS interface implementations ++//////////////////////////////////////////////////////////////////////////////// ++ +impl interface::driver::DeviceDriver for GPIO { + fn compatible(&self) -> &str { + "GPIO" + } -+ -+ fn init(&self) -> interface::driver::Result { -+ use interface::sync::Mutex; -+ -+ let mut r = &self.inner; -+ r.lock(|i| i.map_mini_uart()); -+ -+ Ok(()) -+ } +} -diff -uNr 05_safe_globals/src/bsp/driver/bcm2xxx_mini_uart.rs 06_drivers_gpio_uart/src/bsp/driver/bcm2xxx_mini_uart.rs ---- 05_safe_globals/src/bsp/driver/bcm2xxx_mini_uart.rs -+++ 06_drivers_gpio_uart/src/bsp/driver/bcm2xxx_mini_uart.rs -@@ -0,0 +1,261 @@ +diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs +--- 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs ++++ 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs +@@ -0,0 +1,258 @@ +// SPDX-License-Identifier: MIT +// +// Copyright (c) 2018-2019 Andre Richter @@ -363,27 +363,6 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm2xxx_mini_uart.rs 06_drivers_gpio_ua + self.base_addr as *const _ + } + -+ /// Set up baud rate and characteristics (115200 8N1). -+ fn init(&mut self) -> interface::driver::Result { -+ self.AUX_ENABLES.modify(AUX_ENABLES::MINI_UART_ENABLE::SET); -+ self.AUX_MU_IER.set(0); -+ self.AUX_MU_CNTL.set(0); -+ self.AUX_MU_LCR.write(AUX_MU_LCR::DATA_SIZE::EightBit); -+ self.AUX_MU_MCR.set(0); -+ self.AUX_MU_IER.set(0); -+ self.AUX_MU_IIR.write(AUX_MU_IIR::FIFO_CLEAR::All); -+ self.AUX_MU_BAUD.write(AUX_MU_BAUD::RATE.val(270)); // 115200 baud -+ -+ // Enable receive and send. -+ self.AUX_MU_CNTL -+ .write(AUX_MU_CNTL::RX_EN::Enabled + AUX_MU_CNTL::TX_EN::Enabled); -+ -+ // Clear FIFOs before using the device. -+ self.AUX_MU_IIR.write(AUX_MU_IIR::FIFO_CLEAR::All); -+ -+ Ok(()) -+ } -+ + /// Send a character. + fn write_char(&mut self, c: char) { + // Wait until we can send. @@ -429,7 +408,7 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm2xxx_mini_uart.rs 06_drivers_gpio_ua +} + +//////////////////////////////////////////////////////////////////////////////// -+// OS interface implementations ++// BSP-public +//////////////////////////////////////////////////////////////////////////////// + +/// The driver's main struct. @@ -448,16 +427,38 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm2xxx_mini_uart.rs 06_drivers_gpio_ua + } +} + ++//////////////////////////////////////////////////////////////////////////////// ++// OS interface implementations ++//////////////////////////////////////////////////////////////////////////////// ++use interface::sync::Mutex; ++ +impl interface::driver::DeviceDriver for MiniUart { + fn compatible(&self) -> &str { + "MiniUart" + } + ++ /// Set up baud rate and characteristics (115200 8N1). + fn init(&self) -> interface::driver::Result { -+ use interface::sync::Mutex; -+ + let mut r = &self.inner; -+ r.lock(|i| i.init()) ++ r.lock(|inner| { ++ // Enable register access to the MiniUart ++ inner.AUX_ENABLES.modify(AUX_ENABLES::MINI_UART_ENABLE::SET); ++ inner.AUX_MU_IER.set(0); // disable RX and TX interrupts ++ inner.AUX_MU_CNTL.set(0); // disable send and receive ++ inner.AUX_MU_LCR.write(AUX_MU_LCR::DATA_SIZE::EightBit); ++ inner.AUX_MU_BAUD.write(AUX_MU_BAUD::RATE.val(270)); // 115200 baud ++ inner.AUX_MU_MCR.set(0); // set "ready to send" high ++ ++ // Clear FIFOs before using the device. ++ inner.AUX_MU_IIR.write(AUX_MU_IIR::FIFO_CLEAR::All); ++ ++ // Enable receive and send. ++ inner ++ .AUX_MU_CNTL ++ .write(AUX_MU_CNTL::RX_EN::Enabled + AUX_MU_CNTL::TX_EN::Enabled); ++ }); ++ ++ Ok(()) + } +} + @@ -465,12 +466,10 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm2xxx_mini_uart.rs 06_drivers_gpio_ua +/// by a Mutex to serialize access. +impl interface::console::Write for MiniUart { + fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result { -+ use interface::sync::Mutex; -+ + // Fully qualified syntax for the call to + // `core::fmt::Write::write:fmt()` to increase readability. + let mut r = &self.inner; -+ r.lock(|i| fmt::Write::write_fmt(i, args)) ++ r.lock(|inner| fmt::Write::write_fmt(inner, args)) + } +} + @@ -478,17 +477,31 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm2xxx_mini_uart.rs 06_drivers_gpio_ua + +impl interface::console::Statistics for MiniUart { + fn chars_written(&self) -> usize { -+ use interface::sync::Mutex; -+ + let mut r = &self.inner; -+ r.lock(|i| i.chars_written) ++ r.lock(|inner| inner.chars_written) + } +} +diff -uNr 05_safe_globals/src/bsp/driver/bcm.rs 06_drivers_gpio_uart/src/bsp/driver/bcm.rs +--- 05_safe_globals/src/bsp/driver/bcm.rs ++++ 06_drivers_gpio_uart/src/bsp/driver/bcm.rs +@@ -0,0 +1,11 @@ ++// SPDX-License-Identifier: MIT ++// ++// Copyright (c) 2018-2019 Andre Richter ++ ++//! BCM driver top level. ++ ++mod bcm2837_gpio; ++mod bcm2xxx_mini_uart; ++ ++pub use bcm2837_gpio::GPIO; ++pub use bcm2xxx_mini_uart::MiniUart; + diff -uNr 05_safe_globals/src/bsp/driver.rs 06_drivers_gpio_uart/src/bsp/driver.rs --- 05_safe_globals/src/bsp/driver.rs +++ 06_drivers_gpio_uart/src/bsp/driver.rs -@@ -0,0 +1,17 @@ +@@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +// +// Copyright (c) 2018-2019 Andre Richter @@ -496,16 +509,10 @@ diff -uNr 05_safe_globals/src/bsp/driver.rs 06_drivers_gpio_uart/src/bsp/driver. +//! Drivers. + +#[cfg(feature = "bsp_rpi3")] -+mod bcm2837_gpio; -+ -+#[cfg(feature = "bsp_rpi3")] -+mod bcm2xxx_mini_uart; -+ -+#[cfg(feature = "bsp_rpi3")] -+pub use bcm2837_gpio::GPIO; ++mod bcm; + +#[cfg(feature = "bsp_rpi3")] -+pub use bcm2xxx_mini_uart::MiniUart; ++pub use bcm::*; diff -uNr 05_safe_globals/src/bsp/rpi3/memory_map.rs 06_drivers_gpio_uart/src/bsp/rpi3/memory_map.rs --- 05_safe_globals/src/bsp/rpi3/memory_map.rs @@ -528,7 +535,7 @@ diff -uNr 05_safe_globals/src/bsp/rpi3/memory_map.rs 06_drivers_gpio_uart/src/bs diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs --- 05_safe_globals/src/bsp/rpi3.rs +++ 06_drivers_gpio_uart/src/bsp/rpi3.rs -@@ -4,105 +4,21 @@ +@@ -4,115 +4,59 @@ //! Board Support Package for the Raspberry Pi 3. @@ -590,10 +597,11 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs - } -} - --//////////////////////////////////////////////////////////////////////////////// --// OS interface implementations --//////////////////////////////////////////////////////////////////////////////// -- + //////////////////////////////////////////////////////////////////////////////// +-// BSP-public ++// Global BSP driver instances + //////////////////////////////////////////////////////////////////////////////// + -/// The main struct. -pub struct QEMUOutput { - inner: NullLock, @@ -606,7 +614,15 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs - } - } -} -- ++static GPIO: driver::GPIO = unsafe { driver::GPIO::new(memory_map::mmio::GPIO_BASE) }; ++static MINI_UART: driver::MiniUart = ++ unsafe { driver::MiniUart::new(memory_map::mmio::MINI_UART_BASE) }; + + //////////////////////////////////////////////////////////////////////////////// +-// OS interface implementations ++// Implementation of the kernel's BSP calls + //////////////////////////////////////////////////////////////////////////////// + -/// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded -/// by a Mutex to serialize access. -impl interface::console::Write for QEMUOutput { @@ -616,10 +632,13 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs - // Fully qualified syntax for the call to - // `core::fmt::Write::write:fmt()` to increase readability. - let mut r = &self.inner; -- r.lock(|i| fmt::Write::write_fmt(i, args)) +- r.lock(|inner| fmt::Write::write_fmt(inner, args)) - } --} -- ++/// Board identification. ++pub fn board_name() -> &'static str { ++ "Raspberry Pi 3" + } + -impl interface::console::Read for QEMUOutput {} - -impl interface::console::Statistics for QEMUOutput { @@ -627,30 +646,18 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs - use interface::sync::Mutex; - - let mut r = &self.inner; -- r.lock(|i| i.chars_written) +- r.lock(|inner| inner.chars_written) - } --} -- - //////////////////////////////////////////////////////////////////////////////// --// Global instances -+// Global BSP driver instances - //////////////////////////////////////////////////////////////////////////////// ++/// Return a reference to a `console::All` implementation. ++pub fn console() -> &'static impl interface::console::All { ++ &MINI_UART + } +-//////////////////////////////////////////////////////////////////////////////// +-// Global instances +-//////////////////////////////////////////////////////////////////////////////// +- -static QEMU_OUTPUT: QEMUOutput = QEMUOutput::new(); -+static GPIO: driver::GPIO = unsafe { driver::GPIO::new(memory_map::mmio::GPIO_BASE) }; -+static MINI_UART: driver::MiniUart = -+ unsafe { driver::MiniUart::new(memory_map::mmio::MINI_UART_BASE) }; - - //////////////////////////////////////////////////////////////////////////////// - // Implementation of the kernel's BSP calls -@@ -110,5 +26,15 @@ - - /// Return a reference to a `console::All` implementation. - pub fn console() -> &'static impl interface::console::All { -- &QEMU_OUTPUT -+ &MINI_UART -+} -+ +/// Return an array of references to all `DeviceDriver` compatible `BSP` +/// drivers. +/// @@ -659,6 +666,29 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs +/// The order of devices is the order in which `DeviceDriver::init()` is called. +pub fn device_drivers() -> [&'static dyn interface::driver::DeviceDriver; 2] { + [&GPIO, &MINI_UART] ++} + +-//////////////////////////////////////////////////////////////////////////////// +-// Implementation of the kernel's BSP calls +-//////////////////////////////////////////////////////////////////////////////// ++/// The BSP's main initialization function. ++/// ++/// Called early on kernel start. ++pub fn init() { ++ for i in device_drivers().iter() { ++ if let Err(()) = i.init() { ++ // This message will only be readable if, at the time of failure, ++ // the return value of `bsp::console()` is already in functioning ++ // state. ++ panic!("Error loading driver: {}", i.compatible()) ++ } ++ } + +-/// Return a reference to a `console::All` implementation. +-pub fn console() -> &'static impl interface::console::All { +- &QEMU_OUTPUT ++ // Configure MiniUart's output pins. ++ GPIO.map_mini_uart(); } diff -uNr 05_safe_globals/src/bsp.rs 06_drivers_gpio_uart/src/bsp.rs @@ -702,33 +732,26 @@ diff -uNr 05_safe_globals/src/interface.rs 06_drivers_gpio_uart/src/interface.rs diff -uNr 05_safe_globals/src/main.rs 06_drivers_gpio_uart/src/main.rs --- 05_safe_globals/src/main.rs +++ 06_drivers_gpio_uart/src/main.rs -@@ -38,10 +38,27 @@ +@@ -38,10 +38,19 @@ fn kernel_entry() -> ! { use interface::console::Statistics; -+ // Initialize the BSP's device drivers. -+ for i in bsp::device_drivers().iter() { -+ if let Err(()) = i.init() { -+ // This message will only be readable if, at the time of failure, -+ // the return value of `bsp::console()` is already in functioning -+ // state. -+ panic!("Error loading driver: {}", i.compatible()) -+ } -+ } -+ -+ // If all drivers are loaded, UART is functional now and `println!()` calls -+ // are transmitted on the physical wires. - println!("[0] Hello from pure Rust!"); +- println!("[0] Hello from pure Rust!"); ++ // Run the BSP's initialization code. ++ bsp::init(); - println!("[1] Chars written: {}", bsp::console().chars_written()); -+ println!("[1] Drivers probed:"); ++ // UART should be functional now and `println!()` calls are transmitted on ++ // the physical wires. ++ println!("[0] Booting on: <{}>.", bsp::board_name()); + +- println!("[2] Stopping here."); ++ println!("[1] Drivers loaded:"); + for (i, driver) in bsp::device_drivers().iter().enumerate() { -+ println!(" {}. {}", i + 1, driver.compatible()); ++ println!(" {}. {}", i + 1, driver.compatible()); + } + + println!("[2] Chars written: {}", bsp::console().chars_written()); - -- println!("[2] Stopping here."); + println!("[3] Stopping here."); arch::wait_forever() } diff --git a/06_drivers_gpio_uart/kernel b/06_drivers_gpio_uart/kernel index 66c2a81ca5885a29ed1e0290ee91e31d45eefcd6..b5b938e729dd2737d6fa4bc362153652830fce15 100755 GIT binary patch delta 6807 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 delta 1837 zcmaJ>T})g>6h3n=%PtEPR4anlK%bM)U#np&5(`NFQp95$Fs4rcG6NXyPp-W*2I0g8bYXyPmoCZmBPwWbVwI zpYMF<%$cj6m_0FGc=mk)6ACE5B%0*gX#lf!oW5|7o?a}cTf-SV2hZEDr1QUJ_e}hA z!i7z&6X?*}LFxsTA_((Dv$XsJmv)&^IQ44$xuWtM_(T)rn+xO z2~{!H8v1W#ffn~#xQ&doMs}tXQE|1b!9mRXJzo>qe~V@srvkGjOtkBKS6v-p6$B zgYIAu0W1PXqrkU&t$d8NNUpAi!-fYk6D(qABx<{ZY_`0hZIoHKV6%;EB7%(swNJ|E zDS2l7ljZMXKS{3aP$>;tMp`?eOb@iewx#vwGc7P73Z!Cj1o1T)Xd(Mko+rPu>6A?} z$v(8W$rbj6C6uj{(gpc7?4XeLJu>`(X_i3L-2z_;iTk9n+MA6vy~kM7!p5q~?h2tZ z5MWm1U|Yn_#aT~mn@a%agiJrb3wuI#Gm$tq@HlZ*yb9qbu6`6F!^7ev6LvYZIUumz z9~sz*F>?E{AGBM5wUXgFVvdXc^$|A}FY5GYkh!hSvU0i+5ce!|{k}S}^Su%mm5(<8 z?o;^M7|?pwZgoXRgZpJhrErR+gQh=|#WETzlk|3vMGdD)d?xC@iKBw9j1!)&Jc52I zs9{RB!y&#VlNnXE&D@jIW;7YFaYI@rfn1TUm?AZH-`f7%g<`rXBQbx9{_uTaKWnqq zRgwyNzxErhA{`agv1^2H1T4NQ38QKWnc%-9WKg{~KVv^bB-PKd?2Q#+H%&)!88}4) zY+z!&)o%JhLx8@7Rfu8V#jqbeQ`KzPUPbnucheuF$u)F1r-pu#Gyfptrc^vqOFia2 ziKIcTrHB4^K01FV>jgrpS-#_A;=ym}{9T8`A~n>ozYhK(g@SCw*^IRUmY!eK;lj$| zIH-RCh9aGT^WmQUs>qNo37UGOua5wJGjX;ZX;)5l_w@}ZZ$t*pD}$FJ-Ae1Fp^F~8 zcQKN<`K-m2lQ|d}c)h!;PS=gI3$C2X7hi5ZTcsGrH_R9*hAS+XXURM-u{l?nW6zZ0 zuUQ{UERND6c?SQabd`DXoQ_r5klvMyb&56T)kgv%$Av>@IC2a0h=uR*)dUQDE%hH Tx9qJ$S4jtR6glzhE2{kusKXpa diff --git a/06_drivers_gpio_uart/src/bsp/driver.rs b/06_drivers_gpio_uart/src/bsp/driver.rs index a56b1632..b61d865b 100644 --- a/06_drivers_gpio_uart/src/bsp/driver.rs +++ b/06_drivers_gpio_uart/src/bsp/driver.rs @@ -5,13 +5,7 @@ //! Drivers. #[cfg(feature = "bsp_rpi3")] -mod bcm2837_gpio; +mod bcm; #[cfg(feature = "bsp_rpi3")] -mod bcm2xxx_mini_uart; - -#[cfg(feature = "bsp_rpi3")] -pub use bcm2837_gpio::GPIO; - -#[cfg(feature = "bsp_rpi3")] -pub use bcm2xxx_mini_uart::MiniUart; +pub use bcm::*; diff --git a/06_drivers_gpio_uart/src/bsp/driver/bcm.rs b/06_drivers_gpio_uart/src/bsp/driver/bcm.rs new file mode 100644 index 00000000..bd30e930 --- /dev/null +++ b/06_drivers_gpio_uart/src/bsp/driver/bcm.rs @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +// +// Copyright (c) 2018-2019 Andre Richter + +//! BCM driver top level. + +mod bcm2837_gpio; +mod bcm2xxx_mini_uart; + +pub use bcm2837_gpio::GPIO; +pub use bcm2xxx_mini_uart::MiniUart; diff --git a/06_drivers_gpio_uart/src/bsp/driver/bcm2837_gpio.rs b/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2837_gpio.rs similarity index 88% rename from 06_drivers_gpio_uart/src/bsp/driver/bcm2837_gpio.rs rename to 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2837_gpio.rs index ef357b43..195973b1 100644 --- a/06_drivers_gpio_uart/src/bsp/driver/bcm2837_gpio.rs +++ b/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2837_gpio.rs @@ -21,8 +21,7 @@ register_bitfields! { FSEL15 OFFSET(15) NUMBITS(3) [ Input = 0b000, Output = 0b001, - RXD0 = 0b100, // UART0 - Alternate function 0 - RXD1 = 0b010 // Mini UART - Alternate function 5 + AltFunc5 = 0b010 // Mini UART RX ], @@ -30,8 +29,7 @@ register_bitfields! { FSEL14 OFFSET(12) NUMBITS(3) [ Input = 0b000, Output = 0b001, - TXD0 = 0b100, // UART0 - Alternate function 0 - TXD1 = 0b010 // Mini UART - Alternate function 5 + AltFunc5 = 0b010 // Mini UART TX ] ], @@ -108,10 +106,10 @@ impl GPIOInner { /// /// TX to pin 14 /// RX to pin 15 - fn map_mini_uart(&mut self) { + pub fn map_mini_uart(&mut self) { // Map to pins. self.GPFSEL1 - .modify(GPFSEL1::FSEL14::TXD1 + GPFSEL1::FSEL15::RXD1); + .modify(GPFSEL1::FSEL14::AltFunc5 + GPFSEL1::FSEL15::AltFunc5); // Enable pins 14 and 15. self.GPPUD.set(0); @@ -130,10 +128,11 @@ impl GPIOInner { } //////////////////////////////////////////////////////////////////////////////// -// OS interface implementations +// BSP-public //////////////////////////////////////////////////////////////////////////////// +use interface::sync::Mutex; -/// The driver's public data. +/// The driver's main struct. pub struct GPIO { inner: NullLock, } @@ -144,19 +143,20 @@ impl GPIO { inner: NullLock::new(GPIOInner::new(base_addr)), } } + + // Only visible to other BSP code. + pub fn map_mini_uart(&self) { + let mut r = &self.inner; + r.lock(|inner| inner.map_mini_uart()); + } } +//////////////////////////////////////////////////////////////////////////////// +// OS interface implementations +//////////////////////////////////////////////////////////////////////////////// + impl interface::driver::DeviceDriver for GPIO { fn compatible(&self) -> &str { "GPIO" } - - fn init(&self) -> interface::driver::Result { - use interface::sync::Mutex; - - let mut r = &self.inner; - r.lock(|i| i.map_mini_uart()); - - Ok(()) - } } diff --git a/06_drivers_gpio_uart/src/bsp/driver/bcm2xxx_mini_uart.rs b/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs similarity index 85% rename from 06_drivers_gpio_uart/src/bsp/driver/bcm2xxx_mini_uart.rs rename to 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs index f8504ead..503d9b94 100644 --- a/06_drivers_gpio_uart/src/bsp/driver/bcm2xxx_mini_uart.rs +++ b/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs @@ -139,27 +139,6 @@ impl MiniUartInner { self.base_addr as *const _ } - /// Set up baud rate and characteristics (115200 8N1). - fn init(&mut self) -> interface::driver::Result { - self.AUX_ENABLES.modify(AUX_ENABLES::MINI_UART_ENABLE::SET); - self.AUX_MU_IER.set(0); - self.AUX_MU_CNTL.set(0); - self.AUX_MU_LCR.write(AUX_MU_LCR::DATA_SIZE::EightBit); - self.AUX_MU_MCR.set(0); - self.AUX_MU_IER.set(0); - self.AUX_MU_IIR.write(AUX_MU_IIR::FIFO_CLEAR::All); - self.AUX_MU_BAUD.write(AUX_MU_BAUD::RATE.val(270)); // 115200 baud - - // Enable receive and send. - self.AUX_MU_CNTL - .write(AUX_MU_CNTL::RX_EN::Enabled + AUX_MU_CNTL::TX_EN::Enabled); - - // Clear FIFOs before using the device. - self.AUX_MU_IIR.write(AUX_MU_IIR::FIFO_CLEAR::All); - - Ok(()) - } - /// Send a character. fn write_char(&mut self, c: char) { // Wait until we can send. @@ -204,7 +183,7 @@ impl fmt::Write for MiniUartInner { } //////////////////////////////////////////////////////////////////////////////// -// OS interface implementations +// BSP-public //////////////////////////////////////////////////////////////////////////////// /// The driver's main struct. @@ -223,16 +202,38 @@ impl MiniUart { } } +//////////////////////////////////////////////////////////////////////////////// +// OS interface implementations +//////////////////////////////////////////////////////////////////////////////// +use interface::sync::Mutex; + impl interface::driver::DeviceDriver for MiniUart { fn compatible(&self) -> &str { "MiniUart" } + /// Set up baud rate and characteristics (115200 8N1). fn init(&self) -> interface::driver::Result { - use interface::sync::Mutex; - let mut r = &self.inner; - r.lock(|i| i.init()) + r.lock(|inner| { + // Enable register access to the MiniUart + inner.AUX_ENABLES.modify(AUX_ENABLES::MINI_UART_ENABLE::SET); + inner.AUX_MU_IER.set(0); // disable RX and TX interrupts + inner.AUX_MU_CNTL.set(0); // disable send and receive + inner.AUX_MU_LCR.write(AUX_MU_LCR::DATA_SIZE::EightBit); + inner.AUX_MU_BAUD.write(AUX_MU_BAUD::RATE.val(270)); // 115200 baud + inner.AUX_MU_MCR.set(0); // set "ready to send" high + + // Clear FIFOs before using the device. + inner.AUX_MU_IIR.write(AUX_MU_IIR::FIFO_CLEAR::All); + + // Enable receive and send. + inner + .AUX_MU_CNTL + .write(AUX_MU_CNTL::RX_EN::Enabled + AUX_MU_CNTL::TX_EN::Enabled); + }); + + Ok(()) } } @@ -240,12 +241,10 @@ impl interface::driver::DeviceDriver for MiniUart { /// by a Mutex to serialize access. impl interface::console::Write for MiniUart { fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result { - use interface::sync::Mutex; - // Fully qualified syntax for the call to // `core::fmt::Write::write:fmt()` to increase readability. let mut r = &self.inner; - r.lock(|i| fmt::Write::write_fmt(i, args)) + r.lock(|inner| fmt::Write::write_fmt(inner, args)) } } @@ -253,9 +252,7 @@ impl interface::console::Read for MiniUart {} impl interface::console::Statistics for MiniUart { fn chars_written(&self) -> usize { - use interface::sync::Mutex; - let mut r = &self.inner; - r.lock(|i| i.chars_written) + r.lock(|inner| inner.chars_written) } } diff --git a/06_drivers_gpio_uart/src/bsp/rpi3.rs b/06_drivers_gpio_uart/src/bsp/rpi3.rs index 2c41c552..88a54894 100644 --- a/06_drivers_gpio_uart/src/bsp/rpi3.rs +++ b/06_drivers_gpio_uart/src/bsp/rpi3.rs @@ -24,6 +24,11 @@ static MINI_UART: driver::MiniUart = // Implementation of the kernel's BSP calls //////////////////////////////////////////////////////////////////////////////// +/// Board identification. +pub fn board_name() -> &'static str { + "Raspberry Pi 3" +} + /// Return a reference to a `console::All` implementation. pub fn console() -> &'static impl interface::console::All { &MINI_UART @@ -38,3 +43,20 @@ pub fn console() -> &'static impl interface::console::All { pub fn device_drivers() -> [&'static dyn interface::driver::DeviceDriver; 2] { [&GPIO, &MINI_UART] } + +/// The BSP's main initialization function. +/// +/// Called early on kernel start. +pub fn init() { + for i in device_drivers().iter() { + if let Err(()) = i.init() { + // This message will only be readable if, at the time of failure, + // the return value of `bsp::console()` is already in functioning + // state. + panic!("Error loading driver: {}", i.compatible()) + } + } + + // Configure MiniUart's output pins. + GPIO.map_mini_uart(); +} diff --git a/06_drivers_gpio_uart/src/main.rs b/06_drivers_gpio_uart/src/main.rs index 10e8f2ef..41ceb28d 100644 --- a/06_drivers_gpio_uart/src/main.rs +++ b/06_drivers_gpio_uart/src/main.rs @@ -38,27 +38,19 @@ mod print; fn kernel_entry() -> ! { use interface::console::Statistics; - // Initialize the BSP's device drivers. - for i in bsp::device_drivers().iter() { - if let Err(()) = i.init() { - // This message will only be readable if, at the time of failure, - // the return value of `bsp::console()` is already in functioning - // state. - panic!("Error loading driver: {}", i.compatible()) - } - } + // Run the BSP's initialization code. + bsp::init(); - // If all drivers are loaded, UART is functional now and `println!()` calls - // are transmitted on the physical wires. - println!("[0] Hello from pure Rust!"); + // UART should be functional now and `println!()` calls are transmitted on + // the physical wires. + println!("[0] Booting on: <{}>.", bsp::board_name()); - println!("[1] Drivers probed:"); + println!("[1] Drivers loaded:"); for (i, driver) in bsp::device_drivers().iter().enumerate() { - println!(" {}. {}", i + 1, driver.compatible()); + println!(" {}. {}", i + 1, driver.compatible()); } println!("[2] Chars written: {}", bsp::console().chars_written()); - println!("[3] Stopping here."); arch::wait_forever() }