8

我的代码中有一个奇怪的错误,当我尝试调试它时它消失了。

在我的定时器中断(总是运行系统代码)中,我有这样的事情:

 if (a && lot && of && conditions)
 {
     some_global_flag = 1;                   // breakpoint 2
 }

在我的主循环中,我有

 if (some_global_flag)
 {
     some_global_flag = 0;
     do_something_very_important();   // breakpoint 1
 }

当计时器中的条件(我认为)满足时,永远不会调用主循环中的这个条件。条件是外部的(端口引脚、ADC 结果等)。首先我在位置 1 放了一个断点,它永远不会被触发。

为了检查它,我放了断点 nr。2 some_global_flag = 1;,在这种情况下,代码有效:当条件为真时触发两个断点。

更新1:

为了研究是否有一些计时条件负责,if如果没有调试就永远不会进入计时器中,我在计时器中添加了以下内容:

 if (a && lot && of && conditions)
 {
     some_global_flag = 1;                   // breakpoint 2
 }


 if (some_global_flag)
 {
     #asm("NOP");    // breakpoint 3
 }

该标志不在代码中的其他任何地方使用。它在 RAM 中,并且在开始时 RAM 被清零。

现在,当所有的断点都被禁用(或者只有 main 中的断点 1 被启用)时,代码不能正常工作,函数不会被执行。但是,如果我只启用 NOP 上的断点 3,代码就可以工作!断点被触发,继续后,函数被执行。(它有可见和可听的输出,所以如果它运行就很明显了)

更新 2:

定时器中断是可中断的,在其开始时通过“SEI”。我删除了那条线,但行为并没有以任何明显的方式改变。

更新 3:

我没有使用任何外部存储器。由于我非常接近闪存中的限制,因此我在编译器中进行了最大尺寸优化。

编译器(CodeVision)可以负责吗,还是我做错了什么?

4

5 回答 5

6

调试器可以/确实改变处理器运行和代码执行的方式,所以这并不奇怪。

分而治之。开始删除东西,直到它工作。与此并行的是,只在主循环中添加定时器中断和几行代码,其中 do_something_very_important() 很简单,比如闪烁 LED 或从 uart 中吐出一些东西。如果这不起作用,您将无法使用更大的应用程序。如果这确实有效,则开始在您的中断中添加初始化代码和更多条件,但不要使主循环复杂化,而不是描述的几行。通过添加更多代码来增加中断处理程序条件,直到它失败。

当您到达可以添加一个东西并失败并删除它而不失败的边界时,然后进行一些反汇编以查看它是否是编译器的东西。如果不是很明显,这可能需要另一个 SO 票,“为什么我的 avr 中断处理程序在我添加时中断......”

如果您能够将其简化为十几行主要代码和几条中断行,请将其发布,以便其他人可以在自己的硬件上尝试它,也许可以并行解决。

于 2012-02-08T16:22:49.610 回答
5

这可能是一个典型的优化/调试错误。确保将some_global_flag其标记为易失性。这可能是一个 int uint8 uint64 无论你喜欢...

volatile int some_global_flag

这样你告诉编译器不要对 some_global_flag 的值做任何假设。您必须这样做,因为编译器/优化器看不到对您的中断例程的任何调用,因此它假定 some_global_flag 始终为 0(初始状态)并且从未更改。

抱歉误读了您已经尝试过的部分...

您可以尝试使用 avr-gcc 编译代码,看看是否有相同的行为...

于 2012-02-08T08:04:12.627 回答
4

这可能看起来很奇怪,但最终证明它是由其中一条输入线路上的强瞬变引起的(它为系统供电,但它的 ADC 测量也用作条件)。

系统可以有短时间周期性断电,重要的临时数据保存在内部SRAM的一部分,启动后不清理,设计为随使用保留数据(长达10分钟或更长时间)在 CPU 处于欠压状态时使用一个小电容器。

我没有在问题中发布这个,因为我测试了系统的这一部分并且运行良好,所以我不想让你偏离正轨。

最后我发现,在一个产生非常强瞬变的环境中使用了一个新功能,而我的问题中的一个条件取决于一个状态,该状态取决于“永久 RAM”中的这些变量之一,最后使用断点使我免受瞬态的影响。

最后通过时间调整解决了这个问题。

编辑:帮助我找到问题位置的原因是我在“永久 RAM”区域中记录了我最重要的变量的值,并且可以看到其中一些已损坏。

于 2012-02-08T17:57:07.513 回答
1

这是假设一个 ARM 处理器编写的。

使用断点(RAM 或 ROM bkpoint)强制处理器在断点处从运行模式切换到调试模式(停止模式或监视模式)并强制它以调试速度运行或运行中止处理程序,因此基于 JTAG 调试基本上是侵入式调试。

ETM(嵌入式跟踪宏单元),特别是在 ARM(或其他类型的总线仪表)中,被设计为非侵入式的,可以实时记录指令和数据,以便我们检查实际发生的情况。

于 2014-09-09T15:15:15.863 回答
1

我在这里可能错了,但是如果您使用调试器连接到有问题的电路板并在它应该运行的硬件上调试程序,我认为它可以在执行连接时改变微控制器的行为...... . 其他那个和上面建议的 volatile 关键字我没有任何线索。

于 2012-02-08T08:00:37.697 回答