mmap死了几次访问后无法打开/ dev / mem

时间:2017-06-20 01:51:38

标签: c++ c embedded embedded-linux

我正在使用双核ARM A9上的mmap编写一些用户空间驱动程序来访问FPGA内部的一些HW寄存器。我们有一个定制的SPI模块与另一个芯片通信,我们访问该芯片内部的HW寄存器。我为我的SPI" Driver"写了一个C ++类。基本上打破了对外部芯片内部地址的读/写操作。我使用mmap访问FPGA内部的SPI(仅占用大约100字节的存储空间(0xFF20_2000 - > 0xFF20_007F))。

当我调用SPI类(并且我只为驱动程序执行一次)时,它会通过并执行一个mmap open for SPI HW的基址。

void spi_op::cfg_mmap(){

    if( ( this->fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) {
        printf( "ERROR: could not open \"/dev/mem\"...\n" );
        this->error = 1;
        return;
    }

    uint32_t map_addr_base = this->addr_base & MMAP_BASE_MASK;

    this->virtual_base = mmap( NULL, MMAP_PAGE_SIZE, ( PROT_READ | PROT_WRITE ), MAP_SHARED, this->fd, map_addr_base );

    if( this->virtual_base == MAP_FAILED ) {
        printf( "ERROR: mmap() failed...\n" );
        close( this->fd );
        this->error = 1;
        return;
    }

    //To initialize to the proper pointer in the event not on a page boundary
    this->virtual_base += (SPI_MASTER_ADDR_BASE - map_addr_base);
}

我将SPI硬件寄存器构建为结构/联合,以便于(ier)位操作(我已经知道可以被视为专有的东西,但与问题无关)。 / p>

union spi_regs_reg1 {
    struct {
        volatile uint32_t xxxx: 32;
    } bits;
    volatile uint32_t word;
};

union spi_regs_reg2 {
    struct {
        volatile uint32_t xxxx: 1;
        volatile uint32_t xxxx: 1;
        volatile uint32_t xxxx: 1;
        volatile uint32_t xxxx: 1;
        volatile uint32_t xxxx: 1;
        volatile uint32_t xxxx: 1;
        volatile uint32_t xxxx: 1;
        volatile uint32_t xxxx: 1;
        volatile uint32_t xxxx: 1;
        volatile uint32_t xxxx: 1;
        volatile uint32_t xxxx: 1;
        volatile uint32_t xxxx: 1;
    } bits;
    volatile uint32_t word;
};

struct spi_regs_regs {
    union spi_regs_blockid spi_regs_reg1;
    union spi_regs_gnrlsta spi_regs_reg2;
    blah blah blah

作为init /构造函数的一部分,我有一个spi_regs结构指针,它被赋值

void spi_op::spi_master_init(){

    this->cfg_mmap();

    spi_regs = (struct spi_regs_regs *)(this->virtual_base);


    //an Example of how I can now access the bits in the HW registers
    //Assert the RESET
    spi_regs->spi_regs_reg.bits.spi_reset = 1;

每当我想要读或写时,我现在只需调用spi.read(addr)或spi.write(addr,data)来执行操作。

这似乎工作正常,但偶尔在一堆读/写后我开始出错

"ERROR: could not open "/dev/mem"...". 

现在这是cfg_mmap()任务中的内容。但是我只将它作为构造函数的一部分调用一次。在这个特定的测试中,我正在设置多个不同的设置并运行每个设置并重置其间的外部部分(但不是我用mmap控制的SPI)。我基本上有一个for循环,但SPI类的构造函数是for循环的先行。

作为我输入时的快速测试,我将cfg_mmap任务中的错误消息更改为

"ERROR: blah could not open "/dev/mem"..."

然后在跑步期间我得到了这个

<normal prints from my code>
ERROR: could not open "/dev/mem"...
ERROR: could not open "/dev/mem"...
ERROR: could not open "/dev/mem"...
ERROR: could not open "/dev/mem"...
ERROR: could not open "/dev/mem"...
ERROR: blah could not open "/dev/mem"...
Segmentation fault
root@arria10:~# 

/ dev / mem是否可能过载或类似的东西?我已经在我的代码中进行了一些搜索,我不能在我的生活中找到我不止一次调用SPI类的地方(程序并不复杂)。

1 个答案:

答案 0 :(得分:1)

如果我认为你的课被称为&#34; spi_op&#34;你可能需要使用&#34; munmap(virtual_base,MMAP_PAGE_SIZE)&#34;来创建spi_op :: ~spi_op()(所谓的&#34;析构函数&#34;)。和&#34;关闭(fd)&#34;指令。因此它可能是析构函数的主题:例如,请参阅https://www.tutorialspoint.com/cplusplus/cpp_constructor_destructor.htm。如果您正确使用munmap()和close(),则不应再遇到此问题。