Schrödinger error disappears when breakpoint is set

I have a strange error in my code that disappears when I try to debug it.

In my timer interrupt (the system ticker is always running), I have something like this:

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

in my main loop i have

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

This condition in the main loop is never called when the conditions in the timer are met (I think). Conditions are external (portpins, ADC results, etc.). First I set a breakpoint at position 1, and it never fires.

To test this, I set a breakpoint nr. 2 on the line some_global_flag = 1; , and in this case the code works: both breakpoints start when the conditions are true.

Update 1:

In order to find out if any synchronization condition does not meet, and if the timer is never entered if it works without debugging, I added the following to my timer:

  if (a && lot && of && conditions) { some_global_flag = 1; // breakpoint 2 } if (some_global_flag) { #asm("NOP"); // breakpoint 3 } 

The flag in the code is not used anywhere. It is located in RAM, and RAM at the beginning is cleared to zero.

Now that all breakpoints are disabled (or only breakpoint 1 in the main part is turned on), the code does not work correctly, the function does not execute. However, if I only include breakpoint 3 in the NOP, the code works! The breakpoint starts, and after continuing, the function is executed. (It has a visible and audible output, so it is obvious if it works)

Update 2:

Timer interruption was interrupted by the "SEI" at the beginning. I deleted this line, but the behavior has not changed in any noticeable way.

Update 3:

I do not use external memory. Since I am close to the limit in the flash, I have maximum size optimization in the compiler.

Can the compiler (CodeVision) be responsible, or did I do something very wrong?

+6
source share
5 answers

This may seem strange, but, ultimately, it is caused by strong transients on one of the input lines (which controls the system, but its ADC measurement is also used as a condition).

For a short time, the system can periodically interrupt operation, and important temporary data is stored in the part of the internal SRAM, which is not cleared after startup and is designed to save data (up to 10 minutes or more) using a small capacitor, while the processor is in "brown."

I did not post this in the question because I tested this part of the system and worked perfectly, so I did not want to kick you out of the course.

What I learned at the end is that in the environment that created very strong transients, a new function was used, and one of the conditions of my question depended on a state that depended on one of these variables in "constant RAM", and finally, using a breakpoint saved me from the consequences of this transition.

Finally, the problem was resolved with time adjustments.

Edit: what helped me locate the problem was that I recorded the values ​​of my most important variables in the "read only" area and saw that some of them were damaged.

+3
source

This is probably a typical optimization / debugging error. Make sure some_global_flag marked as mutable. It could be int uint8 uint64 as you like ...

 volatile int some_global_flag 

This way you tell the compiler not to make any assumptions about what the value of some_global_flag will mean. You should do this because the compiler / optimizer does not see any call to your interrupt routine, so it assumes that some_global_flag is always 0 (initial state) and never changed.

Sorry, incorrectly read the part in which you have already tried ...

You can try compiling the code with avr-gcc and see if you have the same behavior ...

+4
source

Debuggers can / can change the way the processor works and execute the code, so this is not surprising.

divide and win. Start deleting things until they work. In parallel with this, start with nothing, add only a timer interrupt and a few lines of code in the main loop with do_something_very_important (), something as simple as blinking headed or spitting something from uart. if this does not work, you will not get more applications to work. If this works, start adding the initialization code and additional conditions to the interrupt, but do not complicate the main loop more than a few lines. Increase the interrupt handler conditions by adding more code back until it works.

When you reach the boundary where you can add one thing and exit it and then delete it and don't work, do some disassembly to find out if this is a compiler. this may require another SO ticket, if it is not obvious, "why is my avr interrupt handler interrupted when I add ..."

If you can bring this to a small number of lines of code to a dozen main and only a few lines of interruptions, send a message so that others can try it on their own equipment and possibly figure it out in parallel.

+4
source

Maybe I'm wrong, but if you use the debugger to attach to the board in question and debug the program on the hardware on which it was supposed to work, I think that it can change the behavior of the microcontroller when it attaches .... Other, that this and the volatile keyword suggested above, I have no hints.

+1
source

This is written on the assumption of an ARM processor.

using a breakpoint (RAM or ROM bkpoint) forces the processor to switch from start mode to debug mode at the break point (either to stop mode or in monitor mode), and force it to work in debug mode or start the interrupt handler and therefore Debug based on JTAG is basically intrusive debugging.

The ETM (built-in Trace Macrocell), in particular in ARM (or other types of measuring instruments), is non-intrusive and can record instructions and data in real time so that we can check what actually happened.

+1
source

Source: https://habr.com/ru/post/907909/


All Articles