pxa303 boot启动 全局变量被意外修改 惊险刺激 请大虾解答。

sailorlyq 2009-12-10 08:25:17
在boot启动的过程中发现全局变量莫名其妙地被修改了。

因为这个时候系统还没有跑起来,所以我分析故障有三个原因。

指针越界访问:
因为修改前后根本没有修改变量的任何代码,所以这个我基本排除。

中断服务程序:
我查看了中断服务程序,修改的都是些局部变量,而且地址都是向着增加的方向。全局变量的地址比临时变量的地址小,临时变量存储在堆中。

栈溢出:
觉得这个可能性很大。因为我在调试的时候发现,当代码量增加的时候程序就特别不稳定,呈现递增趋势,多到一定程度程序会非常慢,再多的话程序就根本无法运行了。当大量减少代码的时候程序运行很稳定。
可是我的疑惑出来了。在分析代码的时候栈空间是非常大的呀。我的这部分boot程序镜像只有22K,从sp指向的地址到全局数据区一共也有2多k的空间。这个空间应该是足够用的呀。这时怎么回事那?

期待大虾解答。
...全文
352 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
zwtchy123 2009-12-15
  • 打赏
  • 举报
回复
bang ding
LJDTJ 2009-12-15
  • 打赏
  • 举报
回复
拷贝eboot是可以用固定大小的。

guopeixin 2009-12-15
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 reallyu 的回复:]
我猜测lz的问题应该是从flash复制代码到sdram的时候,没有正确复制rw段和z0段吧
默认的rw段和z0段是紧接在代码段的后面,一般boot启动时候都会把自己从flash中复制到sdram里面运行.
也许你的程序中复制的大小是个固定值,而不是根据boot代码编译的大小来调整的,所以代码小的时候就不会出错,代码多的时候就出错了.没有正确复制rw段,那么全局变量的值就是sdram初始化后的默认值,一般这个值是0xCDCDCDCD,我不知道为什么,根据经验是这样,也许是调试软件的原因.
C/C++编译器生成汇编函数代码都是遵循 ARM 过程调用标准(APCS)的,哪些寄存器放参数,哪些存放返回值都是规定好的,所以自己编写汇编代码函数给C调用时,也应该遵循这一标准.
[/Quote]
学习经验了
LJDTJ 2009-12-14
  • 打赏
  • 举报
回复
恭喜楼主取得初步成果。楼主是想在marvell的boot基础之上做一个二次boot吗?
seemknow 2009-12-14
  • 打赏
  • 举报
回复
我上回碰到的是全局变量定义、声明混用了BOOL、BOOLEAN,这两个类型一个4字节一个1字节。编译没问题,操作时就错了。见http://blog.csdn.net/seemknow/archive/2009/08/26/4486812.aspx
sailorlyq 2009-12-14
  • 打赏
  • 举报
回复
这么多牛人回帖,申请加精!!!
sailorlyq 2009-12-14
  • 打赏
  • 举报
回复
对堆栈进行了调整,并输出打印信息查看。
全局变量的位置和map文件中说明的位置是一致的。

程序在SVC模式下运行
它的stack起始地址是SP: 0x5c0117FC
数据出错时答应sp,结果是 0x5c010e84。
而全局数据区在 0x5c00a450
所以出现堆栈溢出可能性似乎不大。

根据paul_chao大侠的提示,我打印sp的方法实现如下。

GetSP
MOV a1, SP
STMFD SP!, {R0-R4, LR}
LDMFD SP!, {R0-R4, PC}

供参考。

基本定位文件拷贝大小有限定,接下来找marvell核实。
sailorlyq 2009-12-14
  • 打赏
  • 举报
回复
Reallyu大侠,多谢指点了。我再把我这的情况详细说明一下。

我用Nmake.exe和marvell的编译器联合编译的,生成的.map内存映射文件是这样的
Base Addr Total End Addr Location Type Attr Segment

0x00000000 0x00005560 0x00005560 0x00000000 Code RO CODE
0x5c009000 0x00000418 0x5c009418 0x5c009000 Data RW DATA
0x5c009418 0x00001038 0x5c00a450 0x5c009418 Zero RW BSS

还有
#map out the segments
LAYOUT
## SEGMENT CODE BASE 0x5c013000 ## Debug
SEGMENT CODE BASE 0x00000000 ## Debug
LOAD SECTION Init OF OBM_StartUp
SECTION Reset_Area
SECTION _RO_
SECTION .ctors
SECTION init_data

SEGMENT DATA BASE 0x5c009000
LOAD SECTION _RW_

SEGMENT BSS BASE ALIGN 4
LOAD SECTION _BSS_

从这上面看代码段从0x00000000重定位到了0x5c013000,我的代码也是从nandflash中加载到SRAM的0x5c013000地址。你说的拷贝的文件大小是固定的,这个应该是有可能的,因为大小是在片内的bootrom中确定的。

