pub trait Memory {
// Required methods
fn r8(&mut self, addr: u32) -> u8;
fn r16(&mut self, addr: u32) -> u16;
fn r32(&mut self, addr: u32) -> u32;
fn w8(&mut self, addr: u32, val: u8);
fn w16(&mut self, addr: u32, val: u16);
fn w32(&mut self, addr: u32, val: u32);
// Provided methods
fn x16(&mut self, addr: u32) -> u16 { ... }
fn x32(&mut self, addr: u32) -> u32 { ... }
}
Expand description
Encodes how the Cpu
accesses external memory / memory-mapped devices.
§Handling Memory Access Errors
At the moment, the Memory
trait assumes that all memory operations are
infallible, and as such, doesn’t support returning any sort of Result
from reads / writes. This isn’t correct, as is a known-blocker for
implementing proper Data / Prefetch Abort support (see issue #7)
Nonetheless, there are plenty of scenarios where a memory access might
result in an application error. For example, what if while writing to an
emulated UART device, a std::io::Error
occurs?
Unfortunately, this library doesn’t provide an easy solution to these scenarios (yet?), but here are some possible approaches:
- Write a application-specific, fallible
Memory
trait + an adapter to converts said trait into this crate’sMemory
trait. - Use an “out-of-band” error signaling mechanism (e.g: a mpsc channel, or a shared queue behind a mutex)
e.g: an error occurs during a read operation. The failing device signals an
error using a mpsc::channel, and returns a dummy value (e.g: 0x00).
Cpu::step
finishes executing the instruction, and returns back to user
code. The user code then checks the channel to see if an error had just
occurred, and takes an appropriate action.