系统提示memory fault,不清楚是什么缘由。

调试nandflash驱动时,总提醒“Memory Fault”后而退出驱动程序。后来大概确定了对IO口的操作引起了驱动的错误退出。

对于arm板的IO口操作涉及到两个地方:
1.在startup的中断callout处对IO进行了地址映射,以判断IO口中断;
2.在nandflash驱动的初始化时又对IO地址进行了映射,因为要对nandflash使用的某些IO口进行初始化操作,并且在后续的nandflash操作中需要一些IO口操作。

在nandflash中每到IO操作时便出现“Memory Fault”的错误而推出nandflash驱动,不清楚针这种状况问题在哪?是不是因为存在两次映射而引起的错误或者是其他呢?先谢谢各位了!

可以Debug调试看看是那句话出错吗?

我是通过往串口输出信息来确定在哪里出现的问题,出现错误的地方是在写IO口寄存器处,每out32(……)就出现错误提示

多次映射不会有任何问题.
是SIGSEGV还是SIGBUS?

没有取得权限吧。在main()里加下面这句试试?

ThreadCtl(_NTO_TCTL_IO, 0);

我在main中添加了ThreadCtl(_NTO_TCTL_IO, 0);好像问题依旧。

nandflash出错后的提示信息为:
Process 12297 (fs_etfs_sam9261s) terminated SIGSEGV code=1 fltno=11 ip=00102050 ref=01800c34
Memory fault

我通过串口输出信息确定问题就在于往IO口寄存器写值的位置,我首先使用mmap_device_io映射一下后再使用out32进行操作。

我编写了一个很小的程序,全部代码如下:

#define SAM9261S_PIOC_BASE 0xfffff800

main()
{
uintptr_t handle;
volatile uint32_t inhalt;
if(ThreadCtl(_NTO_TCTL_IO,0)== -1)
printf(“Rechte nicht vorhanden…\n”);
printf(“1\n”);
handle=mmap_device_io(0x40,SAM9261S_PIOC_BASE);
printf(“2\n”);
inhalt=in32(handle + 0x08);
printf("%X\n",inhalt);
}
程序执行后输出信息为:
1
2
Preocees 16392 (io) terminated SIGSEGV code=1 fltno=11 ip=001007cf ref=01800808
Memory fault

郁闷了,修改了很多地方问题依旧。

root下运行的吗?

是在root运行的

蹊跷.
mmap_device_io失败了?你的QNX是什么版本?

试试
#define SAM9261S_PIOC_BASE 0xfffff800ULL

qnx版本为6.2.1
我试了mmap_device_io和mmap_device_memory都是一样的结果。不知道是不是硬件的问题了。

1.对于ThreadCtl(_NTO_TCTL_IO,0)这句话的位置是不是有限制?
2.我在startup的中断callout中有映射io寄存器,此时是不是也应该有如“ThreadCtl(_NTO_TCTL_IO,0)”的语句呢?

应该跟硬件没有关系.
只要ThreadCtl在mmap_device_io之前,就应该没有问题.
callout不用ThreadCtl.

检查一下mmap_device_io的返回值,若有错误的话打印出errno值.

首先谢谢了!
我将代码修改了一下:
#define SAM9261S_PIOC_BASE 0xfffff800ULL

int main()
{
uintptr_t handle;
volatile uint32_t inhalt;

if(ThreadCtl(_NTO_TCTL_IO, 0) == -1)
{
printf("%s", strerror(errno));
exit(-1);
}

handle = mmap_device_io(0x40,SAM9261S_PIOC_BASE);
printf("%s\n", strerror(errno));
printf(“mapped addr:%x\n”,handle);

inhalt=in32(handle + 0x08);
printf("%X\n",inhalt);
return 0;
}
输出信息为:
No error
mapped addr:1800800

Process 16392 (io) terminated SIGSEGV code=1 fltno=11 ip=00100650 ref=01800808
Memory fault

似乎映射没有任何的问题,但是对映射区域的读写都出现了问题。

我对ThreadCtl(_NTO_TCTL_IO, 0)还有一些疑问:
当ThreadCtl(_NTO_TCTL_IO, 0)处理后mmap_device_io映射的区域有没有限制的?完全地得到了其他私有地址空间中映射地址空间的权限吗?假如已经映射的空间很大,而我当前ThreadCtl(_NTO_TCTL_IO, 0)处理后映射的空间比较小,只是它的子集,如此有没有问题的?

怀疑startup中callout的问题,所以又进行了相关的测试。

在原本的板子上我使用了两个串口,一个DEBUG串口,一个UART0串口,uart
0在系统起来后作为控制台使用,而DEBUG口是在startup中作为callout_debug使用的,而在系统起来之后的串口驱动为uart0.
现在想在系统起来之后串口驱动为DBUG的,所以进行了相关的修改,等DBUG驱动起来之后出现了意料之中的事情,当映射了DBUG寄存器之后进行相关操作时整个驱动即中断了,和前面IO操作同样的情况。

不清楚callout哪边导致上述的问题。

大家指点一个调试的方向吧,谢谢了!

如果不用串口驱动,用debug callout会怎么样?
将debug callout代码贴上来看看.

.extern patch_channel
.extern dbg_device

/*


  • r0 - physical address of syspage
  • r1 - virtual address of syspage
  • r2 - offset from start of syspage to start of the callout routine
  • r3 - offset from start of syspage to read/write data used by callout

/
patch_debug:
stmdb sp!,{r4,lr}
add r4, r0, r2 /
address of callout routine */

ldr r0, Lpatch_channel
ldr r1, Ldbg_device
ldr r0, [r0]
add r1, r1, r0, lsl #3
ldr r1, [r1, #DDI_BASE]
mov r0, #SAM9261S_DBGU_SIZE
bl callout_io_map

/* Patch the callout routine */
CALLOUT_PATCH r4, r0, r1, r2, ip
ldmia sp!,{r4,pc}

Lpatch_channel: .word patch_channel
Ldbg_device: .word dbg_device

CALLOUT_START(display_char_sam9261s, 0, patch_debug)
mov ip, #0x000000ff
orr ip, ip, #0x0000ff00
orr ip, ip, #0x00ff0000
orr ip, ip, #0xff000000

0: ldr r3, [ip, #SAM9261S_DBGU_SR]
tst r3, #0x02 /* TX Ready */
beq 0b
str r1, [ip, #SAM9261S_DBGU_THR]

mov pc, lr
CALLOUT_END(display_char_sam9261s)


CALLOUT_START(poll_key_sam9261s, 0, patch_debug)
mov ip, #0x000000ff
orr ip, ip, #0x0000ff00
orr ip, ip, #0x00ff0000
orr ip, ip, #0xff000000

1: ldr r3, [ip, #SAM9261S_DBGU_SR]
tst r3, #0x01 /* RX Ready */
ldrne r0, [ip, #SAM9261S_DBGU_RHR]
mvneq r0, #1

mov pc, lr
CALLOUT_END(poll_key_sam9261s)


CALLOUT_START(break_detect_sam9261s, 0, patch_debug)
mov ip, #0x000000ff
orr ip, ip, #0x0000ff00
orr ip, ip, #0x00ff0000
orr ip, ip, #0xff000000

mov r0, #0
mov pc, lr
CALLOUT_END(break_detect_sam9261s)

全部的代码就是这些了。

一头雾水.