Skip to content

Commit

Permalink
Optimized code for bsta1000b board
Browse files Browse the repository at this point in the history
  • Loading branch information
elliott10 committed Jul 31, 2023
1 parent ca80589 commit b8ad0a7
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 145 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
10 changes: 10 additions & 0 deletions crates/dw_apb_uart/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "dw_apb_uart"
authors = ["Luoyuan Xiao <[email protected]>"]
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"
116 changes: 116 additions & 0 deletions crates/dw_apb_uart/src/dw_apb_uart.rs
Original file line number Diff line number Diff line change
@@ -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<u32>),
(0x04 => ier: ReadWrite<u32>),
(0x08 => fcr: ReadWrite<u32>),
(0x0c => lcr: ReadWrite<u32>),
(0x10 => mcr: ReadWrite<u32>),
(0x14 => lsr: ReadOnly<u32>),
(0x18 => msr: ReadOnly<u32>),
(0x1c => scr: ReadWrite<u32>),
(0x20 => lpdll: ReadWrite<u32>),
(0x24 => _reserved0),
/// Uart Status Register.
(0x7c => usr: ReadOnly<u32>),
(0x80 => _reserved1),
(0xc0 => dlf: ReadWrite<u32>),
(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<u8> {
// 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);
}
}
}
4 changes: 4 additions & 0 deletions crates/dw_apb_uart/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//! Definitions for snps,dw-apb-uart serial
#![no_std]

pub mod dw_apb_uart;
1 change: 1 addition & 0 deletions modules/axhal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
137 changes: 13 additions & 124 deletions modules/axhal/src/platform/aarch64_bsta1000b/dw_apb_uart.rs
Original file line number Diff line number Diff line change
@@ -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<DW8250> = SpinNoIrq::new(DW8250::new(phys_to_virt(UART_BASE)));

register_structs! {
DW8250Regs {
/// Get or Put Register.
(0x00 => rbr: ReadWrite<u32>),
(0x04 => ier: ReadWrite<u32>),
(0x08 => fcr: ReadWrite<u32>),
(0x0c => lcr: ReadWrite<u32>),
(0x10 => mcr: ReadWrite<u32>),
(0x14 => lsr: ReadOnly<u32>),
(0x18 => msr: ReadOnly<u32>),
(0x1c => scr: ReadWrite<u32>),
(0x20 => lpdll: ReadWrite<u32>),
(0x24 => _reserved0),
/// Uart Status Register.
(0x7c => usr: ReadOnly<u32>),
(0x80 => _reserved1),
(0xc0 => dlf: ReadWrite<u32>),
(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<u8> {
// 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<DW8250> = SpinNoIrq::new(DW8250::new(phys_to_virt(UART_BASE).as_usize()));

/// Writes a byte to the console.
pub fn putchar(c: u8) {
Expand All @@ -146,14 +26,23 @@ pub fn getchar() -> Option<u8> {
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")]
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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));
}
}

Expand All @@ -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();

Expand Down
6 changes: 1 addition & 5 deletions modules/axhal/src/platform/aarch64_bsta1000b/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
mod dw_apb_uart;

pub mod mem;
pub mod utils;
pub mod misc;

#[cfg(feature = "smp")]
pub mod mp;
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion modules/axhal/src/platform/aarch64_common/psci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion scripts/make/bsta1000b-fada.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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'
File renamed without changes.
File renamed without changes.

0 comments on commit b8ad0a7

Please sign in to comment.