diff --git a/fw16-epd-gui/src/element/button.rs b/eepy-gui/src/element/button.rs similarity index 99% rename from fw16-epd-gui/src/element/button.rs rename to eepy-gui/src/element/button.rs index 0ae87d8..ff85d15 100644 --- a/fw16-epd-gui/src/element/button.rs +++ b/eepy-gui/src/element/button.rs @@ -4,7 +4,7 @@ use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::primitives::{CornerRadii, PrimitiveStyle, Rectangle, RoundedRectangle}; use embedded_graphics::text::{Alignment, Baseline, Text, TextStyle, TextStyleBuilder}; use embedded_graphics::text::renderer::TextRenderer; -use fw16_epd_program_interface::{Event, TouchEventType}; +use eepy_sys::{Event, TouchEventType}; use crate::draw_target::EpdDrawTarget; use crate::element::{Gui, DEFAULT_PRIMITIVE_STYLE, DEFAULT_TEXT_STYLE}; diff --git a/fw16-epd-gui/src/element/mod.rs b/eepy-gui/src/element/mod.rs similarity index 96% rename from fw16-epd-gui/src/element/mod.rs rename to eepy-gui/src/element/mod.rs index b746122..b7939e3 100644 --- a/fw16-epd-gui/src/element/mod.rs +++ b/eepy-gui/src/element/mod.rs @@ -6,7 +6,7 @@ use embedded_graphics::mono_font::MonoTextStyle; use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::prelude::*; use embedded_graphics::primitives::{PrimitiveStyle, PrimitiveStyleBuilder, Rectangle}; -use fw16_epd_program_interface::Event; +use eepy_sys::Event; use tp370pgh01::{DIM_X, DIM_Y}; use crate::draw_target::EpdDrawTarget; diff --git a/fw16-epd-gui/src/element/slider.rs b/eepy-gui/src/element/slider.rs similarity index 98% rename from fw16-epd-gui/src/element/slider.rs rename to eepy-gui/src/element/slider.rs index 61feca8..f4b60ef 100644 --- a/fw16-epd-gui/src/element/slider.rs +++ b/eepy-gui/src/element/slider.rs @@ -2,7 +2,7 @@ use embedded_graphics::prelude::*; use embedded_graphics::geometry::Point; use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::primitives::{Circle, Line, PrimitiveStyle, Rectangle}; -use fw16_epd_program_interface::{Event, TouchEventType}; +use eepy_sys::{Event, TouchEventType}; use crate::draw_target::EpdDrawTarget; use crate::element::{Gui, DEFAULT_PRIMITIVE_STYLE}; diff --git a/eepy-sys/src/lib.rs b/eepy-sys/src/lib.rs index b0e3fcc..7f1a8b0 100644 --- a/eepy-sys/src/lib.rs +++ b/eepy-sys/src/lib.rs @@ -1,6 +1,7 @@ #![no_std] pub mod header; +pub mod syscall; use core::fmt::{Display, Formatter}; pub use tp370pgh01::IMAGE_BYTES; diff --git a/eepy-sys/src/syscall/mod.rs b/eepy-sys/src/syscall/mod.rs new file mode 100644 index 0000000..a6bfd6d --- /dev/null +++ b/eepy-sys/src/syscall/mod.rs @@ -0,0 +1,24 @@ +/// Perform a raw system call. +#[macro_export] +macro_rules! syscall { + ( + $syscall_num:expr, + $( out $r0out:ident )? $( in $r0in:expr )?, + $( out $r1out:ident )? $( in $r1in:expr )?, + $( out $r2out:ident )? $( in $r2in:expr )?, + $( out $r3out:ident )? $( in $r3in:expr )?, + ) => { + asm!( + "svc #{syscall_num}", + $( in("r0") $r0in, )? + $( lateout("r0") $r0out, )? + $( in("r1") $r1in, )? + $( lateout("r1") $r1out, )? + $( in("r2") $r2in, )? + $( lateout("r2") $r2out, )? + $( in("r3") $r3in, )? + $( lateout("r3") $r3out, )? + syscall_num = const $syscall_num, + ); + } +} diff --git a/eepy/src/main.rs b/eepy/src/main.rs index 1e5c510..b5d007c 100644 --- a/eepy/src/main.rs +++ b/eepy/src/main.rs @@ -5,7 +5,9 @@ mod programs; mod gui; mod serial; mod ringbuffer; +mod syscall; +use core::arch::asm; #[allow(unused_imports)] use panic_probe as _; #[allow(unused_imports)] @@ -37,7 +39,7 @@ use fw16_epd_bsp::hal::timer::{Alarm, Alarm0}; use fw16_epd_bsp::pac::I2C0; use fw16_epd_bsp::pac::interrupt; use eepy_gui::draw_target::EpdDrawTarget; -use eepy_sys::{Event, RefreshBlockMode, SafeOption, TouchEvent, TouchEventType}; +use eepy_sys::{syscall as do_syscall, Event, RefreshBlockMode, SafeOption, TouchEvent, TouchEventType}; use tp370pgh01::rp2040::{Rp2040PervasiveSpiDelays, IoPin}; use tp370pgh01::{Tp370pgh01, IMAGE_BYTES}; use crate::ringbuffer::RingBuffer; @@ -326,6 +328,22 @@ fn main() -> ! { } }*/ + // Test syscall + unsafe { + let mut r0: usize; + let mut r1: usize; + let mut r2: usize; + let mut r3: usize; + do_syscall!( + 31, + out r0 in 0, + out r1 in 1, + out r2 in 2, + out r3 in 3, + ); + debug!("{} {} {} {}", r0, r1, r2, r3); + } + let draw_target = EpdDrawTarget::new(write_image, refresh); gui::gui_main(draw_target); } diff --git a/eepy/src/syscall.rs b/eepy/src/syscall.rs new file mode 100644 index 0000000..32a8413 --- /dev/null +++ b/eepy/src/syscall.rs @@ -0,0 +1,28 @@ +use core::arch::{asm, global_asm}; +use cortex_m_rt::exception; +use defmt::debug; + +global_asm!(include_str!("syscall.s")); + +/// Main syscall (SVC) handler. +/// +/// This function is called by the assembly trampoline code in `syscall.s`. +/// +/// `sp` contains the caller's stack pointer value (taken from either MSP or PSP depending on which +/// stack was active). This is where the register values are pushed when the exception is triggered, +/// so this is where we need to read/write to interface with the caller. +/// This stack location contains (in order): r0, r1, r2, r3, r12, lr, pc, xPSR. +/// The pc value from the stack can be used to extract the literal operand from the SVC instruction +/// which triggered the syscall. +#[no_mangle] +extern "C" fn syscall(sp: *mut usize) { + // Stack contains R0, R1, R2, R3, R12, LR, ReturnAddress, xPSR + let stack_values = unsafe { core::slice::from_raw_parts_mut(sp, 8) }; + let svc_operand = unsafe { (stack_values[6] as *const u8).sub(2).read() }; + debug!("{:x}", svc_operand); + + // Increase the value of R0-R3 by 1 + for i in 0..4 { + stack_values[i] += 1; + } +} \ No newline at end of file diff --git a/eepy/src/syscall.s b/eepy/src/syscall.s new file mode 100644 index 0000000..c36c70f --- /dev/null +++ b/eepy/src/syscall.s @@ -0,0 +1,15 @@ +.global SVCall +.equ SVCall, _SVCall + 1 /* thumb bit */ + +_SVCall: + movs r0, #4 + mov r1, lr + tst r0, r1 + beq .use_msp + mrs r0, psp + ldr r1, =syscall + bx r1 +.use_msp: + mrs r0, msp + ldr r1, =syscall + bx r1 \ No newline at end of file