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: remove broken InvalidateCache syscall This syscall caused weird HardFaults, and also invalidated the entire XIP cache which isn't ideal. The flash syscalls now automatically flush the cache for only the area that was modified, by writing to the flash memory-mapped addresses as specified in the RP2040 datasheet section 2.6.3.2.

+25 -28
+1 -7
eepy-launcher/src/serial.rs
··· 4 4 use usb_device::device::UsbDevice; 5 5 use usbd_serial::SerialPort; 6 6 use eepy_serial::{Response, SerialCommand}; 7 - use eepy_sys::flash::{erase_and_program, invalidate_cache}; 7 + use eepy_sys::flash::erase_and_program; 8 8 use eepy_sys::image::{refresh, write_image, RefreshBlockMode}; 9 9 use eepy_sys::IMAGE_BYTES; 10 10 use eepy_sys::input::{next_event, set_touch_enabled}; ··· 197 197 if *page == num_pages { 198 198 debug("finalising"); 199 199 unsafe { write_flash(&buf[0..4096], 1, 0) }; 200 - 201 - debug("invalidating XIP cache"); 202 - // Invalidate the XIP cache, in case something from the flash area 203 - // we just wrote is in there 204 - unsafe { invalidate_cache() }; 205 - debug("invalidated XIP cache"); 206 200 207 201 NEEDS_REFRESH_PROGRAMS.store(true, Ordering::Relaxed); 208 202 info("Finished writing program");
-8
eepy-sys/src/flash.rs
··· 8 8 Erase = 0, 9 9 Program = 1, 10 10 EraseAndProgram = 2, 11 - InvalidateCache = 3, 12 11 } 13 12 14 13 pub unsafe fn erase(start_addr: u32, len: u32) { ··· 37 36 in start_addr, 38 37 in data.len(), 39 38 in data.as_ptr(), 40 - ); 41 - } 42 - 43 - pub unsafe fn invalidate_cache() { 44 - syscall!( 45 - SyscallNumber::Flash, 46 - in FlashSyscall::InvalidateCache, 47 39 ); 48 40 }
+4 -1
eepy/src/main.rs
··· 132 132 // Region 3: Flash - start: 0x10000000, length 16M 133 133 core.MPU.rnr.write(3); 134 134 core.MPU.rbar.write(0x10000000); 135 + // NOTE: we of course can't actually write to the flash via the XIP memory map, but 136 + // performing writes to the flash memory region flushes the XIP cache for that area of 137 + // flash, so the kernel still needs write access 135 138 core.MPU.rasr.write( 136 139 (0b0 << 28) // disable XN 137 - | (0b110 << 24) // AP: privileged or unprivileged read-only 140 + | (0b010 << 24) // AP: privileged RW, unprivileged RO 138 141 | (0b000 << 19) // TEX 139 142 | (0b110 << 16) // S, C, B: shared, write-through 140 143 | (0b00000000 << 8) // all subregions enabled
+20 -12
eepy/src/syscall.rs
··· 248 248 } 249 249 250 250 mod flash { 251 - use core::arch::asm; 252 251 use core::sync::atomic::Ordering; 253 252 use eepy_sys::flash::FlashSyscall; 254 253 use eepy_sys::header::{SLOT_SIZE, XIP_BASE}; 255 - use fw16_epd_bsp::pac; 256 254 use crate::exception::StackFrame; 257 255 use crate::{FLASHING, FLASHING_ACK}; 258 256 ··· 261 259 Some(FlashSyscall::Erase) => handle_erase(stack_values), 262 260 Some(FlashSyscall::Program) => handle_program(stack_values), 263 261 Some(FlashSyscall::EraseAndProgram) => handle_erase_and_program(stack_values), 264 - Some(FlashSyscall::InvalidateCache) => handle_invalidate_cache(), 265 262 None => panic!("illegal syscall"), 266 263 } 267 264 } ··· 304 301 cortex_m::asm::sev(); 305 302 } 306 303 304 + fn flush_cache_range(start_addr: u32, len: u32) { 305 + // RP2040 Datasheet 2.6.3.2: 306 + // "A write to the 0x10… mirror will look up the addressed location in the cache, and delete 307 + // any matching entry found. Writing to all word-aligned locations in an address range (e.g. 308 + // a flash sector that has just been erased and reprogrammed) therefore eliminates the 309 + // possibility of stale cached data in this range, without suffering the effects of a 310 + // complete cache flush." 311 + 312 + unsafe { 313 + let start_ptr: *mut u32 = XIP_BASE.add(start_addr as usize).cast_mut().cast(); 314 + let words = len / 4; 315 + for _ in 0..words { 316 + start_ptr.add(words as usize).write_volatile(0); 317 + } 318 + } 319 + } 320 + 307 321 fn handle_erase(stack_values: &mut StackFrame) { 308 322 let start_addr = stack_values.r1 as u32; 309 323 let len = stack_values.r2 as u32; ··· 315 329 begin(); 316 330 unsafe { 317 331 rp2040_flash::flash::flash_range_erase(start_addr, len, true); 332 + flush_cache_range(start_addr, len); 318 333 } 319 334 end(); 320 335 } ··· 330 345 begin(); 331 346 unsafe { 332 347 rp2040_flash::flash::flash_range_program(start_addr, data, true); 348 + flush_cache_range(start_addr, data.len() as u32); 333 349 } 334 350 end(); 335 351 } ··· 345 361 begin(); 346 362 unsafe { 347 363 rp2040_flash::flash::flash_range_erase_and_program(start_addr, data, true); 364 + flush_cache_range(start_addr, data.len() as u32); 348 365 } 349 366 end(); 350 - } 351 - 352 - fn handle_invalidate_cache() { 353 - unsafe { 354 - let xip = pac::Peripherals::steal().XIP_CTRL; 355 - xip.flush().write(|w| w.flush().set_bit()); 356 - xip.flush().read(); 357 - asm!("dsb", "isb"); 358 - }; 359 367 } 360 368 }