ARM memory direct access to PRU area

Hello All,

I have a issue with the access to the global memory area commom to PRU’s. I have this routine that writes and reads one memory position ; it works when I choose PRUx_DRAM = 0x0000 ( PRU0 area ) but fails when I choose PRUx_= 0x2000 ( PRU1 area ) and I don’t understand why.
It works by pressing a key and return , and it prints each time the last value + 1. When it doesn’t work the value read is allways 0.

Code listing:

*  Read PRU1 shared memory and print out
*  /var/lib/cloud9/BeagleBone/Green/More/MemExp

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#define PRU_ADDR        0x4A300000      // Start of PRU memory Page 184 am335x TRM
#define PRU_LEN         0x10000         // Length of PRU memory
#define PRUx_DRAM       0x0000         // Offset to DRAM 0x0000 or 0x2000
//#define PRU_SHAREDMEM   0x10000         // Offset to shared memory

volatile unsigned int *pru1DRAM_32int_ptr;        // Points to the start of local DRAM

int main()

    unsigned int    *pru;       // Points to start of PRU memory.
    int fd;
    printf("Servo tester\n");

    fd = open ("/dev/mem", O_RDWR | O_SYNC);
    if (fd == -1) {
        printf ("ERROR: could not open /dev/mem.\n\n");
        return 1;

    pru = mmap (0, PRU_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PRU_ADDR);

    if (pru == MAP_FAILED) {
        printf ("ERROR: could not map memory.\n\n");
        return 1;

    printf ("Using /dev/mem.\n");

    pru1DRAM_32int_ptr = pru + PRUx_DRAM + 0x200;   // Points to 0x200 of PRU1 memory

    int i = 1;
    int j;

        pru1DRAM_32int_ptr[0] = i;
        j = pru1DRAM_32int_ptr[0];
        printf("-> %d\n", j);

        if('q' == getc(stdin)) break;

    if(munmap(pru, PRU_LEN))
        printf("munmap failed\n");
    } else {
        printf("munmap succeeded\n");

Please use volatile unsigned char for any pointer arithmetic so that PRUx_= 0x2000 adds 0x2000 to the address.

When you use unsigned int, adding offset PRUx_= 0x2000 actually adds 0x2000 * sizeof(unsigned int) to the address. Google “C pointer arithmetic” for more information.

Hello dinux,

Yes I found today that the offset for these base adresses are byte counts and one needs to divide by four the offset values ( that usually appeard in the data sheets ) when adding to the base adress. I tried it and it works ok