我的代码中有一个奇怪的错误,当我尝试调试它时会消失。
在我的计时器中断(总是运行系统自动收报机)中我有这样的事情:
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
}
当计时器中的条件(我认为)满足时,从不调用主循环中的这种情况。条件是外部的(portpins,ADC结果等)。 首先,我在位置1放置一个断点,它永远不会被触发。
为了检查它,我把断点nr。 some_global_flag = 1;
行上的2,在这种情况下代码有效:条件为真时触发两个断点。
更新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)可以负责,还是我做错了什么?
答案 0 :(得分:4)
这可能是典型的优化/调试错误。确保将some_global_flag
标记为易失性。这可能是你喜欢的任何内容......
volatile int some_global_flag
这样你就告诉编译器不要对some_global_flag的值做什么假设。您必须执行此操作,因为编译器/优化器无法看到对中断例程的任何调用,因此它假定some_global_flag始终为0(初始状态)并且从不更改。
抱歉误读了您已经尝试过的部分...
您可以尝试使用avr-gcc编译代码,看看您是否有相同的行为......
答案 1 :(得分:4)
调试器可以/确实改变处理器运行和代码执行的方式,因此这并不奇怪。
分而治之。开始删除东西,直到它工作。在没有任何内容的情况下,只需要在主循环中添加定时器中断和几行代码,do_something_very_important()就像闪烁一个led或吐出一些东西一样简单。如果这不起作用你不会让更大的应用程序工作。如果确实有效,则开始在中断中添加初始化代码和更多条件,但不要使主循环复杂化,只需要描述几行。通过添加更多代码来增加中断处理程序条件,直到它失败。当你到达可以添加一个东西并失败并删除它而没有失败的边界时,然后进行一些反汇编以查看它是否是编译器。这可能需要另一张SO票,如果不明显的话,“为什么我的avr中断处理程序会在我添加时中断......”
如果你能够将这一行编写为少量几行代码,那么主要的只有少数中断行,这样就可以发布其他人可以在他们自己的硬件上尝试它并且可能并行计算出来。
答案 2 :(得分:3)
它可能看起来很奇怪,但它最终证明是由其中一条输入线上的强瞬变引起的(它为系统供电但其ADC测量也用作条件)。
系统可能会在短时间内出现周期性电源故障,并且重要的临时数据会保留在内部SRAM的一部分中,而这些内部SRAM在启动后不会被清除并用于保留数据(最多10分钟或更长时间) CPU处于欠压状态时使用小电容。
我没有在问题中发布这个,因为我测试了系统的这一部分而且工作得很好,所以我不想让你偏离正轨。
我最后发现,在一个创造了非常强烈的瞬态的环境中使用了一个新特征,我的问题中的一个条件取决于一个依赖于“永久性”中的一个变量的状态。 RAM“,最后使用断点使我免受瞬态的影响。
最后,通过调整时间来解决问题。
编辑:是什么帮助我找到问题的位置是我在“永久RAM”区域中记录了我最重要的变量的值,并且可以看到其中一些变量被破坏了。
答案 3 :(得分:1)
我可能在这里错了,但是如果你使用调试器连接到有问题的电路板并在硬件上调试它应该运行的程序我认为它可以在执行连接时改变微控制器的行为....其他上面提到的那个和volatile关键字我没有线索。
答案 4 :(得分:1)
这是假设ARM处理器编写的。
使用断点(RAM或ROM bkpoint)强制处理器在断点处从运行模式切换到调试模式(停止模式或监控模式)并强制它以调试速度运行或运行中止处理程序因此基于JTAG的调试基本上是侵入式调试。
ETM(嵌入式跟踪宏单元),特别是ARM(或其他类型的总线检测),设计为非侵入式,可以实时记录指令和数据,以便我们检查实际发生的情况。