From b8ad0a71e1f0b3b45e6ff85e28fedc98d9a780fd Mon Sep 17 00:00:00 2001 From: elliott10 Date: Mon, 31 Jul 2023 15:25:02 +0800 Subject: [PATCH] Optimized code for bsta1000b board --- Cargo.toml | 1 + crates/dw_apb_uart/Cargo.toml | 10 ++ crates/dw_apb_uart/src/dw_apb_uart.rs | 116 +++++++++++++++ crates/dw_apb_uart/src/lib.rs | 4 + modules/axhal/Cargo.toml | 1 + .../platform/aarch64_bsta1000b/dw_apb_uart.rs | 137 ++---------------- .../aarch64_bsta1000b/{utils.rs => misc.rs} | 19 +-- .../src/platform/aarch64_bsta1000b/mod.rs | 6 +- .../axhal/src/platform/aarch64_common/psci.rs | 3 +- scripts/make/bsta1000b-fada.mk | 2 +- .../bsta1000b}/bsta1000b-fada-arceos.its | 0 .../bsta1000b}/bsta1000b-fada.dtb | Bin 12 files changed, 154 insertions(+), 145 deletions(-) create mode 100644 crates/dw_apb_uart/Cargo.toml create mode 100644 crates/dw_apb_uart/src/dw_apb_uart.rs create mode 100644 crates/dw_apb_uart/src/lib.rs rename modules/axhal/src/platform/aarch64_bsta1000b/{utils.rs => misc.rs} (83%) rename {scripts/bsta1000b-fada => tools/bsta1000b}/bsta1000b-fada-arceos.its (100%) rename {scripts/bsta1000b-fada => tools/bsta1000b}/bsta1000b-fada.dtb (100%) diff --git a/Cargo.toml b/Cargo.toml index 9c3d3d5a6d..17dc95fca1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ members = [ "crates/allocator", "crates/arm_gic", "crates/arm_pl011", + "crates/dw_apb_uart", "crates/axerrno", "crates/axfs_devfs", "crates/axfs_ramfs", diff --git a/crates/dw_apb_uart/Cargo.toml b/crates/dw_apb_uart/Cargo.toml new file mode 100644 index 0000000000..490d71267f --- /dev/null +++ b/crates/dw_apb_uart/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "dw_apb_uart" +authors = ["Luoyuan Xiao "] +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +tock-registers = "0.8" diff --git a/crates/dw_apb_uart/src/dw_apb_uart.rs b/crates/dw_apb_uart/src/dw_apb_uart.rs new file mode 100644 index 0000000000..c5982cb72f --- /dev/null +++ b/crates/dw_apb_uart/src/dw_apb_uart.rs @@ -0,0 +1,116 @@ +//! snps,dw-apb-uart serial driver + +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_structs, + registers::{ReadOnly, ReadWrite}, +}; + +register_structs! { + DW8250Regs { + /// Get or Put Register. + (0x00 => rbr: ReadWrite), + (0x04 => ier: ReadWrite), + (0x08 => fcr: ReadWrite), + (0x0c => lcr: ReadWrite), + (0x10 => mcr: ReadWrite), + (0x14 => lsr: ReadOnly), + (0x18 => msr: ReadOnly), + (0x1c => scr: ReadWrite), + (0x20 => lpdll: ReadWrite), + (0x24 => _reserved0), + /// Uart Status Register. + (0x7c => usr: ReadOnly), + (0x80 => _reserved1), + (0xc0 => dlf: ReadWrite), + (0xc4 => @END), + } +} + +/// dw-apb-uart serial driver: DW8250 +pub struct DW8250 { + base_vaddr: usize, +} + +impl DW8250 { + /// New a DW8250 + pub const fn new(base_vaddr: usize) -> Self { + Self { base_vaddr } + } + + const fn regs(&self) -> &DW8250Regs { + unsafe { &*(self.base_vaddr as *const _) } + } + + /// DW8250 initialize + pub fn init(&mut self) { + const UART_SRC_CLK: u32 = 25000000; + const BST_UART_DLF_LEN: u32 = 6; + const BAUDRATE: u32 = 115200; + //const BAUDRATE: u32 = 38400; + + let get_baud_divider = |baudrate| (UART_SRC_CLK << (BST_UART_DLF_LEN - 4)) / baudrate; + let divider = get_baud_divider(BAUDRATE); + + // Waiting to be no USR_BUSY. + while self.regs().usr.get() & 0b1 != 0 {} + + // bst_serial_hw_init_clk_rst + + /* Disable interrupts and Enable FIFOs */ + self.regs().ier.set(0); + self.regs().fcr.set(1); + + /* Disable flow ctrl */ + self.regs().mcr.set(0); + + /* Clear MCR_RTS */ + self.regs().mcr.set(self.regs().mcr.get() | (1 << 1)); + + /* Enable access DLL & DLH. Set LCR_DLAB */ + self.regs().lcr.set(self.regs().lcr.get() | (1 << 7)); + + /* Set baud rate. Set DLL, DLH, DLF */ + self.regs().rbr.set((divider >> BST_UART_DLF_LEN) & 0xff); + self.regs() + .ier + .set((divider >> (BST_UART_DLF_LEN + 8)) & 0xff); + self.regs().dlf.set(divider & ((1 << BST_UART_DLF_LEN) - 1)); + + /* Clear DLAB bit */ + self.regs().lcr.set(self.regs().lcr.get() & !(1 << 7)); + + /* Set data length to 8 bit, 1 stop bit, no parity. Set LCR_WLS1 | LCR_WLS0 */ + self.regs().lcr.set(self.regs().lcr.get() | 0b11); + } + + /// DW8250 serial output + pub fn putchar(&mut self, c: u8) { + // Check LSR_TEMT + // Wait for last character to go. + while self.regs().lsr.get() & (1 << 6) == 0 {} + self.regs().rbr.set(c as u32); + } + + /// DW8250 serial input + pub fn getchar(&mut self) -> Option { + // Check LSR_DR + // Wait for a character to arrive. + if self.regs().lsr.get() & 0b1 != 0 { + Some((self.regs().rbr.get() & 0xff) as u8) + } else { + None + } + } + + /// DW8250 serial interrupt enable or disable + pub fn set_ier(&mut self, enable: bool) { + if enable { + // Enable interrupts + self.regs().ier.set(1); + } else { + // Disable interrupts + self.regs().ier.set(0); + } + } +} diff --git a/crates/dw_apb_uart/src/lib.rs b/crates/dw_apb_uart/src/lib.rs new file mode 100644 index 0000000000..c19410922a --- /dev/null +++ b/crates/dw_apb_uart/src/lib.rs @@ -0,0 +1,4 @@ +//! Definitions for snps,dw-apb-uart serial +#![no_std] + +pub mod dw_apb_uart; diff --git a/modules/axhal/Cargo.toml b/modules/axhal/Cargo.toml index 12af1d923b..13afcf21df 100644 --- a/modules/axhal/Cargo.toml +++ b/modules/axhal/Cargo.toml @@ -49,6 +49,7 @@ aarch64-cpu = "9.3" tock-registers = "0.8" arm_gic = { path = "../../crates/arm_gic" } arm_pl011 = { path = "../../crates/arm_pl011" } +dw_apb_uart = { path = "../../crates/dw_apb_uart" } [build-dependencies] axconfig = { path = "../axconfig" } diff --git a/modules/axhal/src/platform/aarch64_bsta1000b/dw_apb_uart.rs b/modules/axhal/src/platform/aarch64_bsta1000b/dw_apb_uart.rs index dfb72caf29..3981fb1f61 100644 --- a/modules/axhal/src/platform/aarch64_bsta1000b/dw_apb_uart.rs +++ b/modules/axhal/src/platform/aarch64_bsta1000b/dw_apb_uart.rs @@ -1,133 +1,13 @@ //! snps,dw-apb-uart serial driver -use memory_addr::{PhysAddr, VirtAddr}; -use spinlock::SpinNoIrq; -use tock_registers::interfaces::{Readable, Writeable}; -use tock_registers::register_structs; -use tock_registers::registers::{ReadOnly, ReadWrite}; - use crate::mem::phys_to_virt; +use dw_apb_uart::dw_apb_uart::DW8250; +use memory_addr::PhysAddr; +use spinlock::SpinNoIrq; const UART_BASE: PhysAddr = PhysAddr::from(axconfig::UART_PADDR); -static UART: SpinNoIrq = SpinNoIrq::new(DW8250::new(phys_to_virt(UART_BASE))); - -register_structs! { - DW8250Regs { - /// Get or Put Register. - (0x00 => rbr: ReadWrite), - (0x04 => ier: ReadWrite), - (0x08 => fcr: ReadWrite), - (0x0c => lcr: ReadWrite), - (0x10 => mcr: ReadWrite), - (0x14 => lsr: ReadOnly), - (0x18 => msr: ReadOnly), - (0x1c => scr: ReadWrite), - (0x20 => lpdll: ReadWrite), - (0x24 => _reserved0), - /// Uart Status Register. - (0x7c => usr: ReadOnly), - (0x80 => _reserved1), - (0xc0 => dlf: ReadWrite), - (0xc4 => @END), - } -} - -struct DW8250 { - base_vaddr: VirtAddr, -} - -impl DW8250 { - const fn new(base_vaddr: VirtAddr) -> Self { - Self { base_vaddr } - } - - const fn regs(&self) -> &DW8250Regs { - unsafe { &*(self.base_vaddr.as_ptr() as *const _) } - } - - fn init(&mut self) { - const UART_SRC_CLK: u32 = 25000000; - const BST_UART_DLF_LEN: u32 = 6; - const BAUDRATE: u32 = 115200; - //const BAUDRATE: u32 = 38400; - - let get_baud_divider = |baudrate| (UART_SRC_CLK << (BST_UART_DLF_LEN - 4)) / baudrate; - let divider = get_baud_divider(BAUDRATE); - - // Waiting to be no USR_BUSY. - while self.regs().usr.get() & 0b1 != 0 {} - - // bst_serial_hw_init_clk_rst - - /* Disable interrupts and Enable FIFOs */ - self.regs().ier.set(0); - self.regs().fcr.set(1); - - /* Disable flow ctrl */ - self.regs().mcr.set(0); - - /* Clear MCR_RTS */ - self.regs().mcr.set(self.regs().mcr.get() | (1 << 1)); - - /* Enable access DLL & DLH. Set LCR_DLAB */ - self.regs().lcr.set(self.regs().lcr.get() | (1 << 7)); - - dmb(); - - /* Set baud rate. Set DLL, DLH, DLF */ - self.regs().rbr.set((divider >> BST_UART_DLF_LEN) & 0xff); - self.regs() - .ier - .set((divider >> (BST_UART_DLF_LEN + 8)) & 0xff); - self.regs().dlf.set(divider & ((1 << BST_UART_DLF_LEN) - 1)); - - /* Clear DLAB bit */ - self.regs().lcr.set(self.regs().lcr.get() & !(1 << 7)); - - dmb(); - - /* Set data length to 8 bit, 1 stop bit, no parity. Set LCR_WLS1 | LCR_WLS0 */ - self.regs().lcr.set(self.regs().lcr.get() | 0b11); - - dmb(); - } - - fn putchar(&mut self, c: u8) { - // Check LSR_TEMT - // Wait for last character to go. - while self.regs().lsr.get() & (1 << 6) == 0 {} - self.regs().rbr.set(c as u32); - } - - fn getchar(&mut self) -> Option { - // Check LSR_DR - // Wait for a character to arrive. - if self.regs().lsr.get() & 0b1 != 0 { - Some((self.regs().rbr.get() & 0xff) as u8) - } else { - None - } - } - - fn set_ier(&mut self, enable: bool) { - if enable { - // Enable interrupts - self.regs().ier.set(1); - } else { - // Disable interrupts - self.regs().ier.set(0); - } - dmb(); - } -} - -/// Memory Barrier -fn dmb() { - unsafe { - core::arch::asm!("dmb sy"); - } -} +static UART: SpinNoIrq = SpinNoIrq::new(DW8250::new(phys_to_virt(UART_BASE).as_usize())); /// Writes a byte to the console. pub fn putchar(c: u8) { @@ -146,14 +26,23 @@ pub fn getchar() -> Option { UART.lock().getchar() } +/// Memory Barrier +fn dmb() { + unsafe { + core::arch::asm!("dmb sy"); + } +} + /// UART simply initialize pub fn init_early() { UART.lock().init(); + dmb(); } /// Set UART IRQ Enable pub fn init_irq() { UART.lock().set_ier(true); + dmb(); #[cfg(feature = "irq")] { diff --git a/modules/axhal/src/platform/aarch64_bsta1000b/utils.rs b/modules/axhal/src/platform/aarch64_bsta1000b/misc.rs similarity index 83% rename from modules/axhal/src/platform/aarch64_bsta1000b/utils.rs rename to modules/axhal/src/platform/aarch64_bsta1000b/misc.rs index 374ec53b87..8954132e19 100644 --- a/modules/axhal/src/platform/aarch64_bsta1000b/utils.rs +++ b/modules/axhal/src/platform/aarch64_bsta1000b/misc.rs @@ -1,18 +1,9 @@ +pub use crate::platform::aarch64_common::psci::system_off as terminate; + use crate::mem::phys_to_virt; use crate::time::{busy_wait, Duration}; use core::ptr::{read_volatile, write_volatile}; -/// 微秒(us) 延时器 -pub fn usdelay(us: u64) { - let d = Duration::from_micros(us); - busy_wait(d); -} - -/// 毫秒(ms) 延时器 -pub fn msdelay(ms: u64) { - usdelay(ms * 1000); -} - /// Do QSPI reset pub fn reset_qspi() { // qspi exit 4-byte mode @@ -23,10 +14,10 @@ pub fn reset_qspi() { let value = read_volatile(ptr); trace!("SAFETY CRM RESET CTRL = {:#x}", value); write_volatile(ptr, value & !(0b11 << 15)); - msdelay(100); + busy_wait(Duration::from_millis(100)); write_volatile(ptr, value | (0b11 << 15)); - msdelay(100); + busy_wait(Duration::from_millis(100)); } } @@ -49,7 +40,7 @@ pub fn do_reset() { axlog::ax_println!("resetting ...\n"); // wait 50 ms - msdelay(50); + busy_wait(Duration::from_millis(50)); // disable_interrupts(); diff --git a/modules/axhal/src/platform/aarch64_bsta1000b/mod.rs b/modules/axhal/src/platform/aarch64_bsta1000b/mod.rs index 4a352cb274..3bd56b56c8 100644 --- a/modules/axhal/src/platform/aarch64_bsta1000b/mod.rs +++ b/modules/axhal/src/platform/aarch64_bsta1000b/mod.rs @@ -1,7 +1,7 @@ mod dw_apb_uart; pub mod mem; -pub mod utils; +pub mod misc; #[cfg(feature = "smp")] pub mod mp; @@ -19,10 +19,6 @@ pub mod time { pub use crate::platform::aarch64_common::generic_timer::*; } -pub mod misc { - pub use crate::platform::aarch64_common::psci::system_off as terminate; -} - extern "C" { fn exception_vector_base(); fn rust_main(cpu_id: usize, dtb: usize); diff --git a/modules/axhal/src/platform/aarch64_common/psci.rs b/modules/axhal/src/platform/aarch64_common/psci.rs index 03baacf2f9..a64cf835ba 100644 --- a/modules/axhal/src/platform/aarch64_common/psci.rs +++ b/modules/axhal/src/platform/aarch64_common/psci.rs @@ -89,7 +89,7 @@ pub fn psci_cpu_on(cpuid: usize, entry_point: usize, arg: usize) -> i32 { err } -pub fn psci_cpu_off(cpuid: usize, entry_point: usize) { +pub fn psci_cpu_off(_cpuid: usize) { const PSCI_POWER_STATE_TYPE_STANDBY: u32 = 0; const PSCI_POWER_STATE_TYPE_POWER_DOWN: u32 = 1; const PSCI_0_2_POWER_STATE_TYPE_SHIFT: u32 = 16; @@ -138,6 +138,7 @@ pub fn psci_errno_tran(errno: i32) -> i32 { } /// PSCI return values, inclusive of all PSCI versions +#[allow(non_camel_case_types)] #[derive(Debug)] pub enum PsciRetNo { PSCI_RET_SUCCESS = 0, diff --git a/scripts/make/bsta1000b-fada.mk b/scripts/make/bsta1000b-fada.mk index bafcbc743d..41858f8fe6 100644 --- a/scripts/make/bsta1000b-fada.mk +++ b/scripts/make/bsta1000b-fada.mk @@ -2,5 +2,5 @@ export RUSTFLAGS fada: build gzip -9 -cvf $(OUT_BIN) > arceos-fada.bin.gz - mkimage -f scripts/bsta1000b-fada/bsta1000b-fada-arceos.its arceos-fada.itb + mkimage -f tools/bsta1000b/bsta1000b-fada-arceos.its arceos-fada.itb @echo 'Built the FIT-uImage arceos-fada.itb' diff --git a/scripts/bsta1000b-fada/bsta1000b-fada-arceos.its b/tools/bsta1000b/bsta1000b-fada-arceos.its similarity index 100% rename from scripts/bsta1000b-fada/bsta1000b-fada-arceos.its rename to tools/bsta1000b/bsta1000b-fada-arceos.its diff --git a/scripts/bsta1000b-fada/bsta1000b-fada.dtb b/tools/bsta1000b/bsta1000b-fada.dtb similarity index 100% rename from scripts/bsta1000b-fada/bsta1000b-fada.dtb rename to tools/bsta1000b/bsta1000b-fada.dtb