| Crates.io | jelly-mem_access |
| lib.rs | jelly-mem_access |
| version | 0.2.5 |
| created_at | 2021-12-18 02:07:15.784288+00 |
| updated_at | 2025-08-07 12:57:08.250296+00 |
| description | Memory Mapped I/O access library |
| homepage | |
| repository | https://github.com/ryuz/jelly-mem_access |
| max_upload_size | |
| id | 499887 |
| size | 101,831 |
The jelly-mem_access library provides a unified interface for accessing memory-mapped I/O (MMIO) in both bare-metal and Linux environments. It is designed to simplify register access and memory operations, supporting a wide range of use cases, including:
no_std support./dev/uio devices for user-space interrupt handling and memory access.u-dma-buf for high-performance data transfer.This library is ideal for embedded systems developers and those working with custom hardware requiring efficient memory-mapped I/O access.
Direct MMIO access for bare-metal or Linux environments. Useful for register operations on custom hardware.
// Example: Bare-metal MMIO access
type RegisterWordSize = u64;
let mmio_acc = MmioAccessor::<RegisterWordSize>::new(0xffff0000, 0x10000);
mmio_acc.write_mem_u8(0x00, 0x12); // addr : 0xffff0000
mmio_acc.write_mem_u16(0x02, 0x1234); // addr : 0xffff0002
mmio_acc.write_reg_u32(0x10, 0x12345678); // addr : 0xffff0080 <= 0x10 * size_of<RegisterWordSize>()
mmio_acc.read_reg_u32(0x10); // addr : 0xffff0080 <= 0x10 * size_of<RegisterWordSize>()
Linux UIO provides user-space access to device memory and interrupts via /dev/uio*. This library makes interrupt handling and register access easy.
// Example: UIO access and interrupt handling
type RegisterWordSize = usize;
let uio_num = 1; // ex.) /dev/uio1
let uio_acc = UioAccessor::<RegisterWordSize>::new(uio_num).unwrap();
uio_acc.set_irq_enable(true).unwrap(); // Enable IRQ
uio_acc.write_reg_u32(0x00, 0x1).unwrap();
let irq_count = uio_acc.wait_irq().unwrap(); // Wait for IRQ
println!("IRQ count: {}", irq_count);
// Polling for IRQ (non-blocking)
if uio_acc.peek_irq(100).unwrap() {
println!("IRQ detected!");
}
// Or, get IRQ count if available (returns None on timeout)
if let Some(count) = uio_acc.poll_irq(100).unwrap() {
println!("IRQ count: {}", count);
}
You can also open it by specifying a name obtained from /sys/class/uio:
let uio_acc = UioAccessor::<u32>::new_with_name("uio-sample").unwrap();
Efficient DMA buffer management for high-speed data transfer. Requires the u-dma-buf kernel module.
use jelly_mem_access::MemAccess;
let udmabuf_num = 4; // ex.) /dev/udmabuf4
let udmabuf_acc = UdmabufAccessor::<usize>::new("udmabuf4", false).unwrap();
println!("udmabuf4 phys addr : 0x{:x}", udmabuf_acc.phys_addr()); // MemAccess trait required
println!("udmabuf4 size : 0x{:x}", udmabuf_acc.size()); // MemAccess trait required
unsafe {
udmabuf_acc.write_mem_u32(0x00, 0x1234); // DMA buffer write (unsafe for direct memory access)
}
Accessing /dev/mem allows direct memory-mapped I/O to physical addresses. Note: root privileges are required. Use with caution.
let mem_acc = MmapAccessor::<usize>::new("/dev/mem", 0xa0000000, 0x1000).unwrap();
mem_acc.write_reg_u32(0x10, 0x12345678).unwrap();
let value = mem_acc.read_reg_u32(0x10).unwrap();
println!("Value at register 0x10: 0x{:x}", value);
The subclone method allows you to clone a part of the memory region as a new accessor. This is useful for accessing a specific sub-region or for register-level operations with different types.
// Example: Clone a sub-region as u8 type
let mmio_acc = MmioAccessor::<u32>::new(0xffff0000, 0x10000);
let sub_acc = mmio_acc.subclone8(0x100, 0x10); // Access 0xffff0100 for 0x10 bytes as u8
sub_acc.write_mem_u8(0x00, 0xAA);
let val = sub_acc.read_mem_u8(0x00);
println!("Value in subclone region: 0x{:x}", val);
MIT License