u-boot nand flash read/write debug(2018-08-01)

机器感知

一个专注于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;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值