Practical examples
Here are some examples of how you could use typed memory.
Each example includes the call to posix_typed_mem_open() followed by the POSIX method (using mmap()) and the QNX OS method (using shm_ctl() with SHMCTL_TYMEM). These examples don't include any checking for errors.
Allocating contiguous memory from system RAM
int fd = posix_typed_mem_open( "/memory/ram/sysram", O_RDWR,
POSIX_TYPED_MEM_ALLOCATE_CONTIG);
void *vaddr = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
shm_fd = shm_open(SHM_ANON, O_RDWR, 0600);
shm_ctl(shm_fd, SHMCTL_ANON | SHMCTL_TYMEM | SHMCTL_PHYS,
(uint64_t)tymem_fd, 0x100000);
We specified POSIX_TYPED_MEM_ALLOCATE_CONTIG in the call to posix_typed_mem_open(), so we need to add SHMCTL_PHYS in the call to shm_ctl().
Defining packet memory and allocating from it
Startup Librarychapter of Building Embedded Systems) to add an asinfo entry for the packet memory:
as_add(phys_addr, phys_addr + size - 1, AS_ATTR_NONE, "packet_memory", mem_id);
where phys_addr is the physical address of the SRAM,
size is the SRAM size, and mem_id is the ID of the
parent (typically memory
, which is returned by
as_default()).
packet_memory
,
which you can then use as POSIX typed memory.
The following code allows different applications to allocate pages from
packet_memory
:
int fd = posix_typed_mem_open( "packet_memory", O_RDWR,
POSIX_TYPED_MEM_ALLOCATE);
void *vaddr = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
shm_fd = shm_open(SHM_ANON, O_RDWR, 0600);
shm_ctl( shm_fd, SHMCTL_ANON | SHMCTL_TYMEM, (uint64_t)tymem_fd, 0x100000);
int fd = posix_typed_mem_open( "packet_memory", O_RDWR,
POSIX_TYPED_MEM_MAP_ALLOCATABLE);
void *vaddr = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
shm_fd = shm_open(SHM_ANON, O_RDWR, 0600);
shm_ctl( shm_fd, SHMCTL_ANON | SHMCTL_TYMEM, (uint64_t)tymem_fd, 0x100000);
Defining a DMA-safe region
On some hardware, due to limitations of the chipset or memory controller, it may not be possible to perform DMA to arbitrary addresses in the system. In some cases, the chipset has only the ability to DMA to a subset of all physical RAM. This has traditionally been difficult to solve without statically reserving some portion of RAM for driver DMA buffers (which is potentially wasteful). Typed memory provides a clean abstraction to solve this issue. Here, we provide an example.
Startup Librarychapter of Building Embedded Systems) to define an asinfo entry for DMA-safe memory. Make this entry be a child of
ram
:
as_add_containing( dma_addr, dma_addr + size - 1, AS_ATTR_RAM, "dma", "ram");
where dma_addr is the start of the DMA-safe RAM, and
size is the size of the DMA-safe region.
dma
,
which is a child of ram
.
Drivers can then use it to allocate DMA-safe buffers:
int fd = posix_typed_mem_open( "ram/dma", O_RDWR,
POSIX_TYPED_MEM_ALLOCATE_CONTIG);
void *vaddr = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
shm_fd = shm_open(SHM_ANON, O_RDWR, 0600);
shm_ctl(shm_fd, SHMCTL_ANON | SHMCTL_TYMEM | SHMCTL_PHYS,
(uint64_t)tymem_fd, 0x100000);
We specified POSIX_TYPED_MEM_ALLOCATE_CONTIG in the call to posix_typed_mem_open(), so we need to add SHMCTL_PHYS in the call to shm_ctl().