这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 请教各位大侠,nand的TFFS和ftp上传超过20k时发生错误的问题

共10条 1/1 1 跳转至

请教各位大侠,nand的TFFS和ftp上传超过20k时发生错误的问题

菜鸟
2007-06-28 06:28:37     打赏

目前nandflash可以格式话,可以加载,但在用ftp上传文件时出现问题,上传小于20k的文件没有问题,但上传大一点的文件就会出现异常:异常如下
Data abort
Exception address: 0x300a1964
Current Processor Status Register: 0x20000013
Task: 0x33df7c8c "tFtpdServ1"
trcStack aborted: error in top frame
由于问题一直存在所以我更换了ftpdlib.c,ftplib.c ,则list目录的问题解决了,但异常还是出现!
我的开发环境是5.5,芯片是2410,nandflash是k9f1208 定义的是norflash的ftlsystffs.c和tffsconfig.c都用的是norflash的,写了read函数
请问这会是哪里出现的问题呢?
考虑如下:
1.有时后会出现
0x33dfce20 (tDcacheUpd): disk cache error: device 33ffc08c block 249 errno c0006, disk removed while writing data, possible data loss ,此情况只出现过一两次
问:是cache的原因吗?
2.有是会出现
Exception number 16: Task: 0x33e22b58 (tFtpdServ1)
Data abort
Program Counter: 0x3009ce38
Status Register: 0x20000013
0 : logical2Physical ()
此函数是在ftllite.c中定义如下
/*----------------------------------------------------------------------*/
/* l o g i c a l 2 P h y s i c a l */
/* */
/* Returns the physical address of a logical sector no. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : logical sector no. */
/* */
/* Returns: */
/* CardAddress : physical address of sector */
/*----------------------------------------------------------------------*/

static CardAddress logical2Physical(Flare vol, LogicalSectorNo address)
{
return physicalBase(&vol,vol.logicalUnits[address >> (vol.unitSizeBits - SECTOR_SIZE_BITS)]) |
(((CardAddress) address << SECTOR_SIZE_BITS) & vol.unitOffsetMask);
}

问题如下:
1:有可能是ftpsever的问题,如果是:请问可能是哪些方面的?
2:TFFS驱动的问题,有时候会提示到findFreeSector这个函数有问题
3:还是要用nandflash的翻译层?但用上就只能辨识到,调用不到其他函数




关键词: 请教     各位     大侠     上传     超过     发生     错误     问题    

菜鸟
2007-06-28 19:00:00     打赏
2楼

看起来,你的问题更加像MMU配置的问题,或者是对齐问题,CPU好像经常在跳数据异常。不知道你啥架构。

等woodhead版主来看看吧,tffs他太精通了。


菜鸟
2007-06-28 23:09:00     打赏
3楼

谢谢yaopg大侠的回答:

①芯片是 三星 arm9 2410 nandflash 为 k9f1208 对应bank1(0X08000000--0X10000000)

#define NFLASH_BASE_ADRS (0x08000000)
#define NFLASH_SIZE (0x04000000)

mmu定义如下:

{
(void *) (0x08000000),
(void *) (0x08000000),
ROUND_UP (0x04000000, PAGE_SIZE),
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT
},

但在romInit.s没有对bank1进行初始化,只对bank0进行了初始话,但我觉得不会是这里的问题,因为格式化和加载都没有问题。

②read函数的输出为:

READ: address = 0x0, length = 0x44

READ: address = 0x10000, length = 0x44 /*不明白length为什么是0x44 ?*/

READ: address = 0x20000, length = 0x44

一直读到

READ: address = 0x3ff0000, length = 0x44

结束(共计64m,每隔64kb读一次,共计1024次)

Erase函数的输出为:

firstBlock = 0x0, numOfBlock = 0x4

ERASE: blockNo = 0x0

ERASE: blockNo = 0x1

ERASE: blockNo = 0x2

ERASE: blockNo = 0x3

WRITE: address = 0x0, length = 0x4c, mode = 0

WRITE: address = 0x14, length = 0x2, mode = 1/*这里调用了Write函数 但不明白红色参数的意思*/

不至于数据扇区只写了这么点长度的数据吧?
先总结到次,在调试调试!请大侠帮忙解决这个问题。


