内存访问中的分段错误

时间:2018-07-30 06:10:32

标签: c mmap

我已将0x40000000的基地址映射到虚拟内存地址。但是,当我尝试读取0x40100000位置上的寄存器值时,出现了分段错误。 mmap()函数中使用的页面大小为4K,其中文件描述符的值为3

从主调用init()函数以初始化内存: 这里的UWord8unsigned charUWord32unsigned int

UWord8 init()
{
    UWord8 error;
    printf("Initializing Devices in Zynq...\n\r\n\r");
    error = initMemory();

    if(error)
    {
        printf("PL:\tAccess Denied\n\r");
        return 1;
    }

    if(!error)
    {
        error = initFpga();
        if(error)
        {
            printf("Access Denied to mmap...\n\r");
            return 1;
        }
    }
}

UWord8 initMemory(void)
{
    UWord8 error = 0;

    //Initializing /dev/mem
    fd = open(MEMORY_ACCESS, READ_WRITE);

    if(fd < 1)
    {
        error = 1;
        #if DEBUG_MODE
            printf("Could not open /dev/mem for access\n");
        #endif
    }
    else
    {
        printf("Value of fd is %u\n", fd);
        page_size = sysconf(_SC_PAGESIZE);
        printf("The page size is %u\n", page_size);
        #if DEBUG_MODE
            printf("Successfully opened /dev/mem for access\n");
        #endif
    }

    //Opening text file for writing pointer data
    fp = fopen("/home/pointer_data.txt", "a");

    if(fp == NULL)
    {
        error = 1;
        #if DEBUG_MODE
            printf("Could not open text file for writing.\n\r");
        #endif
    }
    else
    {
        #if DEBUG_MODE
            printf("Successfully opened text file for writing.\n\r");
        #endif
    }
    return error;
}

UWord8 initFpga(void)
{
    UWord8 error = 0;
    unsigned page_addr, device_addr;

    device_addr = BASE_ADDRESS;
    page_addr = (device_addr & (~(page_size-1)));
    fpga_pageOffset = device_addr - page_addr;
    fpga_ptr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_addr); //mmap the device into memory

    if(fpga_ptr == NULL)
    {
        printf("Memory mapping to Base address 0x%08x failed...\n\r",BASE_ADDRESS);
        error = 1;
    }   
    return error;
}

以下是该函数在特定地址处读取的值,发送给该函数的地址是相对于基地址的偏移量:

UWord32 _getWord(UWord32 address)
{
    UWord32 data = *((unsigned *)(fpga_ptr + fpga_pageOffset + address));
    printf("peek 0x%08x =0x%08x\n\r", BASE_ADDRESS + address, data);
    return data;
}

此行没有错误:

_getWord(0x000ffff8)

但是我在以下方面遇到了细分错误:

_getWord(0x00100000)

1 个答案:

答案 0 :(得分:1)

创建内存映射时,将其大小设置为等于页面大小-4kb。

fpga_ptr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_addr); //mmap the device into memory

这转换为0x1000个字节,但是您尝试在映射开始之后访问数据0x100000个字节,这会引起分段错误。要解决此问题,请映射更大的内存区域。例如:

fpga_ptr = mmap(NULL, 0x1000 * page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_addr);

这将使您可以访问内存映射开始之后的下一个0x1000000字节。