segmentation error



  • Hallo,

    ich habe 2 init functionen die speicher mappen...funtion1 funktioniert, leider gibt es bei funktion2 einen segmenation error...
    funktion1 verwendet /dev/mem (ich weiss ich sollte nicht direkt auf /dev/mem zugreifen...)
    funktion2 verwendet /dev/uio0 wobei /dev/uio0 auf addresse 0x40000000 beginnt, groesse: 0x400000
    irgendwo sollte der fehler im offset sein!?

    ///////////////////////////////////////////////////////////////////////////////
    // works fine:
    #define OSC_FPGA_BASE_ADDR 0x40100000
    #define OSC_FPGA_BASE_SIZE 0x30000
    #define OSC_FPGA_CHA_OFFSET    0x10000
    #define OSC_FPGA_CHB_OFFSET    0x20000
    
    osc_fpga_reg_mem_t *g_osc_fpga_reg_mem = NULL;
    uint32_t           *g_osc_fpga_cha_mem = NULL;
    uint32_t           *g_osc_fpga_chb_mem = NULL;
    
    void init() {
        /* Page variables used to calculate correct mapping addresses */
        void *page_ptr;
        long page_addr, page_off, page_size = sysconf(_SC_PAGESIZE);
    
        /* If module was already initialized once, clean all internals. */
        if(__osc_fpga_cleanup_mem() < 0)
            return -1;
    
        /* Open /dev/mem to access directly system memory */
        g_osc_fpga_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
        if(g_osc_fpga_mem_fd < 0) {
            fprintf(stderr, "open(/dev/mem) failed: %s\n", strerror(errno));
            return -1;
        }
    
        /* Calculate correct page address and offset from OSC_FPGA_BASE_ADDR and
         * OSC_FPGA_BASE_SIZE 
         */
        page_addr = OSC_FPGA_BASE_ADDR & (~(page_size-1));
        page_off  = OSC_FPGA_BASE_ADDR - page_addr;
    
        /* Map FPGA memory space to page_ptr. */
        page_ptr = mmap(NULL, OSC_FPGA_BASE_SIZE, PROT_READ | PROT_WRITE,
                              MAP_SHARED, g_osc_fpga_mem_fd, page_addr);
        if((void *)page_ptr == MAP_FAILED) {
            fprintf(stderr, "mmap() failed: %s\n", strerror(errno));
            __osc_fpga_cleanup_mem();
            return -1;
        }
    
        /* Set FPGA OSC module pointers to correct values. */
        g_osc_fpga_reg_mem = page_ptr + page_off;
        g_osc_fpga_cha_mem = (uint32_t *)g_osc_fpga_reg_mem + 
            (OSC_FPGA_CHA_OFFSET / sizeof(uint32_t));
        g_osc_fpga_chb_mem = (uint32_t *)g_osc_fpga_reg_mem + 
            (OSC_FPGA_CHB_OFFSET / sizeof(uint32_t));
     }
    
    ////////////////////////////////////////////////////////////////////////////////
    // produces a segmentation fault:
    
    osc_fpga_reg_mem_t *g_osc_fpga_reg_mem = NULL;
    uint32_t           *g_osc_fpga_cha_mem = NULL;
    uint32_t           *g_osc_fpga_chb_mem = NULL;
    
    #define OSC_FPGA_BASE_ADDR 0x100000
    #define OSC_FPGA_BASE_SIZE 0x400000
    #define OSC_FPGA_CHA_OFFSET    0x10000
    #define OSC_FPGA_CHB_OFFSET    0x20000
    
    /** The FPGA register structure (defined in fpga_osc.h) */
    osc_fpga_reg_mem_t *g_osc_fpga_reg_mem = NULL;
    /** The FPGA input signal buffer pointer for channel A */
    uint32_t           *g_osc_fpga_cha_mem = NULL;
    /** The FPGA input signal buffer pointer for channel B */
    uint32_t           *g_osc_fpga_chb_mem = NULL;
    
    void init() {
    	/* Page variables used to calculate correct mapping addresses */
    	void *page_ptr;
    
    	/* If module was already initialized, clean all internals */
    	if(__osc_fpga_cleanup_mem() < 0)
    	    return -1;
    
    	/* Open /dev/mem to access directly system memory */
    	// dev/uio0 starts at 0x40000000, size: 0x400000
    
    	g_osc_fpga_mem_fd = open("/dev/uio0", O_RDWR | O_SYNC);
    	if(g_osc_fpga_mem_fd < 0) {
    	    fprintf(stderr, "open(/dev/uio0) failed: %s\n", strerror(errno));
    	    return -1;
    	}
    
    	page_ptr = mmap(NULL, OSC_FPGA_BASE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, g_osc_fpga_mem_fd, 0);
    
    	/* Map FPGA memory space to page_ptr. */
    	if((void *)page_ptr == MAP_FAILED) {
    	    fprintf(stderr, "mmap() failed: %s\n", strerror(errno));
    	    __osc_fpga_cleanup_mem();
    	    return -1;
    	}
    
    	/* Set FPGA AWG module pointers to correct values. */
    	g_osc_fpga_reg_mem = (osc_fpga_reg_mem_t *)((uint8_t*) page_ptr + OSC_FPGA_BASE_ADDR);
    	g_osc_fpga_cha_mem = (uint32_t *)((uint8_t*) page_ptr + OSC_FPGA_BASE_ADDR + OSC_FPGA_CHA_OFFSET);
    	g_osc_fpga_chb_mem = (uint32_t *)((uint8_t*) page_ptr + OSC_FPGA_BASE_ADDR + OSC_FPGA_CHB_OFFSET);
    }
    


  • das problem ist das /dev/uio den offset unterschiedlich handled...

    https://www.kernel.org/doc/htmldocs/uio-howto/mmap_device_memory.html:

    From userspace, the different mappings are distinguished by adjusting the offset parameter of the mmap() call. To map the memory of mapping N, you have to use N times the page size as your offset:
    
    offset = N * getpagesize();
    

    jedoch weiss ich nicht was N sein soll?!



  • Note that UIO implements mmap() in an unusual way. The last parameter
    (“offset”, 0 in the example above) is used to tell UIO which mapping we want to
    use. It has to be set to N*getpagesize() for mapping number N. An offset
    cannot be given, UIO always maps from the beginning of the memory. This
    strange behaviour of mmap() was necessary to allow devices to have more than
    one address range that can be mapped. If mmap() was successful, map_addr is
    a pointer to the beginning of the device's memory.


Anmelden zum Antworten