菜鸟
2007-06-28 23:25:00     打赏
4楼

NAND FLASH不像NOR一样是全地址映射的。MMU中应该不需要添加0x04000000这么大个区域。应该是添加你的NAND FLASH芯片寄存器的区间大小就可以了,那个ROUND_UP的宏具体代码是啥呀?

romInit.s中不对Bank1进行初始化有没有问题,关键是看对bank1最基本的初始化是否搞完(VxWorks的MMU库能正常工作)和VxWorks的MMU和缓存打开前(亦即MMU表格条目里面的内容发生作用前)是否访问bank1的内容,如果没有就没关系,因为一旦VxWorks的MMU库发生作用(在比较后面了,,),都是按照那个表格里面的转换关系来的了。

还要注意一下,代码中是否存在指针类型强制转换的语句--因为这样最有可能造成不对齐的数据访问,CPU会报错。

红色部分的要分析代码,,,,呵呵。


菜鸟
2007-06-29 20:35:00     打赏
5楼

1、下面是发生错误的位置:

/* so if the reason was device removal, stop right here */
if( TRUE == cbioRdyChgdGet (dev))
{
/* override errno for removed disk */
errno = S_ioLib_DISK_NOT_PRESENT ;

/* dont issue warning for read errors on removal, only for writes */
if (( rw == CBIO_WRITE ) || ( rw == CBIO_WRITE_THROUGH ))
{
/* write error, issue warning to the console */
INFO_MSG(errorMsgTemplate,
(int) dev,
dev->cbioParams.lastErrBlk,
dev->cbioParams.lastErrno,
(int) "disk removed while writing data, possible data loss",
0,0
);
}
return(ERROR);
}
应该是其他错误引起了disk的remove以后导致的,跟cache无关,是dosfs和tffs的结合部分cbio的问题。

2、每次读0x44字节的问题,这是正常现象,在tffs里面,每个block(或者称为unit)的头部都有一个用于管理的结构体,这个结构体共68字节,定长,每次mount的时候都会去读出来校验。

typedef struct {
char formatPattern[15];
unsigned char noOfTransferUnits; /* no. of transfer units */
LEulong wearLevelingInfo;
LEushort logicalUnitNo;
unsigned char log2SectorSize;
unsigned char log2UnitSize;
LEushort firstPhysicalEUN; /* units reserved for boot image */
LEushort noOfUnits; /* no. of formatted units */
LEulong virtualMediumSize; /* virtual size of volume */
LEulong directAddressingMemory; /* directly addressable memory */
LEushort noOfPages; /* no. of virtual pages */
unsigned char flags;
unsigned char eccCode;
LEulong serialNumber;
LEulong altEUHoffset;
LEulong BAMoffset;
char reserved[12];
char embeddedCIS[4]; /* Actual length may be larger. By
default, this contains FF's */
} UnitHeader;

3、能否做个试验,在shell上创建和读写超过一个block大小的文件。个人感觉出问题的可能在nand类型flash模拟成nor型的时候,没有处理好第三页的16个字节,导致了地址上侧重复,如果是这样,可能存在文件在操作到block结尾的时候出错。如果shell上操作文件没有问题,应该可以肯定是ftp的问题了。


菜鸟
2007-07-01 18:42:00     打赏
6楼

根据yaopg大侠的提示,去掉了mmu的多余的关于nandflash的映射,确实nandflash不对应任何bank,通过2410的nand接口来控制,只需定义NAND FLASH芯片寄存器的区间。

上传60.4kb文件时串口输出如下:

READ: address = 0x80400, length = 0x200.............................................READ: address = 0x8f200, length = 0x200

间隔512byte读一次,也就是1个page,共计59.5kb,之后读到下面的奇怪地址

