我正在通过将UART的物理基地址映射到用户空间来访问UART。读取操作成功,但写入操作导致分段错误。下面是我的代码
#define READ_REG32(reg) ( *((volatile int *) (reg)) )
#define WRITE_REG32(reg,value) ( *((volatile int *) (reg)) = value )
static int Write_on_uart()
{
void * map_base;
FILE *f;
int type,fd;
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd) {
printf("Success to open /dev/mem fd=%08x\n", fd);
}
else {
printf("Fail to open /dev/mem fd=%08x\n", fd);
}
map_base = mmap(0, ALLOC_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x21E8000);
type = READ_REG32(map_base + UCR1);
printf("READ_REG32 successful\n");
printf("Going to WRITE_REG32 register\n");
WRITE_REG32(map_base + UTXD,'R'); ///Got segementation fault
printf("WRITE_REG32 successful\n");
close(fd);
munmap(map_base, ALLOC_SIZE);
printf("reg32[%08x] = value[%08x] \n", map_base, type);
type = (type & ( 1 << 27 )) >> 27 ;
printf("reg32[%08x] = value[%08x] \n", map_base, type);
return type;
}
分段错误如下:
, *pte=00000000, *ppte=00000000
[ 50.354260] CPU: 0 PID: 401 Comm: raw_uart_access Not tainted 4.9.84-+gb2a7f2f #4
[ 50.381000] Hardware name: Freescale i.MX6 UltraLite (Device Tree)
[ 50.397017] task: 9229d140 task.stack: 9271a000
[ 50.411233] PC is at 0x1057c
[ 50.423459] LR is at 0x10574
[ 50.435355] pc : [<0001057c>] lr : [<00010574>] psr: 200d0010
[ 50.435355] sp : 7e8b4c80 ip : 00000000 fp : 7e8b4c9c
[ 50.464647] r10: 76f61fac r9 : 00000000 r8 : 00000000
[ 50.478608] r7 : 00000000 r6 : 00010408 r5 : 00000000 r4 : 00010634
[ 50.493738] r3 : ffffffff r2 : 00000010 r1 : 76f60210 r0 : ffffffff
[ 50.508645] Flags: nzCv IRQs on FIQs on Mode USER_32 ISA ARM Segment user
[ 50.532259] Control: 10c5387d Table: 9297806a DAC: 00000055
[ 50.546485] CPU: 0 PID: 401 Comm: raw_uart_access Not tainted 4.9.84-+gb2a7f2f #4
[ 50.570395] Hardware name: Freescale i.MX6 UltraLite (Device Tree)
[ 50.585015] Backtrace:
[ 50.595863] [<8010bd3c>] (dump_backtrace) from [<8010c014>] (show_stack+0x18/0x1c)
[ 50.620055] r7:00000017 r6:600d0113 r5:00000000 r4:80c1c9f0
[ 50.634156] [<8010bffc>] (show_stack) from [<8042ed84>] (dump_stack+0x90/0xa4)
[ 50.657979] [<8042ecf4>] (dump_stack) from [<80108a98>] (show_regs+0x14/0x18)
[ 50.673778] r7:00000017 r6:0000007f r5:0000000b r4:9229d140
[ 50.688016] [<80108a84>] (show_regs) from [<801147e0>] (__do_user_fault+0xc4/0xc8)
[ 50.712379] [<8011471c>] (__do_user_fault) from [<801149f0>] (do_page_fault+0x20c/0x3a4)
[ 50.737755] r8:0000007f r7:00000017 r6:9267dc40 r5:9229d140 r4:9271bfb0
[ 50.753746] [<801147e4>] (do_page_fault) from [<8010134c>] (do_DataAbort+0x44/0xc0)
[ 50.779830] r10:76f61fac r9:00000000 r8:9271bfb0 r7:0000007f r6:801147e4 r5:00000017
[ 50.806897] r4:80c09db4
[ 50.819029] [<80101308>] (do_DataAbort) from [<8010cee0>] (__dabt_usr+0x40/0x60)
[ 50.845699] Exception stack(0x9271bfb0 to 0x9271bff8)
[ 50.860521] bfa0: ffffffff 76f60210 00000010 ffffffff
[ 50.887867] bfc0: 00010634 00000000 00010408 00000000 00000000 00000000 76f61fac 7e8b4c9c
[ 50.915238] bfe0: 00000000 7e8b4c80 00010574 0001057c 200d0010 ffffffff
[ 50.931721] r8:10c5387d r7:10c5387d r6:ffffffff r5:200d0010 r4:0001057c
有人可以给我提示吗?
答案 0 :(得分:0)
您可能想看看'uio',这是一个框架,可帮助在Linux中实现用户模式驱动程序。除了通常需要与中断同步之外,它还允许平台代码来确保在页表条目中为映射设置正确的访问位。
某些架构(例如x86)会将物理地址范围与属性相关联,以使诸如“设备模式”之类的东西始终由总线正确实现。 ARMv7不会这样做,程序员应负责确保使用正确的总线协议。我怀疑/ dev / mem的mmap会这样做。结果是您的写操作可能被发布为设备注册不支持的总线操作。
PAT之类的“有用”内容是X86不能用于精美内容的部分原因;但是,ARM的成本由程序员承担。
此外,*(volatile int *)x几乎没有意义,因此有时可能会起作用。