mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-16 20:22:26 +00:00
feat: UART terminal (#7)
* feat: basic terminal * feat: execute application via terminal
This commit is contained in:
committed by
GitHub
parent
34a66ff87a
commit
f33100d36b
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ sd.img
|
||||
settings.json
|
||||
.DS_Store
|
||||
.venv
|
||||
.nvimlog
|
||||
|
||||
9
.vscode/launch.json
vendored
9
.vscode/launch.json
vendored
@@ -58,15 +58,12 @@
|
||||
],
|
||||
"preLaunchTask": "Run QEMU wo window"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "Attach LLDB",
|
||||
"name": "LLDB",
|
||||
"type": "lldb",
|
||||
"request": "attach",
|
||||
"debugServer": 1234,
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/target/aarch64-unknown-none/debug/nova",
|
||||
"stopOnEntry": true,
|
||||
"processCreateCommands": ["gdb-remote localhost:1234"]
|
||||
"preLaunchTask": "Run QEMU wo window"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -40,12 +40,19 @@ version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "nova"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"heap",
|
||||
"libm",
|
||||
"log",
|
||||
"nova_error",
|
||||
"paste",
|
||||
]
|
||||
|
||||
@@ -17,6 +17,7 @@ libm = "0.2.15"
|
||||
heap = {path = "workspace/heap"}
|
||||
nova_error = {path = "workspace/nova_error"}
|
||||
paste = "1.0.15"
|
||||
log = "0.4.29"
|
||||
|
||||
[workspace]
|
||||
|
||||
|
||||
@@ -106,6 +106,18 @@ pub enum PhysSource {
|
||||
#[repr(align(4096))]
|
||||
pub struct PageTable([TableEntry; TABLE_ENTRY_COUNT]);
|
||||
|
||||
impl Iterator for PageTable {
|
||||
type Item = VirtAddr;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
for (offset, entity) in self.0.iter().enumerate() {
|
||||
if entity.is_invalid() {
|
||||
return Some(offset);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
#[no_mangle]
|
||||
pub static mut TRANSLATIONTABLE_TTBR0: PageTable = PageTable([TableEntry { value: 0 }; 512]);
|
||||
#[no_mangle]
|
||||
@@ -197,7 +209,7 @@ fn map_range_dynamic(
|
||||
|
||||
/// Allocate a singe page.
|
||||
pub fn alloc_page(
|
||||
virtual_address: usize,
|
||||
virtual_address: VirtAddr,
|
||||
base_table: *mut PageTable,
|
||||
additional_flags: u64,
|
||||
) -> Result<(), NovaError> {
|
||||
@@ -209,6 +221,28 @@ pub fn alloc_page(
|
||||
)
|
||||
}
|
||||
|
||||
/// Allocate a singe page in one block.
|
||||
pub fn find_free_kerne_page_in_block(start: VirtAddr) -> Result<VirtAddr, NovaError> {
|
||||
if !start.is_multiple_of(GRANULARITY) {
|
||||
return Err(NovaError::Misalignment);
|
||||
}
|
||||
|
||||
let (off1, off2, _) = virtual_address_to_table_offset(start);
|
||||
let offsets = [off1, off2];
|
||||
let table = unsafe {
|
||||
&mut *navigate_table(
|
||||
core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR1),
|
||||
&offsets,
|
||||
true,
|
||||
)?
|
||||
};
|
||||
|
||||
if let Some(virt_addr) = table.next() {
|
||||
return Ok(virt_addr);
|
||||
}
|
||||
Err(NovaError::OutOfMeomory)
|
||||
}
|
||||
|
||||
/// Allocate a single page at an explicit `physical_address`.
|
||||
pub fn alloc_page_explicit(
|
||||
virtual_address: usize,
|
||||
|
||||
@@ -77,7 +77,7 @@ configure_mmu_el1:
|
||||
.align 4
|
||||
.global el1_to_el0
|
||||
el1_to_el0:
|
||||
|
||||
mov x8, x0
|
||||
// Set SPSR_EL1: return to EL0t
|
||||
mov x0, #(0b0000)
|
||||
msr SPSR_EL1, x0
|
||||
@@ -93,5 +93,6 @@ el1_to_el0:
|
||||
|
||||
isb
|
||||
|
||||
mov x0, x8
|
||||
// Return to EL0
|
||||
eret
|
||||
|
||||
@@ -19,6 +19,8 @@ pub const EL0_STACK_SIZE: usize = LEVEL2_BLOCK_SIZE * 2;
|
||||
pub const MAILBOX_VIRTUAL_ADDRESS: VirtAddr = 0xFFFF_FF81_FFFF_E000;
|
||||
pub static mut MAILBOX_PHYSICAL_ADDRESS: Option<PhysAddr> = None;
|
||||
|
||||
pub const APPLICATION_TRANSLATION_TABLE_VA: VirtAddr = 0xFFFF_FF81_FE00_0000;
|
||||
|
||||
extern "C" {
|
||||
static __text_end: u64;
|
||||
static __share_end: u64;
|
||||
@@ -99,6 +101,7 @@ pub fn initialize_mmu_translation_tables() {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Allocate Mailbox buffer
|
||||
{
|
||||
let addr = reserve_page();
|
||||
unsafe { MAILBOX_PHYSICAL_ADDRESS = Some(addr) };
|
||||
|
||||
@@ -4,10 +4,8 @@ mod bitmaps;
|
||||
|
||||
use bitmaps::BASIC_LEGACY;
|
||||
|
||||
use crate::{
|
||||
pi3::mailbox::{read_mailbox, write_mailbox},
|
||||
println,
|
||||
};
|
||||
use crate::pi3::mailbox::{read_mailbox, write_mailbox};
|
||||
use log::error;
|
||||
#[repr(align(16))]
|
||||
struct Mailbox([u32; 36]);
|
||||
|
||||
@@ -237,7 +235,7 @@ impl Default for FrameBuffer {
|
||||
|
||||
let _ = read_mailbox(8);
|
||||
if mailbox.0[1] == 0 {
|
||||
println!("Failed");
|
||||
error!("Mailbox request was not processed!");
|
||||
}
|
||||
|
||||
mailbox.0[28] &= 0x3FFFFFFF;
|
||||
|
||||
@@ -2,8 +2,9 @@ use core::arch::asm;
|
||||
|
||||
use crate::{
|
||||
aarch64::registers::{daif::mask_all, read_esr_el1, read_exception_source_el},
|
||||
get_current_el, println,
|
||||
get_current_el,
|
||||
};
|
||||
use log::debug;
|
||||
|
||||
const INTERRUPT_BASE: u32 = 0x3F00_B000;
|
||||
const IRQ_PENDING_BASE: u32 = INTERRUPT_BASE + 0x204;
|
||||
@@ -66,17 +67,17 @@ unsafe extern "C" fn rust_synchronous_interrupt_no_el_change() {
|
||||
mask_all();
|
||||
|
||||
let source_el = read_exception_source_el() >> 2;
|
||||
println!("--------Sync Exception in EL{}--------", source_el);
|
||||
println!("No EL change");
|
||||
println!("Current EL: {}", get_current_el());
|
||||
println!("{:?}", EsrElX::from(read_esr_el1()));
|
||||
println!("Return register address: {:#x}", read_esr_el1());
|
||||
println!("-------------------------------------");
|
||||
debug!("--------Sync Exception in EL{}--------", source_el);
|
||||
debug!("No EL change");
|
||||
debug!("Current EL: {}", get_current_el());
|
||||
debug!("{:?}", EsrElX::from(read_esr_el1()));
|
||||
debug!("Return register address: {:#x}", read_esr_el1());
|
||||
debug!("-------------------------------------");
|
||||
}
|
||||
|
||||
fn set_return_to_kernel_main() {
|
||||
fn set_return_to_kernel_loop() {
|
||||
unsafe {
|
||||
asm!("ldr x0, =kernel_main", "msr ELR_EL1, x0");
|
||||
asm!("ldr x0, =kernel_loop", "msr ELR_EL1, x0");
|
||||
asm!("mov x0, #(0b0101)", "msr SPSR_EL1, x0");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,11 @@ use crate::{
|
||||
gpio::{read_gpio_event_detect_status, reset_gpio_event_detect_status},
|
||||
uart::clear_uart_interrupt_state,
|
||||
},
|
||||
println, read_address, write_address,
|
||||
read_address, write_address,
|
||||
};
|
||||
use alloc::vec::Vec;
|
||||
use log::{debug, info};
|
||||
|
||||
struct InterruptHandlers {
|
||||
source: IRQSource,
|
||||
function: fn(),
|
||||
@@ -60,9 +62,9 @@ unsafe extern "C" fn rust_irq_handler() {
|
||||
if pending_irqs & GPIO_PENDING_BIT_OFFSET != 0 {
|
||||
handle_gpio_interrupt();
|
||||
let source_el = read_exception_source_el() >> 2;
|
||||
println!("Source EL: {}", source_el);
|
||||
println!("Current EL: {}", get_current_el());
|
||||
println!("Return register address: {:#x}", read_esr_el1());
|
||||
debug!("Source EL: {}", source_el);
|
||||
debug!("Current EL: {}", get_current_el());
|
||||
debug!("Return register address: {:#x}", read_esr_el1());
|
||||
}
|
||||
|
||||
if let Some(handler_vec) = unsafe { &*core::ptr::addr_of_mut!(INTERRUPT_HANDLERS) } {
|
||||
@@ -76,7 +78,7 @@ unsafe extern "C" fn rust_irq_handler() {
|
||||
}
|
||||
|
||||
fn handle_gpio_interrupt() {
|
||||
println!("Interrupt");
|
||||
debug!("GPIO interrupt triggered");
|
||||
for i in 0..=53u32 {
|
||||
let val = read_gpio_event_detect_status(i);
|
||||
|
||||
@@ -84,7 +86,7 @@ fn handle_gpio_interrupt() {
|
||||
#[allow(clippy::single_match)]
|
||||
match i {
|
||||
26 => {
|
||||
println!("Button Pressed");
|
||||
info!("Button Pressed");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use crate::{
|
||||
aarch64::registers::{daif::mask_all, read_elr_el1, read_esr_el1, read_exception_source_el},
|
||||
get_current_el,
|
||||
interrupt_handlers::{set_return_to_kernel_main, EsrElX, TrapFrame},
|
||||
interrupt_handlers::{set_return_to_kernel_loop, EsrElX, TrapFrame},
|
||||
pi3::mailbox,
|
||||
println,
|
||||
};
|
||||
|
||||
use log::{debug, error, warn};
|
||||
|
||||
/// Synchronous Exception Handler
|
||||
///
|
||||
/// Source is a lower Exception level, where the implemented level
|
||||
@@ -15,22 +16,23 @@ use crate::{
|
||||
unsafe extern "C" fn rust_synchronous_interrupt_imm_lower_aarch64(frame: &mut TrapFrame) -> usize {
|
||||
mask_all();
|
||||
let esr: EsrElX = EsrElX::from(read_esr_el1());
|
||||
debug!("Synchronous interrupt from lower EL triggered");
|
||||
log_sync_exception();
|
||||
match esr.ec {
|
||||
0b100100 => {
|
||||
log_sync_exception();
|
||||
println!("Cause: Data Abort from a lower Exception level");
|
||||
warn!("Cause: Data Abort from a lower Exception level");
|
||||
}
|
||||
0b010101 => {
|
||||
println!("Cause: SVC instruction execution in AArch64");
|
||||
debug!("Cause: SVC instruction execution in AArch64");
|
||||
return handle_svc(frame);
|
||||
}
|
||||
_ => {
|
||||
println!("Unknown Error Code: {:b}", esr.ec);
|
||||
error!("Synchronous interrupt: Unknown Error Code: {:b}", esr.ec);
|
||||
}
|
||||
}
|
||||
println!("Returning to kernel main...");
|
||||
|
||||
set_return_to_kernel_main();
|
||||
warn!("UnhandledException -> Returning to kernel...");
|
||||
set_return_to_kernel_loop();
|
||||
0
|
||||
}
|
||||
|
||||
@@ -46,11 +48,11 @@ fn handle_svc(frame: &mut TrapFrame) -> usize {
|
||||
|
||||
fn log_sync_exception() {
|
||||
let source_el = read_exception_source_el() >> 2;
|
||||
println!("--------Sync Exception in EL{}--------", source_el);
|
||||
println!("Exception escalated to EL {}", get_current_el());
|
||||
println!("Current EL: {}", get_current_el());
|
||||
debug!("--------Sync Exception in EL{}--------", source_el);
|
||||
debug!("Exception escalated to EL {}", get_current_el());
|
||||
debug!("Current EL: {}", get_current_el());
|
||||
let esr: EsrElX = EsrElX::from(read_esr_el1());
|
||||
println!("{:?}", esr);
|
||||
println!("Return address: {:#x}", read_elr_el1());
|
||||
println!("-------------------------------------");
|
||||
debug!("{:?}", esr);
|
||||
debug!("Return address: {:#x}", read_elr_el1());
|
||||
debug!("-------------------------------------");
|
||||
}
|
||||
|
||||
45
src/lib.rs
45
src/lib.rs
@@ -3,12 +3,13 @@
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use core::{
|
||||
arch::asm,
|
||||
panic::PanicInfo,
|
||||
ptr::{read_volatile, write_volatile},
|
||||
};
|
||||
use log::LevelFilter;
|
||||
use log::{Level, Metadata, Record};
|
||||
|
||||
use heap::Heap;
|
||||
|
||||
@@ -18,10 +19,11 @@ use crate::{
|
||||
WRITABLE,
|
||||
},
|
||||
interrupt_handlers::irq::initialize_interrupt_handler,
|
||||
logger::DefaultLogger,
|
||||
pi3::timer::sleep_s,
|
||||
terminal::{flush_terminal, init_terminal},
|
||||
};
|
||||
|
||||
static LOGGER: UartLogger = UartLogger;
|
||||
static PERIPHERAL_BASE: usize = 0x3F00_0000;
|
||||
|
||||
unsafe extern "C" {
|
||||
@@ -31,7 +33,7 @@ unsafe extern "C" {
|
||||
#[global_allocator]
|
||||
pub static mut GLOBAL_ALLOCATOR: Heap = Heap::empty();
|
||||
|
||||
pub unsafe fn init_kernel_heap() {
|
||||
pub unsafe fn initialize_kernel_heap() {
|
||||
let start = core::ptr::addr_of_mut!(__kernel_end) as usize | KERNEL_VIRTUAL_MEM_SPACE;
|
||||
let size = LEVEL2_BLOCK_SIZE * 2;
|
||||
|
||||
@@ -54,9 +56,9 @@ pub mod aarch64;
|
||||
pub mod configuration;
|
||||
pub mod framebuffer;
|
||||
pub mod interrupt_handlers;
|
||||
pub mod logger;
|
||||
|
||||
pub mod pi3;
|
||||
pub mod terminal;
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn read_address(address: u32) -> u32 {
|
||||
@@ -80,14 +82,33 @@ pub fn get_current_el() -> u64 {
|
||||
el >> 2
|
||||
}
|
||||
|
||||
static mut KERNEL_INITIALIZED: bool = false;
|
||||
|
||||
pub fn initialize_kernel() {
|
||||
if unsafe { KERNEL_INITIALIZED } {
|
||||
return;
|
||||
}
|
||||
unsafe { init_kernel_heap() };
|
||||
logger::set_logger(Box::new(DefaultLogger));
|
||||
unsafe { initialize_kernel_heap() };
|
||||
initialize_interrupt_handler();
|
||||
unsafe { KERNEL_INITIALIZED = true };
|
||||
init_terminal();
|
||||
}
|
||||
|
||||
struct UartLogger;
|
||||
|
||||
impl log::Log for UartLogger {
|
||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
metadata.level() <= Level::Debug
|
||||
}
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
if self.enabled(record.metadata()) {
|
||||
println!("{} - {}", record.level(), record.args());
|
||||
if record.level() <= Level::Info {
|
||||
flush_terminal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) {}
|
||||
}
|
||||
|
||||
pub fn init_logger() {
|
||||
log::set_logger(&LOGGER)
|
||||
.map(|()| log::set_max_level(LevelFilter::Debug))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
use core::fmt::Write;
|
||||
|
||||
use alloc::{boxed::Box, fmt};
|
||||
|
||||
use crate::peripherals::uart;
|
||||
|
||||
static mut LOGGER: Option<Box<dyn Logger>> = None;
|
||||
|
||||
pub trait Logger: Write + Sync {
|
||||
fn flush(&mut self);
|
||||
}
|
||||
|
||||
pub struct DefaultLogger;
|
||||
|
||||
impl Logger for DefaultLogger {
|
||||
fn flush(&mut self) {}
|
||||
}
|
||||
|
||||
impl Write for DefaultLogger {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
uart::Uart.write_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log {
|
||||
() => {};
|
||||
($($arg:tt)*) => {
|
||||
$crate::logger::log(format_args!($($arg)*))
|
||||
};
|
||||
}
|
||||
|
||||
pub fn log(args: fmt::Arguments) {
|
||||
if let Some(logger) = unsafe { &mut *core::ptr::addr_of_mut!(LOGGER) } {
|
||||
logger.write_str("\n").unwrap();
|
||||
logger.write_fmt(args).unwrap();
|
||||
logger.flush();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_logger(logger: Box<dyn Logger>) {
|
||||
unsafe {
|
||||
LOGGER = Some(logger);
|
||||
}
|
||||
}
|
||||
65
src/main.rs
65
src/main.rs
@@ -6,6 +6,7 @@ use core::{
|
||||
arch::{asm, global_asm},
|
||||
ptr::write_volatile,
|
||||
};
|
||||
use log::{debug, info};
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
@@ -14,7 +15,7 @@ use nova::{
|
||||
aarch64::registers::{daif, read_id_aa64mmfr0_el1},
|
||||
configuration::memory_mapping::initialize_mmu_translation_tables,
|
||||
framebuffer::{FrameBuffer, BLUE, GREEN, RED},
|
||||
get_current_el,
|
||||
get_current_el, init_logger,
|
||||
interrupt_handlers::irq::{enable_irq_source, IRQSource},
|
||||
peripherals::{
|
||||
gpio::{
|
||||
@@ -23,7 +24,7 @@ use nova::{
|
||||
},
|
||||
uart::uart_init,
|
||||
},
|
||||
println,
|
||||
print, println,
|
||||
};
|
||||
|
||||
global_asm!(include_str!("vector.S"));
|
||||
@@ -33,7 +34,6 @@ static mut FRAMEBUFFER: Option<FrameBuffer> = None;
|
||||
|
||||
extern "C" {
|
||||
fn el2_to_el1();
|
||||
fn el1_to_el0();
|
||||
fn configure_mmu_el1();
|
||||
static mut __bss_start: u32;
|
||||
static mut __bss_end: u32;
|
||||
@@ -60,16 +60,18 @@ pub extern "C" fn main() -> ! {
|
||||
|
||||
// Set ACT Led to Outout
|
||||
let _ = set_gpio_function(21, GPIOFunction::Output);
|
||||
init_logger();
|
||||
|
||||
println!("Hello World!");
|
||||
println!("Exception level: {}", get_current_el());
|
||||
info!("Hello World!");
|
||||
info!("Current exception level: {}", get_current_el());
|
||||
|
||||
info!("initializing MMU...");
|
||||
initialize_mmu_translation_tables();
|
||||
unsafe { configure_mmu_el1() };
|
||||
println!("MMU initialized...");
|
||||
info!("MMU configured!");
|
||||
|
||||
println!("Register: AA64MMFR0_EL1: {:064b}", read_id_aa64mmfr0_el1());
|
||||
println!("Moving El2->EL1");
|
||||
debug!("Register: AA64MMFR0_EL1: {:064b}", read_id_aa64mmfr0_el1());
|
||||
info!("Moving El2->EL1");
|
||||
unsafe { FRAMEBUFFER = Some(FrameBuffer::default()) };
|
||||
|
||||
unsafe {
|
||||
@@ -89,28 +91,32 @@ unsafe fn zero_bss() {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn kernel_main() -> ! {
|
||||
println!("Kernel Start...");
|
||||
pub extern "C" fn kernel_main() {
|
||||
nova::initialize_kernel();
|
||||
info!("Kernel Initialized...");
|
||||
info!("Current exception Level: {}", get_current_el());
|
||||
|
||||
let mut test_vector = Vec::new();
|
||||
for i in 0..20 {
|
||||
test_vector.push(i);
|
||||
}
|
||||
println!("heap allocation test: {:?}", test_vector);
|
||||
debug!("heap allocation test: {:?}", test_vector);
|
||||
|
||||
println!("Exception Level: {}", get_current_el());
|
||||
enable_irq_source(IRQSource::UartInt);
|
||||
|
||||
kernel_loop();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn kernel_loop() {
|
||||
daif::unmask_all();
|
||||
|
||||
unsafe {
|
||||
el1_to_el0();
|
||||
};
|
||||
|
||||
#[allow(clippy::empty_loop)]
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn el0() -> ! {
|
||||
pub extern "C" fn el0(input: usize) {
|
||||
println!("Jumped into EL0");
|
||||
|
||||
// Set GPIO 26 to Input
|
||||
@@ -119,8 +125,6 @@ pub extern "C" fn el0() -> ! {
|
||||
gpio_pull_up(26);
|
||||
set_falling_edge_detect(26, true);
|
||||
|
||||
enable_irq_source(IRQSource::UartInt);
|
||||
|
||||
if let Some(fb) = unsafe { FRAMEBUFFER.as_mut() } {
|
||||
for i in 0..1080 {
|
||||
fb.draw_pixel(50, i, BLUE);
|
||||
@@ -134,13 +138,28 @@ pub extern "C" fn el0() -> ! {
|
||||
fb.draw_function(cos, 0, 101, RED);
|
||||
}
|
||||
|
||||
loop {
|
||||
let temp = syscall(67);
|
||||
println!("{} °C", temp / 1000);
|
||||
let _temp = syscall(67);
|
||||
|
||||
println!("Calculting prime to: {}", input);
|
||||
|
||||
for i in 3..input {
|
||||
let mut is_prime = true;
|
||||
for j in 3..i {
|
||||
if i == j {
|
||||
continue;
|
||||
}
|
||||
if i % j == 0 {
|
||||
is_prime = false;
|
||||
}
|
||||
}
|
||||
if is_prime {
|
||||
print!("{} ", i);
|
||||
}
|
||||
}
|
||||
println!("");
|
||||
|
||||
blink_gpio(SpecificGpio::OnboardLed as u8, 500);
|
||||
}
|
||||
}
|
||||
|
||||
fn cos(x: u32) -> f64 {
|
||||
libm::cos(x as f64 * 0.1) * 20.0
|
||||
|
||||
@@ -1,53 +1,92 @@
|
||||
use core::fmt::Write;
|
||||
use core::arch::asm;
|
||||
|
||||
use alloc::string::String;
|
||||
use nova::{
|
||||
interrupt_handlers::register_interrupt_handler, logger::Logger,
|
||||
peripherals::uart::read_uart_data, print, println,
|
||||
|
||||
use crate::{
|
||||
interrupt_handlers::irq::{register_interrupt_handler, IRQSource},
|
||||
peripherals::uart::read_uart_data,
|
||||
pi3::mailbox::read_soc_temp,
|
||||
print, println,
|
||||
};
|
||||
|
||||
pub static mut TERMINAL: Option<Terminal> = None;
|
||||
|
||||
pub struct Terminal {
|
||||
buffer: String,
|
||||
input: String,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn el1_to_el0();
|
||||
}
|
||||
|
||||
impl Default for Terminal {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Terminal {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
buffer: String::new(),
|
||||
input: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&mut self) {
|
||||
println!("{}", self.buffer);
|
||||
print!("> {}", self.input);
|
||||
self.buffer.clear();
|
||||
print!("\n> {}", self.input);
|
||||
}
|
||||
|
||||
fn exec(&mut self) {
|
||||
print!("\n");
|
||||
let val = self.input.clone();
|
||||
self.input.clear();
|
||||
|
||||
match val.as_str() {
|
||||
"temp" => {
|
||||
println!("{}", read_soc_temp([0]).unwrap()[1]);
|
||||
}
|
||||
"el0" => unsafe {
|
||||
let i = 69;
|
||||
asm!("", in("x0") i);
|
||||
el1_to_el0();
|
||||
},
|
||||
_ => {
|
||||
println!("Unknown command: \"{}\"", self.input);
|
||||
}
|
||||
}
|
||||
self.input.clear();
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Terminal {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
self.buffer.push_str(s);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Logger for Terminal {
|
||||
fn flush(&mut self) {
|
||||
println!("{}", self.buffer);
|
||||
print!("> {}", self.input);
|
||||
self.buffer.clear();
|
||||
}
|
||||
pub fn init_terminal() {
|
||||
unsafe { TERMINAL = Some(Terminal::new()) };
|
||||
register_terminal_interrupt_handler();
|
||||
}
|
||||
|
||||
fn terminal_uart_rx_interrupt_handler() {
|
||||
print!("{}", read_uart_data());
|
||||
let input = read_uart_data();
|
||||
#[allow(static_mut_refs)]
|
||||
if let Some(term) = unsafe { TERMINAL.as_mut() } {
|
||||
match input {
|
||||
'\r' => {
|
||||
term.exec();
|
||||
term.flush();
|
||||
}
|
||||
_ => {
|
||||
term.input.push(input);
|
||||
print!("{}", input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_terminal_interrupt_handler() {
|
||||
register_interrupt_handler(
|
||||
nova::interrupt_handlers::IRQSource::UartInt,
|
||||
terminal_uart_rx_interrupt_handler,
|
||||
);
|
||||
pub fn flush_terminal() {
|
||||
#[allow(static_mut_refs)]
|
||||
if let Some(term) = unsafe { TERMINAL.as_mut() } {
|
||||
term.flush();
|
||||
}
|
||||
}
|
||||
|
||||
fn register_terminal_interrupt_handler() {
|
||||
register_interrupt_handler(IRQSource::UartInt, terminal_uart_rx_interrupt_handler);
|
||||
}
|
||||
|
||||
@@ -11,4 +11,5 @@ pub enum NovaError {
|
||||
Misalignment,
|
||||
InvalidGranularity,
|
||||
Paging,
|
||||
OutOfMeomory,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user