forked from arceos-org/arceos
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Supports car automotive platform bsta1000b
Build cmd: make A=apps/fs/shell ARCH=aarch64 SMP=8 PLATFORM=aarch64-bsta1000b APP_FEATURES="axstd/driver-ramdisk,axstd/irq" fada
- Loading branch information
Showing
29 changed files
with
651 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ | |
*.img | ||
actual.out | ||
qemu.log | ||
rusty-tags.vi |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "dw_apb_uart" | ||
authors = ["Luoyuan Xiao <[email protected]>"] | ||
version = "0.1.0" | ||
edition = "2021" | ||
license = "GPL-2.0" | ||
repository = "https://github.com/elliott10/arceos/tree/main/crates/dw_apb_uart" | ||
description = "Uart snps,dw-apb-uart driver in Rust for BST A1000b FADA board." | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
tock-registers = "0.8" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
//! Definitions for snps,dw-apb-uart serial driver. | ||
//! Uart snps,dw-apb-uart driver in Rust for BST A1000b FADA board. | ||
#![no_std] | ||
|
||
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); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
modules/axhal/src/platform/aarch64_bsta1000b/dw_apb_uart.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
//! snps,dw-apb-uart serial driver | ||
use crate::mem::phys_to_virt; | ||
use 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).as_usize())); | ||
|
||
/// Writes a byte to the console. | ||
pub fn putchar(c: u8) { | ||
let mut uart = UART.lock(); | ||
match c { | ||
b'\r' | b'\n' => { | ||
uart.putchar(b'\r'); | ||
uart.putchar(b'\n'); | ||
} | ||
c => uart.putchar(c), | ||
} | ||
} | ||
|
||
/// Reads a byte from the console, or returns [`None`] if no input is available. | ||
pub fn getchar() -> Option<u8> { | ||
UART.lock().getchar() | ||
} | ||
|
||
/// UART simply initialize | ||
pub fn init_early() { | ||
UART.lock().init(); | ||
} | ||
|
||
/// Set UART IRQ Enable | ||
#[cfg(feature = "irq")] | ||
pub fn init_irq() { | ||
UART.lock().set_ier(true); | ||
crate::irq::register_handler(crate::platform::irq::UART_IRQ_NUM, handle); | ||
} | ||
|
||
/// UART IRQ Handler | ||
pub fn handle() { | ||
trace!("Uart IRQ Handler"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
use crate::mem::{MemRegion, PhysAddr}; | ||
use page_table_entry::{aarch64::A64PTE, GenericPTE, MappingFlags}; | ||
|
||
/// Returns platform-specific memory regions. | ||
pub(crate) fn platform_regions() -> impl Iterator<Item = MemRegion> { | ||
crate::mem::default_free_regions().chain(crate::mem::default_mmio_regions()) | ||
} | ||
|
||
pub(crate) unsafe fn init_boot_page_table( | ||
boot_pt_l0: &mut [A64PTE; 512], | ||
boot_pt_l1: &mut [A64PTE; 512], | ||
) { | ||
// 0x0000_0000_0000 ~ 0x0080_0000_0000, table | ||
boot_pt_l0[0] = A64PTE::new_table(PhysAddr::from(boot_pt_l1.as_ptr() as usize)); | ||
// 0x0000_0000_0000..0x0000_4000_0000, 1G block, device memory | ||
boot_pt_l1[0] = A64PTE::new_page( | ||
PhysAddr::from(0), | ||
MappingFlags::READ | MappingFlags::WRITE | MappingFlags::DEVICE, | ||
true, | ||
); | ||
// 1G block, device memory | ||
boot_pt_l1[1] = A64PTE::new_page( | ||
PhysAddr::from(0x40000000), | ||
MappingFlags::READ | MappingFlags::WRITE | MappingFlags::DEVICE, | ||
true, | ||
); | ||
// 1G block, normal memory | ||
boot_pt_l1[2] = A64PTE::new_page( | ||
PhysAddr::from(0x80000000), | ||
MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXECUTE, | ||
true, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
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}; | ||
|
||
/// Do QSPI reset | ||
pub fn reset_qspi() { | ||
// qspi exit 4-byte mode | ||
// exit_4byte_qspi(); | ||
|
||
let ptr = phys_to_virt((axconfig::A1000BASE_SAFETYCRM + 0x8).into()).as_mut_ptr() as *mut u32; | ||
unsafe { | ||
let value = read_volatile(ptr); | ||
trace!("SAFETY CRM RESET CTRL = {:#x}", value); | ||
write_volatile(ptr, value & !(0b11 << 15)); | ||
busy_wait(Duration::from_millis(100)); | ||
|
||
write_volatile(ptr, value | (0b11 << 15)); | ||
busy_wait(Duration::from_millis(100)); | ||
} | ||
} | ||
|
||
/// Do CPU reset | ||
pub fn reset_cpu() { | ||
reset_qspi(); | ||
|
||
//Data Width = 32 | ||
let ptr = phys_to_virt((axconfig::A1000BASE_SAFETYCRM + 0x8).into()).as_mut_ptr() as *mut u32; | ||
unsafe { | ||
write_volatile(ptr, read_volatile(ptr) & !0b1); | ||
} | ||
|
||
loop {} | ||
} | ||
|
||
/// reboot system | ||
#[allow(dead_code)] | ||
pub fn do_reset() { | ||
axlog::ax_println!("resetting ...\n"); | ||
|
||
// wait 50 ms | ||
busy_wait(Duration::from_millis(50)); | ||
|
||
// disable_interrupts(); | ||
|
||
reset_cpu(); | ||
|
||
// NOT REACHED | ||
warn!("NOT REACHED Resetting"); | ||
} | ||
|
||
/// bootmode define bit [27:26], from strap pin | ||
#[allow(dead_code)] | ||
pub fn get_bootmode() -> u32 { | ||
unsafe { | ||
let ptr = phys_to_virt((axconfig::A1000BASE_TOPCRM).into()).as_mut_ptr() as *mut u32; | ||
(ptr.read_volatile() >> 26) & 0x7 | ||
} | ||
} |
Oops, something went wrong.