firmware for my Touchscreen E-Paper Input Module for Framework Laptop 16
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

eepy: initial work on userspace USB interrupt handling

+158 -36
+17 -1
eepy-sys/src/usb.rs
··· 1 - // TODO 1 + #[repr(usize)] 2 + #[derive(Copy, Clone, Debug, Eq, PartialEq)] 3 + #[cfg_attr(feature = "defmt", derive(defmt::Format))] 4 + pub enum UsbSyscall { 5 + UsbRet = 0, 6 + } 7 + 8 + impl TryFrom<usize> for UsbSyscall { 9 + type Error = (); 10 + 11 + fn try_from(value: usize) -> Result<Self, Self::Error> { 12 + match value { 13 + x if x == UsbSyscall::UsbRet as usize => Ok(UsbSyscall::UsbRet), 14 + _ => Err(()), 15 + } 16 + } 17 + }
+30
eepy/src/exception.rs
··· 1 + use defmt::Formatter; 2 + 3 + #[derive(Copy, Clone, Debug, Eq, PartialEq)] 4 + pub(crate) struct StackFrame { 5 + pub r0: usize, 6 + pub r1: usize, 7 + pub r2: usize, 8 + pub r3: usize, 9 + pub r12: usize, 10 + pub lr: *const u8, 11 + pub pc: *const u8, 12 + pub xpsr: usize, 13 + } 14 + 15 + impl defmt::Format for StackFrame { 16 + fn format(&self, fmt: Formatter) { 17 + defmt::write!( 18 + fmt, 19 + "r0=0x{:x} r1=0x{:x} r2=0x{:x} r3=0x{:x} r12=0x{:x} lr={:x} pc={:x} xpsr=0x{:x}", 20 + self.r0, 21 + self.r1, 22 + self.r2, 23 + self.r3, 24 + self.r12, 25 + self.lr, 26 + self.pc, 27 + self.xpsr, 28 + ) 29 + } 30 + }
+16 -3
eepy/src/main.rs
··· 5 5 mod ringbuffer; 6 6 mod syscall; 7 7 mod launcher; 8 + mod usb; 9 + mod exception; 8 10 9 11 extern crate panic_probe; 10 12 extern crate defmt_rtt; ··· 235 237 236 238 let mut timer = Timer::new(pac.TIMER, &mut pac.RESETS, &clocks); 237 239 // make sure temperature sensor has read temperature 238 - timer.delay_ms(35); 240 + //timer.delay_ms(35); 239 241 let mut alarm = timer.alarm_0().unwrap(); 240 242 alarm.enable_interrupt(); 241 243 critical_section::with(|cs| GLOBAL_ALARM0.borrow_ref_mut(cs).replace(alarm)); ··· 278 280 GLOBAL_USB_DEVICE = Some(usb_device); 279 281 } 280 282 281 - unsafe { pac::NVIC::unmask(interrupt::USBCTRL_IRQ) }; 283 + unsafe { 284 + core.NVIC.set_priority(interrupt::USBCTRL_IRQ, 0b11000000); 285 + pac::NVIC::unmask(interrupt::USBCTRL_IRQ); 286 + 287 + // FIXME testing 288 + core.NVIC.set_priority(interrupt::SW5_IRQ, 0b11000000); 289 + pac::NVIC::unmask(interrupt::SW5_IRQ); 290 + } 282 291 283 292 let mut mc = Multicore::new(&mut pac.PSM, &mut pac.PPB, &mut sio.fifo); 284 293 let core1 = &mut mc.cores()[1]; ··· 350 359 351 360 trace!("TIMER_IRQ_0"); 352 361 362 + 353 363 if ALARM0.is_none() { 354 364 critical_section::with(|cs| *ALARM0 = GLOBAL_ALARM0.borrow(cs).take()); 355 365 } ··· 372 382 TEMP.store(clamped, Ordering::Relaxed); 373 383 374 384 alarm.clear_interrupt(); 375 - alarm.schedule(1.minutes()).unwrap(); 385 + alarm.schedule(1.secs()).unwrap(); 376 386 } else { 377 387 // I2C bus was in use, so try again in a short time 378 388 alarm.clear_interrupt(); ··· 381 391 } 382 392 383 393 critical_section::with(|cs| GLOBAL_I2C.borrow(cs).replace(i2c)); 394 + 395 + // FIXME testing 396 + pac::NVIC::pend(interrupt::SW5_IRQ); 384 397 } 385 398 386 399 #[interrupt]
+5 -32
eepy/src/syscall.rs
··· 3 3 use eepy_sys::exec::exec; 4 4 use eepy_sys::header::slot; 5 5 use eepy_sys::syscall::SyscallNumber; 6 + use crate::exception::StackFrame; 6 7 use crate::SRAM_END; 7 8 8 9 global_asm!(include_str!("syscall.s")); 9 10 10 - #[derive(Copy, Clone, Debug, Eq, PartialEq)] 11 - struct StackFrame { 12 - r0: usize, 13 - r1: usize, 14 - r2: usize, 15 - r3: usize, 16 - r12: usize, 17 - lr: *const u8, 18 - pc: *const u8, 19 - xpsr: usize, 20 - } 21 - 22 - impl defmt::Format for StackFrame { 23 - fn format(&self, fmt: Formatter) { 24 - defmt::write!( 25 - fmt, 26 - "r0=0x{:x} r1=0x{:x} r2=0x{:x} r3=0x{:x} r12=0x{:x} lr={:x} pc={:x} xpsr=0x{:x}", 27 - self.r0, 28 - self.r1, 29 - self.r2, 30 - self.r3, 31 - self.r12, 32 - self.lr, 33 - self.pc, 34 - self.xpsr, 35 - ) 36 - } 37 - } 38 - 39 11 /// Main syscall (SVC) handler. 40 12 /// 41 13 /// This function is called by the assembly trampoline code in `syscall.s`. ··· 58 30 Ok(SyscallNumber::Misc) => misc::handle_misc(stack_values), 59 31 Ok(SyscallNumber::Image) => image::handle_image(stack_values), 60 32 Ok(SyscallNumber::Input) => input::handle_input(stack_values), 61 - Ok(SyscallNumber::Usb) => todo!("usb syscalls"), 33 + Ok(SyscallNumber::Usb) => crate::usb::handle_usb(stack_values), 62 34 Ok(SyscallNumber::Exec) => handle_exec(stack_values, using_psp), 63 35 Err(_) => panic!("illegal syscall"), 64 36 } ··· 81 53 panic!("tried to exec invalid program"); 82 54 } 83 55 84 - (*program).load(); 85 56 stack_values.pc = core::mem::transmute((*program).entry); 86 57 stack_values.lr = program_return_handler as *const u8; 87 58 ··· 102 73 ptr = in(reg) SRAM_END, 103 74 ) 104 75 } 76 + 77 + (*program).load(); 105 78 } 106 79 } 107 80 108 81 // NOTE: this function runs in unprivileged thread mode 109 - extern "C" fn program_return_handler() { 82 + extern "C" fn program_return_handler() -> ! { 110 83 exec(0); 111 84 } 112 85
+65
eepy/src/usb.rs
··· 1 + use core::arch::{asm, global_asm}; 2 + use defmt::trace; 3 + use eepy_sys::misc::get_serial; 4 + use eepy_sys::usb::UsbSyscall; 5 + use fw16_epd_bsp::pac; 6 + use fw16_epd_bsp::pac::interrupt; 7 + use crate::exception::StackFrame; 8 + 9 + global_asm!(include_str!("usb.s")); 10 + 11 + extern "C" { 12 + fn usb_ret(); 13 + } 14 + 15 + extern "C" fn example_usb_handler() { 16 + // Do a syscall so it shows up in the kernel logs 17 + // (we should be in unprivileged thread mode here so we can't use defmt) 18 + core::hint::black_box(get_serial()); 19 + } 20 + 21 + #[no_mangle] 22 + extern "C" fn handle_usb_irq(sp: *mut StackFrame, using_psp: bool) { 23 + trace!("fake USBCTRL_IRQ"); 24 + 25 + if !using_psp { 26 + return; 27 + } 28 + 29 + unsafe { 30 + let new_sp = sp.sub(1); 31 + new_sp.write(StackFrame { 32 + r0: 0, 33 + r1: 0, 34 + r2: 0, 35 + r3: 0, 36 + r12: 0, 37 + lr: usb_ret as *const u8, 38 + pc: example_usb_handler as *const u8, 39 + xpsr: 0x1000000, 40 + }); 41 + 42 + asm!( 43 + "msr psp, {new_psp}", 44 + new_psp = in(reg) new_sp, 45 + ); 46 + } 47 + } 48 + 49 + pub(crate) fn handle_usb(stack_values: &mut StackFrame) { 50 + match UsbSyscall::try_from(stack_values.r0) { 51 + Ok(UsbSyscall::UsbRet) => handle_usb_ret(stack_values), 52 + Err(_) => {}, 53 + } 54 + } 55 + 56 + fn handle_usb_ret(stack_values: &mut StackFrame) { 57 + trace!("usb_ret"); 58 + unsafe { 59 + let new_sp = (&raw mut *stack_values).add(1); 60 + asm!( 61 + "msr psp, {new_psp}", 62 + new_psp = in(reg) new_sp, 63 + ); 64 + } 65 + }
+25
eepy/src/usb.s
··· 1 + //.global USBCTRL_IRQ 2 + .global SW5_IRQ 3 + 4 + .thumb_func 5 + //USBCTRL_IRQ: 6 + SW5_IRQ: 7 + ldr r2, =handle_usb_irq 8 + movs r0, #4 9 + mov r1, lr 10 + tst r0, r1 11 + beq 100f // use_msp 12 + mrs r0, psp 13 + movs r1, #1 14 + bx r2 15 + 100: // use_msp 16 + mrs r0, msp 17 + movs r1, #0 18 + bx r2 19 + 20 + .global usb_ret 21 + 22 + .thumb_func 23 + usb_ret: 24 + movs r0, #0 25 + svc #3