Electronic – What “external” source can change a General Purpose Working Register if no interrupts are enabled

atmegamemory

I have a 8-bit ATmega processor (from the 48/88/168 family) and encounter a strange behavior: after a brown-out reset, sometimes (around 20%-30%) it fails to start after a short brown-out. It always starts correctly after a longer power-down.

I narrowed down the problem to the part of the startup which is generated by the compiler and has the role of clearing the RAM:

;CLEAR SRAM
    LDI  R24,LOW(__CLEAR_SRAM_SIZE)
    LDI  R25,HIGH(__CLEAR_SRAM_SIZE)
    LDI  R26,LOW(__SRAM_START)
    LDI  R27,HIGH(__SRAM_START)
__CLEAR_SRAM:
    ST   X+,R30
    SBIW R24,1
    BRNE __CLEAR_SRAM

This code segment does the following: it counts down the word in R24,R25, meanwhile incrementing the X Register (R26,R27) and writing R30 (which is zero) to the location pointed by the X Register. This clears the RAM until R24,R25 reaches zero. However, the code is stuck in this loop. Whenever I halt the progam, it stops on one of the last 3 lines in the above code, with seemingly random values in R24 and R25. Interestingly, if I run it step by step, it correctly decrements R24, and when it reaches zero, it correctly sets R24 to 0xFF and decrements R25. When I set both to a very small number they correctly reach zero and the loop is exited correctly, but only when running it step-by step. It seems that something writes some values into R24 or R25, but I have interrupts disabled, and I even set breakpoints to the interrupt registers to make sure and they are never triggered.

When this test is running (stuck in the loop) the power is stable, so there is no brownout while in this loop.

The watchdog is disabled while we are in this loop.

Does anyone have any ideas what to look for?

Best Answer

"The watchdog is disabled while we are in this loop." - So you provided code that disables the watchdog? Note that it will not be disabled automatically by a normal reset.

The ATmega1284P datasheet quotes for example:

Note: If the Watchdog is accidentally enabled, for example by a runaway pointer or brown-out condition, the device will be reset and the Watchdog Timer will stay enabled. If the code is not set up to handle the Watchdog, this might lead to an eternal loop of time-out resets.

Then there's the WDTON fuse which forces the WDT to be always on. You may want to check on that.

Oh, and by the way: You did enable the brown-out detector of the µC, didn't you? - Otherwise, upon a brown-out condition, anything could happen to the internal state of the µC.