feat: orangepi3 reset via r_wdog

This commit is contained in:
2021-10-07 19:07:59 +03:00
parent eb3460a010
commit cf21dc9b9a
4 changed files with 107 additions and 9 deletions
@@ -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) };
+15 -7
View File
@@ -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)),
}
}
}