2

I would like an embedded device to wait before entering a certain state until I can set up the remote debugger via JTAG to continue execution.

I tried to use an infinite loop continuing execution by setting the program counter to the next instruction.

I'm using a constant expression so as the loop doesn't get optimized away as the SEI CERT C Coding Standard states in MSC06-C as compliant example:

while(1);

My problem is now that gcc optimizes away everything following this code in the same function and at first glance I found no gcc option to specifically prevent this.

Is this the right way to do what I want? And how is it done the right way?

user2011659
  • 847
  • 1
  • 7
  • 15
  • 1
    Does this help? https://stackoverflow.com/questions/39832958/gcc-o0-still-optimizes-out-unused-code-is-there-a-compile-flag-to-change-tha – matt Feb 08 '21 at 20:53
  • "Is this the right way to do what I want?" I'm going to say no, and venture *that* might be a better question. – matt Feb 08 '21 at 20:58
  • If you make the loop condition a volatile variable the compiler should worry that it could change for no reason - then the loop would have to stay and so would the code after. https://godbolt.org/z/qGT5rv – Jerry Jeremiah Feb 08 '21 at 20:58
  • Why can't you setup the JTAG debugger first and use it to start/stop the processor? – jwdonahue Feb 08 '21 at 20:59
  • Related for C++: [Prevent C++11 removal of endless loops](https://stackoverflow.com/q/24298314) (C++ doesn't have the C rule that infinite loops with a constant controlling expression are valid. Are you sure you're compiling as C, not C++?) – Peter Cordes Nov 08 '22 at 06:59

1 Answers1

3

I would probably do

volatile int keep_spinning = 1;
while (keep_spinning) ; // spin

This way the compiler cannot prove that the loop is infinite, so it cannot remove it nor anything that follows.

It also gives you a convenient way to continue execution when you are ready: just use your remote debugger to poke the value 0 into the variable keep_spinning.

It may be more convenient if you make it global (or perhaps static), in addition to being volatile. Global variables are likely to be easier for your debugger to find, since they have symbols, and they are less likely to be incorrectly optimized out by buggy compilers like in Eugene Sh.'s comment below.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • Don't make it static. If you do that, compiler can figure out there's no code in scope capable of changing that value. – jwdonahue Feb 08 '21 at 21:01
  • This does not always work (probably bugs, but yet..). See here: https://stackoverflow.com/questions/55457835/arm-compiler-5-do-not-fully-respect-volatile-qualifier A way to work around it is to `int keep_spinning=1; while(*(volatile int*)&keep_spinning)...` – Eugene Sh. Feb 08 '21 at 21:02
  • 3
    @jwdonahue: The author intends it to be `volatile` and `static`. The compiler will not be able to conclude it cannot be changed because `volatile` means it can be changed by means unknown to the compiler. Making it `static` means it will have a record in the debugging information (and maybe in the object module information as a local symbol) so the debugger can find it easily. Without that, it is automatic and is created on the stack and is may not be known to the debugger and would have to be found by manually inspecting the instructions. – Eric Postpischil Feb 08 '21 at 21:04
  • @EricPostpischil, [6.7.3 Type qualifiers, #7](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) seems to give the implementers some wiggle room on that, where it says "What constitutes an access to an object that has volatile-qualified type is implementation-defined". And there's 5.1.2.3 #4. My interpretation may be biased from experience that some compilers (perhaps non-conforming?) may in fact ignore volatile on a non-global, non memory mapped register variable and remove unreachable code based on the obvious fact that nothing can modify that variable. – jwdonahue Feb 09 '21 at 20:21
  • 1
    I've always thought that saying `static volatile` is kind of like saying water isn't wet. – jwdonahue Feb 09 '21 at 20:27
  • @jwdonahue: If, for some particular implementation, there exists some program that nominally exercises the translation limits given in N1570 5.2.4.1 and that the implementation processes as defined by the Standard, nothing the implementation does with any other source text would render it non-conforming. Rather than try to specify what range of Conforming or Strictly Conforming C Programs an implementation should process usefully, the Standard leaves that question as a Quality of Implementation issue. – supercat Aug 05 '21 at 21:01
  • 2
    @jwdonahue: `static volatile` is like saying "I might change this with a debugger while stopped at any breakpoint". A `volatile` variable in normal DRAM (not a pointed-to MMIO address) isn't useful for much else in modern C, although `static volatile sig_atomic_t` has some guarantees wrt. signal handlers. A signal handler defined in the same file could usefully use `static volatile` for communication. The weird thing would be `const volatile` (with or without static scope); that's a lot more like "water isn't wet", although I think you can still change it with a debugger. – Peter Cordes Nov 08 '22 at 07:04