// 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, console, driver, exception, info, memory, time}; /// Early init code. /// /// # Safety /// /// - Only a single core must be active and running this function. /// - The init calls in this function must appear in the correct order: /// - MMU + Data caching must be activated at the earliest. Without it, any atomic operations, /// e.g. the yet-to-be-introduced spinlocks in the device drivers (which currently employ /// NullLocks instead of spinlocks), will fail to work (properly) on the RPi SoCs. #[no_mangle] unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; use memory::mmu::interface::MMU; exception::handling_init(); if let Err(string) = memory::mmu::mmu().enable_mmu_and_caching() { panic!("MMU: {}", string); } for i in bsp::driver::driver_manager().all_device_drivers().iter() { if let Err(x) = i.init() { panic!("Error loading driver: {}: {}", i.compatible(), x); } } bsp::driver::driver_manager().post_device_driver_init(); // println! is usable from here on. // Transition from unsafe to safe. kernel_main() } /// The main function running after the early init. fn kernel_main() -> ! { use console::console; use driver::interface::DriverManager; info!("{}", libkernel::version()); info!("Booting on: {}", bsp::board_name()); info!("MMU online. Special regions:"); bsp::memory::mmu::virt_mem_layout().print_layout(); 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!("Echoing input now"); // Discard any spurious received characters before going into echo mode. console().clear_rx(); loop { let c = console().read_char(); console().write_char(c); } }