3

最近,在我的嵌入式软件中,我面临着一个 - 对我来说 - 奇怪的行为。

我得到了什么:运行一个 32 位 AVR32 控制器,从外部 SDRAM 启动程序,因为文件太大而无法直接从微控制器闪存启动。由于物理内存映射,内存区域分为:

堆栈(从 0x1000 开始,长度为 0xF000)(<0x1000 受 MPU 保护)

EBI SDRAM(从 0xD0000000 开始,长度为 0x00400000)。


会发生什么:不幸的是,我遇到了一个无法重现的异常。查看我给定的堆栈跟踪,会发生以下不规则事件:

名称:总线错误数据获取 - 事件源:数据总线 - 存储的返回地址:第一个未完成的指令

此外,堆栈指针具有有效值,而发生异常的地址(获取指令的最后入口点)指向内存必杀技(例如 0x496e6372,大约 0x5...、0x6...)。我想,这必须是手册所说的“第一个未完成的指令”。但是,我的源代码中的行始终是相同的:通过指针从数据数组访问成员函数。

      if(mSomeArray[i])
      {
         mSomeArray[i]->someFunction(); <-- Crash
      }

事情是:添加或删除其他源代码会使事件消失并再次返回。


我的想法:有些东西正在破坏我的记忆(映射)。这可能会出现哪些错误?

  • 缓冲区溢出?
  • SDRAM 控制器可能被关闭,所以它会丢失一些数据。这不是不可能,而是不太可能
  • 堆栈足够大,我已经用水印检查过
  • 数据总线速率和 AVR 时钟设置正确

如何解决这个问题:更多断言?不幸的是,我无法使用 AVRStudio 进行调试。任何人的提示或想法?还是我错过了一些明显的东西?


编辑:

用户提到的方法:

  • 检查函数指针和数组条目的地址
  • 堆栈数组的覆盖
  • 未正确写入中断
  • 未初始化的指针
  • i通过在崩溃情况下检查阵列访问
  • 使用异常处理程序地址进行非法内存访问
  • 使用snprintf而不是sprintf

该线程的后期附录:问题是旧软件模块中的错误数组访问(设置了错误的索引),与我的模块无关。我偶然发现了这个,奇怪的是它没有更早出现,我花了很长时间才找到代码行。我将唯一给出的答案标记为正确的解决方案。

谢谢大家的意见。

照顾(你的软件;))

4

1 回答 1

1

这里有一些想法:

  1. 检查“i”以确保它在数组范围内。
  2. 检查即将被调用的函数指针的地址。它应该在 SDRAM 中有一个地址。
  3. 查看芯片是否有异常处理地址,当它访问非法内存时会跳转到该地址。一旦你在那里,输出一些调试数据
  4. 如果您的调试器允许,请在写入时在 someFunction() 上设置断点。当它覆盖函数指针时,这将捕获一些其他函数。
于 2015-09-23T18:15:57.887 回答