在Linux上映射ARM全局定时器

时间:2016-11-12 18:52:52

标签: linux timer arm

我已经能够在Zynq 7000板上使用Xilinx SDK创建一个裸机应用程序来访问ARM全局计时器。但是,我正在尝试使用mmap在Xilinx Linux中映射ARM全局定时器并访问它。我使用以下代码:

game[2][le]

每当我尝试访问此虚拟地址时,都会出现分段错误。我发现我的mmap返回的是errno = 22,表示无效参数。我使用mmap来映射相同用户空间中的axi空间,除了地址和它们有效之外,它们具有相同的参数。

我怀疑这个地区有点特别。与ARM infopage一样,它将此区域定义为私有区域。我不明白这究竟是什么意思以及我访问arm全局计时器的解决方案是什么。

P.S我已经知道新的Xilinx Linux内核具有内置驱动程序来访问此全局计时器。但是我无法构建最新的内核并使用它,因为没有关于如何使用计时器的明确帮助。我现在正在寻求两种解决方案。

1 个答案:

答案 0 :(得分:0)

您必须创建一个函数来从内核获取虚拟地址。 观看此视频,您将找到解决方案 https://www.youtube.com/watch?v=XtvVfjIm9Xw&feature=youtu.be

#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)

void *getvaddr(int phys_addr)
{
    void *mapped_base;
    int memfd;

    void *mapped_dev_base;
    off_t dev_base = phys_addr;

    memfd = open("/dev/mem", O_RDWR | O_SYNC); // to open this, the program needs to be run as root
    if (memfd == -1)
    {
        printf("Can't open /dev/mem.\n");
        exit(0);
    }

    // Map one page of memory into user space such that the device is in that page, but it may not
    // be at the start of the page

    mapped_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd,
                    dev_base & ~MAP_MASK);
    if (mapped_base == (void *)-1)
    {
        printf("Can't map the memory to user space.\n");
        exit(0);
    }

    // get the address of the device in user space which will be an offset from the base
    // that was mapped as memory is mapped at the start of the page

    mapped_dev_base = mapped_base + (dev_base & MAP_MASK);
    return mapped_dev_base;
}