READ: address = 0x600, length = 0x200
READ: address = 0x8f400, length = 0x200
READ: address = 0x800, length = 0x200
READ: address = 0x9fa00, length = 0x200
READ: address = 0xb0000, length = 0x244 length是580 Byte,超过一个page ,这个长度是不是有问题?
WRITE: address = 0xb004c, length = 0x4, mode = 0
WRITE: address = 0xb0400, length = 0x200, mode = 0
READ: address = 0x804, length = 0x4
READ: address = 0xc0000, length = 0x244
WRITE: address = 0xc004c, length = 0x4, mode = 0
WRITE: address = 0xc004c, length = 0x4, mode = 1
WRITE: address = 0xc0404, length = 0x4, mode = 0
WRITE: address = 0x804, length = 0x4, mode = 1
WRITE: address = 0x90238, length = 0x4, mode = 1
READ: address = 0x80600, length = 0x200
READ: address = 0x80600, length = 0x200
READ: address = 0xd0000, length = 0x244
WRITE: address = 0xd004c, length = 0x4, mode = 0
WRITE: address = 0xd0400, length = 0x200, mode = 0
WRITE: address = 0xd004c, length = 0x4, mode = 1
WRITE: address = 0x80050, length = 0x4, mode = 1
READ: address = 0x600, length = 0x200
READ: address = 0x8fe00, length = 0x200
READ: address = 0xe0000, length = 0x244
WRITE: address = 0xe004c, length = 0x4, mode = 0
WRITE: address = 0xe0400, length = 0x200, mode = 0
READ: address = 0x614, length = 0x4
READ: address = 0x800, length = 0x200
READ: address = 0xc0400, length = 0x200
WRITE: address = 0xc0400, length = 0x200, mode = 1
WRITE: address = 0x54, length = 0x4, mode = 1
WRITE: address = 0xc004c, length = 0x4, mode = 1
READ: address = 0xf0000, length = 0x244
WRITE: address = 0xf004c, length = 0x4, mode = 0
WRITE: address = 0xf004c, length = 0x4, mode = 1
WRITE: address = 0xf0414, length = 0x4, mode = 0
WRITE: address = 0x614, length = 0x4, mode = 1
WRITE: address = 0x80240, length = 0x4, mode = 1
READ: address = 0xc0400, length = 0x200
READ: address = 0xb0400, length = 0x200
READ: address = 0x777700a4, length = 0x4 这里的地址更加奇怪,这个地址不存在呀?
0x33e74ae0 (tFtpdServ1): disk cache error: device 33e9ff60 block 249 errno c0006, disk removed while writing data, possible data loss
0x33e74ae0 (tFtpdServ1): disk cache error: device 33e9ff60 block 264 errno c0006, disk removed while writing data, possible data loss


菜鸟
2007-07-01 19:42:00     打赏
7楼

接上面

READ: address = 0x80400, length = 0x200
READ: address = 0xd0400, length = 0x200
READ: address = 0x80800, length = 0x200

READ: address = 0x82e00, length = 0x200
READ: address = 0x80400, length = 0x200
READ: address = 0xd0400, length = 0x200
READ: address = 0x80800, length = 0x200

READ: address = 0x8f200, length = 0x200
READ: address = 0x600, length = 0x200
READ: address = 0xf0400, length = 0x200
READ: address = 0xe0400, length = 0x200
READ: address = 0xe0000, length = 0x200
READ: address = 0x3dd2600, length = 0x200
READ: address = 0xc0400, length = 0x200
READ: address = 0xb0400, length = 0x200
READ: address = 0x33320000, length = 0x200 此处的地址是不正确的,但不知道为什么会读到这个地址?
READ: address = 0x1003000, length = 0x200

自此文件上传结束:特别注意红色字体部分
但从cuteftp看其文件大小属性为0,于是下载下来,结果文件大小就是0,从输出write函数看来只写了868Byte
且有mode=1的情况存在,mode=1表示擦写到c区域了呀?


为了确定是否是ftp的问题,我用同样的tfp代码对norflash进行操作,结果ftp上传774kb的文件成功,且大小相符,下载也能成功,也可以正常打开,只是时间很长,下载一个800kb文件要10分钟,(时间是否正常,我的tffs和bootrom在同一块norflash上)且有时下载到80%时cutetfp就提示超时:接收服务器响应时发生超时(60000 毫秒)。然后重新连接。

由此可以看出tfp是有一定的小问题,估计在网卡驱动那里,但问题不大,不足以造成象在nandflash上,上传20kb的文件,由此可以确定是nandflash的驱动的问题,于是先检查read函数


菜鸟
2007-07-02 19:44:00     打赏
8楼

代码中还存在混乱的地方,觉得你应该在代码中加入更多的调试语句,特别是对于地址不知道从哪里来的,需要详细跟踪出来。可以在所有调用那个READ的函数前加上跟踪语句。

