Search code examples
pythoncraspberry-pi3mmap

Convert mmap object (mmaps don't support concatenation) / convert c code to python


Hello every one I'm trying to convert below code to python (Accessing the raspberry pi 1Mhz timer), I'm stuck when to mmap object we need to + TIMER_OFFSET (timer = (long long int *)((char *)st_base + TIMER_OFFSET);) when I try to do it in Python I got SystemError: mmaps don't support concatenation. I was looking for convert mmap object but I find nothing, Can we fight this ? It is possible to convert whole this code to python? I mean now I have second thoughts about it ?

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

#define ST_BASE (0x3F003000)
#define TIMER_OFFSET (4)

int main(int argc, char *argv[]) {
    long long int t, prev, *timer; // 64 bit timer
    int fd;
    void *st_base; // byte ptr to simplify offset math

    // get access to system core memory
    if (-1 == (fd = open("/dev/mem", O_RDONLY))) {
        fprintf(stderr, "open() failed.\n");
        return 255;
    }

    // map a specific page into process's address space
    if (MAP_FAILED == (st_base = mmap(NULL, 4096,
                        PROT_READ, MAP_SHARED, fd, ST_BASE))) {
        fprintf(stderr, "mmap() failed.\n");
        return 254;
    }

    // set up pointer, based on mapped page
    timer = (long long int *)((char *)st_base + TIMER_OFFSET); //<- here is problem

    // read initial timer
    prev = *timer;
    // and wait
    sleep(1);

    while (1==1) { // forever
        // read new timer
        t = *timer;
        printf("Timer diff = %lld    \r", prev);
        fflush(stdout);
        // save current timer
        prev = t;
        // and wait
        sleep(1);
    }
    // will never get here
    return 0;
}

Python code (for now I skip this ifs) :

ST_BASE = 0x3F003000
TIMER_OFFSET = 4
import struct
sizeof_long_long = struct.calcsize('q')

def timer():
    while True:
        fd = os.open("/dev/mem",os.O_RDWR | os.O_SYNC)
        stBase = mmap.mmap(fileno=fd,length=4096,offset=ST_BASE)
        timer_bytes = stBase[TIMER_OFFSET:TIMER_OFFSET + sizeof_long_long]
        #print(timer_bytes)
        timer_value, = struct.unpack('q', timer_bytes)
        print(timer_value)
        os.close(fd)

Solution

  • Almost good :) Just unpack_from instead off unpack

    import os, mmap, sys
    import struct
    
    ST_BASE = 0x3F003000
    TIMER_OFFSET = 4
    sizeof_long_long = struct.calcsize("Q")
    LENGTH = TIMER_OFFSET + sizeof_long_long
    
    def timer():
        fd = os.open("/dev/mem", os.O_RDONLY | os.O_SYNC)
        stBase = mmap.mmap(fileno=fd, length=4096, access=mmap.ACCESS_COPY, offset=ST_BASE)
        os.close(fd)
    
        while True:
            timer_value = struct.unpack_from("Q", stBase, TIMER_OFFSET)[0]
            print("timer_value")