InvAdErZz
InvAdErZz

Reputation: 49

c mmap write long to mmaped-area

i want to write a python-c-extension which should write a list of integers into a ram-area because my first version with python was a little bit to slow (30 ms).

In python this perfectly works with following code:

with open("/dev/mem", "r+b") as f:                                      # open file
    ddr_mem = mmap.mmap(f.fileno(), PRU_ICSS_LEN, offset=PRU_ICSS)      # map pru shared-ram

while offset < ramSize:
    ddr_mem[(sharedRam+offset):(sharedRam+offset+4)] = struct.pack('i', self.data[self.i])
    offset += 4
    self.i += 1

Because in the list are only long integer values (4 Bytes) the offset will be increased by 4 for every new value in the list.

As the mmap-area is 12 kB big it is possible to write 3072 values into it, because 12288 Byte / 4 Byte = 3072 or i am wrong?

Now within my c extension i tried the same with this piece of code:

if(ddrMem == NULL) {
    //printf("\nopen: shared-ram...");
    mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (mem_fd < 0) {
        printf("Failed to open /dev/mem (%s)\n", strerror(errno));
        return NULL;
    }
    /* map the DDR memory */
    ddrMem = mmap(0, 0x0FFFFFFF, PROT_WRITE | PROT_READ, MAP_SHARED, mem_fd, PRU_ICSS + OFFSET_DDR + 0xE000); //TODO: weird offset - 0xE000
    if (ddrMem == NULL) {
        printf("Failed to map the device (%s)\n", strerror(errno));
        close(mem_fd);
        return NULL;
    }

for (i = 0; i < d_len; i++) {
    PyObject* temp = PySequence_Fast_GET_ITEM(seq, i);
    elem = PyInt_AsLong(temp);                  
    *((long*) DDR_regaddr+offset) = elem;    // write to shared ram
    offset = offset + 4;

    if(offset >= (ramSize)){
        offset = 0;
    }

But now only every fourth address in the ram-area will get a new value. If i increase the offset with one it works but then i am able to write twice the data --> 6144 elements.

What is the trick ? What i am doing wrong ? Are theses calulations right ? I am not sure if i am right with my thougts.

Upvotes: 0

Views: 560

Answers (2)

InvAdErZz
InvAdErZz

Reputation: 49

Ok sorry.. :(

Wrong memory mapping !

-> missed an offset of 0xF000

But many thanks @kevr - this was also very helpful :)

Upvotes: 0

kevr
kevr

Reputation: 455

Your offset is incorrect because you are performing pointer arithmetic, which already accounts for the size of the long in question.

Try incrementing your pointer by 1 instead of 4.

long *ptr = 0xff;
long *ptrOffset = ptr + 1; // Will access the next 'long' space in memory
long *ptrOffset2 = ptr + 4; // Will access the fourth next 'long' space in memory

Also, the size of the long is actually architecture and compiler dependent. Assuming that it is 4 bytes is not safe.

Upvotes: 1

Related Questions