UART
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
use crate::{
|
||||
arch::{mmio_read, mmio_write},
|
||||
dev::{irq::InterruptHandler, serial::SerialDevice, Device},
|
||||
};
|
||||
use address::PhysicalAddress;
|
||||
|
||||
pub struct AuxUart;
|
||||
pub struct Aux;
|
||||
|
||||
impl Aux {
|
||||
const REG_AUX_ENABLES: PhysicalAddress = PhysicalAddress::new(0x3F215004);
|
||||
const AUX_ENABLES_MUART: u32 = 1 << 0;
|
||||
|
||||
pub unsafe fn enable_uart(&self) {
|
||||
let tmp = mmio_read(Self::REG_AUX_ENABLES);
|
||||
mmio_write(Self::REG_AUX_ENABLES, tmp | Self::AUX_ENABLES_MUART);
|
||||
}
|
||||
}
|
||||
|
||||
impl AuxUart {
|
||||
const AUX_MU_BASE: PhysicalAddress = PhysicalAddress::new(0x3F215000);
|
||||
const REG_AUX_MU_IO: PhysicalAddress = Self::AUX_MU_BASE.add(0x40);
|
||||
const REG_AUX_MU_IER: PhysicalAddress = Self::AUX_MU_BASE.add(0x44);
|
||||
const REG_AUX_MU_CNTL: PhysicalAddress = Self::AUX_MU_BASE.add(0x60);
|
||||
|
||||
const AUX_MU_CNTL_TE: u32 = 1 << 1;
|
||||
const AUX_MU_CNTL_RE: u32 = 1 << 0;
|
||||
|
||||
const AUX_MU_IER_RIE: u32 = 1 << 0;
|
||||
}
|
||||
|
||||
impl InterruptHandler for Aux {
|
||||
fn do_irq(&self, _irq: u32) {}
|
||||
}
|
||||
|
||||
impl Device for AuxUart {
|
||||
fn name(&self) -> &'static str {
|
||||
"BCM283x Mini-UART"
|
||||
}
|
||||
|
||||
unsafe fn enable(&self) {
|
||||
AUX.enable_uart();
|
||||
|
||||
mmio_write(Self::REG_AUX_MU_IER, Self::AUX_MU_IER_RIE);
|
||||
mmio_write(
|
||||
Self::REG_AUX_MU_CNTL,
|
||||
Self::AUX_MU_CNTL_TE | Self::AUX_MU_CNTL_RE,
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn disable(&self) {}
|
||||
}
|
||||
|
||||
impl SerialDevice for AuxUart {
|
||||
fn send(&self, ch: u8) {
|
||||
unsafe {
|
||||
mmio_write(Self::REG_AUX_MU_IO, ch as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InterruptHandler for AuxUart {
|
||||
fn do_irq(&self, _irq: u32) {
|
||||
let byte = unsafe { mmio_read(Self::REG_AUX_MU_IO) } as u8;
|
||||
debugln!("{}", byte as char);
|
||||
}
|
||||
}
|
||||
|
||||
pub static AUX: Aux = Aux;
|
||||
pub static UART: AuxUart = AuxUart;
|
||||
@@ -0,0 +1,138 @@
|
||||
use crate::{
|
||||
arch::{cpu, mmio_read, mmio_write},
|
||||
dev::{irq::InterruptController, Device},
|
||||
};
|
||||
use address::PhysicalAddress;
|
||||
|
||||
pub struct Qa7Intc;
|
||||
pub struct Bcm2837Intc;
|
||||
|
||||
pub struct Intc {
|
||||
qa7_intc: Qa7Intc,
|
||||
bcm2837_intc: Bcm2837Intc,
|
||||
}
|
||||
|
||||
impl Bcm2837Intc {
|
||||
const REG_PENDING_IRQ1: PhysicalAddress = PhysicalAddress::new(0x3F00B204);
|
||||
const REG_PENDING_IRQ2: PhysicalAddress = PhysicalAddress::new(0x3F00B208);
|
||||
|
||||
const REG_ENABLE_IRQ1: PhysicalAddress = PhysicalAddress::new(0x3F00B210);
|
||||
const REG_ENABLE_IRQ2: PhysicalAddress = PhysicalAddress::new(0x3F00B214);
|
||||
}
|
||||
|
||||
impl Qa7Intc {
|
||||
const REG_TIMER_INTC: PhysicalAddress = PhysicalAddress::new(0x40000040);
|
||||
const REG_INT_SRC: PhysicalAddress = PhysicalAddress::new(0x40000060);
|
||||
|
||||
const INTC_CNTPNSIRQ_IRQ: u32 = 1 << 1;
|
||||
}
|
||||
|
||||
impl Device for Intc {
|
||||
fn name(&self) -> &'static str {
|
||||
"BCM283x Interrupt Controller"
|
||||
}
|
||||
|
||||
unsafe fn enable(&self) {}
|
||||
unsafe fn disable(&self) {}
|
||||
}
|
||||
|
||||
impl Device for Qa7Intc {
|
||||
fn name(&self) -> &'static str {
|
||||
"Broadcom QA7 Interrupt Controller"
|
||||
}
|
||||
|
||||
unsafe fn enable(&self) {}
|
||||
unsafe fn disable(&self) {}
|
||||
}
|
||||
|
||||
impl Device for Bcm2837Intc {
|
||||
fn name(&self) -> &'static str {
|
||||
"BCM2837 Interrupt Controller"
|
||||
}
|
||||
|
||||
unsafe fn enable(&self) {}
|
||||
unsafe fn disable(&self) {}
|
||||
}
|
||||
|
||||
impl InterruptController for Qa7Intc {
|
||||
unsafe fn enable_irq(&self, irq: u32) {
|
||||
match irq {
|
||||
super::IRQ_LOCAL_TIMER => {
|
||||
let phys_core_id = cpu::get_phys_id();
|
||||
let tmp = mmio_read(Self::REG_TIMER_INTC + 4 * phys_core_id);
|
||||
mmio_write(
|
||||
Self::REG_TIMER_INTC + 4 * phys_core_id,
|
||||
tmp | Self::INTC_CNTPNSIRQ_IRQ,
|
||||
);
|
||||
}
|
||||
_ => panic!("Unhandled IRQ number: {}", irq),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn disable_irq(&self, _irq: u32) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn is_irq_pending(&self, irq: u32) -> bool {
|
||||
unsafe { mmio_read(Self::REG_INT_SRC) & (1 << irq) != 0 }
|
||||
}
|
||||
|
||||
unsafe fn clear_irq(&self, _irq: u32) {}
|
||||
}
|
||||
|
||||
impl InterruptController for Bcm2837Intc {
|
||||
unsafe fn enable_irq(&self, irq: u32) {
|
||||
if irq < 32 {
|
||||
mmio_write(Self::REG_ENABLE_IRQ1, 1 << irq);
|
||||
} else if irq < 64 {
|
||||
mmio_write(Self::REG_ENABLE_IRQ2, 1 << (irq - 32));
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn disable_irq(&self, _irq: u32) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn is_irq_pending(&self, irq: u32) -> bool {
|
||||
if irq < 32 {
|
||||
unsafe { mmio_read(Self::REG_PENDING_IRQ1) & (1 << irq) != 0 }
|
||||
} else if irq < 64 {
|
||||
unsafe { mmio_read(Self::REG_PENDING_IRQ2) & (1 << (irq - 32)) != 0 }
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn clear_irq(&self, _irq: u32) {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
impl InterruptController for Intc {
|
||||
unsafe fn enable_irq(&self, irq: u32) {
|
||||
if irq < 16 {
|
||||
self.qa7_intc.enable_irq(irq);
|
||||
} else {
|
||||
self.bcm2837_intc.enable_irq(irq - 16);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn disable_irq(&self, _irq: u32) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn is_irq_pending(&self, irq: u32) -> bool {
|
||||
if irq < 16 {
|
||||
self.qa7_intc.is_irq_pending(irq)
|
||||
} else {
|
||||
self.bcm2837_intc.is_irq_pending(irq - 16)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn clear_irq(&self, _irq: u32) {}
|
||||
}
|
||||
|
||||
pub static INTC: Intc = Intc {
|
||||
qa7_intc: Qa7Intc,
|
||||
bcm2837_intc: Bcm2837Intc,
|
||||
};
|
||||
@@ -1,52 +1,23 @@
|
||||
use crate::mem::phys::{init_from_iter, SimpleMemoryIterator, UsableMemory};
|
||||
use address::PhysicalAddress;
|
||||
|
||||
pub mod aux;
|
||||
pub mod intc;
|
||||
pub mod mbox;
|
||||
pub mod smp;
|
||||
pub mod timer;
|
||||
|
||||
use crate::{
|
||||
arch::{cpu, mmio_read, mmio_write},
|
||||
dev::irq::InterruptController,
|
||||
mem::phys::{init_from_iter, SimpleMemoryIterator, UsableMemory},
|
||||
};
|
||||
use address::PhysicalAddress;
|
||||
|
||||
pub struct Intc;
|
||||
|
||||
impl Intc {
|
||||
const REG_TIMER_INTC: PhysicalAddress = PhysicalAddress::new(0x40000040);
|
||||
const REG_INT_SRC: PhysicalAddress = PhysicalAddress::new(0x40000060);
|
||||
|
||||
const INTC_CNTPNSIRQ_IRQ: u32 = 1 << 1;
|
||||
}
|
||||
|
||||
impl InterruptController for Intc {
|
||||
unsafe fn init(&self) {}
|
||||
|
||||
unsafe fn enable_irq(&self, irq: u32) {
|
||||
match irq {
|
||||
IRQ_LOCAL_TIMER => {
|
||||
let phys_core_id = cpu::get_phys_id();
|
||||
let tmp = mmio_read(Self::REG_TIMER_INTC + 4 * phys_core_id);
|
||||
mmio_write(Self::REG_TIMER_INTC + 4 * phys_core_id, tmp | Self::INTC_CNTPNSIRQ_IRQ);
|
||||
}
|
||||
_ => panic!("Unhandled IRQ number: {}", irq),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn disable_irq(&self, _irq: u32) {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn is_irq_pending(&self, irq: u32) -> bool {
|
||||
unsafe { mmio_read(Self::REG_INT_SRC) & (1 << irq) != 0 }
|
||||
}
|
||||
|
||||
unsafe fn clear_irq(&self, _irq: u32) {
|
||||
}
|
||||
}
|
||||
|
||||
pub static INTC: Intc = Intc;
|
||||
|
||||
pub const IRQ_LOCAL_TIMER: u32 = 1;
|
||||
pub const IRQ_AUX: u32 = 16 + 29;
|
||||
|
||||
// TODO as long as AUX is not used for anything else?
|
||||
pub const IRQ_UART: u32 = IRQ_AUX;
|
||||
|
||||
pub use aux::UART as AUX_UART;
|
||||
pub use intc::INTC;
|
||||
// Configured as primary UART
|
||||
pub use AUX_UART as UART;
|
||||
|
||||
// pub const INT_SRC_TIMER: u32 = 1 << 11;
|
||||
// pub const INT_SRC_MBOX0: u32 = 1 << 4;
|
||||
|
||||
@@ -61,3 +32,5 @@ pub fn init_phys_memory() {
|
||||
init_from_iter(iter);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() {}
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
use crate::arch;
|
||||
|
||||
pub mod timer;
|
||||
|
||||
use address::PhysicalAddress;
|
||||
|
||||
pub const IRQ_LOCAL_TIMER: u32 = 30;
|
||||
pub const IRQ_UART: u32 = 32 + 1;
|
||||
pub const IRQ_RTC: u32 = 32 + 2;
|
||||
|
||||
pub const GICD_BASE: PhysicalAddress = PhysicalAddress::new(0x08000000usize);
|
||||
pub const GICC_BASE: PhysicalAddress = PhysicalAddress::new(0x08010000usize);
|
||||
|
||||
pub const PL031_BASE: PhysicalAddress = PhysicalAddress::new(0x09010000usize);
|
||||
pub const PL011_BASE: PhysicalAddress = PhysicalAddress::new(0x09000000usize);
|
||||
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
arch::timer::enable_rtc();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,61 @@
|
||||
use crate::{
|
||||
arch::{intrin, machine},
|
||||
dev::irq::{self, InterruptController, InterruptHandler},
|
||||
dev::{
|
||||
irq::{self, InterruptController, InterruptHandler},
|
||||
Device,
|
||||
},
|
||||
};
|
||||
|
||||
struct ArmTimer;
|
||||
|
||||
impl Device for ArmTimer {
|
||||
fn name(&self) -> &'static str {
|
||||
"ARM Generic Timer"
|
||||
}
|
||||
|
||||
unsafe fn enable(&self) {
|
||||
intrin::write_cntp_ctl_el0(1);
|
||||
}
|
||||
|
||||
unsafe fn disable(&self) {
|
||||
intrin::write_cntp_ctl_el0(0);
|
||||
}
|
||||
}
|
||||
|
||||
impl InterruptHandler for ArmTimer {
|
||||
fn do_irq(&self, _irq: u32) {
|
||||
debugln!("T");
|
||||
unsafe {
|
||||
intrin::write_cntp_tval_el0(100000);
|
||||
intrin::write_cntp_tval_el0(10000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn enable_local_timer() {
|
||||
LOCAL_TIMER.enable();
|
||||
|
||||
let intc = irq::get_intc();
|
||||
irq::set_irq_handler(machine::IRQ_LOCAL_TIMER, &LOCAL_TIMER);
|
||||
intc.enable_irq(machine::IRQ_LOCAL_TIMER);
|
||||
}
|
||||
|
||||
intrin::write_cntp_ctl_el0(1);
|
||||
// TODO bcm283x RTC?
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "mach_virt")] {
|
||||
use crate::dev::pl031::Pl031;
|
||||
|
||||
static PL031: Pl031 = Pl031::new(machine::PL031_BASE);
|
||||
|
||||
use PL031 as RTC;
|
||||
|
||||
pub unsafe fn enable_rtc() {
|
||||
RTC.enable();
|
||||
|
||||
let intc = irq::get_intc();
|
||||
irq::set_irq_handler(machine::IRQ_RTC, &RTC);
|
||||
intc.enable_irq(machine::IRQ_RTC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LOCAL_TIMER: ArmTimer = ArmTimer;
|
||||
|
||||
+2
-11
@@ -1,5 +1,4 @@
|
||||
use crate::arch::mmio_write;
|
||||
use address::PhysicalAddress;
|
||||
use crate::dev::serial::{SerialDevice, SERIAL0};
|
||||
use core::fmt;
|
||||
use spin::Mutex;
|
||||
|
||||
@@ -7,15 +6,7 @@ struct Debug;
|
||||
|
||||
impl Debug {
|
||||
fn putc(&mut self, ch: u8) {
|
||||
unsafe {
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "mach_rpi3b")] {
|
||||
mmio_write(PhysicalAddress::new(0x3F215040), ch as u32);
|
||||
} else if #[cfg(feature = "mach_virt")] {
|
||||
mmio_write(PhysicalAddress::new(0x09000000), ch as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
SERIAL0.send(ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::dev::Device;
|
||||
use alloc::collections::LinkedList;
|
||||
|
||||
#[repr(C)]
|
||||
@@ -28,9 +29,7 @@ pub struct IrqRegisters {
|
||||
far: usize,
|
||||
}
|
||||
|
||||
pub trait InterruptController {
|
||||
unsafe fn init(&self);
|
||||
|
||||
pub trait InterruptController: Device {
|
||||
unsafe fn enable_irq(&self, irq: u32);
|
||||
unsafe fn disable_irq(&self, irq: u32);
|
||||
|
||||
@@ -91,5 +90,5 @@ cfg_if! {
|
||||
}
|
||||
|
||||
pub unsafe fn init() {
|
||||
get_intc().init();
|
||||
get_intc().enable();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
arch::{mmio_read, mmio_write},
|
||||
dev::irq::InterruptController,
|
||||
dev::{irq::InterruptController, Device},
|
||||
};
|
||||
use address::PhysicalAddress;
|
||||
|
||||
@@ -9,13 +9,23 @@ pub struct Gic {
|
||||
gicc_base: PhysicalAddress,
|
||||
}
|
||||
|
||||
impl InterruptController for Gic {
|
||||
unsafe fn init(&self) {
|
||||
impl Device for Gic {
|
||||
fn name(&self) -> &'static str {
|
||||
"ARM Generic Interrupt Controller"
|
||||
}
|
||||
|
||||
unsafe fn enable(&self) {
|
||||
mmio_write(self.gicd_base + Self::GICD_CTLR, Self::GICD_CTLR_ENABLE);
|
||||
mmio_write(self.gicc_base + Self::GICC_CTLR, Self::GICC_CTLR_ENABLE);
|
||||
mmio_write(self.gicc_base + Self::GICC_PMR, 0xFF);
|
||||
}
|
||||
|
||||
unsafe fn disable(&self) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl InterruptController for Gic {
|
||||
unsafe fn enable_irq(&self, irq: u32) {
|
||||
self.set_irq_config(irq, 1);
|
||||
self.unmask_irq(irq);
|
||||
|
||||
@@ -1 +1,11 @@
|
||||
pub mod irq;
|
||||
pub mod serial;
|
||||
|
||||
pub mod pl011;
|
||||
pub mod pl031;
|
||||
|
||||
pub trait Device {
|
||||
fn name(&self) -> &'static str;
|
||||
unsafe fn enable(&self);
|
||||
unsafe fn disable(&self);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
use crate::{
|
||||
arch::{mmio_read, mmio_write},
|
||||
dev::{irq::InterruptHandler, serial::SerialDevice, Device},
|
||||
};
|
||||
use address::PhysicalAddress;
|
||||
|
||||
pub struct Pl011 {
|
||||
base: PhysicalAddress,
|
||||
}
|
||||
|
||||
impl InterruptHandler for Pl011 {
|
||||
fn do_irq(&self, _irq: u32) {
|
||||
let tmp = unsafe { mmio_read(self.base + Self::UARTRIS) };
|
||||
if tmp & Self::UARTRIS_RXRIS != 0 {
|
||||
let ch = unsafe { mmio_read(self.base + Self::UARTDR) } as u8;
|
||||
debugln!("{}", ch as char);
|
||||
unsafe {
|
||||
mmio_write(self.base + Self::UARTICR, Self::UARTICR_RXIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for Pl011 {
|
||||
fn name(&self) -> &'static str {
|
||||
"PL011 UART"
|
||||
}
|
||||
|
||||
unsafe fn enable(&self) {
|
||||
mmio_write(self.base + Self::UARTCR, 0);
|
||||
mmio_write(self.base + Self::UARTCLR_H, 3 << 5);
|
||||
mmio_write(
|
||||
self.base + Self::UARTIMSC,
|
||||
Self::UARTIMSC_RXIM,
|
||||
);
|
||||
mmio_write(
|
||||
self.base + Self::UARTCR,
|
||||
Self::UARTCR_TXE | Self::UARTCR_RXE | Self::UARTCR_UARTEN,
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn disable(&self) {}
|
||||
}
|
||||
|
||||
impl SerialDevice for Pl011 {
|
||||
fn send(&self, ch: u8) {
|
||||
unsafe {
|
||||
while mmio_read(self.base + Self::UARTFR) & Self::UARTFR_BUSY != 0 {}
|
||||
mmio_write(self.base + Self::UARTDR, ch as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pl011 {
|
||||
const UARTDR: usize = 0x00;
|
||||
const UARTFR: usize = 0x18;
|
||||
const UARTCLR_H: usize = 0x2C;
|
||||
const UARTCR: usize = 0x30;
|
||||
const UARTIMSC: usize = 0x38;
|
||||
const UARTRIS: usize = 0x3C;
|
||||
const UARTICR: usize = 0x44;
|
||||
|
||||
const UARTCR_UARTEN: u32 = 1 << 0;
|
||||
const UARTCR_TXE: u32 = 1 << 8;
|
||||
const UARTCR_RXE: u32 = 1 << 9;
|
||||
|
||||
const UARTFR_BUSY: u32 = 1 << 3;
|
||||
|
||||
const UARTIMSC_RXIM: u32 = 1 << 4;
|
||||
|
||||
const UARTRIS_RXRIS: u32 = 1 << 4;
|
||||
|
||||
const UARTICR_RXIC: u32 = 1 << 4;
|
||||
|
||||
pub const fn new(base: PhysicalAddress) -> Self {
|
||||
Self { base }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
use crate::{
|
||||
arch::{mmio_read, mmio_write},
|
||||
dev::{irq::InterruptHandler, Device},
|
||||
};
|
||||
use address::PhysicalAddress;
|
||||
|
||||
pub struct Pl031 {
|
||||
base: PhysicalAddress,
|
||||
}
|
||||
|
||||
impl Pl031 {
|
||||
const RTCDR: usize = 0x00;
|
||||
const RTCMR: usize = 0x04;
|
||||
const RTCCR: usize = 0x0C;
|
||||
const RTCIMSC: usize = 0x10;
|
||||
const RTCICR: usize = 0x1C;
|
||||
|
||||
pub const fn new(base: PhysicalAddress) -> Self {
|
||||
Self { base }
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for Pl031 {
|
||||
fn name(&self) -> &'static str {
|
||||
"ARM PL031 RTC"
|
||||
}
|
||||
|
||||
unsafe fn enable(&self) {
|
||||
let tmp = mmio_read(self.base + Self::RTCDR);
|
||||
mmio_write(self.base + Self::RTCMR, tmp + 1);
|
||||
|
||||
mmio_write(self.base + Self::RTCIMSC, 1);
|
||||
mmio_write(self.base + Self::RTCCR, 1);
|
||||
}
|
||||
|
||||
unsafe fn disable(&self) {}
|
||||
}
|
||||
|
||||
impl InterruptHandler for Pl031 {
|
||||
fn do_irq(&self, _irq: u32) {
|
||||
let time_int = unsafe { mmio_read(self.base + Self::RTCDR) };
|
||||
unsafe {
|
||||
mmio_write(self.base + Self::RTCICR, 1);
|
||||
mmio_write(self.base + Self::RTCMR, time_int + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
use crate::dev::Device;
|
||||
|
||||
pub trait SerialDevice: Device {
|
||||
fn send(&self, ch: u8);
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "mach_rpi3b")] {
|
||||
use crate::arch::mach_bcm283x;
|
||||
|
||||
pub use mach_bcm283x::UART as SERIAL0;
|
||||
} else {
|
||||
use crate::{dev::pl011::Pl011, arch::machine};
|
||||
|
||||
pub static SERIAL0: Pl011 = Pl011::new(machine::PL011_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
SERIAL0.enable();
|
||||
}
|
||||
}
|
||||
+12
-2
@@ -21,12 +21,13 @@ pub mod dev;
|
||||
#[cfg(feature = "fdt-rs")]
|
||||
pub mod fdt;
|
||||
pub mod mem;
|
||||
pub mod time;
|
||||
|
||||
pub use mem::KernelSpace;
|
||||
|
||||
use address::PhysicalAddress;
|
||||
use arch::{cpu, intrin, smp, timer};
|
||||
use dev::irq;
|
||||
use arch::{timer, cpu, intrin, smp};
|
||||
use dev::irq::{self, InterruptController};
|
||||
|
||||
pub fn entry_common() -> ! {
|
||||
smp::init_ipi_delivery();
|
||||
@@ -43,6 +44,7 @@ pub fn entry_common() -> ! {
|
||||
#[no_mangle]
|
||||
extern "C" fn kernel_bsp_main(fdt_base: PhysicalAddress) -> ! {
|
||||
cpu::init(0);
|
||||
dev::serial::init();
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "fdt-rs")] {
|
||||
@@ -55,6 +57,14 @@ extern "C" fn kernel_bsp_main(fdt_base: PhysicalAddress) -> ! {
|
||||
}
|
||||
}
|
||||
mem::heap::init();
|
||||
arch::machine::init();
|
||||
|
||||
// Enable IRQs for SERIAL0
|
||||
let intc = irq::get_intc();
|
||||
irq::set_irq_handler(arch::machine::IRQ_UART, &dev::serial::SERIAL0);
|
||||
unsafe {
|
||||
intc.enable_irq(arch::machine::IRQ_UART);
|
||||
}
|
||||
|
||||
debug!("BSP init finished\n");
|
||||
//smp::wakeup_ap_cpus();
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#[derive(Debug)]
|
||||
pub struct Time {
|
||||
pub year: u32,
|
||||
pub mday: u8,
|
||||
pub mon: u8,
|
||||
pub hour: u8,
|
||||
pub min: u8,
|
||||
pub sec: u8
|
||||
}
|
||||
@@ -6,10 +6,15 @@ if [ -z "${MACH}" ]; then
|
||||
MACH=rpi3b
|
||||
fi
|
||||
|
||||
if [ -z "$QEMU_BIN" ]; then
|
||||
QEMU_BIN=qemu-system-aarch64
|
||||
fi
|
||||
|
||||
ARCH=aarch64-unknown-none-${MACH}
|
||||
KERNEL=target/${ARCH}/debug/kernel
|
||||
|
||||
QEMU_OPTS=""
|
||||
QEMU_OPTS="-chardev stdio,nowait,id=char0,mux=on \
|
||||
-mon chardev=char0"
|
||||
|
||||
if [ "$QEMU_DINT" = 1 ]; then
|
||||
QEMU_OPTS="$QEMU_OPTS -d int"
|
||||
@@ -19,22 +24,23 @@ case ${MACH} in
|
||||
rpi3b)
|
||||
QEMU_OPTS="$QEMU_OPTS \
|
||||
-serial null \
|
||||
-serial stdio \
|
||||
-serial chardev:char0 \
|
||||
-dtb bcm2837-rpi-3-b.dtb \
|
||||
-M raspi3b"
|
||||
;;
|
||||
virt)
|
||||
KERNEL=target/${ARCH}/debug/kernel.bin
|
||||
QEMU_OPTS="$QEMU_OPTS \
|
||||
-serial stdio \
|
||||
-serial chardev:char0 \
|
||||
-M virt,virtualization=on \
|
||||
-cpu cortex-a57 \
|
||||
-m 256"
|
||||
esac
|
||||
QEMU_OPTS="$QEMU_OPTS \
|
||||
-kernel ${KERNEL} \
|
||||
-display none \
|
||||
-s"
|
||||
|
||||
./build.sh
|
||||
|
||||
qemu-system-aarch64 ${QEMU_OPTS}
|
||||
${QEMU_BIN} ${QEMU_OPTS}
|
||||
|
||||
Reference in New Issue
Block a user