···11#![no_std]
2233pub mod header;
44+pub mod syscall;
4556use core::fmt::{Display, Formatter};
67pub use tp370pgh01::IMAGE_BYTES;
+24
eepy-sys/src/syscall/mod.rs
···11+/// Perform a raw system call.
22+#[macro_export]
33+macro_rules! syscall {
44+ (
55+ $syscall_num:expr,
66+ $( out $r0out:ident )? $( in $r0in:expr )?,
77+ $( out $r1out:ident )? $( in $r1in:expr )?,
88+ $( out $r2out:ident )? $( in $r2in:expr )?,
99+ $( out $r3out:ident )? $( in $r3in:expr )?,
1010+ ) => {
1111+ asm!(
1212+ "svc #{syscall_num}",
1313+ $( in("r0") $r0in, )?
1414+ $( lateout("r0") $r0out, )?
1515+ $( in("r1") $r1in, )?
1616+ $( lateout("r1") $r1out, )?
1717+ $( in("r2") $r2in, )?
1818+ $( lateout("r2") $r2out, )?
1919+ $( in("r3") $r3in, )?
2020+ $( lateout("r3") $r3out, )?
2121+ syscall_num = const $syscall_num,
2222+ );
2323+ }
2424+}
+19-1
eepy/src/main.rs
···55mod gui;
66mod serial;
77mod ringbuffer;
88+mod syscall;
891010+use core::arch::asm;
911#[allow(unused_imports)]
1012use panic_probe as _;
1113#[allow(unused_imports)]
···3739use fw16_epd_bsp::pac::I2C0;
3840use fw16_epd_bsp::pac::interrupt;
3941use eepy_gui::draw_target::EpdDrawTarget;
4040-use eepy_sys::{Event, RefreshBlockMode, SafeOption, TouchEvent, TouchEventType};
4242+use eepy_sys::{syscall as do_syscall, Event, RefreshBlockMode, SafeOption, TouchEvent, TouchEventType};
4143use tp370pgh01::rp2040::{Rp2040PervasiveSpiDelays, IoPin};
4244use tp370pgh01::{Tp370pgh01, IMAGE_BYTES};
4345use crate::ringbuffer::RingBuffer;
···325327 program.entry()(&pft);
326328 }
327329 }*/
330330+331331+ // Test syscall
332332+ unsafe {
333333+ let mut r0: usize;
334334+ let mut r1: usize;
335335+ let mut r2: usize;
336336+ let mut r3: usize;
337337+ do_syscall!(
338338+ 31,
339339+ out r0 in 0,
340340+ out r1 in 1,
341341+ out r2 in 2,
342342+ out r3 in 3,
343343+ );
344344+ debug!("{} {} {} {}", r0, r1, r2, r3);
345345+ }
328346329347 let draw_target = EpdDrawTarget::new(write_image, refresh);
330348 gui::gui_main(draw_target);
+28
eepy/src/syscall.rs
···11+use core::arch::{asm, global_asm};
22+use cortex_m_rt::exception;
33+use defmt::debug;
44+55+global_asm!(include_str!("syscall.s"));
66+77+/// Main syscall (SVC) handler.
88+///
99+/// This function is called by the assembly trampoline code in `syscall.s`.
1010+///
1111+/// `sp` contains the caller's stack pointer value (taken from either MSP or PSP depending on which
1212+/// stack was active). This is where the register values are pushed when the exception is triggered,
1313+/// so this is where we need to read/write to interface with the caller.
1414+/// This stack location contains (in order): r0, r1, r2, r3, r12, lr, pc, xPSR.
1515+/// The pc value from the stack can be used to extract the literal operand from the SVC instruction
1616+/// which triggered the syscall.
1717+#[no_mangle]
1818+extern "C" fn syscall(sp: *mut usize) {
1919+ // Stack contains R0, R1, R2, R3, R12, LR, ReturnAddress, xPSR
2020+ let stack_values = unsafe { core::slice::from_raw_parts_mut(sp, 8) };
2121+ let svc_operand = unsafe { (stack_values[6] as *const u8).sub(2).read() };
2222+ debug!("{:x}", svc_operand);
2323+2424+ // Increase the value of R0-R3 by 1
2525+ for i in 0..4 {
2626+ stack_values[i] += 1;
2727+ }
2828+}