Skip to content

Memory access

Matthijs van Duin edited this page Jul 25, 2019 · 4 revisions

Summary

Both uio.device.Uio and uio.device.MemRegion support the following methods:

  • .map() -> memoryview
  • .map( length, offset ) -> memoryview
  • .read( length, offset ) -> bytes
  • .write( data, offset ) where data is a bytes object or some other object supporting the buffer interface
  • .map( SomeCtypesType, offset ) -> SomeCtypesType where SomeCtypesType is some class provided by python's ctypes module

In all cases the offset argument is optional and defaults to zero.

Summary for uio_pruss:

If pruss is an instance of the uio.ti.icss.Icss class (which is a subclass of uio.device.Uio), then the methods above therefore are available on both pruss itself and the various uio.device.MemRegion objects you can find among its attributes:

  • pruss.dram0 (offset 0x00000 in pruss, up to 8KB)
  • pruss.dram1 (offset 0x02000 in pruss, up to 8KB)
  • pruss.dram2 (offset 0x10000 in pruss, up to 64KB)
  • pruss.iram0 (offset 0x34000 in pruss, up to 16KB)
  • pruss.iram1 (offset 0x38000 in pruss, up to 16KB)
  • pruss.ddr (separate memory region outside pruss itself)
  • pruss.core0.iram (same as pruss.iram0)
  • pruss.core1.iram (same as pruss.iram1)
  • pruss.core0.dram (same as pruss.dram0)
  • pruss.core1.dram (same as pruss.dram1)
  • pruss.core0.peer_dram (same as pruss.dram1)
  • pruss.core1.peer_dram (same as pruss.dram0)
  • pruss.core0.shared_dram (same as pruss.dram2)
  • pruss.core1.shared_dram (same as pruss.dram2)

Device memory regions

The uio.device.MemRegion class represents a region of memory (or memory-mapped registers) associated with an uio device. You can access the top-level memory regions of an uio.device.Uio instance dev by name or by index:

  • dev.region( name ) -> MemRegion
  • dev.region( index ) -> MemRegion
  • dev.region() -> MemRegion is the default region, i.e. index 0.

You can also create subregions of an existing region rgn:

  • rgn.subregion( offset, size, name ) -> MemRegion (name is optional and defaults to None)
  • dev.subregion( offset, size, name ) -> MemRegion creates a subregion of dev.region()

Public attributes of MemRegion objects:

  • rgn.address : int — physical address of start of region
  • rgn.size : int — region size in bytes
  • rgn.end : int — physical address of end of region (== rgn.address + rgn.size)
  • rgn.mappable : int — mappable size of region in bytes
  • rgn.parent : MemRegion (or None)
  • rgn.name : str (or None)
  • rgn.uio : Uio (or None if not a top-level region of an uio device)
  • rgn.index : int (or None if not a top-level region of an uio device)

Reading and writing device memory

If the memory region is mappable, there are various ways of accessing it:

(For all of these methods, offset is optional and defaults to zero.)

rgn.write( data, offset ) writes data into the memory region at given offset. data must be an object that implements the buffer protocol, such as:

rgn.read( length, offset ) -> bytes reads a given number of bytes from the memory region at given offset. The data is returned as a bytes object.

rgn.read( type, offset ) -> type where type is a ctypes data type object reads an instance of this type from the memory region at given offset. For example, rgn.read( ctypes.c_uint32 * 4, offset ) would read four 32-bit unsigned integers.

As a shorthand, you can read from / write to the default region of a device using dev.read( ... ) / dev.write( ... ).

Direct mapping of device memory

rgn.map() -> memoryview returns a memoryview which directly represents the memory region.

rgn.map( length, offset ) -> memoryview returns a slice thereof.

rgn.map( type, offset ) -> type where type is a ctypes data type object maps an instance of this type in the memory region at given offset. Unlike rgn.read, the returned ctypes data object does not contain a copy of the data but directly represents device memory, i.e.:

data = rgn.map( ctypes.c_uint32 * 4 )
print( data[0] )   # <-- this reads from device memory
data[1] = 42       # <-- this writes to device memory

As a shorthand, you can map (part of) the default region of a device using dev.map( ... ).