调试U-Boot笔记(七)

    对不起,这几天工作很忘没有抽得出空学习,上次我们找通过U-boot命令将U-Boot.bin烧到NorFlash失败的原因,详情请回顾 《调试U-Boot笔记(六)》
    总体来讲,问题是出在 write_hword() 函数中的最后 验证写入的数据是否与实现一致时出的错。
*addr = CMD_READ_ARRAY;
if (chip == ERR || *addr != data)    // *addr != data
    rc = ERR_PROG_ERROR;
if (iflag)
    为什么写入的东西结果读出来不一致呢?想一下,在上一次实验中,写入的数据是18(10010B),结果读出来的是1107(10001010011B)。比较一下二进制:
    18    000000 10010
    1107  100010 10011
    我们发觉它们的1~4位都是1001,这个是不是给我们一点提示?
    NorFlash在擦除时是将所有的位都清成0,当写入数据时将对应的位置1,进行OR运行,所以叫NorFlash。与此相反的NandFlash则是在擦除时将所有位置1,写入时与写入的数据进行AND运算。
    我们可以进行一个大胆的猜测,NorFlash原来这个地址上的数据并没有被擦除,原来的值为100010 000011,当我们写入18(10010)时,与100010000011进行OR运行,最终得到 100010 10011。
 
    为了证实我的这一个推论,只要将写入前addr地址上的值打印出来就知道了。
    调试U-Boot笔记(七)
    在写数据之前,先打印一下result的值。OK, Let me have a try.
    调试U-Boot笔记(七)
    在写入数据之前,我们从地址上读出的数据是1107,这确实说明NorFlash没有被擦除,不然这个值要么是0xFFFFFFFF要么是0x00000000,怎么会是一个1107呢?
 
    既然是没有擦除引起的,那么我就来查找一下到底是为什么没有擦除。
    我们要关注:u-boot/board/my2440/flash.c 文件中的 flash_erase() 函数:
    调试U-Boot笔记(七)
int flash_erase (flash_info_t * info, int s_first, int s_last)
    {
        ushort result;
        int iflag, cflag, prot, sect;
        int rc = ERR_OK;
        int chip;
        /* first look for protection bits */
        if (info->flash_id == FLASH_UNKNOWN)
            return ERR_UNKNOWN_FLASH_TYPE;
        if ((s_first < 0) || (s_first > s_last)) {
            return ERR_INVAL;
        }
        if ((info->flash_id & FLASH_VENDMASK) !=
         (AMD_MANUFACT & FLASH_VENDMASK)) {
            return ERR_UNKNOWN_FLASH_VENDOR;
        }
        prot = 0;
        for (sect = s_first; sect <= s_last; ++sect) {
            if (info->protect[sect]) {
                prot++;
            }
        }
        if (prot)
            return ERR_PROTECTED;
        /*
         * Disable interrupts which might cause a timeout
         * here. Remember that our exception vectors are
         * at address 0 in the flash, and we don't want a
         * (ticker) exception to happen while the flash
         * chip is in programming mode.
         */
        cflag = icache_status ();
        icache_disable ();
        iflag = disable_interrupts ();
        /* Start erase on unprotected sectors */
        for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
            printf ("Erasing sector %2d ... ", sect);
            /* arm simple, non interrupt dependent timer */
            reset_timer_masked ();
            if (info->protect[sect] == 0) {    /* not protected */
                vu_short *addr = (vu_short *) (info->start[sect]);
                MEM_FLASH_ADDR1 = CMD_UNLOCK1;
                MEM_FLASH_ADDR2 = CMD_UNLOCK2;
                MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
                MEM_FLASH_ADDR1 = CMD_UNLOCK1;
                MEM_FLASH_ADDR2 = CMD_UNLOCK2;
                *addr = CMD_ERASE_CONFIRM;
                /* wait until flash is ready */
                chip = 0;
                do {
                    result = *addr;
                    /* check timeout */
                    if (get_timer_masked () >
                     CFG_FLASH_ERASE_TOUT) {
                        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
                        chip = TMO;
                        break;
                    }
                    if (!chip
                     && (result & 0xFFFF) & BIT_ERASE_DONE)
                        chip = READY;
                    if (!chip
                     && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
                        chip = ERR;
                } while (!chip);
                MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
                if (chip == ERR) {
                    rc = ERR_PROG_ERROR;
                    goto outahere;
                }
                if (chip == TMO) {
                    rc = ERR_TIMOUT;
                    goto outahere;
                }
                printf ("ok.n");
            } else {    /* it was protected */
                printf ("protected!n");
            }
        }
        if (ctrlc ())
            printf ("User Interrupt!n");
    outahere:
        /* allow flash to settle - wait 10 ms */
        udelay_masked (10000);
        if (iflag)
            enable_interrupts ();
        if (cflag)
            icache_enable ();
        return rc;
    }

    第一步:8~20,是在对一些基本信息进行校验。
    第二步:20~29,检查Flash芯片的保护标志,如果还有扇区还处于保存状态则返回 ERR_PROTECTED 。
    第三步:38~40,关中断与cache。
    第四步: 42~100,正式执行擦除操作。
    第五步:102~116,现场恢复
    结合U-Boot命令执行结果输出:
    调试U-Boot笔记(七)
 
    可以分析出:
    (1)程序输出了“Erasing sector 0...”说明函数执行到了第四步。
    (2)程序没有输出:“Ok.”,“protected!”,也没有输出“User Interrupt!”信息,说明程序地执行擦除操作时执行了 L88 或 L92 处的 goto outahere; 直接跳到 L105去执行了。
 
    今天到此为止,明天继续……

你可能感兴趣的:(u-boot,axd,Jlink,NorFlash)