机器感知
一个专注于SLAM、机器视觉、Linux 等相关技术文章分享的公众号
nand read 30000000 0 10000
NAND read: device 0 offset 0x0, size 0x10000
entry nand_read=mtd_read
entry mtd_read and call mtd->_read
entry nand_read
entry nand_do_read_ops
need_skip = 0
NAND read from offset 0 failed -74
0 bytes read: ERROR
出错代码位置:
if (!need_skip) {
rval = nand_read(nand, offset, length, buffer);
if (!rval || rval == -EUCLEAN)
return 0;
*length = 0;
printf("NAND read from offset %llx failed %d\n",
offset, rval);
return rval;
}
一个设置项:nand->ecc.mode = NAND_ECC_SOFT;
所影响的代码:
case NAND_ECC_SOFT:
ecc->calculate = nand_calculate_ecc;
ecc->correct = nand_correct_data;
ecc->read_page = nand_read_page_swecc;
ecc->read_subpage = nand_read_subpage;
ecc->write_page = nand_write_page_swecc;
ecc->read_page_raw = nand_read_page_raw;/********/
ecc->write_page_raw = nand_write_page_raw;
ecc->read_oob = nand_read_oob_std;
ecc->write_oob = nand_write_oob_std;
if (!ecc->size)
ecc->size = 256;
ecc->bytes = 3;
ecc->strength = 1;
break;
case NAND_ECC_NONE:
pr_warn("NAND_ECC_NONE selected by board driver. This is not recommended!\n");
ecc->read_page = nand_read_page_raw;
ecc->write_page = nand_write_page_raw;
ecc->read_oob = nand_read_oob_std;
ecc->read_page_raw = nand_read_page_raw;
ecc->write_page_raw = nand_write_page_raw;
ecc->write_oob = nand_write_oob_std;
ecc->size = mtd->writesize;
ecc->bytes = 0;
ecc->strength = 0;
break;
读失败可能是没加片选操作chip->select_chip(mtd, 0);
片选命令不需要再加了,在读命令发出前,前段代码有发送片选命令
现在的问题是可以正确读出nandflash中的数据,但是总是提示读错误,不知为何!
终于找到原因了:
是ecc校验有问题,u-boot中默认支持的ecc页大小与我的板子上的不符合,具体如下
/*
* Check ECC mode, default to software if 3byte/512byte hardware ECC is
* selected and we have 256 byte pagesize fallback to software ECC
*/
..nand_scant_tail:
switch (ecc->mode) {...}位于nand_base.c中
在此语句上添加ecc->mode=NAND_ECC_NONE,即使用ecc校验,重新编译下载后,完美成功。
测试结果:其中读结束返回的大小为bytes字节,而cmp返回的是字数words,即4个字节
u-boot-2015.10 # nand read 30080000 0 80000
NAND read: device 0 offset 0x0, size 0x80000
entry nand_read=mtd_read
entry mtd_read and call mtd->_read
entry nand_read
entry nand_do_read_ops
oob=0,ret=0,ecc_fail=0,max_bitflips=0
nand_read return value=0
mtd_read:ret_code=0,ecc_strength=0
need_skip = 0,rval=0
524288 bytes read: OK
u-boot-2015.10 # nand read 30000000 0 80000
NAND read: device 0 offset 0x0, size 0x80000
entry nand_read=mtd_read
entry mtd_read and call mtd->_read
entry nand_read
entry nand_do_read_ops
oob=0,ret=0,ecc_fail=0,max_bitflips=0
nand_read return value=0
mtd_read:ret_code=0,ecc_strength=0
need_skip = 0,rval=0
524288 bytes read: OK
u-boot-2015.10 # cmp 30000000 30080000 7ffff
word at 0x30080000 (0xea000014) != word at 0x30100000 (0x7b8c33ce)
Total of 131072 word(s) were the same
nand write操作:
NAND write: device 0 offset 0xfffff00, size 0x100
Attempt to write non page-aligned data
0 bytes written: ERROR
u-boot-2015.10 # nand write 30000000 f000000 800
NAND write: device 0 offset 0xf000000, size 0x800
entry nand_read=mtd_read
entry mtd_read and call mtd->_read
entry nand_read
entry nand_do_read_ops
oob=0,ret=0,ecc_fail=0,max_bitflips=0
nand_read return value=0
mtd_read:ret_code=0,ecc_strength=0
NAND write to offset f000000 failed -5
0 bytes written: ERROR
从下面的输出并结合代码可以看出:之所以会出现读操作,并不是刚开始认为的写操作函数变成了
读操作函数,而是写操作中有数据校验这个功能,所以需要重新读出数据进行对比,因此有了读操作
的信息输出。
Flash: 2 MiB
NAND: set mtd->_read = nand_read<872222912>
set mtd->_write = nand_write<872219876>
256 MiB
u-boot-2015.10 # nand write 30100000 f000000 800
NAND write: device 0 offset 0xf000000, size 0x800
entry mtd_write and call mtd->_write
entry nand_read=mtd_read
entry mtd_read and call mtd->_read
entry nand_read
entry nand_do_read_ops
oob=0,ret=0,ecc_fail=0,max_bitflips=0
nand_read return value=0
mtd_read:ret_code=0,ecc_strength=0
NAND write to offset f000000 failed -5
0 bytes written: ERROR
现在可以确定了确实是写函数有问题了。
if (!chip->read_byte || chip->read_byte == nand_read_byte)
chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
if (!chip->read_word)
chip->read_word = nand_read_word;
if (!chip->block_bad)
chip->block_bad = nand_block_bad;
if (!chip->block_markbad)
chip->block_markbad = nand_default_block_markbad;
if (!chip->write_buf || chip->write_buf == nand_write_buf)
chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
if (!chip->write_byte || chip->write_byte == nand_write_byte)
chip->write_byte = busw ? nand_write_byte16 : nand_write_byte;
if (!chip->read_buf || chip->read_buf == nand_read_buf)
chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
写操作技术路线:
chip->write_page = nand_write_page;
|->if (unlikely(raw))
status = chip->ecc.write_page_raw(mtd, chip, buf,oob_required);
目前看没有什么问题,可是没有发现发送写命令的操作!
通过查看代码,基本可以确定,确实没有发送写命令。
include/linux/mtd/nand.h:#define NAND_CMD_SEQIN 0x80
找到了,源代码是有发送写命令的,看来问题还在别处:
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
if (unlikely(raw))
status = chip->ecc.write_page_raw(mtd, chip, buf,
oob_required);
对比1.1.6的代码,和2015.10的还是有一些差别的
接下来检查一下硬件相关的操作,即发送写指令是否正确。
/* hwcontrol always must be implemented */
nand->cmd_ctrl = s3c24x0_hwcontrol;