aboutsummaryrefslogtreecommitdiff
path: root/src/bsp
diff options
context:
space:
mode:
authorChristian Cunningham <cc@localhost>2022-08-26 17:25:34 -0700
committerChristian Cunningham <cc@localhost>2022-08-26 17:25:34 -0700
commita04cf2dbb8d2e890405fbf0a1022aaad3015b1e8 (patch)
tree381892074d13c059d50cb88caa41f8a8722c07ce /src/bsp
parent7f3d7d9ce9818078b6a4616b4c31a28e2868397b (diff)
Modularize
Diffstat (limited to 'src/bsp')
-rw-r--r--src/bsp/drivers/gpio/mod.rs28
-rw-r--r--src/bsp/drivers/mod.rs2
-rw-r--r--src/bsp/drivers/uart/console.rs112
-rw-r--r--src/bsp/drivers/uart/mod.rs119
-rw-r--r--src/bsp/mod.rs1
5 files changed, 262 insertions, 0 deletions
diff --git a/src/bsp/drivers/gpio/mod.rs b/src/bsp/drivers/gpio/mod.rs
new file mode 100644
index 0000000..a94c6e5
--- /dev/null
+++ b/src/bsp/drivers/gpio/mod.rs
@@ -0,0 +1,28 @@
+/// # GPIO Register
+pub mod GPPUD {
+ const ADDR: u32 = 0x3F200094;
+ pub fn set(v: u32) {
+ use crate::cpu::store32;
+ store32(ADDR, v)
+ }
+ pub fn clear() {
+ set(0)
+ }
+}
+/// # GPIO Clock 0 Register
+pub mod GPPUDCLK0 {
+ const ADDR: u32 = 0x3F200098;
+ const MASK: u32 = (1 << 14) | (1 << 15);
+ pub fn set(v: u32) {
+ use crate::cpu::store32;
+ store32(ADDR, v)
+ }
+ pub fn init() {
+ use crate::cpu::spin_for_n_cycles;
+ super::GPPUD::clear();
+ spin_for_n_cycles(150);
+ set(MASK);
+ spin_for_n_cycles(150);
+ set(0);
+ }
+}
diff --git a/src/bsp/drivers/mod.rs b/src/bsp/drivers/mod.rs
new file mode 100644
index 0000000..eda17fa
--- /dev/null
+++ b/src/bsp/drivers/mod.rs
@@ -0,0 +1,2 @@
+mod gpio;
+pub mod uart;
diff --git a/src/bsp/drivers/uart/console.rs b/src/bsp/drivers/uart/console.rs
new file mode 100644
index 0000000..e3ee2f2
--- /dev/null
+++ b/src/bsp/drivers/uart/console.rs
@@ -0,0 +1,112 @@
+//! # UART Console Definition
+use super::*;
+use crate::bsp::drivers::gpio::*;
+use crate::cpu::*;
+use crate::lib::sync::interface::Mutex;
+use crate::lib::sync::SpinLock;
+use core::fmt;
+
+/// # UART Inner Structure
+///
+/// Keeps record of the console statistics.
+struct UartInner {
+ chars_written: usize,
+}
+
+/// # UART Structure
+///
+/// Wraps the UART writer in a sharable lock.
+pub struct Uart {
+ inner: SpinLock<UartInner>,
+}
+
+impl UartInner {
+ /// # Clear statistics
+ ///
+ /// Create the writer with cleared statistics
+ pub const fn new() -> Self {
+ Self { chars_written: 0 }
+ }
+
+ /// # Initialize the UART setup
+ ///
+ /// Set baud rate and timings
+ pub fn init(&mut self) {
+ UART::CR::off();
+ GPPUDCLK0::init();
+ UART::ICR::clear();
+ UART::IBRD::set(9);
+ UART::FBRD::set(49);
+ UART::LCRH::enable8();
+ UART::IMSC::mask();
+ UART::CR::all_on();
+ }
+
+ /// # Write `char` to UART
+ fn write_char(&mut self, ch: char) {
+ while UART::FR::TXFF::is_set() {
+ nop();
+ }
+ UART::DR::set(ch);
+ self.chars_written += 1;
+ }
+
+ /// # Flush UART
+ fn flush(&self) {
+ while UART::FR::BUSY::is_set() {
+ nop();
+ }
+ }
+}
+
+impl fmt::Write for UartInner {
+ /// # Write string to UART console
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ for c in s.chars() {
+ self.write_char(c);
+ }
+ Ok(())
+ }
+}
+
+impl Uart {
+ /// # Create sharable UART wrapper
+ pub const fn new() -> Self {
+ Self {
+ inner: SpinLock::new(UartInner::new()),
+ }
+ }
+
+ /// # Call UART initialization
+ pub fn init(&self) -> Result<(), &'static str> {
+ self.inner.lock(|inner| inner.init());
+ Ok(())
+ }
+}
+
+impl crate::lib::console::interface::Write for Uart {
+ /// # Write `char` to UART
+ fn write_char(&self, c: char) {
+ self.inner.lock(|inner| inner.write_char(c));
+ }
+
+ /// # Write formatted string to UART
+ fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
+ self.inner.lock(|inner| fmt::Write::write_fmt(inner, args))
+ }
+
+ /// # Flush UART
+ fn flush(&self) {
+ self.inner.lock(|inner| inner.flush());
+ }
+}
+
+impl crate::lib::console::interface::Statistics for Uart {
+ /// # Get `char` written stats
+ fn chars_written(&self) -> usize {
+ self.inner.lock(|inner| inner.chars_written)
+ }
+}
+
+/// # UART Writer + Stats
+impl crate::lib::console::interface::All for Uart {}
diff --git a/src/bsp/drivers/uart/mod.rs b/src/bsp/drivers/uart/mod.rs
new file mode 100644
index 0000000..ad11e12
--- /dev/null
+++ b/src/bsp/drivers/uart/mod.rs
@@ -0,0 +1,119 @@
+/// # UART Registers
+pub mod UART {
+ /// # Flag Register
+ pub mod FR {
+ pub mod BUSY {
+ const MASK: u32 = 1 << 3;
+ pub fn is_set() -> bool {
+ super::read() & MASK != 0
+ }
+
+ pub fn is_clear() -> bool {
+ !is_set()
+ }
+ }
+ pub mod TXFF {
+ const MASK: u32 = 1 << 5;
+ pub fn is_set() -> bool {
+ super::read() & MASK != 0
+ }
+
+ pub fn is_clear() -> bool {
+ !is_set()
+ }
+ }
+ const ADDR: u32 = 0x3F201018;
+ //pub const TXFF: u32 = 1 << 5;
+ pub fn read() -> u32 {
+ use crate::cpu::load32;
+ load32(ADDR)
+ }
+ }
+ /// # Data Register
+ pub mod DR {
+ const ADDR: u32 = 0x3F201000;
+ pub fn set(c: char) {
+ use crate::cpu::store32;
+ store32(ADDR, c as u32);
+ }
+ }
+ /// # Control Register
+ pub mod CR {
+ const ADDR: u32 = 0x3F201030;
+ const UART_ENABLE: u32 = 1 << 0;
+ const TX_ENABLE: u32 = 1 << 8;
+ const RX_ENABLE: u32 = 1 << 9;
+ pub fn set(v: u32) {
+ use crate::cpu::store32;
+ store32(ADDR, v);
+ }
+ pub fn off() {
+ set(0);
+ }
+ pub fn all_on() {
+ set(UART_ENABLE + TX_ENABLE + RX_ENABLE)
+ }
+ }
+ /// # Integer Baud Rate
+ pub mod IBRD {
+ const ADDR: u32 = 0x3F201024;
+ pub fn set(v: u32) {
+ use crate::cpu::store32;
+ store32(ADDR, v);
+ }
+ }
+ /// # Fractional Baud Rate
+ pub mod FBRD {
+ const ADDR: u32 = 0x3F201028;
+ pub fn set(v: u32) {
+ use crate::cpu::store32;
+ store32(ADDR, v);
+ }
+ }
+ /// # Interrupt Control Register
+ pub mod ICR {
+ const ADDR: u32 = 0x3F201044;
+ pub fn set(v: u32) {
+ use crate::cpu::store32;
+ store32(ADDR, v);
+ }
+ pub fn clear() {
+ set(0x7FF);
+ }
+ }
+ /// # Line Control Register
+ pub mod LCRH {
+ const ADDR: u32 = 0x3F20102C;
+ const FIFO_ENABLE: u32 = 1 << 4;
+ const FIVE_BIT: u32 = 0b00 << 5;
+ const SIX_BIT: u32 = 0b01 << 5;
+ const SEVEN_BIT: u32 = 0b10 << 5;
+ const EIGHT_BIT: u32 = 0b11 << 5;
+ pub fn set(v: u32) {
+ use crate::cpu::store32;
+ store32(ADDR, v);
+ }
+ pub fn enable8() {
+ set(FIFO_ENABLE + EIGHT_BIT);
+ }
+ }
+ /// # Interrupt Mask Set/ Clear Register
+ pub mod IMSC {
+ const ADDR: u32 = 0x3F201038;
+ const MASK: u32 =
+ (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10);
+ pub fn set(v: u32) {
+ use crate::cpu::store32;
+ store32(ADDR, v);
+ }
+ pub fn mask() {
+ set(MASK);
+ }
+ }
+}
+
+mod console;
+pub use console::*;
+
+/// # Public reference to console.
+pub static UART_WRITER: Uart = Uart::new();
diff --git a/src/bsp/mod.rs b/src/bsp/mod.rs
new file mode 100644
index 0000000..2c554a7
--- /dev/null
+++ b/src/bsp/mod.rs
@@ -0,0 +1 @@
+pub mod drivers;