linux内存分区运行程序,linux mmap从用户空间应用程序访问PCI内存区域

作为我的PCI驱动程序的第一级测试,我希望我可以通过/sys/bus/pci/devices/0000:01:00.0/resource0访问pci_iomap区域

来自我的用户应用程序的文mmap的手册页,我找到的示例程序以及其他帖子似乎表明用户进程访问应该有效.但是有些文章似乎表明mmap调用需要通过ioctl访问器在内核中完成.

我的问题是PCI sysfs资源文件的mmap()应该来自应用程序空间吗?

当我运行我的代码时,mmap返回看起来像有效地址的内容但是当我尝试访问虚拟地址时出现Bus错误.

我相信我的终端设备是一个PCI到Xilinx AXI桥接器,它在FPGA上运行正常,因为我可以通过Windows PCIe实用程序(Win驱动程序)进行R / W操作

我使用的是Linux版本3.12.37的NXP LS1021A ARM7处理器.

谢谢

法案

并不是说我希望任何人调试我的代码,但我正在做的事情最好用代码来解释,所以我也把它包括在内.如果粘贴的代码无法正确显示,我深表歉意.希望它能做到.

我运行下面的代码并得到

root @ ls1021aiot:〜#pcimem /sys/bus/pci/devices/0000:01:00.0/resource0 0 w

/sys/bus/pci/devices/0000:01:00.0/resource0已打开.

目标偏移量为0x0,页面大小为4096,映射掩码为0xFFF

mmap(0,4096,0×3,0x1,3,0×0)

mmap(0,4096,0×3,0x1,3,0×0)

PCI内存将4096字节区域映射到map_base 0x76fb5000.

PCI内存映射访问0x 76FB5000.

总线错误

/*

* pcimem.c: Simple program to read/write from/to a pci device from userspace.

*

* Copyright (C) 2010, Bill Farrow (bfarrow@beyondelectronics.us)

*

* Based on the devmem2.c code

* Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)

*

* This program is free software; you can redistribute it and/or modify

* it under the terms of the GNU General Public License as published by

* the Free Software Foundation; either version 2 of the License, or

* (at your option) any later version.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program; if not, write to the Free Software

* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

*

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define PRINT_ERROR \

do { \

fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \

__LINE__, __FILE__, errno, strerror(errno)); exit(1); \

} while(0)

#define MAP_SIZE 4096UL

#define MAP_MASK (MAP_SIZE - 1)

int main(int argc, char **argv) {

int fd;

void *map_base, *virt_addr;

uint32_t read_result, writeval;

char *filename;

off_t target;

int access_type = 'w';

if(argc < 3) {

// pcimem /sys/bus/pci/devices/0001\:00\:07.0/resource0 0x100 w 0x00

// argv[0] [1] [2] [3] [4]

fprintf(stderr, "\nUsage:\t%s { sys file } { offset } [ type [ data ] ]\n"

"\tsys file: sysfs file for the pci resource to act on\n"

"\toffset : offset into pci memory region to act upon\n"

"\ttype : access operation type : [b]yte, [h]alfword, [w]ord\n"

"\tdata : data to be written\n\n",

argv[0]);

exit(1);

}

filename = argv[1];

target = strtoul(argv[2], 0, 0);

if(argc > 3)

access_type = tolower(argv[3][0]);

if((fd = open(filename, O_RDWR | O_SYNC)) == -1){

PRINT_ERROR;

}

printf("%s opened.\n", filename);

printf("Target offset is 0x%x, page size is %ld map mask is 0x%lX\n", (int) target, sysconf(_SC_PAGE_SIZE), MAP_MASK);

fflush(stdout);

/* Map one page */

#if 0

//map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t) (target & ~MAP_MASK));

//map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);

#endif

printf("mmap(%d, %ld, 0x%x, 0x%x, %d, 0x%x)\n", 0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (int) (target & ~MAP_MASK));

map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (target & ~MAP_MASK));

if(map_base == (void *) -1){

printf("PCI Memory mapped ERROR.\n");

PRINT_ERROR;

close(fd);

return 1;

}

printf("mmap(%d, %ld, 0x%x, 0x%x, %d, 0x%x)\n", 0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (int) (target & ~MAP_MASK));

printf("PCI Memory mapped %ld byte region to map_base 0x%08lx.\n", MAP_SIZE, (unsigned long) map_base);

fflush(stdout);

virt_addr = map_base + (target & MAP_MASK);

printf("PCI Memory mapped access 0x %08X.\n", (uint32_t ) virt_addr);

switch(access_type) {

case 'b':

read_result = *((uint8_t *) virt_addr);

break;

case 'h':

read_result = *((uint16_t *) virt_addr);

break;

case 'w':

read_result = *((uint32_t *) virt_addr);

printf("READ Value at offset 0x%X (%p): 0x%X\n", (int) target, virt_addr, read_result);

break;

default:

fprintf(stderr, "Illegal data type '%c'.\n", access_type);

exit(2);

}

fflush(stdout);

if(argc > 4) {

writeval = strtoul(argv[4], 0, 0);

switch(access_type) {

case 'b':

*((uint8_t *) virt_addr) = writeval;

read_result = *((uint8_t *) virt_addr);

break;

case 'h':

*((uint16_t *) virt_addr) = writeval;

read_result = *((uint16_t *) virt_addr);

break;

case 'w':

*((uint32_t *) virt_addr) = writeval;

read_result = *((uint32_t *) virt_addr);

break;

}

printf("Written 0x%X; readback 0x%X\n", writeval, read_result);

fflush(stdout);

}

if(munmap(map_base, MAP_SIZE) == -1) { PRINT_ERROR;}

close(fd);

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值