uboot环境变量不能保存的调试

来源:互联网 发布:拜月教主 知乎 编辑:程序博客网 时间:2024/06/07 22:36

在我的板子上设计了2个uboot,分为大小u-boot。小u用于启动,因为程序小,所以速度快,而且适合放在单个块(128K)中.大u包含网络,功能全面。

在实际的启动过程中,小u出现不能保存环境变量的问题,本文用于记述我的调试过程。

出现该问题首先想到的是修改配置文件,把所有更flash env相关的配置宏全部找了一遍,并且做了各种各样的组合尝试。以失败告终。

接下来只好深入代码去查找原因,发现出错是因为

Attempt to write not page aligned data

查看语句得知,这个主要是


进一步的跟踪变得异常困难,主要的问题在于:当我想通过printk函数打印一些输出时,可执行程序经常启动不起来。尤其是在出错语句附近,每次加printk语句都会导致系统启动失败(启动到printk时打印不出东西,然后还挂死在该语句上)。百思不得其解,直至现在尚未搞清。

于是想到用仿真器调试。BDI仿真器可以单步执行语句,同时也可以配合GDB(DDD)进行调试,具体方法建另一篇文章。但是悲哀的发现,没有办法直接通过BDI加载代码,因为要想通过BDI加载的前提就是BDI先要初始化DRAM,使得程序可以先放在RAM中。对我目前所用芯片(DM8148)的初始化会涉及不少寄存器,但我查遍身边的资料,都没有发现这些寄存器定义,况且,调试这个部分也挺费时间。

那么不用仿真器加载,只是用仿真器控制或者查看,是否可以呢。答案是可以的。我们可以连上仿真器,同时通过flash正常启动,这个时候分别有2个过程同时进行。1)板子通过Nand flash正常启动,程序被加载到RAM后执行。2)仿真器在检测到开电后通过JTAG通信得知有ARM开始工作,然后hold住正在执行的程序。 在实际的实验中,当仿真器hold住程序时,u-boot程序往往已经运行了大部分,所有的初始化过程都已经完成了。因此无法通过程序单步来观察整个初始化过程的变化,也许可以通过设置仿真器来改进JTAG通信的速度,使得仿真器能更快的hold住程序,但是多次尝试后发现很难,毕竟JTAG通信过快反过来会带来JTAG的连接失败。

于是想到通过仿真器重置PC指针,使得u-boot再次重新执行,并在执行前在关键代码处设置断点,实验发现2个地方与预想的不一致,1)再次执行的程序与第一次执行的输出不一致,有一些明显的错误输出的log。2)我确实可以用仿真器使得在相应的位置停下来。但是当我用ddd真正执行单步时,发现指针乱飞,完全不是想想的那样,于是只好作罢。

放弃仿真器后,同事提了一个很好的建议,不用print语句,那可以往一段固定地址的buffer输出东西,然后还是用仿真器,通过查看对应的地址就能获知实际设置的值了。按照这个思路,在查询u-boot.map后找了一个肯定不用的地方,然后往里面直接写数据,就像这样:

*(unsigned int *)(0x80200000) = reg_value;

编译运行时发现,还是和printk一样的问题,程序hang,无法输出任何东西。

没有足够的log支持,只能仔细阅读源代码,试图找到是否是某些指针赋值之类的问题,最后把nand初始化的部分倒是理解透彻了。趁此回忆一下:

NAND的初始化源于drivers/mtd/nand/nand.c,这个文件

nand_init(void)

    --> nand_init_chip(nand_info[i], &nand_chip[i], base_address[i])

          --> board_nand_init(nand) -> nand_scan -> add_mtd_device

                -->[ti81xx_nand.c]nand setting

                nand_scan

                -->[nand_base.c] nand_scan_ident() -> nand_scan_tail()

                                                硬件检测Nand               设置mtd和chip的参数,包括本文所讲的pagesize等


最后在u-boot的一个讨论中发现,printk不是标准的u-boot log输出语句,用printf反过来更标准一些,于是尝试用printf来打印一些log,果然,出现程序hang的概率大幅减小。最后发现,在赋值语句3048的前后加打印语句,会出现十分奇特的现象。

3047         printf(A)

3048         chip->subpagesize = mtd->writesize >> mtd->subpage_sft;

3049         printf(B)

小u在启动时只出现了B,A始终没有出现。大u启动时一切正常,A,B依次出现。

 

以上所有的怀疑最后都集中到了一点,程序发生错乱极有可能是因为优化过度。理论上来说这里的语句不应该会被优化掉,因为在赋值语句的后面马上就出现了引用。尝试实验,将对应的chip指针改成volatile类型,一些正常。

其实上述过程的很多地方已经可以想象到是因为程序优化问题了。但是我没有往那方面想,于是,始终得不到正确答案。       


原创粉丝点击