How to find DDR physical address for passing data to/from pruss?

I’m learning how to use the PRUSS, have most of it under control (or at least not stuck). I’ve followed the examples posted at

Problem is understanding how to pass data in DDR. PRUSS data (shared or pru data) makes sense - just look at /sys/class/uio/uio0/maps/map0/addr to find the base (physical) address for the PRUSS and use the offsets in the global memory map to access data in the PRUSS. But what about using DDR? Examples in the package noted above use the “magic number” of 0x8000_1000 as the physical address for DDR for passing data. That seems to work in the examples, but how would one determine that programmatically? Is the uio_pruss kernel driver setting this up? If so, where is the connection to 0x8000_1000?

My understanding is that /sys/class/uio/uio0/maps/map0/addr provides the physical address for the PRU (which does match the offset in the device tree for the pruss - 0x4a30_0000). Documentation for uio leads me to believe that /sys/class/uio/uio0/maps/map1/addr would provide the physical address of the “next region” mapped by the driver, which I would expect would be the DDR claimed by the uio_pruss kernel driver (the value is 0x9cd0_0000). However, code in the example source PRU_memAcc_DDR_sharedRAM.c just uses hardcoded values of 0x8000_0000 for DDR base physical address and 0x0000_1000 for an offset, and using mmap on /dev/mem writes to that location. Likewise, the example assembly PRU_memAcc_DDR_sharedRAM.p hardcodes the 0x1000 offset as an immediate value loaded into the configurable constant register.

Further complicating understanding, the example loader code seems to ignore the …map1/addr value when building its structure of addresses, instead just incrementing the value of …map0/addr by one page (4096). Also, the mmap is not on /dev/mem but instead /dev/uio0.

Finally, I found this that looked promising: but there is yet another “magic number” - in this case, subtracting 0x1000_0000 from the physical address reported by …map2/addr (apparently this is for the BBW, which had three memory regions (map1 is L3, map2 is DDR) and adding 0x1000_0000 to the size reported by …map2/size, and mmap into /dev/mem.

So the questions are:

  1. Is the uio_pruss kernel driver claiming DDR memory?
  2. If so, how can I determine it’s physical address?
  3. Why use mmap on /dev/uio0 rather than /dev/mem?


A shortened version of this question, which I really want to understand for this specific project and as general learning for use of Linux in embedded systems:

What is the correct way to correctly use memory in userspace to access registers and memory used by device drivers (specifically the PRU in this case)?

Is the example provided correct, both the app_loader “helper” code and/or the example applications? They seem to be inconsistent with one another?

Most examples provided in the github are correct enough for me to use them. If you niticed any particular bug, please address it exactly.
To access PRU registers, and PRU memory you should use the driver.
The driver calls (like prussdrv_map_prumem) return pointers you can use to directly read/write PRU hardware.
Ther resulting code might look like (writing to the local PRU RAM, from the client):

static char *pruMem;

pruMem[THIS_PRU_NUMBER] = 0;

Another case is if you want to pass the DDR buffer address so that it will write there. The simplest case (IMHO) is to use the frame buffer /dev/fb0.
Open it, find DDR mapping parameters, and pass to the PRU.