feat: orangepi3 reset via r_wdog
This commit is contained in:
@@ -16,12 +16,14 @@ use error::Errno;
|
||||
mod gpio;
|
||||
mod uart;
|
||||
mod rtc;
|
||||
mod wdog;
|
||||
|
||||
pub use gic::IrqNumber;
|
||||
pub use gpio::PinAddress;
|
||||
use gpio::Gpio;
|
||||
use uart::Uart;
|
||||
use rtc::Rtc;
|
||||
use wdog::RWdog;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub fn init_board() -> Result<(), Errno> {
|
||||
@@ -40,6 +42,16 @@ pub fn init_board() -> Result<(), Errno> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Performs board reset
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: may interrupt critical processes
|
||||
pub unsafe fn reset_board() -> ! {
|
||||
R_WDOG.reset_board()
|
||||
}
|
||||
|
||||
const R_WDOG_BASE: usize = 0x07020400;
|
||||
const UART0_BASE: usize = 0x05000000;
|
||||
const RTC_BASE: usize = 0x07000000;
|
||||
const PIO_BASE: usize = 0x0300B000;
|
||||
@@ -64,6 +76,7 @@ pub fn intc() -> &'static impl IntController<IrqNumber = IrqNumber> {
|
||||
&GIC
|
||||
}
|
||||
|
||||
static R_WDOG: RWdog = unsafe { RWdog::new(R_WDOG_BASE) };
|
||||
static UART0: Uart = unsafe { Uart::new(UART0_BASE, IrqNumber::new(32)) };
|
||||
static LOCAL_TIMER: GenericTimer = GenericTimer {};
|
||||
pub(super) static GPIO: Gpio = unsafe { Gpio::new(PIO_BASE) };
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
use crate::dev::{Device, rtc::RtcDevice, irq::{IntController, IntSource}};
|
||||
use crate::arch::{MemoryIo, machine::{self, IrqNumber}};
|
||||
use crate::arch::{
|
||||
machine::{self, IrqNumber},
|
||||
MemoryIo,
|
||||
};
|
||||
use crate::dev::{
|
||||
irq::{IntController, IntSource},
|
||||
rtc::RtcDevice,
|
||||
Device,
|
||||
};
|
||||
use crate::sync::IrqSafeNullLock;
|
||||
use error::Errno;
|
||||
use tock_registers::{
|
||||
interfaces::{Readable, Writeable, ReadWriteable},
|
||||
interfaces::{Readable, Writeable},
|
||||
register_bitfields, register_structs,
|
||||
registers::{ReadOnly, ReadWrite, WriteOnly},
|
||||
registers::{ReadOnly, ReadWrite},
|
||||
};
|
||||
|
||||
register_bitfields! {
|
||||
@@ -42,7 +49,7 @@ register_structs! {
|
||||
|
||||
pub struct Rtc {
|
||||
regs: IrqSafeNullLock<MemoryIo<Regs>>,
|
||||
irq: IrqNumber
|
||||
irq: IrqNumber,
|
||||
}
|
||||
|
||||
impl Regs {
|
||||
@@ -51,7 +58,8 @@ impl Regs {
|
||||
if sec == 0 {
|
||||
return;
|
||||
}
|
||||
self.ALARM0_IRQ_STA.write(ALARM0_IRQ_STA::ALARM0_IRQ_PEND::SET);
|
||||
self.ALARM0_IRQ_STA
|
||||
.write(ALARM0_IRQ_STA::ALARM0_IRQ_PEND::SET);
|
||||
self.ALARM0_IRQ_EN.write(ALARM0_IRQ_EN::ALARM0_IRQ_EN::SET);
|
||||
self.ALARM0_COUNTER.set(self.ALARM0_CUR_VLU.get() + sec - 1);
|
||||
self.ALARM0_ENABLE.write(ALARM0_ENABLE::ALM_0_EN::SET);
|
||||
@@ -94,7 +102,7 @@ impl Rtc {
|
||||
pub const unsafe fn new(base: usize, irq: IrqNumber) -> Self {
|
||||
Self {
|
||||
regs: IrqSafeNullLock::new(MemoryIo::new(base)),
|
||||
irq
|
||||
irq,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,9 +110,16 @@ impl SerialDevice for Uart {
|
||||
|
||||
impl IntSource for Uart {
|
||||
fn handle_irq(&self) -> Result<(), Errno> {
|
||||
let regs = self.regs.lock();
|
||||
let byte = regs.DR_DLL.get();
|
||||
let byte = self.regs.lock().DR_DLL.get();
|
||||
debugln!("irq byte = {:#04x}!", byte);
|
||||
|
||||
if byte == 0x1B {
|
||||
debugln!("Received ESC, resetting");
|
||||
unsafe {
|
||||
machine::reset_board();
|
||||
}
|
||||
}
|
||||
|
||||
use crate::dev::gpio::{GpioDevice};
|
||||
machine::GPIO.toggle_pin(machine::PinAddress::new(3, 26));
|
||||
Ok(())
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
use crate::arch::MemoryIo;
|
||||
use crate::sync::IrqSafeNullLock;
|
||||
use tock_registers::{
|
||||
interfaces::Writeable, register_bitfields, register_structs, registers::ReadWrite,
|
||||
};
|
||||
|
||||
register_bitfields! {
|
||||
u32,
|
||||
CTRL [
|
||||
KEY OFFSET(1) NUMBITS(12) [
|
||||
Value = 0xA57
|
||||
],
|
||||
RESTART OFFSET(0) NUMBITS(1) []
|
||||
],
|
||||
CFG [
|
||||
CONFIG OFFSET(0) NUMBITS(2) [
|
||||
System = 1
|
||||
]
|
||||
],
|
||||
MODE [
|
||||
EN OFFSET(0) NUMBITS(1) []
|
||||
]
|
||||
}
|
||||
|
||||
register_structs! {
|
||||
#[allow(non_snake_case)]
|
||||
RWdogRegs {
|
||||
(0x00 => IRQ_EN: ReadWrite<u32>),
|
||||
(0x04 => IRQ_STA: ReadWrite<u32>),
|
||||
(0x08 => _res0),
|
||||
(0x10 => CTRL: ReadWrite<u32, CTRL::Register>),
|
||||
(0x14 => CFG: ReadWrite<u32, CFG::Register>),
|
||||
(0x18 => MODE: ReadWrite<u32, MODE::Register>),
|
||||
(0x1C => @END),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct RWdog {
|
||||
regs: IrqSafeNullLock<MemoryIo<RWdogRegs>>,
|
||||
}
|
||||
|
||||
impl RWdog {
|
||||
/// Performs board reset
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: may interrupt critical processes
|
||||
pub unsafe fn reset_board(&self) -> ! {
|
||||
let regs = self.regs.lock();
|
||||
|
||||
regs.CFG.write(CFG::CONFIG::System);
|
||||
regs.MODE.write(MODE::EN::SET);
|
||||
regs.CTRL.write(CTRL::KEY::Value + CTRL::RESTART::SET);
|
||||
|
||||
loop {
|
||||
asm!("wfe");
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs an instance of R_WDOG peripheral.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Does not perform `base` validation.
|
||||
pub const unsafe fn new(base: usize) -> Self {
|
||||
Self {
|
||||
regs: IrqSafeNullLock::new(MemoryIo::new(base)),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user