另外堆栈的的情况如下:
IRQ模式下SP初始值是0x5c012FFC
SVC模式下SP初始值是0x5c0107FC
sailorlyq 2009-12-14
  • 打赏
  • 举报
回复
差不多那个意思,用obm来引导eboot。

还有个奇怪的问题,同样减小代码量以后就不会出现。

为什么会导致提示flash通信校验错误。*DFC_STATUS & DFC_SR_DBERR这是判断条件。
DFC_STATUS是状态寄存器,DFC_SR_DBERR是标志位。他们都是常量。
开始我以为DFC_STATUS数据被修改了,所以才造成判断错误。现在看来不是。确实出现了状态寄存器的校验位被置位。

很诡异呀。
Reallyu 2009-12-13
  • 打赏
  • 举报
回复
我猜测lz的问题应该是从flash复制代码到sdram的时候,没有正确复制rw段和z0段吧
默认的rw段和z0段是紧接在代码段的后面,一般boot启动时候都会把自己从flash中复制到sdram里面运行.
也许你的程序中复制的大小是个固定值,而不是根据boot代码编译的大小来调整的,所以代码小的时候就不会出错,代码多的时候就出错了.没有正确复制rw段,那么全局变量的值就是sdram初始化后的默认值,一般这个值是0xCDCDCDCD,我不知道为什么,根据经验是这样,也许是调试软件的原因.
C/C++编译器生成汇编函数代码都是遵循 ARM 过程调用标准(APCS)的,哪些寄存器放参数,哪些存放返回值都是规定好的,所以自己编写汇编代码函数给C调用时,也应该遵循这一标准.
LJDTJ 2009-12-13
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 paul_chao 的回复:]
LZ 怀疑是 stack, 那就用 assembly 写一个 GetSP 的 function

GetSP
mov    a1, sp
mov    pc, lr

再在每一个 function 的 entry point 加入一句

DWORD GetSP(void);

RETAILMSG(1, (TEXT("SP=0x%X @ function XXX\r\n"), GetSP()));

再去对对看您对 Stack 的规划即可

Paul, Chao @ Techware

[/Quote]

Paul, Chao大侠给的原型是DWORD GetSP(void);返回值为DWORD型。
楼主用int tem = GetSP(); 的话,函数编译时自己做了类型转换。不清楚楼主的具体用法,个人感觉这样来用并不能解决程序执行中止的问题。
sailorlyq 2009-12-12
  • 打赏
  • 举报
回复
找到答案了,在代码段中。
sailorlyq 2009-12-12
  • 打赏
  • 举报
回复
在调试的时候发现一个问题,常量的话是放在代码段中还是数据段中呢?
LJDTJ 2009-12-12
  • 打赏
  • 举报
回复
学习
sailorlyq 2009-12-12
  • 打赏
  • 举报
回复
刚才试验了
GetSP
mov a1, sp
mov pc, lr

但是出现了一个问题,程序执行的时候被中止了。
我可以这样调用GetSP吗?

int tem = GetSP();
编译的时候没有出错。
paul_chao 2009-12-11
  • 打赏
  • 举报
回复
LZ 怀疑是 stack, 那就用 assembly 写一个 GetSP 的 function

GetSP
mov a1, sp
mov pc, lr

再在每一个 function 的 entry point 加入一句

DWORD GetSP(void);

RETAILMSG(1, (TEXT("SP=0x%X @ function XXX\r\n"), GetSP()));

再去对对看您对 Stack 的规划即可

Paul, Chao @ Techware
ProgrammerNO1 2009-12-11
  • 打赏
  • 举报
回复
标题很雷人啊,呵,刺激

某些局部函数内有无用到static?
sailorlyq 2009-12-11
  • 打赏
  • 举报
回复
guopeixin大侠能不能说的更详细一些呀,多谢。
91program 2009-12-11
  • 打赏
  • 举报
回复
看看全局变量都在哪里被修改的,如果没有被非法修改,再看自己的程序,有没有内存覆盖的问题吧

如果还没有,再考虑stack

从简单的问题开始,一个个排除
guopeixin 2009-12-11
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 sailorlyq 的回复:]
各位大侠,如果调整堆栈的话是不是修改sp的初始值就可以?例如
  MOV    SP, r2            ; Assign stack pointer for IRQ handler
  MOV    SP, r2            ; Assign stack pointer for SVC handler

IRQ的sp是固定的,我缩小了IRQ stackzize的大小。向下移动了SVC的sp指针。这样就加大了SVC的stack size。可是故障仍然存在。
我这样调整堆栈对吗?

让我奇怪的是代码量减少的话数据就不会出错,而且很稳定。

[/Quote]
呵呵,典型的stack问题的特征
加载更多回复(9)

19,503

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