This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

u-boot读取数据时打印nand: bit-flip corrected @oob=0

TI的工程师您好,

我正在移植  ti-processor-sdk-linux-am335x-evm-01.00.00.00  中的   u-boot-2014.07-g7e537bf      nand驱动,make am335x_evm_nandboot_config,根据板子配置nand的pinmux,nand芯片型号是S34ML08G101TF100

启动后不断打印nand: bit-flip corrected @oob=0

这里应该是正在读取nand中的环境变量,问题是每个页都在oob[0]发生位翻转???并且执行save命令是正常的:

U-Boot# sa
Saving Environment to NAND...
Erasing NAND...
Erasing at 0x1c0000 -- 100% complete.
Writing to NAND... OK

以下是启动信息:

U-Boot 2014.07-00107-ga6ef75a-dirty (Dec 01 2015 - 14:07:04)

I2C:   ready
DRAM:  512 MiB
NAND:  ONFI flash detected
NAND device: Manufacturer ID: 0x01, Chip ID: 0xd3 (AMD/Spansion S34ML08G1)
1024 MiB

nand: bit-flip corrected @oob=0
nand: bit-flip corrected @oob=0
nand: bit-flip corrected @oob=0
nand: bit-flip corrected @oob=0
nand: bit-flip corrected @oob=0
nand: bit-flip corrected @oob=0
nand: bit-flip corrected @oob=0
nand: bit-flip corrected @oob=0
nand: bit-flip corrected @oob=0
nand: bit-flip corrected @oob=0

  • 问题查出来了,随机读函数不能传递参数page,在uboot源码中搜索NAND_CMD_RNDOUT,只有TI的omap_read_page_bch函数传递了page参数,其他厂家的代码都是传-1的,所以将page改成-1就好了。由此猜测,TI的BSP是否对ONFI规范的flash存在不兼容的情况?

    cmdfunc最终调用nand_base.c中的nand_command函数,

    static void nand_command(struct mtd_info *mtd, unsigned int command,
                 int column, int page_addr)
    {
        register struct nand_chip *chip = mtd->priv;
        int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
        uint32_t rst_sts_cnt = CONFIG_SYS_NAND_RESET_CNT;

        /* Write out the command to the device */
        if (command == NAND_CMD_SEQIN) {
            int readcmd;

            if (column >= mtd->writesize) {
                /* OOB area */
                column -= mtd->writesize;
                readcmd = NAND_CMD_READOOB;
            } else if (column < 256) {
                /* First 256 bytes --> READ0 */
                readcmd = NAND_CMD_READ0;
            } else {
                column -= 256;
                readcmd = NAND_CMD_READ1;
            }
            chip->cmd_ctrl(mtd, readcmd, ctrl);
            ctrl &= ~NAND_CTRL_CHANGE;
        }
        chip->cmd_ctrl(mtd, command, ctrl);

        /* Address cycle, when necessary */
        ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
        /* Serially input address */
        if (column != -1) {
            /* Adjust columns for 16 bit buswidth */
            if ((chip->options & NAND_BUSWIDTH_16) &&
                    !nand_opcode_8bits(command))
                column >>= 1;
            chip->cmd_ctrl(mtd, column, ctrl);
            ctrl &= ~NAND_CTRL_CHANGE;
        }
        if (page_addr != -1) {
            chip->cmd_ctrl(mtd, page_addr, ctrl);
            ctrl &= ~NAND_CTRL_CHANGE;
            chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
            /* One more address cycle for devices > 32MiB */
            if (chip->chipsize > (32 << 20))
                chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
        }
        chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);

        /*
         * Program and erase have their own busy handlers status and sequential
         * in needs no delay
         */
        switch (command) {

        case NAND_CMD_PAGEPROG:
        case NAND_CMD_ERASE1:
        case NAND_CMD_ERASE2:
        case NAND_CMD_SEQIN:
        case NAND_CMD_STATUS:
            return;

        case NAND_CMD_RESET:
            if (chip->dev_ready)
                break;
            udelay(chip->chip_delay);
            chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
                       NAND_CTRL_CLE | NAND_CTRL_CHANGE);
            chip->cmd_ctrl(mtd,
                       NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
            while (!(chip->read_byte(mtd) & NAND_STATUS_READY) &&
                (rst_sts_cnt--));
            return;

            /* This applies to read commands */
        default:
            /*
             * If we don't have access to the busy pin, we apply the given
             * command delay
             */
            if (!chip->dev_ready) {
                udelay(chip->chip_delay);
                return;
            }
        }
        /*
         * Apply this short delay always to ensure that we do wait tWB in
         * any case on any machine.
         */
        ndelay(100);

        nand_wait_ready(mtd);
    }