Compare commits
No commits in common. "adc45f6aa272e75be225395077b7e3c992de1796" and "c1d2723f7d1a44791768df60afe041aa11fb89c4" have entirely different histories.
adc45f6aa2
...
c1d2723f7d
|
@ -1,3 +0,0 @@
|
||||||
//! Modules specific to the aarch64 architecture.
|
|
||||||
|
|
||||||
pub mod time;
|
|
|
@ -1,88 +0,0 @@
|
||||||
//! The implementation of the time management trait for aarch64.
|
|
||||||
|
|
||||||
use core::arch::asm;
|
|
||||||
use core::time::Duration;
|
|
||||||
|
|
||||||
use crate::traits::time::TimeManager;
|
|
||||||
use crate::println;
|
|
||||||
|
|
||||||
const NS_PER_S: u64 = 1_000_000_000;
|
|
||||||
const CNTP_CTL_EL0_ENABLE_MASK: u64 = 0b001;
|
|
||||||
const CNTP_CTL_EL0_IMASK_MASK: u64 = 0b010;
|
|
||||||
const CNTP_CTL_EL0_ISTATUS_MASK: u64 = 0b100;
|
|
||||||
|
|
||||||
/// AARCH64 Timer.
|
|
||||||
struct Timer;
|
|
||||||
|
|
||||||
/// The global timer.
|
|
||||||
static TIME_MANAGER: Timer = Timer;
|
|
||||||
|
|
||||||
/// Return a reference to the global time manager.
|
|
||||||
pub fn time_manager() -> &'static impl TimeManager {
|
|
||||||
&TIME_MANAGER
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TimeManager for Timer {
|
|
||||||
fn frequency(&self) -> u64 {
|
|
||||||
let freq: u64;
|
|
||||||
unsafe {
|
|
||||||
asm!("mrs {0:x}, CNTFRQ_EL0", out(reg) freq, options(nomem, nostack));
|
|
||||||
}
|
|
||||||
freq
|
|
||||||
}
|
|
||||||
|
|
||||||
fn uptime(&self) -> Duration {
|
|
||||||
let ticks: u64;
|
|
||||||
unsafe {
|
|
||||||
// Protect against out of order execution
|
|
||||||
// https://developer.arm.com/documentation/dui0802/b/CIHGHHIE
|
|
||||||
// In effect this flush the processor pipeline
|
|
||||||
asm!("ISB", options(nostack));
|
|
||||||
asm!("mrs {0:x}, CNTPCT_EL0", out(reg) ticks, options(nomem, nostack));
|
|
||||||
}
|
|
||||||
Duration::from_nanos((ticks*NS_PER_S)/self.frequency())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sleep(&self, duration: Duration) {
|
|
||||||
if duration.is_zero() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let tmp = match self.frequency().checked_mul(duration.as_nanos() as u64) {
|
|
||||||
None => {
|
|
||||||
println!("Cannot sleep this long, skipping");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Some(tmp) => tmp,
|
|
||||||
};
|
|
||||||
let ticks = tmp / NS_PER_S;
|
|
||||||
|
|
||||||
if ticks > u32::max_value().into() {
|
|
||||||
println!("Cannot wait more than 2^32-1 ticks on aarch64, skipping");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ticks == 0 {
|
|
||||||
println!("Duration is smaller than a clock tick, skipping.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable the timer and mask (disable) the interrupt
|
|
||||||
let mut ctl: u64 = CNTP_CTL_EL0_ENABLE_MASK + CNTP_CTL_EL0_IMASK_MASK;
|
|
||||||
unsafe {
|
|
||||||
// set the register values for the timer
|
|
||||||
asm!("msr CNTP_TVAL_EL0, {0:x}", in(reg) ticks, options(nomem, nostack));
|
|
||||||
asm!("msr CNTP_CTL_EL0, {0:x}", in(reg) ctl, options(nomem, nostack));
|
|
||||||
}
|
|
||||||
// Loop waiting for the timer to run out
|
|
||||||
while (ctl & CNTP_CTL_EL0_ISTATUS_MASK) == 0 {
|
|
||||||
unsafe {
|
|
||||||
asm!("mrs {0:x}, CNTP_CTL_EL0", out(reg) ctl, options(nomem, nostack));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Disable the counter
|
|
||||||
ctl &= !CNTP_CTL_EL0_ENABLE_MASK;
|
|
||||||
unsafe {
|
|
||||||
asm!("msr CNTP_CTL_EL0, {0:x}", in(reg) ctl, options(nomem, nostack));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,6 +6,3 @@ pub mod rpi3;
|
||||||
|
|
||||||
#[cfg(feature = "target_rpi4")]
|
#[cfg(feature = "target_rpi4")]
|
||||||
pub mod rpi4;
|
pub mod rpi4;
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
pub mod aarch64;
|
|
||||||
|
|
121
src/log.rs
121
src/log.rs
|
@ -1,121 +0,0 @@
|
||||||
//! Module implementing the `print!`/`println!` macro.
|
|
||||||
|
|
||||||
/// Log an debug info
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! debug {
|
|
||||||
($string:expr) => ({
|
|
||||||
use $crate::traits::time::TimeManager;
|
|
||||||
let timestamp = $crate::time_manager().uptime();
|
|
||||||
$crate::print::_print(format_args_nl!(
|
|
||||||
concat!("[{:>6}.{:06}] DEBUG: ", $string),
|
|
||||||
timestamp.as_secs(),
|
|
||||||
timestamp.subsec_micros(),
|
|
||||||
));
|
|
||||||
});
|
|
||||||
($format_string:expr, $($arg:tt)*) => ({
|
|
||||||
use $crate::traits::time::TimeManager;
|
|
||||||
let timestamp = $crate::time_manager().uptime();
|
|
||||||
$crate::print::_print(format_args_nl!(
|
|
||||||
concat!("[{:>6}.{:06}] DEBUG: ", $format_string),
|
|
||||||
timestamp.as_secs(),
|
|
||||||
timestamp.subsec_micros(),
|
|
||||||
$($arg)*
|
|
||||||
));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Log an info
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! info {
|
|
||||||
($string:expr) => ({
|
|
||||||
use $crate::traits::time::TimeManager;
|
|
||||||
let timestamp = $crate::time_manager().uptime();
|
|
||||||
$crate::print::_print(format_args_nl!(
|
|
||||||
concat!("[{:>6}.{:06}] INFO: ", $string),
|
|
||||||
timestamp.as_secs(),
|
|
||||||
timestamp.subsec_micros(),
|
|
||||||
));
|
|
||||||
});
|
|
||||||
($format_string:expr, $($arg:tt)*) => ({
|
|
||||||
use $crate::traits::time::TimeManager;
|
|
||||||
let timestamp = $crate::time_manager().uptime();
|
|
||||||
$crate::print::_print(format_args_nl!(
|
|
||||||
concat!("[{:>6}.{:06}] INFO: ", $format_string),
|
|
||||||
timestamp.as_secs(),
|
|
||||||
timestamp.subsec_micros(),
|
|
||||||
$($arg)*
|
|
||||||
));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Log an warning
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! warn {
|
|
||||||
($string:expr) => ({
|
|
||||||
use $crate::traits::time::TimeManager;
|
|
||||||
let timestamp = $crate::time_manager().uptime();
|
|
||||||
$crate::print::_print(format_args_nl!(
|
|
||||||
concat!("[{:>6}.{:06}] WARN: ", $string),
|
|
||||||
timestamp.as_secs(),
|
|
||||||
timestamp.subsec_micros(),
|
|
||||||
));
|
|
||||||
});
|
|
||||||
($format_string:expr, $($arg:tt)*) => ({
|
|
||||||
use $crate::traits::time::TimeManager;
|
|
||||||
let timestamp = $crate::time_manager().uptime();
|
|
||||||
$crate::print::_print(format_args_nl!(
|
|
||||||
concat!("[{:>6}.{:06}] WARN: ", $format_string),
|
|
||||||
timestamp.as_secs(),
|
|
||||||
timestamp.subsec_micros(),
|
|
||||||
$($arg)*
|
|
||||||
));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Log an error
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! error {
|
|
||||||
($string:expr) => ({
|
|
||||||
use $crate::traits::time::TimeManager;
|
|
||||||
let timestamp = $crate::time_manager().uptime();
|
|
||||||
$crate::print::_print(format_args_nl!(
|
|
||||||
concat!("[{:>6}.{:06}] ERR: ", $string),
|
|
||||||
timestamp.as_secs(),
|
|
||||||
timestamp.subsec_micros(),
|
|
||||||
));
|
|
||||||
});
|
|
||||||
($format_string:expr, $($arg:tt)*) => ({
|
|
||||||
use $crate::traits::time::TimeManager;
|
|
||||||
let timestamp = $crate::time_manager().uptime();
|
|
||||||
$crate::print::_print(format_args_nl!(
|
|
||||||
concat!("[{:>6}.{:06}] ERR: ", $format_string),
|
|
||||||
timestamp.as_secs(),
|
|
||||||
timestamp.subsec_micros(),
|
|
||||||
$($arg)*
|
|
||||||
));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Log a fatal error
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! fatal {
|
|
||||||
($string:expr) => ({
|
|
||||||
use $crate::traits::time::TimeManager;
|
|
||||||
let timestamp = $crate::time_manager().uptime();
|
|
||||||
$crate::print::_print(format_args_nl!(
|
|
||||||
concat!("[{:>6}.{:06}] FATAL: ", $string),
|
|
||||||
timestamp.as_secs(),
|
|
||||||
timestamp.subsec_micros(),
|
|
||||||
));
|
|
||||||
});
|
|
||||||
($format_string:expr, $($arg:tt)*) => ({
|
|
||||||
use $crate::traits::time::TimeManager;
|
|
||||||
let timestamp = $crate::time_manager().uptime();
|
|
||||||
$crate::print::_print(format_args_nl!(
|
|
||||||
concat!("[{:>6}.{:06}] FATAL: ", $format_string),
|
|
||||||
timestamp.as_secs(),
|
|
||||||
timestamp.subsec_micros(),
|
|
||||||
$($arg)*
|
|
||||||
));
|
|
||||||
})
|
|
||||||
}
|
|
35
src/main.rs
35
src/main.rs
|
@ -20,25 +20,17 @@ mod utils;
|
||||||
mod panic;
|
mod panic;
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
mod print;
|
mod print;
|
||||||
#[cfg(not(test))]
|
|
||||||
mod log;
|
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use core::arch::global_asm;
|
use core::arch::global_asm;
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
|
|
||||||
use core::time::Duration;
|
|
||||||
|
|
||||||
// TODO: handle this with features
|
// TODO: handle this with features
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use crate::bsp::rpi3::uart::console;
|
use crate::bsp::rpi3::uart::console;
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use crate::bsp::rpi3::gpio;
|
use crate::bsp::rpi3::gpio;
|
||||||
#[cfg(not(test))]
|
|
||||||
use crate::bsp::aarch64::time::time_manager;
|
|
||||||
|
|
||||||
use crate::traits::time::TimeManager;
|
|
||||||
|
|
||||||
// TODO: move this to BSP
|
// TODO: move this to BSP
|
||||||
/// Pause the core with a infinit loop
|
/// Pause the core with a infinit loop
|
||||||
|
@ -76,12 +68,6 @@ pub unsafe fn _start_rust() -> ! {
|
||||||
bsp::rpi3::uart::init();
|
bsp::rpi3::uart::init();
|
||||||
println!("Hello there");
|
println!("Hello there");
|
||||||
|
|
||||||
debug!("debug");
|
|
||||||
info!("info");
|
|
||||||
warn!("warn");
|
|
||||||
error!("error");
|
|
||||||
fatal!("fatal");
|
|
||||||
|
|
||||||
let mut buffer = ['X'; 200];
|
let mut buffer = ['X'; 200];
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut c = console().read_char();
|
let mut c = console().read_char();
|
||||||
|
@ -103,22 +89,23 @@ pub unsafe fn _start_rust() -> ! {
|
||||||
println!("");
|
println!("");
|
||||||
|
|
||||||
match gpio::set_pin_fonction(21, gpio::PinFunction::Output) {
|
match gpio::set_pin_fonction(21, gpio::PinFunction::Output) {
|
||||||
Ok(()) => info!("Successfully set pin to output"),
|
Ok(()) => println!("Successfully set pin to output"),
|
||||||
Err(err) => warn!("Failled to set pin: {}", err),
|
Err(err) => println!("Failled to set pin: {err}"),
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
match gpio::set_pin_output_state(21, gpio::PinOutputState::High) {
|
match gpio::set_pin_output_state(21, gpio::PinOutputState::High) {
|
||||||
Ok(()) => info!("OUTPUT 21 UP"),
|
Ok(()) => (),
|
||||||
Err(_err) => warn!("Failled to set pin 21 to High"),
|
Err(_err) => println!("Failled to set pin 21 to High"),
|
||||||
|
}
|
||||||
|
for _ in 0..5000000 {
|
||||||
|
asm!("nop");
|
||||||
}
|
}
|
||||||
time_manager().sleep(Duration::from_secs(1));
|
|
||||||
match gpio::set_pin_output_state(21, gpio::PinOutputState::Low) {
|
match gpio::set_pin_output_state(21, gpio::PinOutputState::Low) {
|
||||||
Ok(()) => info!("OUTPUT 21 DOWN"),
|
Ok(()) => (),
|
||||||
Err(_err) => warn!("Failled to set pin 21 to Low"),
|
Err(_err) => println!("Failled to set pin 21 to Low"),
|
||||||
}
|
}
|
||||||
time_manager().sleep(Duration::from_secs(1));
|
for _ in 0..5000000 {
|
||||||
if time_manager().uptime().as_secs() >= 60 {
|
asm!("nop");
|
||||||
panic!("Times out");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
use crate::fatal;
|
use crate::println;
|
||||||
use crate::wait_forever;
|
use crate::wait_forever;
|
||||||
|
|
||||||
/// Avoid nested panic
|
/// Avoid nested panic
|
||||||
|
@ -32,11 +32,10 @@ fn panic(info: &PanicInfo) -> ! {
|
||||||
_ => ("???", 0, 0),
|
_ => ("???", 0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
fatal!(
|
println!(
|
||||||
"Kernel panic!\n\n\
|
"Kernel panic!\n\n\
|
||||||
Panic location:\n File: '{}', line {}, column {}\n\n\
|
Panic location:\n File: '{location}', line {line}, column {column}\n\n\
|
||||||
{}",
|
{}",
|
||||||
location, line, column,
|
|
||||||
info.message().unwrap_or(&format_args!(""))
|
info.message().unwrap_or(&format_args!(""))
|
||||||
);
|
);
|
||||||
wait_forever()
|
wait_forever()
|
||||||
|
|
|
@ -10,4 +10,3 @@
|
||||||
|
|
||||||
pub mod console;
|
pub mod console;
|
||||||
pub mod synchronization;
|
pub mod synchronization;
|
||||||
pub mod time;
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
//! Traits for time management primitives.
|
|
||||||
|
|
||||||
use core::time::Duration;
|
|
||||||
|
|
||||||
pub trait TimeManager {
|
|
||||||
|
|
||||||
/// Return the clock frequency, meaning the resolution of the
|
|
||||||
/// time mesurement.
|
|
||||||
fn frequency(&self) -> u64;
|
|
||||||
|
|
||||||
/// The uptime since last power-on.
|
|
||||||
fn uptime(&self) -> Duration;
|
|
||||||
|
|
||||||
/// Sleep for the duration.
|
|
||||||
fn sleep(&self, duration: Duration);
|
|
||||||
}
|
|
Loading…
Reference in New Issue