// SPDX-License-Identifier: MIT OR Apache-2.0 // // Copyright (c) 2018-2022 Andre Richter // Rust embedded logo for `make doc`. #![doc( html_logo_url = "https://raw.githubusercontent.com/rust-embedded/wg/master/assets/logo/ewg-logo-blue-white-on-transparent.png" )] //! The `kernel` binary. #![feature(format_args_nl)] #![no_main] #![no_std] use libkernel::{bsp, cpu, driver, exception, info, memory, state, time, warn}; /// Early init code. /// /// When this code runs, virtual memory is already enabled. /// /// # Safety /// /// - Only a single core must be active and running this function. /// - Printing will not work until the respective driver's MMIO is remapped. #[no_mangle] unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); memory::init(); // Instantiate and init all device drivers. if let Err(x) = bsp::driver::driver_manager().instantiate_drivers() { panic!("Error instantiating drivers: {}", x); } for i in bsp::driver::driver_manager().all_device_drivers().iter() { if let Err(x) = i.init() { panic!("Error loading driver: {}: {}", i.compatible(), x); } } // Let device drivers register and enable their handlers with the interrupt controller. for i in bsp::driver::driver_manager().all_device_drivers() { if let Err(msg) = i.register_and_enable_irq_handler() { warn!("Error registering IRQ handler: {}", msg); } } bsp::memory::mmu::kernel_add_mapping_records_for_precomputed(); // Unmask interrupts on the boot CPU core. exception::asynchronous::local_irq_unmask(); // Announce conclusion of the kernel_init() phase. state::state_manager().transition_to_single_core_main(); // Transition from unsafe to safe. kernel_main() } /// The main function running after the early init. fn kernel_main() -> ! { use driver::interface::DriverManager; info!("{}", libkernel::version()); info!("Booting on: {}", bsp::board_name()); info!("MMU online:"); memory::mmu::kernel_print_mappings(); let (_, privilege_level) = exception::current_privilege_level(); info!("Current privilege level: {}", privilege_level); info!("Exception handling state:"); exception::asynchronous::print_state(); info!( "Architectural timer resolution: {} ns", time::time_manager().resolution().as_nanos() ); info!("Drivers loaded:"); for (i, driver) in bsp::driver::driver_manager() .all_device_drivers() .iter() .enumerate() { info!(" {}. {}", i + 1, driver.compatible()); } info!("Registered IRQ handlers:"); exception::asynchronous::irq_manager().print_handler(); info!("Echoing input now"); cpu::wait_forever(); }