wip dynamic loading
This commit is contained in:
11
Cargo.toml
11
Cargo.toml
@@ -3,7 +3,16 @@ resolver = "3"
|
||||
members = ["kernel", "abi", "shared", "user-apps/calculator"]
|
||||
|
||||
[profile.release]
|
||||
debug = 2
|
||||
debug = true
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
|
||||
[profile.release-binary]
|
||||
inherits = "release"
|
||||
lto = true
|
||||
debug = false
|
||||
opt-level = "s"
|
||||
|
||||
[profile.dev]
|
||||
lto = true
|
||||
|
||||
2
justfile
2
justfile
@@ -1,4 +1,4 @@
|
||||
kernel: calculator
|
||||
cargo run --bin kernel
|
||||
calculator:
|
||||
RUSTFLAGS="-C link-arg=--noinhibit-exec" cargo build --bin calculator --release
|
||||
RUSTFLAGS="-C link-arg=--noinhibit-exec" cargo build --bin calculator --profile release-binary
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![allow(static_mut_refs)]
|
||||
use crate::abi;
|
||||
use crate::{abi, storage::SDCARD};
|
||||
use abi_sys::{CallAbiTable, EntryFn};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use core::{
|
||||
alloc::Layout,
|
||||
ffi::c_void,
|
||||
@@ -10,8 +10,43 @@ use core::{
|
||||
slice::from_raw_parts_mut,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use embedded_sdmmc::ShortFileName;
|
||||
use goblin::elf::{Elf, header::ET_DYN, program_header::PT_LOAD, sym};
|
||||
|
||||
pub async fn read_binary(name: &ShortFileName) -> Option<Vec<u8>> {
|
||||
let mut guard = SDCARD.get().lock().await;
|
||||
let sd = guard.as_mut()?;
|
||||
|
||||
let mut buf = Vec::new();
|
||||
|
||||
defmt::info!("sd closure");
|
||||
sd.access_root_dir(|root_dir| {
|
||||
// Try to open the file directly by name
|
||||
defmt::info!("trying to open file: {:?}", name);
|
||||
if let Ok(file) = root_dir.open_file_in_dir(name, embedded_sdmmc::Mode::ReadOnly) {
|
||||
defmt::info!("opened");
|
||||
let mut temp = [0u8; 512];
|
||||
|
||||
defmt::info!("caching binary");
|
||||
loop {
|
||||
match file.read(&mut temp) {
|
||||
Ok(n) if n > 0 => buf.extend_from_slice(&temp[..n]),
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
defmt::info!("done");
|
||||
let _ = file.close();
|
||||
}
|
||||
});
|
||||
|
||||
if buf.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(buf)
|
||||
}
|
||||
|
||||
// userland ram region defined in memory.x
|
||||
unsafe extern "C" {
|
||||
static __userapp_start__: u8;
|
||||
|
||||
@@ -30,6 +30,7 @@ use crate::{
|
||||
ui::{SELECTIONS, ui_handler},
|
||||
usb::usb_handler,
|
||||
};
|
||||
use abi_sys::EntryFn;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
@@ -48,7 +49,7 @@ use embassy_rp::{
|
||||
spi::{self, Spi},
|
||||
usb as embassy_rp_usb,
|
||||
};
|
||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
|
||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel, mutex::Mutex};
|
||||
use embassy_time::{Delay, Timer};
|
||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||
use embedded_sdmmc::SdCard as SdmmcSdCard;
|
||||
@@ -66,7 +67,7 @@ static mut CORE1_STACK: Stack<16384> = Stack::new();
|
||||
static EXECUTOR0: StaticCell<Executor> = StaticCell::new();
|
||||
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
|
||||
|
||||
static mut ARENA: [u8; 10000] = [0; 10000];
|
||||
static mut ARENA: [u8; 10 * 1024] = [0; 10 * 1024];
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: Talck<spin::Mutex<()>, ClaimOnOom> =
|
||||
@@ -121,19 +122,30 @@ async fn main(_spawner: Spawner) {
|
||||
executor0.run(|spawner| unwrap!(spawner.spawn(kernel_task(display, sd, mcu, p.USB))));
|
||||
}
|
||||
|
||||
// One-slot channel to pass EntryFn from core1
|
||||
static BINARY_CH: Channel<CriticalSectionRawMutex, EntryFn, 1> = Channel::new();
|
||||
|
||||
// runs dynamically loaded elf files
|
||||
#[embassy_executor::task]
|
||||
async fn userland_task() {
|
||||
// DRIVERS_READY.wait().await;
|
||||
let recv = BINARY_CH.receiver();
|
||||
loop {
|
||||
let entry = recv.receive().await;
|
||||
|
||||
// defmt::info!("Loading binary");
|
||||
// let binary_data: &[u8] =
|
||||
// include_bytes!("../../target/thumbv8m.main-none-eabihf/release/calculator");
|
||||
// disable kernel ui
|
||||
{
|
||||
let mut state = TASK_STATE.lock().await;
|
||||
*state = TaskState::Kernel;
|
||||
}
|
||||
|
||||
// defmt::info!("Running binary");
|
||||
// let entry = unsafe { load_binary(binary_data).unwrap() };
|
||||
entry().await;
|
||||
|
||||
// entry().await;
|
||||
// enable kernel ui
|
||||
{
|
||||
let mut state = TASK_STATE.lock().await;
|
||||
*state = TaskState::Ui;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Display {
|
||||
@@ -224,8 +236,8 @@ async fn kernel_task(display: Display, sd: Sd, mcu: Mcu, usb: USB) {
|
||||
SDCARD.get().lock().await.replace(SdCard::new(sdcard, det));
|
||||
};
|
||||
|
||||
let usb = embassy_rp_usb::Driver::new(usb, Irqs);
|
||||
let usb_fut = usb_handler(usb);
|
||||
// let usb = embassy_rp_usb::Driver::new(usb, Irqs);
|
||||
// let usb_fut = usb_handler(usb);
|
||||
|
||||
let key_abi_fut = async {
|
||||
loop {
|
||||
|
||||
@@ -8,11 +8,11 @@ use embassy_sync::lazy_lock::LazyLock;
|
||||
use embassy_sync::mutex::Mutex;
|
||||
use embassy_time::Delay;
|
||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||
use embedded_sdmmc::LfnBuffer;
|
||||
use embedded_sdmmc::{
|
||||
Block, BlockCount, BlockDevice, BlockIdx, Directory, SdCard as SdmmcSdCard, TimeSource,
|
||||
Timestamp, Volume, VolumeIdx, VolumeManager, sdcard::Error,
|
||||
};
|
||||
use embedded_sdmmc::{LfnBuffer, ShortFileName};
|
||||
|
||||
pub const MAX_DIRS: usize = 4;
|
||||
pub const MAX_FILES: usize = 5;
|
||||
@@ -34,6 +34,12 @@ impl TimeSource for DummyTimeSource {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct FileName {
|
||||
pub long_name: String,
|
||||
pub short_name: ShortFileName,
|
||||
}
|
||||
|
||||
pub struct SdCard {
|
||||
det: Input<'static>,
|
||||
volume_mgr: VolMgr,
|
||||
@@ -100,7 +106,7 @@ impl SdCard {
|
||||
res.map_err(|_| ())
|
||||
}
|
||||
|
||||
fn access_root_dir(&mut self, mut access: impl FnMut(Dir)) {
|
||||
pub fn access_root_dir(&mut self, mut access: impl FnMut(Dir)) {
|
||||
let volume0 = self.volume_mgr.open_volume(VolumeIdx(0)).unwrap();
|
||||
let root_dir = volume0.open_root_dir().unwrap();
|
||||
|
||||
@@ -108,7 +114,7 @@ impl SdCard {
|
||||
}
|
||||
|
||||
/// Returns a Vec of file names (long format) that match the given extension (e.g., "BIN")
|
||||
pub fn list_files_by_extension(&mut self, ext: &str) -> Result<Vec<String>, ()> {
|
||||
pub fn list_files_by_extension(&mut self, ext: &str) -> Result<Vec<FileName>, ()> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
// Only proceed if card is inserted
|
||||
@@ -120,11 +126,14 @@ impl SdCard {
|
||||
let mut lfn_buffer = LfnBuffer::new(&mut lfn_storage);
|
||||
|
||||
self.access_root_dir(|dir| {
|
||||
dir.iterate_dir_lfn(&mut lfn_buffer, |_entry, name| {
|
||||
dir.iterate_dir_lfn(&mut lfn_buffer, |entry, name| {
|
||||
if let Some(name) = name {
|
||||
let name = String::from_str(name).unwrap();
|
||||
if name.contains(ext) {
|
||||
result.push(name);
|
||||
result.push(FileName {
|
||||
long_name: name,
|
||||
short_name: entry.name.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use crate::{
|
||||
TASK_STATE, TaskState,
|
||||
BINARY_CH, TASK_STATE, TaskState,
|
||||
display::{FRAMEBUFFER, SCREEN_HEIGHT, SCREEN_WIDTH},
|
||||
format,
|
||||
peripherals::keyboard,
|
||||
storage::FileName,
|
||||
usb::RESTART_USB,
|
||||
};
|
||||
use alloc::{string::String, vec::Vec};
|
||||
@@ -43,7 +44,7 @@ use embedded_text::TextBox;
|
||||
use shared::keyboard::{KeyCode, KeyState};
|
||||
|
||||
pub static SELECTIONS: Mutex<CriticalSectionRawMutex, SelectionList> =
|
||||
Mutex::new(SelectionList::new(Vec::new()));
|
||||
Mutex::new(SelectionList::new());
|
||||
|
||||
pub async fn ui_handler() {
|
||||
loop {
|
||||
@@ -59,7 +60,22 @@ pub async fn ui_handler() {
|
||||
let mut selections = SELECTIONS.lock().await;
|
||||
selections.down();
|
||||
}
|
||||
KeyCode::Enter | KeyCode::JoyRight => (),
|
||||
KeyCode::Enter | KeyCode::JoyRight => {
|
||||
let selections = SELECTIONS.lock().await;
|
||||
let selection = selections.selections
|
||||
[selections.current_selection as usize - 1]
|
||||
.clone();
|
||||
|
||||
defmt::info!(
|
||||
"loading selected binary: {:?}",
|
||||
&selection.long_name.as_str()
|
||||
);
|
||||
let bytes = crate::elf::read_binary(&selection.short_name)
|
||||
.await
|
||||
.unwrap();
|
||||
let entry = unsafe { crate::elf::load_binary(&bytes).unwrap() };
|
||||
BINARY_CH.send(entry).await;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@@ -71,7 +87,7 @@ pub async fn ui_handler() {
|
||||
}
|
||||
|
||||
async fn draw_selection() {
|
||||
let file_names: Vec<String> = {
|
||||
let file_names: Vec<FileName> = {
|
||||
let guard = SELECTIONS.lock().await;
|
||||
guard.selections.clone()
|
||||
};
|
||||
@@ -104,7 +120,7 @@ async fn draw_selection() {
|
||||
return;
|
||||
};
|
||||
|
||||
let chain = Chain::new(Text::new(first, Point::zero(), text_style));
|
||||
let chain = Chain::new(Text::new(&first.long_name, Point::zero(), text_style));
|
||||
|
||||
// for _ in 0..file_names.len() {
|
||||
// let chain = chain.append(Text::new(
|
||||
@@ -124,15 +140,16 @@ async fn draw_selection() {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SelectionList {
|
||||
current_selection: u16,
|
||||
pub selections: Vec<String>,
|
||||
pub selections: Vec<FileName>,
|
||||
}
|
||||
|
||||
impl SelectionList {
|
||||
pub const fn new(selections: Vec<String>) -> Self {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
selections,
|
||||
selections: Vec::new(),
|
||||
current_selection: 0,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user