我正在使用双核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类的地方(程序并不复杂)。
答案 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(),则不应再遇到此问题。