/*给你一个加调试消息的例子吧。这个比较方便,固定打印所在函数、代码行等有用信息,并可以给4个参数和相应的格式化字符串,可以在中断中使用。
也可以定义调试级别,级别越小则优先级越高,通常可把1,2,3用于起初的寄存器访问和错误界定的级别,5以上用于正确信息的提示。
在成品代码中也可以保留这些调试信息不删除--只要把调试标记给关了,就可以了。虽然代码看来咯嗦,但完全不影响代码大小和代码执行速度
限制是:格式化字符串必须为常量字符串 */

/* 调试开放标记,如果调试好了,就 #undef MY_XXX_DEBUG */
#define MY_XXX_DEBUG /* */

#ifdef MY_XXX_DEBUG
/* 调试级别,越高,调试打印的内容就越多。 */
LOCAL int myXXXDebugLevel = 10;
#define MY_XXX_DEBUG_MSG(level,fmt,arg0,arg1,arg2,arg3) \
if (level <= myXXXDebugLevel) \
{ \
logMsg("my file name: func: %s, line: %d "fmt".\n", \
(int)(__FUNCTION__) , (int)(__LINE__) ,(int)(arg0),(int)(arg1),(int)(arg2),(int)(arg3)); \
}
#else /* 如果不需要调试输出了,把所有的调试消息语句置为nothing */
#define MY_XXX_DEBUG_MSG(level,fmt,arg0,arg1,arg2,arg3)
#endif /* #ifdef MY_XXX_DEBUG */

/* 下面是使用例子 */


MY_XXX_DEBUG_MSG(1,"fatal error,ref = 0x%08x,id = %d",ptr,ptr->id,0,0); /* 格式化字符串为常数,末尾不换行,参数不转换格式,没有参数或者参数不够的情况下,把剩余的参数全部填0,参数个数不能少 */
MY_XXX_DEBUG_MSG(6,"send ok,ref = 0x%08x,id = %d",ptr,ptr->id,0,0);

期待对你有一点点帮助。

[align=right][color=#000066][此贴子已经被作者于2007-7-2 11:45:28编辑过][/color][/align]

菜鸟
2007-07-05 01:20:00     打赏
9楼
我也出现了类似的问题,就是调用copy复制文件到flash,再复制回来,发现文件大小一样,但部分内容为0x00或者是0xFF,并且是整个Page成块出现。

为此我专门调用底层的nandMTDRead和nandMTDWrite作了测试,就是写一段进取,再读出来,逐字节比较,遍历整个flash存储空间,没有发现错误。测试是这样的

for(i =0; i < FLASH_BLOCKS; i ++){

flashErase(i) /*擦除一个Block*/

nandMTDWrite /*写入*/

nandMTDRead /*读回*/

Comapare() /*比较*/

}

如果不用erase的话就会写入错误。

我的VxWorks里面没有使用MMU,也没有进行映射。

看了上面的帖子,我有个问题还想问一下,我怀疑驱动里的overwrite实现有问题。对于nand flash来说,上层传递的write模式中的overwrite在底层应该怎么实现,同过擦除写入实现吗?但是要擦除又必须擦除整个Block。。。
我参考了VxWorks里的NFDC2048的驱动,对于overwrite也没有做特殊的处理。

另外,yaopg,read和write中的地址是上层的ftllite.c或者是nftllite.c传进来的,我的理解是Tffs是根据分配算法来写到某个地址里,地址不确定,正是这点让调试变得很难,不知道我这样理解对不对? [align=right][color=#000066][此贴子已经被作者于2007-7-4 18:45:01编辑过][/color][/align]

菜鸟
2007-07-05 03:01:00     打赏
10楼

看到woodhead大师在

http://www.eb-mag.com.cn/bbs/TopicOther.asp?t=5&BoardID=3&id=107291

上的写道

1、overwrite不需要处理

2、write函数中的buffer的地址传进来的时候是相对于base address的偏移,write函数内部需要调用map做映射。

overwrite不需要处理是仅对NOR Flash来说吗?

尽管不太明白,回去好好琢磨琢磨再试验一把,各位有什么新进展及时交流啊

[align=right][color=#000066][此贴子已经被作者于2007-7-4 19:18:08编辑过][/color][/align]

共10条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]