uboot环境变量不能保存的调试
2011-09-05 18:44
246 查看
在我的板子上设计了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类型,一些正常。
其实上述过程的很多地方已经可以想象到是因为程序优化问题了。但是我没有往那方面想,于是,始终得不到正确答案。
在实际的启动过程中,小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类型,一些正常。
其实上述过程的很多地方已经可以想象到是因为程序优化问题了。但是我没有往那方面想,于是,始终得不到正确答案。
相关文章推荐
- norflash移植及uboot 保存环境变量实验
- uboot环境变量区为何不能放在data段
- UBoot支持双启动(Nor and Nand)及环境变量保存的实现
- mac 终端保存环境变量后 ls 等命令不能找到(command not fond)
- Siebel 系统调试的环境变量
- uboot 环境变量设置研究
- eclipse调试java不能看到变量的值
- Mac OS X系统下android环境变量配置和真机调试
- uboot的环境变量
- 抢救Centos修改环境变量后不能启动
- 关于u-boot同时支持nand启动和Nor启动 环境变量的保存位置
- 调试符号环境变量正确配置方法
- uboot环境变量实现分析
- grub2 linux等命令中不能使用环境变量
- AIX下用su切换用户时不能加载环境变量的问题解决
- windows 环境变量被改变了,不能使用cmd ?怎么办?
- U-Boot移植--环境变量保存位置
- uboot环境变量实现分析
- uboot移植到6410开发板的过程及环境变量的修改
- uboot环境变量与内核MTD分区关系