Skip to content

Commit

Permalink
Supports car automotive platform bsta1000b
Browse files Browse the repository at this point in the history
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
elliott10 committed Aug 22, 2023
1 parent 2c4c32f commit cc2679d
Show file tree
Hide file tree
Showing 29 changed files with 651 additions and 25 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ jobs:
- name: Build fs/shell for aarch64-raspi4
run: make PLATFORM=aarch64-raspi4 A=apps/fs/shell FEATURES=driver-bcm2835-sdhci

- name: Build helloworld for aarch64-bsta1000b
run: make PLATFORM=aarch64-bsta1000b A=apps/helloworld

build-apps-for-std:
runs-on: ${{ matrix.os }}
strategy:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
*.img
actual.out
qemu.log
rusty-tags.vi
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"crates/allocator",
"crates/arm_gic",
"crates/arm_pl011",
"crates/dw_apb_uart",
"crates/axerrno",
"crates/axfs_devfs",
"crates/axfs_ramfs",
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ include scripts/make/qemu.mk
include scripts/make/test.mk
ifeq ($(PLATFORM_NAME), aarch64-raspi4)
include scripts/make/raspi4.mk
else ifeq ($(PLATFORM_NAME), aarch64-bsta1000b)
include scripts/make/bsta1000b-fada.mk
endif

build: $(OUT_DIR) $(OUT_BIN)
Expand Down
44 changes: 44 additions & 0 deletions crates/arm_gic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,47 @@ pub enum TriggerMode {
/// level is active, and deasserted whenever the level is not active.
Level = 1,
}

/// Different types of interrupt that the GIC handles.
pub enum InterruptType {
/// Software-generated interrupt.
///
/// SGIs are typically used for inter-processor communication and are
/// generated by a write to an SGI register in the GIC.
SGI,
/// Private Peripheral Interrupt.
///
/// Peripheral interrupts that are private to one core.
PPI,
/// Shared Peripheral Interrupt.
///
/// Peripheral interrupts that can delivered to any connected core.
SPI,
}

/// Translate an interrupt of a given type to a GIC INTID.
pub const fn translate_irq(id: usize, int_type: InterruptType) -> Option<usize> {
match int_type {
InterruptType::SGI => {
if id < SGI_RANGE.end {
Some(id)
} else {
None
}
}
InterruptType::PPI => {
if id < PPI_RANGE.end - PPI_RANGE.start {
Some(id + PPI_RANGE.start)
} else {
None
}
}
InterruptType::SPI => {
if id < SPI_RANGE.end - SPI_RANGE.start {
Some(id + SPI_RANGE.start)
} else {
None
}
}
}
}
13 changes: 13 additions & 0 deletions crates/dw_apb_uart/Cargo.toml
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"
118 changes: 118 additions & 0 deletions crates/dw_apb_uart/src/lib.rs
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);
}
}
}
1 change: 1 addition & 0 deletions modules/axhal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,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" }
1 change: 1 addition & 0 deletions modules/axhal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#![feature(asm_const)]
#![feature(naked_functions)]
#![feature(const_maybe_uninit_zeroed)]
#![feature(const_option)]
#![feature(doc_auto_cfg)]

#[allow(unused_imports)]
Expand Down
44 changes: 44 additions & 0 deletions modules/axhal/src/platform/aarch64_bsta1000b/dw_apb_uart.rs
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");
}
33 changes: 33 additions & 0 deletions modules/axhal/src/platform/aarch64_bsta1000b/mem.rs
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,
);
}
60 changes: 60 additions & 0 deletions modules/axhal/src/platform/aarch64_bsta1000b/misc.rs
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
}
}
Loading

0 comments on commit cc2679d

Please sign in to comment.