This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Code Monkey Analysis

All,

I am trying to track down a problem of some code that was written by an 'overseas' 3rd party (I will be nice and not state the country of origin).

This code uses a single timer set at a 1mS interrupt rate in order to determine if the SPI is still communicating externally with it's master. If no communications are detected the timer resets the SPI port, clears the interrupt, and jumps to the reset vector. The problem is: the SPI port remains dead until a power cycle is accomplished.

The obvious fix is to use the watchdog (which is what I will eventually do), but I would like to understand the why of why this does not work (yes, bad coding practice is the real reason)...

Since the code jumps to the reset vector this is what I have been able to analyze:

(1) Since this is not a true reset (ie: via watchdog) all hardware registers are not reset - problem potential here.
(2) The jump to the reset vector was accomplished while in supervisor mode, so the privleged registers (ie: SP,etc) can be written.
(3) The timer interrupt was cleared prior to making the jump to the reset vector, so all interrupts are still enabled.
(4) Since this is not a true reset, all resident code can still execute (ie: interrupt handlers).
(5) The startup code will reset all initialized data, registers, etc prior to jumping to program main(), effectively returning data to a power up state.

One reason I can currently come up with as to why the SPI is never functional after this occurs is that maybe an interrupt occurs while in the startup code (clearing a tracking variable or resetting the processor registers). But the interrupt would also inhibit the startup code until it was serviced. This potential cause is (probably) not the only reason for this issue, and why I am asking for your input(s).

Unfortunately, this board has no JTAG to connect so stepping through the code is not an option. I could write to the serial port - if it was connected, but it isnt. Right now I am trying to analyze my way through this code before using a 'hammer' approach to solving this problem.

What else am I missing in this analysis? Thanks.

Parents Reply Children
  • The funny thing here is that the "volatile" keyword is known to be one of the most problematic for compilers. Not just in efficiency, but in producing broken code.
    www.cs.utah.edu/.../emsoft08-preprint.pdf

    A good link about volatile:
    blog.regehr.org/.../28

  • Found these gems associated to the name of this thread (credit to the authors). Applicability is in the readers eyes:

    "The infinite monkey theorem states that a monkey hitting keys at random on a typewriter keyboard for an infinite amount of time will almost surely type a given text, such as the complete works of William Shakespeare."

    Better yet:

    "Would a million rednecks shooting at road signs ultimately produce the entire works of Shakespeare in braille?"

  • Per,

    Didnt want to 'cross this bridge' in the original post as most of the responses to this 'structuring' (used very loosely here - actually probably the wrong description altogether) would have probably masked the original question(s) I was trying to get answered above.

    After reading the abstract to the first link I must take the time now to stop and read this information to conclusion prior to resuming my other functions (I guess it was also for me so as not to get waylayed).

    Good, informational links though.

    Thanks.

  • Tamir,

    I call this criminal (especially since money was accepted for this trash).

  • The paper submitted by Utah SC should be a MUST READ for anyone that is about to use the volatile keyword.

    What is unnerving here is that the lack of clarity from the C specification allows individual interpretation as to how the compiler should/will handle these situations. As a consequence, it was found that compiler bugs are commonplace!

    I was well aware that a severe processing hit was occuring because of the declarations, but was unaware of the bug potential generated from the compiler

    Thankfully, I do not see (at this point) any real need with having to use the volatile keyword within any portion of this code. The downside to removing these keywords is that, the way this code has been written (read: hacked), that some undocumented timing dependency(ies) will rear its(their) ugly head(s) and smite me. What deadline?

  • The paper submitted by Utah SC should be a MUST READ for anyone that is about to use the volatile keyword.

    A note of caution: the description of volatile in the 'C' standard is sufficiently vague that some of the interpretations used in that paper are open to debate. A particular example that springs to mind is the explanation and example given in section 2.1 - this one has been fairly convincingly debunked out there on the internet.

  • But the important thing is that the description of the volatile keyword in the 'C' standard is sufficiently vague that it doesn't matter what you debunk in one debate - it still matters what specific compiler developers thought the description meant.

    The bottom line is that we are extremely vulnerable, since we are relying on what the compiler developer thought, and not what the standard writers thought. And a large number of people are assuming things that either should be wrong, or are wrong for their specific compiler.

  • we are relying on what the compiler developer thought, and not what the standard writers thought

    "if you heard what I thought I said we would understand each other"

    Erik

  • ...is that even if there is an issue with your compiler you may never even be provided with that information:

    "Table 1: Results from applying access summary testing....or cannot provide details due to
    license restrictions."

  • But the important thing is that the description of the volatile keyword in the 'C' standard is sufficiently vague that it doesn't matter what you debunk in one debate - it still matters what specific compiler developers thought the description meant.

    Indeed, but section 2.1 in that paper does not seem to conform to any reasonable interpretation of the standard.

    I do wish implementors would all provide detailed documentation for volatile setting out just exactly what guarantees are provided by the toolchain.

  • The bottom line is that we are extremely vulnerable, since we are relying on what the compiler developer thought, and not what the standard writers thought.

    That's in no way particular to the implementation of "volatile", i.e. we're no more vulnerable because of this than because of other aspects of the language.

    Every single bit of C code in every single program out there relies on the assumption that the compiler developer interpreted the language definition the same as the author of that C code. The language definition exists for the express purpose of supplying the basis for such equal interpretation.

    If that fails to work out, it has to be found out how that happened --- all the way to a lawsuit, if all else fails. Sometimes the conclusion is that the language standard is, in fact, defective. Most of the time, though, it's the code author thinking that the standard makes promises that it actually didn't.

  • I have at least twice caught the Keil ARM compiler generating the wrong assembly code (at least, as far as I could judge) - it always implicated automatic variables that could not be mapped to registers but to the stack instead (without compiler optimization). But the problem disappeared after rebuilding, and no test program has managed to recreate it.
    Apart from that - no complaints.

  • "But the problem disappeared after rebuilding..."

    Assuming you left the compiler options (such as optimisations), I find that hard to believe. What you're saying suggests some sort of randomness in the compiler generated code. Not very likely.

  • As I said, I may be wrong. But two other people confirmed what I saw, and we did see that the computation that was performed resulted in a wrong answer. Or maybe this was plainly a debugger/compiler interaction that was not perfect. I hope to be able to catch it again.

  • ...the compiler developer interpreted the language definition the same as the author of that C code.

    I agree with the statement in point. However, the issue regarding the volatile keyword falls outside of this point because the specification provides no real clarity regarding implied use.

    For example, the C specification merely states: "At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete" AND "At sequence points, volatile objects are stable in the sense that previous accesses are complete and subsequent accesses have not yet occurred.

    As a programmer, how are we to know the implications of these statements? Should we? The reference that Jack made regarding the following code snippet from the Utah CS paper as being debunked:

    volatile int buffer_ready;
    char buffer[BUF_SIZE];
    
    void buffer_init()
    {
       int i;
       for (i=0; i<BUF_SIZE; i++)
          buffer[i] = 0;
       buffer_ready = 1;
    }
    

    is a prime example of the potential for a problem to occur. To me, it is clear that the compiler would never move the variable buffer_ready above the for loop in optimizations. But, the result of the lack of clarity regarding the volatile keyword allows the compiler writer to do so if they wish. The specification only provides 'guidance' at sequence points (the for loop is itself a sequence point according to Annex C guidelines).

    In this case there is no 'common ground' for interpretation between the programmer and the compiler developer.