use C abi for syscalls
This commit is contained in:
@@ -29,62 +29,48 @@ pub enum CallAbiTable {
|
||||
GenRand = 5,
|
||||
}
|
||||
|
||||
pub type PrintAbi = extern "Rust" fn(msg: &str);
|
||||
pub type PrintAbi = extern "C" fn(ptr: *const u8, len: usize);
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn print(msg: &str) {
|
||||
unsafe {
|
||||
let ptr = CALL_ABI_TABLE[CallAbiTable::Print as usize];
|
||||
let f: PrintAbi = core::mem::transmute(ptr);
|
||||
f(msg);
|
||||
}
|
||||
let f: PrintAbi = unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::Print as usize]) };
|
||||
f(msg.as_ptr(), msg.len());
|
||||
}
|
||||
|
||||
pub type SleepAbi = extern "Rust" fn(ms: u64);
|
||||
pub type SleepAbi = extern "C" fn(ms: u64);
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn sleep(ms: u64) {
|
||||
unsafe {
|
||||
let ptr = CALL_ABI_TABLE[CallAbiTable::Sleep as usize];
|
||||
let f: SleepAbi = core::mem::transmute(ptr);
|
||||
let f: SleepAbi = unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::Sleep as usize]) };
|
||||
f(ms);
|
||||
}
|
||||
}
|
||||
|
||||
pub type LockDisplay = extern "Rust" fn(lock: bool);
|
||||
pub type LockDisplay = extern "C" fn(lock: bool);
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn lock_display(lock: bool) {
|
||||
unsafe {
|
||||
let ptr = CALL_ABI_TABLE[CallAbiTable::LockDisplay as usize];
|
||||
let f: LockDisplay = core::mem::transmute(ptr);
|
||||
let f: LockDisplay =
|
||||
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::LockDisplay as usize]) };
|
||||
f(lock);
|
||||
}
|
||||
}
|
||||
|
||||
pub type DrawIterAbi = extern "Rust" fn(pixels: &[Pixel<Rgb565>]);
|
||||
pub type DrawIterAbi = extern "C" fn(ptr: *const Pixel<Rgb565>, len: usize);
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn draw_iter(pixels: &[Pixel<Rgb565>]) {
|
||||
unsafe {
|
||||
let ptr = CALL_ABI_TABLE[CallAbiTable::DrawIter as usize];
|
||||
let f: DrawIterAbi = core::mem::transmute(ptr);
|
||||
f(pixels);
|
||||
}
|
||||
let f: DrawIterAbi =
|
||||
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::DrawIter as usize]) };
|
||||
f(pixels.as_ptr(), pixels.len());
|
||||
}
|
||||
|
||||
pub type GetKeyAbi = extern "Rust" fn() -> Option<KeyEvent>;
|
||||
pub type GetKeyAbi = extern "C" fn() -> KeyEvent;
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn get_key() -> Option<KeyEvent> {
|
||||
unsafe {
|
||||
let ptr = CALL_ABI_TABLE[CallAbiTable::GetKey as usize];
|
||||
let f: GetKeyAbi = core::mem::transmute(ptr);
|
||||
pub fn get_key() -> KeyEvent {
|
||||
let f: GetKeyAbi =
|
||||
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallAbiTable::GetKey as usize]) };
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
pub type GenRand = extern "Rust" fn(req: &mut RngRequest);
|
||||
|
||||
#[repr(C)]
|
||||
pub enum RngRequest {
|
||||
@@ -93,6 +79,8 @@ pub enum RngRequest {
|
||||
Bytes { ptr: *mut u8, len: usize },
|
||||
}
|
||||
|
||||
pub type GenRand = extern "C" fn(req: &mut RngRequest);
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn gen_rand(req: &mut RngRequest) {
|
||||
unsafe {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use abi_sys::{DrawIterAbi, GetKeyAbi, LockDisplay, PrintAbi, RngRequest, SleepAbi};
|
||||
use abi_sys::{
|
||||
DrawIterAbi, GenRand, GetKeyAbi, LockDisplay, Modifiers, PrintAbi, RngRequest, SleepAbi,
|
||||
};
|
||||
use core::sync::atomic::Ordering;
|
||||
use embassy_rp::clocks::{RoscRng, clk_sys_freq};
|
||||
use embedded_graphics::{Pixel, draw_target::DrawTarget, pixelcolor::Rgb565};
|
||||
@@ -9,18 +11,20 @@ use crate::{
|
||||
display::{FB_PAUSED, FRAMEBUFFER},
|
||||
};
|
||||
|
||||
// ensure the abi and the kernel fn signatures are the same
|
||||
const _: PrintAbi = print;
|
||||
const _: SleepAbi = sleep;
|
||||
const _: LockDisplay = lock_display;
|
||||
const _: DrawIterAbi = draw_iter;
|
||||
const _: GetKeyAbi = get_key;
|
||||
pub extern "C" fn print(ptr: *const u8, len: usize) {
|
||||
// SAFETY: caller guarantees `ptr` is valid for `len` bytes
|
||||
let slice = unsafe { core::slice::from_raw_parts(ptr, len) };
|
||||
|
||||
pub extern "Rust" fn print(msg: &str) {
|
||||
defmt::info!("{:?}", msg);
|
||||
if let Ok(msg) = core::str::from_utf8(slice) {
|
||||
defmt::info!("print: {}", msg);
|
||||
} else {
|
||||
defmt::warn!("print: <invalid utf8>");
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "Rust" fn sleep(ms: u64) {
|
||||
const _: SleepAbi = sleep;
|
||||
pub extern "C" fn sleep(ms: u64) {
|
||||
let cycles_per_ms = clk_sys_freq() / 1000;
|
||||
let total_cycles = ms * cycles_per_ms as u64;
|
||||
|
||||
@@ -29,20 +33,33 @@ pub extern "Rust" fn sleep(ms: u64) {
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "Rust" fn lock_display(lock: bool) {
|
||||
const _: LockDisplay = lock_display;
|
||||
pub extern "C" fn lock_display(lock: bool) {
|
||||
FB_PAUSED.store(lock, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
const _: DrawIterAbi = draw_iter;
|
||||
// TODO: maybe return result
|
||||
pub extern "Rust" fn draw_iter(pixels: &[Pixel<Rgb565>]) {
|
||||
pub extern "C" fn draw_iter(pixels: *const Pixel<Rgb565>, len: usize) {
|
||||
let pixels = unsafe { core::slice::from_raw_parts(pixels, len) };
|
||||
unsafe { FRAMEBUFFER.draw_iter(pixels.iter().copied()).unwrap() }
|
||||
}
|
||||
|
||||
pub extern "Rust" fn get_key() -> Option<KeyEvent> {
|
||||
unsafe { KEY_CACHE.dequeue() }
|
||||
const _: GetKeyAbi = get_key;
|
||||
pub extern "C" fn get_key() -> KeyEvent {
|
||||
if let Some(event) = unsafe { KEY_CACHE.dequeue() } {
|
||||
event
|
||||
} else {
|
||||
KeyEvent {
|
||||
key: abi_sys::KeyCode::Unknown(0),
|
||||
state: abi_sys::KeyState::Idle,
|
||||
mods: Modifiers::empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "Rust" fn gen_rand(req: &mut RngRequest) {
|
||||
const _: GenRand = gen_rand;
|
||||
pub extern "C" fn gen_rand(req: &mut RngRequest) {
|
||||
let mut rng = RoscRng;
|
||||
|
||||
match req {
|
||||
|
||||
@@ -14,6 +14,7 @@ pub mod keyboard {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct KeyEvent {
|
||||
pub key: KeyCode,
|
||||
pub state: KeyState,
|
||||
@@ -22,6 +23,7 @@ pub mod keyboard {
|
||||
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum KeyState {
|
||||
Idle = 0,
|
||||
Pressed = 1,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#![no_main]
|
||||
|
||||
extern crate alloc;
|
||||
use abi::{KeyCode, display::Display, get_key, lock_display, print};
|
||||
use abi::{KeyCode, KeyState, display::Display, get_key, lock_display, print};
|
||||
use alloc::{format, string::String, vec, vec::Vec};
|
||||
use core::panic::PanicInfo;
|
||||
use embedded_graphics::{
|
||||
@@ -105,7 +105,8 @@ pub fn main() {
|
||||
lock_display(false);
|
||||
}
|
||||
|
||||
if let Some(event) = get_key() {
|
||||
let event = get_key();
|
||||
if event.state != KeyState::Idle {
|
||||
match event.key {
|
||||
KeyCode::Char(ch) => {
|
||||
input.push(ch);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
extern crate alloc;
|
||||
use abi::{
|
||||
KeyCode, Rng,
|
||||
KeyCode, KeyState, Rng,
|
||||
display::{Display, SCREEN_HEIGHT, SCREEN_WIDTH},
|
||||
get_key, lock_display, print, sleep,
|
||||
};
|
||||
@@ -46,7 +46,8 @@ pub fn main() {
|
||||
);
|
||||
|
||||
loop {
|
||||
if let Some(event) = get_key() {
|
||||
let event = get_key();
|
||||
if event.state != KeyState::Idle {
|
||||
let direction = match event.key {
|
||||
KeyCode::Up => Direction::Up,
|
||||
KeyCode::Down => Direction::Down,
|
||||
@@ -56,7 +57,7 @@ pub fn main() {
|
||||
_ => Direction::None,
|
||||
};
|
||||
game.set_direction(direction);
|
||||
}
|
||||
};
|
||||
|
||||
// ensure all draws show up at once
|
||||
lock_display(true);
|
||||
|
||||
Reference in New Issue
Block a user