调试U-Boot笔记(六)

    我按照以前实验笔记《 使用JLink烧写bin文件到Mini2440》所示的方法去烧录u-boot到NandFlash。结果烧是烧进去了,但是启动不成功。这个问题稍后再研究。
 
    昨天我们查看了Flash写入失败的相关代码。我在怀疑自己是不是在配置的时候选错了芯片型号。从电路原理图上看,我们的NorFlash芯片型号是:AM29LV160DB/SST39VF1601。
    经过一番查找,终于搞明白了。
 
    在 u-boot/board/ 目录下有很多个文件夹。每一个文件夹以板子的型号命令,比如smdk2400,smdk2410,my2440等。在每一个文件夹下都有该板子单独的设备 驱动文件。在my2440这个文件夹下就有一个flash.c文件。这个文件里定义了NorFlash驱动函数。
    调试U-Boot笔记(六)
   
    既然我们找到了这个文件,那么我们就用AXD单步进行调试一下。
 
    单步执行 > protect off all 时,运行到do_protect()函数。我发现在
    调试U-Boot笔记(六)
    红框所地的代码并没有执行。我查看了一下 include/configs/my2440.h文件,没有搜到CFG_FLASH_PROTECTION 宏的定义。不知道这会对烧写U-Boot到NorFlash有无影响。
 
    我还遇到一个问题,为什么在AXD里调试U-Boot,看不到变量里的值。我记得用ADS编写代码再用AXD调试时都可以看到的嘛。如何解决?

    在board/my2440/flash.c文件中搜索宏 ERR_PROG_ERROR.
    可以搜到两处使用了ERR_PROG_ERROR宏:
  •     volatile static int write_hword (flash_info_t * info, ulong dest, ushort data)
  •     int flash_erase (flash_info_t * info, int s_first, int s_last)
    其中write_hword()应该是在命令 “cp.b 0x30000000 0 40000”时出错的主要原因。看代码如下:
volatile static int write_hword (flash_info_t * info, ulong dest, ushort data)
    {
        vu_short *addr = (vu_short *) dest;
        ushort result;
        int rc = ERR_OK;
        int cflag, iflag;
        int chip;
        /*
         * Check if Flash is (sufficiently) erased
         */
        result = *addr;
        if ((result & data) != data)
            return ERR_NOT_ERASED;
        /*
         * 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 ();
        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
        MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
        *addr = CMD_PROGRAM;
        *addr = data;
        /* arm simple, non interrupt dependent timer */
        reset_timer_masked ();
        /* wait until flash is ready */
        chip = 0;
        do {
            result = *addr;
            /* check timeout */
            if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
                chip = ERR | TMO;
                break;
            }
            if (!chip && ((result & 0x80) == (data & 0x80)))
                chip = READY;
            if (!chip && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {
                result = *addr;
                if ((result & 0x80) == (data & 0x80))
                    chip = READY;
                else
                    chip = ERR;
            }
        } while (!chip);
        *addr = CMD_READ_ARRAY;
        if (chip == ERR || *addr != data)
            rc = ERR_PROG_ERROR;
        if (iflag)
            enable_interrupts ();
        if (cflag)
            icache_enable ();
        return rc;
    }
    见L63~64可知,只有chip的值为ERR或则从addr地址上读出来的数据不等于data就会返回ERR_PROG_ERROR错误。
    ERR只在代码的44,56两处出现。但如果执行了44行的代那,那么chip的值应该是ERR|TMO=0x03,不等于ERR。那么只有在56行这个有可能。分析一下50~57行代码的功能:
    在40行 result = *addr,从addr地址上读取一个数据。在50行处检查result的第5位 ( (result & 0xFFFF ) & BIT_PROGRAM_ERROR),如果为1则表示写错误。然后在51行再读取一次,再进行一次检查。如果数据正常却将chip置为READY,否则置为ERR。
 
    为了找到倒底是哪里出错,在将在这里加调试信息。
    调试U-Boot笔记(六)
   
    编译后生成u-boot.bin文件,然后复制到e:u-boot-gdbu-boot.bin。再进行调试。
    在终端看到如上:
    调试U-Boot笔记(六)
    可见,得到失败的原因了,是359行处 (*addr != data) 条件不成立。不过有一点问题,如果*addr读出的值与读的次数有关就可能不太确定了。还是再小改一下:
   
    调试U-Boot笔记(六)
    结果再次执行,显示结果:
    调试U-Boot笔记(六)
    看来,还真是读出来的值不一致引起的。这个该怎么办呢?

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