【发布时间】:2015-09-22 09:03:12
【问题描述】:
最近,我在嵌入式软件中遇到了一个 - 对我来说 - 奇怪的行为。
我得到了什么: 运行 32 位 AVR32 控制器,从外部 SDRAM 启动程序,因为文件太大,无法直接从微控制器闪存启动。由于物理内存映射,内存区域分为:
堆栈(从0x1000开始,长度为0xF000)(
EBI SDRAM(从 0xD0000000 开始,长度为 0x00400000)。
会发生什么:不幸的是,我遇到了一个无法重现的异常。查看我给定的堆栈跟踪,发生以下不规则事件:
名称:总线错误数据获取 - 事件源:数据总线 - 存储的返回地址:第一个未完成的指令
此外,堆栈指针具有有效值,而发生异常的地址(获取指令的最后入口点)指向内存必杀技(例如 0x496e6372、0x5...、0x6.... )。我想,这必须是手册所说的“第一个未完成的指令”。但是,我的源代码中的行始终是相同的:通过指针从数据数组访问成员函数。
if(mSomeArray[i])
{
mSomeArray[i]->someFunction(); <-- Crash
}
事情是:添加或删除其他源代码会使事件消失并再次返回。
我的想法:某些东西正在破坏我的记忆(映射)。这可能会出现哪些错误?
- 缓冲区溢出?
- SDRAM 控制器可能已关闭,因此会丢失一些数据。这不是不可能,而是不太可能
- 堆栈够大了,我已经用水印检查过了
- 数据总线速率和 AVR 时钟设置正确
如何解决这个问题:更多断言?不幸的是,我无法使用 AVRStudio 进行调试。任何人的提示或想法?还是我遗漏了一些明显的东西?
编辑:
用户提到的方法:
- 检查函数指针和数组条目的地址
- 堆栈数组的覆盖
- 未正确写入中断
- 未初始化的指针
- 在崩溃情况下通过
i检查数组访问 - 使用异常处理程序地址进行非法内存访问
- 使用
snprintf而不是sprintf
线程的后期附录:问题是旧软件模块中的错误数组访问(设置了错误的索引),与我的模块无关。我偶然发现了这个,奇怪的是它没有更早出现,我花了很长时间才找到代码行。我将唯一给出的答案标记为正确的解决方案。
感谢大家的意见。
照顾好(你的软件;))
【问题讨论】:
-
如果您在代码的前面调用该函数,会触发总线错误吗?
-
@LPs:没有。有可能该函数可以被调用 n 次并且不会崩溃。任何时候都可能发生异常。这就是为什么我无法正确复制它。
-
bug来袭时函数指针指向的地址是什么?当这种情况发生时,你能在函数指针结构的其他成员中看到什么奇怪的东西吗?
if(mSomeArray[i])这行很可疑,这表明您实际上并不完全知道该指针指向的位置,这反过来又使处理该指针数组的任何代码成为最可能的罪魁祸首。 -
C 不支持异常,su 在这里使用标签是有问题的(描述仅指编程语言,而不是硬件异常)。但是,
AVR与较小的 8 位 MCU 有关。 AVR32 具有完全不同的架构。 -
-1 破坏内存的方法有很多,这个问题太含糊了。您可能正在覆盖堆栈上的数组。或者你的中断没有正确写入。或者您的指针未初始化或... 调试此问题的唯一方法是使用调试器逐步检查每一行代码,或者花几天时间在您的脑海中模拟代码以找到您的错误。
标签: c exception embedded avr32