【问题标题】:AVR32 exception: Bus Data ErrorAVR32 异常:总线数据错误
【发布时间】: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


【解决方案1】:

这里有一些想法:

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

【讨论】:

  • 感谢您的进一步输入。进一步发现:“i”是一个有效值,函数指针地址无效。不幸的是,我不能使用调试器(如最初的帖子中所述)。对我的异常处理程序进行进一步调查可能是一种有用的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多