diff --git a/Cargo.lock b/Cargo.lock index e1ca0dc..544a7cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,8 +20,6 @@ dependencies = [ "embedded-graphics", "embedded-sdmmc", "rand_core 0.9.3", - "spin 0.10.0", - "talc", ] [[package]] @@ -1039,6 +1037,7 @@ dependencies = [ [[package]] name = "embedded-snake" version = "0.0.3" +source = "git+https://github.com/LegitCamper/embedded-snake-rs#3986819c55819283dc5c1e89717d2a2f52e9b161" dependencies = [ "embedded-graphics", "rand_core 0.9.3", diff --git a/abi/Cargo.toml b/abi/Cargo.toml index 935faa5..47e7d1f 100644 --- a/abi/Cargo.toml +++ b/abi/Cargo.toml @@ -7,6 +7,4 @@ edition = "2024" embedded-sdmmc = { version = "0.9.0", default-features = false } embedded-graphics = "0.8.1" abi_sys = { path = "../abi_sys" } -talc = "4.4.3" -spin = "0.10.0" rand_core = "0.9.3" diff --git a/abi/src/lib.rs b/abi/src/lib.rs index 7fadd43..9805a2c 100644 --- a/abi/src/lib.rs +++ b/abi/src/lib.rs @@ -1,18 +1,26 @@ #![no_std] -pub use abi_sys::keyboard; -use abi_sys::{RngRequest, keyboard::KeyEvent}; -use rand_core::RngCore; -use talc::*; - extern crate alloc; -static mut ARENA: [u8; 10000] = [0; 10000]; +pub use abi_sys::keyboard; +use abi_sys::{RngRequest, alloc, dealloc, keyboard::KeyEvent}; +use core::alloc::{GlobalAlloc, Layout}; +use rand_core::RngCore; #[global_allocator] -static ALLOCATOR: Talck, ClaimOnOom> = - Talc::new(unsafe { ClaimOnOom::new(Span::from_array(core::ptr::addr_of!(ARENA).cast_mut())) }) - .lock(); +static ALLOC: Alloc = Alloc; + +struct Alloc; + +unsafe impl GlobalAlloc for Alloc { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + alloc(layout.into()) + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + dealloc(ptr, layout.into()); + } +} pub fn print(msg: &str) { abi_sys::print(msg.as_ptr(), msg.len()); diff --git a/abi_sys/Cargo.toml b/abi_sys/Cargo.toml index a64b5e5..e30198a 100644 --- a/abi_sys/Cargo.toml +++ b/abi_sys/Cargo.toml @@ -4,7 +4,8 @@ version = "0.1.0" edition = "2024" [features] -default = [] +default = ["alloc"] +alloc = [] defmt = ["dep:defmt"] [dependencies] diff --git a/abi_sys/src/lib.rs b/abi_sys/src/lib.rs index b7ac704..db81b70 100644 --- a/abi_sys/src/lib.rs +++ b/abi_sys/src/lib.rs @@ -1,42 +1,89 @@ #![no_std] +#[cfg(feature = "alloc")] +use core::alloc::Layout; + use embedded_graphics::{ Pixel, pixelcolor::{Rgb565, raw::RawU16}, prelude::{IntoStorage, Point}, }; use embedded_sdmmc::DirEntry; -use strum::EnumIter; - -pub const ABI_CALL_TABLE_COUNT: usize = 10; - -#[derive(Clone, Copy, EnumIter)] -#[repr(u8)] -pub enum CallAbiTable { - PrintString = 0, - SleepMs = 1, - GetMs = 2, - LockDisplay = 3, - DrawIter = 4, - GetKey = 5, - GenRand = 6, - ListDir = 7, - ReadFile = 8, - FileLen = 9, -} +use strum::{EnumCount, EnumIter}; pub type EntryFn = fn(); +pub const ABI_CALL_TABLE_COUNT: usize = 12; +const _: () = assert!(ABI_CALL_TABLE_COUNT == CallTable::COUNT); + +#[derive(Clone, Copy, EnumIter, EnumCount)] +#[repr(u8)] +pub enum CallTable { + Alloc = 0, + Dealloc = 1, + PrintString = 2, + SleepMs = 3, + GetMs = 4, + LockDisplay = 5, + DrawIter = 6, + GetKey = 7, + GenRand = 8, + ListDir = 9, + ReadFile = 10, + FileLen = 11, +} + #[unsafe(no_mangle)] #[unsafe(link_section = ".syscall_table")] pub static mut CALL_ABI_TABLE: [usize; ABI_CALL_TABLE_COUNT] = [0; ABI_CALL_TABLE_COUNT]; +#[cfg(feature = "alloc")] +#[repr(C)] +pub struct CLayout { + size: usize, + alignment: usize, +} + +#[cfg(feature = "alloc")] +impl Into for CLayout { + fn into(self) -> Layout { + unsafe { Layout::from_size_align_unchecked(self.size, self.alignment) } + } +} + +#[cfg(feature = "alloc")] +impl From for CLayout { + fn from(value: Layout) -> Self { + Self { + size: value.size(), + alignment: value.align(), + } + } +} + +pub type AllocAbi = extern "C" fn(layout: CLayout) -> *mut u8; + +#[unsafe(no_mangle)] +pub extern "C" fn alloc(layout: CLayout) -> *mut u8 { + let f: AllocAbi = unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::Alloc as usize]) }; + f(layout) +} + +pub type DeallocAbi = extern "C" fn(ptr: *mut u8, layout: CLayout); + +#[unsafe(no_mangle)] +pub extern "C" fn dealloc(ptr: *mut u8, layout: CLayout) { + let f: DeallocAbi = + unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::Dealloc as usize]) }; + f(ptr, layout) +} + pub type PrintAbi = extern "C" fn(ptr: *const u8, len: usize); #[unsafe(no_mangle)] pub extern "C" fn print(ptr: *const u8, len: usize) { let f: PrintAbi = - unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::PrintString as usize]) }; + unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::PrintString as usize]) }; f(ptr, len); } @@ -45,7 +92,7 @@ pub type SleepMsAbi = extern "C" fn(ms: u64); #[unsafe(no_mangle)] pub extern "C" fn sleep(ms: u64) { let f: SleepMsAbi = - unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::SleepMs as usize]) }; + unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::SleepMs as usize]) }; f(ms); } @@ -53,7 +100,7 @@ pub type GetMsAbi = extern "C" fn() -> u64; #[unsafe(no_mangle)] pub extern "C" fn get_ms() -> u64 { - let f: GetMsAbi = unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::GetMs as usize]) }; + let f: GetMsAbi = unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::GetMs as usize]) }; f() } @@ -62,7 +109,7 @@ pub type LockDisplay = extern "C" fn(lock: bool); #[unsafe(no_mangle)] pub extern "C" fn lock_display(lock: bool) { let f: LockDisplay = - unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::LockDisplay as usize]) }; + unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::LockDisplay as usize]) }; f(lock); } @@ -105,12 +152,12 @@ pub type DrawIterAbi = extern "C" fn(ptr: *const CPixel, len: usize); #[unsafe(no_mangle)] pub extern "C" fn draw_iter(ptr: *const CPixel, len: usize) { let f: DrawIterAbi = - unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::DrawIter as usize]) }; + unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::DrawIter as usize]) }; f(ptr, len); } pub mod keyboard { - use crate::{CALL_ABI_TABLE, CallAbiTable}; + use crate::{CALL_ABI_TABLE, CallTable}; bitflags::bitflags! { #[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] @@ -333,7 +380,7 @@ pub mod keyboard { #[unsafe(no_mangle)] pub extern "C" fn get_key() -> KeyEventC { let f: GetKeyAbi = - unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::GetKey as usize]) }; + unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::GetKey as usize]) }; f() } } @@ -350,7 +397,7 @@ pub type GenRand = extern "C" fn(req: &mut RngRequest); #[unsafe(no_mangle)] pub extern "C" fn gen_rand(req: &mut RngRequest) { unsafe { - let ptr = CALL_ABI_TABLE[CallAbiTable::GenRand as usize]; + let ptr = CALL_ABI_TABLE[CallTable::GenRand as usize]; let f: GenRand = core::mem::transmute(ptr); f(req) } @@ -371,7 +418,7 @@ pub extern "C" fn list_dir( file_len: usize, ) -> usize { unsafe { - let ptr = CALL_ABI_TABLE[CallAbiTable::ListDir as usize]; + let ptr = CALL_ABI_TABLE[CallTable::ListDir as usize]; let f: ListDir = core::mem::transmute(ptr); f(str, len, files, file_len) } @@ -394,7 +441,7 @@ pub extern "C" fn read_file( buf_len: usize, ) -> usize { unsafe { - let ptr = CALL_ABI_TABLE[CallAbiTable::ReadFile as usize]; + let ptr = CALL_ABI_TABLE[CallTable::ReadFile as usize]; let f: ReadFile = core::mem::transmute(ptr); f(str, len, read_from, buf, buf_len) } @@ -405,7 +452,7 @@ pub type FileLen = extern "C" fn(str: *const u8, len: usize) -> usize; #[unsafe(no_mangle)] pub extern "C" fn file_len(str: *const u8, len: usize) -> usize { unsafe { - let ptr = CALL_ABI_TABLE[CallAbiTable::FileLen as usize]; + let ptr = CALL_ABI_TABLE[CallTable::FileLen as usize]; let f: FileLen = core::mem::transmute(ptr); f(str, len) } diff --git a/kernel/src/abi.rs b/kernel/src/abi.rs index 027b021..7a8a843 100644 --- a/kernel/src/abi.rs +++ b/kernel/src/abi.rs @@ -1,6 +1,6 @@ use abi_sys::{ - CPixel, DrawIterAbi, FileLen, GenRand, GetMsAbi, ListDir, LockDisplay, PrintAbi, ReadFile, - RngRequest, SleepMsAbi, keyboard::*, + AllocAbi, CLayout, CPixel, DeallocAbi, DrawIterAbi, FileLen, GenRand, GetMsAbi, ListDir, + LockDisplay, PrintAbi, ReadFile, RngRequest, SleepMsAbi, keyboard::*, }; use alloc::{string::ToString, vec::Vec}; use core::sync::atomic::Ordering; @@ -15,6 +15,18 @@ use crate::{ storage::{Dir, File, SDCARD}, }; +const _: AllocAbi = alloc; +pub extern "C" fn alloc(layout: CLayout) -> *mut u8 { + // SAFETY: caller guarantees layout is valid + unsafe { alloc::alloc::alloc(layout.into()) } +} + +const _: DeallocAbi = dealloc; +pub extern "C" fn dealloc(ptr: *mut u8, layout: CLayout) { + // SAFETY: caller guarantees ptr and layout are valid + unsafe { alloc::alloc::dealloc(ptr, layout.into()) }; +} + const _: PrintAbi = print; pub extern "C" fn print(ptr: *const u8, len: usize) { // SAFETY: caller guarantees `ptr` is valid for `len` bytes diff --git a/kernel/src/display.rs b/kernel/src/display.rs index ee7996b..8269e85 100644 --- a/kernel/src/display.rs +++ b/kernel/src/display.rs @@ -21,7 +21,7 @@ type DISPLAY = ST7365P< pub const SCREEN_WIDTH: usize = 320; pub const SCREEN_HEIGHT: usize = 320; -pub static mut FRAMEBUFFER: AtomicFrameBuffer = AtomicFrameBuffer::new(); +pub static mut FRAMEBUFFER: AtomicFrameBuffer = AtomicFrameBuffer; pub static FB_PAUSED: AtomicBool = AtomicBool::new(false); pub async fn init_display( diff --git a/kernel/src/elf.rs b/kernel/src/elf.rs index 2fcec1b..334e3ab 100644 --- a/kernel/src/elf.rs +++ b/kernel/src/elf.rs @@ -2,7 +2,7 @@ use crate::{ abi, storage::{File, SDCARD}, }; -use abi_sys::CallAbiTable; +use abi_sys::CallTable; use abi_sys::EntryFn; use alloc::{vec, vec::Vec}; use bumpalo::Bump; @@ -194,18 +194,20 @@ fn patch_abi( unsafe { base.add((sym.st_value as usize) - min_vaddr as usize) } as *mut usize; - for (idx, call) in CallAbiTable::iter().enumerate() { + for (idx, call) in CallTable::iter().enumerate() { let ptr = match call { - CallAbiTable::PrintString => abi::print as usize, - CallAbiTable::SleepMs => abi::sleep as usize, - CallAbiTable::GetMs => abi::get_ms as usize, - CallAbiTable::LockDisplay => abi::lock_display as usize, - CallAbiTable::DrawIter => abi::draw_iter as usize, - CallAbiTable::GetKey => abi::get_key as usize, - CallAbiTable::GenRand => abi::gen_rand as usize, - CallAbiTable::ListDir => abi::list_dir as usize, - CallAbiTable::ReadFile => abi::read_file as usize, - CallAbiTable::FileLen => abi::file_len as usize, + CallTable::Alloc => abi::alloc as usize, + CallTable::Dealloc => abi::dealloc as usize, + CallTable::PrintString => abi::print as usize, + CallTable::SleepMs => abi::sleep as usize, + CallTable::GetMs => abi::get_ms as usize, + CallTable::LockDisplay => abi::lock_display as usize, + CallTable::DrawIter => abi::draw_iter as usize, + CallTable::GetKey => abi::get_key as usize, + CallTable::GenRand => abi::gen_rand as usize, + CallTable::ListDir => abi::list_dir as usize, + CallTable::ReadFile => abi::read_file as usize, + CallTable::FileLen => abi::file_len as usize, }; unsafe { table_base.add(idx as usize).write(ptr); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 887b65d..8b0e247 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -241,19 +241,21 @@ async fn setup_display(display: Display, spawner: Spawner) { spawner.spawn(display_handler(display)).unwrap(); } +// psram is kind of useless on the pico calc +// ive opted to use the pimoroni with on onboard xip psram instead async fn setup_psram(psram: Psram) { - let psram = init_psram( - psram.pio, psram.sclk, psram.mosi, psram.miso, psram.cs, psram.dma1, psram.dma2, - ) - .await; + // let psram = init_psram( + // psram.pio, psram.sclk, psram.mosi, psram.miso, psram.cs, psram.dma1, psram.dma2, + // ) + // .await; - #[cfg(feature = "defmt")] - defmt::info!("psram size: {}", psram.size); + // #[cfg(feature = "defmt")] + // defmt::info!("psram size: {}", psram.size); - if psram.size == 0 { - #[cfg(feature = "defmt")] - defmt::info!("\u{1b}[1mExternal PSRAM was NOT found!\u{1b}[0m"); - } + // if psram.size == 0 { + // #[cfg(feature = "defmt")] + // defmt::info!("\u{1b}[1mExternal PSRAM was NOT found!\u{1b}[0m"); + // } #[cfg(feature = "pimoroni2w")] { @@ -291,6 +293,7 @@ async fn kernel_task( setup_mcu(mcu).await; Timer::after_millis(250).await; setup_display(display, spawner).await; + #[cfg(feature = "pimoroni2w")] setup_psram(psram).await; setup_sd(sd).await; diff --git a/user-apps/gif/src/main.rs b/user-apps/gif/src/main.rs index 3407a83..c749bf2 100644 --- a/user-apps/gif/src/main.rs +++ b/user-apps/gif/src/main.rs @@ -4,15 +4,15 @@ extern crate alloc; use abi::{ display::{Display, lock_display}, - fs::read_file, + fs::{file_len, read_file}, get_key, get_ms, keyboard::{KeyCode, KeyState}, print, sleep, }; -use alloc::format; +use alloc::{format, vec::Vec}; use core::panic::PanicInfo; use embedded_graphics::{image::ImageDrawable, pixelcolor::Rgb565}; -use tinygif::{Gif, Header}; +use tinygif::Gif; #[panic_handler] fn panic(info: &PanicInfo) -> ! { @@ -33,19 +33,20 @@ pub fn main() { print("Starting Gif app"); let mut display = Display; - static mut BUF: [u8; 256] = [0_u8; 256]; + let size = file_len("/gifs/bad_apple.gif"); + let mut buf = Vec::with_capacity(size); + let read = read_file("/gifs/bad_apple.gif", 0, &mut buf); + assert!(read == size); - read_file("/gif/bad_apple.gif", 0, unsafe { &mut BUF[0..6] }); - - let gif_header = Header::parse(unsafe { &BUF[0..6] }); - - let image = Gif::::from_slice().unwrap(); + let gif = Gif::::from_slice(&buf).unwrap(); loop { - for frame in image.frames() { + for frame in gif.frames() { let start = get_ms(); + lock_display(true); frame.draw(&mut display).unwrap(); + lock_display(false); sleep(((frame.delay_centis as u64) * 10).saturating_sub(start)); @@ -56,9 +57,6 @@ pub fn main() { _ => (), }; }; - - lock_display(true); - lock_display(false); } } } diff --git a/user-apps/snake/Cargo.toml b/user-apps/snake/Cargo.toml index 5ce4e74..7eb0d67 100644 --- a/user-apps/snake/Cargo.toml +++ b/user-apps/snake/Cargo.toml @@ -6,5 +6,5 @@ edition = "2024" [dependencies] abi = { path = "../../abi" } embedded-graphics = "0.8.1" -embedded-snake = { path = "../../../embedded-snake-rs" } +embedded-snake = { git = "https://github.com/LegitCamper/embedded-snake-rs" } rand = { version = "0.9.0", default-features = false }