Reset Source Detection

Go To Last Post
26 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Freaks,

I have the following code:

void main(void)
{
   unsigned char ResetSrc = MCUSR;   // save reset source
   MCUSR = 0x00;  // cleared for next reset detection

   ... // further initialisation

   if (ResetSrc & PORF)
      cputs("PWR RESET\n\r");
   if (ResetSrc & EXTRF)
      cputs("EXT RESET\n\r");
   if (ResetSrc & BORF)
      cputs("BOD RESET\n\r");
   if (ResetSrc & WDRF)
      cputs("WDT RESET\n\r");

   ... //rest of code

Problem is that I don't seem to be able to generate a POR on its own. I always get a POR followed by a BOR. The code would suggest that both the POR and BOR are set. BORF is supposed to be cleared by a POR.
I can trigger a BOR on its own and a EXT on its own but POR is always followed by the BOR.

I cannot believe that I have such a slow rising VCC that the system exits POR and then jumps into BOR before I have the chance to execute the clear MCUSR. I guess it could occur during ICCs auto generated initialisation code but I'm reluctant to believe it.

Anyone able to shed some light on this? Am I doing something wrong? Am I missing some thing?

Thanks
Steve

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is your BOD threshold set correctly? You never said which AVR chip you are using and there are differences in the BOD setup. Tell us which AVR you are using, what your clock speed is and what your Vcc level is.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've used this across a number of ATmegas including 8,168,324P,128,2560/1.
Clock speeds vary but are usually either 4,8,16MHz. Sometimes IntRC sometimes Ext Xtal, 1k_65ms.
The BOD threshold is usually set to 4.3V (or the highest possible with VCC=5V. I have experimented with various BOD thresholds and noticed that the false BOD report does tend to dissappear when using a lower threshold but still 5V VCC.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

POR threshold (ATMega8) is 1.4V typ, while BOD threshold is typ 2.6V for the lower setting. While VCC<1.4V, both comparators (POR and BOD) detect undervoltage and their respective circuits are active; thus both bits in the register get set during this time.

The description of BOD is slightly misleading, as it suggests, that BOD reset gets active only during falling VCC - this is clearly not the case, try some simple "blinkey" and simply rise slowly VCC above POR threshold - it won't start until BOD threshold.

That in your experiments sometimes BOD doesn't get set, is probably caused by the deliberately "slow" nature of BOD - you probably pulsed VCC faster than the typ 2us needed to activate BOD.

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I put together a simple test with a STK500/501 using an AT90CAN128 clocked at 7.3728 MHz external crystal, with a 5 volt Vcc with BOD enabled at 4.1 volts (the highest BOD for this chip). Port B is connected to the STK500 LEDs. This simple program was used:

#include "can128def.inc"

    clr r0
    in  r18, MCUSR
    out MCUSR, r0

    ldi r16, 0xff
    out DDRB, r16
    com r18
    out PORTB, r18
loop:
    rjmp loop

By simply powering on the STK500 power I get:
MCUSR = BORF, EXTRF and PORF flags.

By pressing the STK500 reset switch I get:
MCUSR = EXTRF flag.

Then I removed the STK500 reset jumper and powering up got this:
MCUSR = BORF and PORF flags.

Obviously the MCUSR register works correctly and multiple reset source events may occur during power up. You cannot get only a power up PORF unless you disable the BOD, but the AVR will not operate reliably without an enabled BOD or an external BOD circuit. This isn't because of the rising speed of Vcc, it is because of the different trigger thresholds of power on and BOD levels. The rising Vcc level must go through the PORF threshold first, then through the BOD threshold level second on the way to powering up the AVR.

At 5 volt Vcc you must set your BOD level according to the AVR clock speed. For example at 16 MHz the AVR is usually specified to operate at 4.5 volts minimum. If you set a 2.7 volt BOD level it will fail to protect the AVR since it would run at 16 MHz down to 2.7 volts Vcc which is way out of specification for the AVR.

If you are not seeing a BORF during power on at really low BOD levels, then something is going wrong with your setup or hardware.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

schtevo wrote:
The code would suggest that both the POR and BOR are set. BORF is supposed to be cleared by a POR.
No not really. Notice in the data sheet the MCUSR flag bits have no initial value. These bits are only set by the hardware.

For example the AT90CAN128 data sheet Figure 7-1 Reset Logic, shows the reset hardware connections go to the individual MCUSR register flag bits. There is nothing in this figure to suggest any reset source is superior to any other reset source. The only thing that does make sense is that Vcc must of course rise to some minimal level before anything (including the MCUSR register) works at all.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is intersting, as I always assumed only one bit would be set (assuming the register initially cleared). I've always used the CodeVision Wizard template that looks at the bits one-by-one with an if-else so only one will be "logged". That still probably makes sense, and pick PORF first ("higher priority") and that will then ignore the "lower priority" BORF?

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

BORF is supposed to be cleared by a POR.

Quote:

No not really. Notice in the data sheet the MCUSR flag bits have no initial value. These bits are only set by the hardware.

I am/was with schtevo on this one as the datasheets for some recent models all say
Quote:
• Bit 2 – BORF: Brown-out Reset Flag
This bit is set if a Brown-out Reset occurs. The bit is reset by a Power-on Reset, or by writing a logic zero to the flag.

Now, everyone could be right with this scenario:

-- power drops; BORF set.
-- power drops more and/or comes on; PORF set; PORF clears BORF.
-- but voltage still below BODLEVEL; PORF already set; BORF set anew...

Time for some experimenting with my tame system. ;)

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd say my scenario above holds (Mega640):

-- Initial programming I get the EXTRF as expected
-- Power-cycle gives both PORF & BORF as y'all have seen
-- "Forced" brown-out only gives BORF only

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Reading it literally the MCUSR register BORF bit is reset by a Power-on Reset, which is over when Vpot (rising) exceeds its threshold at a very low Vcc level. The Power On Reset circuit sets the Internal Reset flip flop and holds the Timeout Delay Counters in reset. Then after Vpot (rising) the Power On Reset circuit releases the Timeout Delay Counters reset which will eventually clear the Internal Reset flip flop (this example ignores the BOD). Obviously the Internal Reset flip flop output cannot be clearing any MCUSR bits or any Internal Reset trigger source, not just only the Power On Reset, would reset the MCUSR flag bits.

So yes, I believe the Power-on Reset event before Vpot (rising) resets the MCUSR register BORF bit, most likely directly through some connection with the Power On Reset circuit before the Internal Reset flip flop output. However, the BORF bit is still being actively set by the brown out condition until Vcc rises above the BOD Vbot level. The Power-on Reset of BORF is temporary and the BOD hardware reasserts BORF long before the AVR Internal Reset flip flop is finally released.

If the BORF bit reset was absolute, then it would be impossible to get both PORF and BORF set together at the same time. The PORF and BORF are two separate reset events only sharing the same time domain because of the Internal Reset flip flop operation (since both of these reset sources are ORed together to operate the same Internal Reset flip flop and Timeout Delay Counters).

Last Edited: Tue. May 26, 2009 - 08:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Puzzled, here.

gcc offers a big song and dance about reading the MCUSR really early in initialization AND copying that into a variable that is protected from the normal initialization process. I don't see that in the initial post. Nor any subsequent comments.

Is all that unnecessary?

Thanks
Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The OP was using ICC, not GCC. The really early reading, copying and clearing of MCUSR is directly from the data sheet. I guess GCC doesn't have any built in handling of MCUSR and I don't remember what ICC has for this. Obviously, the CodeVision Wizard does handle this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW, I tried lowering the Vcc to 3.3 volts on the STK500, then back to 5 volts and as expected only got the BORF flag.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

If the BORF bit reset was absolute, then it would be impossible to get both PORF and BORF set together at the same time.

Well, this is a bit of a tempest in a teapot and I'm sure that youv've got the technical correctness on your side. !) Are you sure that those block diagrams really reflect the AVR internals? 2) From an old bit-pusher's point of view my scenario of BORF triggering both on the way down and the way up fits the symptoms, and also still leaves the datasheet correct that PORF clears BORF. (And it works with doing the clear on the fall below PO voltage level, or the rise above it.)

Now, if it really mattered could it be tested by going down, setting BORF on the way, then come up held in reset and do a disable of the BOD and then ... Makes my head hurt.

Now where was this swamp we are trying to drain? Oh, yeah. schtevo, will the CV method work for you? I log the reset cause in a number of apps and use the CV method, and it is helpful in the field to see if BORF or PORF or WDRF when a problem controller is being diagnosed. It just involves picking your priority and using else-if.

if (MCUSR & 1)
   {
   // Power-on Reset
   MCUSR&=0xE0;
   reset_cause = 1;
   }
else if (MCUSR & 2)
   {
   // External Reset
   MCUSR&=0xE0;
   reset_cause = 2;
   }
else if (MCUSR & 4)
   {
   // Brown-Out Reset
   MCUSR&=0xE0;
   reset_cause = 3;
   }
else if (MCUSR & 8)
   {
   // Watchdog Reset
   MCUSR&=0xE0;
   reset_cause = 4;
   }
else if (MCUSR & 0x10)
   {
   // JTAG Reset
   MCUSR&=0xE0;
   reset_cause = 5;
   }
else
	{
	reset_cause = 9; // undetermined (runaway code)
	}

ee_restart_cause = reset_cause;

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The part that hurts heads depends on the individual AVR chip. My AT90CAN128 example has a Vpot of 1.4 minimum to 2.3 maximum. The lowest BOD Vbot level is 2.5 volts with a 70 mV Hysteresis. To definitively measure exactly how and what is happening with the power on reset, you would at least need to be able to read MCUSR at Vcc voltages below the BOD reset level and probably just below Vpot, which is of course not possible.

From experience, I no longer "trust" ATMEL data sheets. However, in this case the data sheet description seems reasonable and there are simple/logical/reasonable explanations the fit the observed operation and known behaviors.

For even more fun some data sheets list a Vccrr (Vcc Rise Rate to ensure internal Power-on Reset signal) in V/ms. I suppose a really slow rising power on Vcc might get a BORF without the expected PORF. That could really confuse any program code trying to use the MCUSR information.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wow! Thanks for the lengthy and detailed discussion guys. It all confirms what I was thinking from my research; it is pretty much impossible to get a true POR (only) condition form a power-up.

I actually performed a few more tests with every combination of BOD threshold and every start-up delay option using both a 16MHz xtal and also the internal 8MHz. (all on an m2560) Not once was I able to generate a POR without the BOR. I was able to generate a BOR in solice as expected.

In terms of using ICC, I'm not aware of a method I can use to save the MCUSR any earlier that the 1st line in main(). I realise this occurs after all the ICC generated initialisation. Maybe some inline asm can be interted before this. I don't know. In any case I don't believe its going to help as the issue appears to be hardware related.

I guess if its really important for me to detect the true single source of a reset, the best way is the if/else method rather than my if only method.

Thanks again people.

Cheers,
Steve.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One time I helped someone with ICC detect a warm start (no PORF) where SRAM wasn't corrupted by a Vcc loss. He had a real time clock that would loose the time setting on other types of resets. I seem to remember he had to modify the ICC initialization code for MCUSR and copy the clock data to an initialization protected memory location, before ICC wiped it out during initialization. There was some documentation on an ICC user interface/modification for this. It was his ICC, documentation and support. It was also a long time ago, so I don't remember the details and I haven't used ICC since.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Is all that unnecessary?

AFAIK, yes. The MCUSR is a latched register. Why should it be any different 3 seconds after the AVR starts than 3 microseconds after the AVR starts? (well, OK, in the 3us perhaps the power is still ramping and causing the effect being discussed here). But I don't see why the read of MCUSR would be any different after 30 opcode fetches or 300,000. So I'm not sure why it's suggested to read it "early" (like putting it in .init3 in GCC)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

So I'm not sure why it's suggested to read it "early" (like putting it in .init3 in GCC)

I guess "early" is relative. 1) Does the prologue fuss with it? Then you want to at least grab a copy before that. 2) Is your prologue lengthy? E.G., clear a whole bunch of external memory, or a slow memory-mapped peripheral device? Then you might want to grab it early. (The pathological condition that comes to mind is WDTON with a very short fuse.) 3) Do it "early" in main(), as opposed to say after all init and ready for the main loop. Why? If you have runaway code in the init the true cause could be masked (pun intended). For example, if you have a thunk vector that fires when SEI done, or a bad pointer, or other runaway code. If not grabbed and cleared, you'd think you were getting constant PORF or whatever.

I'd say either pick a "priority" like I/CV do if that is good enough. One could report it in the fashion of file attributes:
EWPBJ
so the "combo" would come up as --PB-, a watchdog as -W---, runaway as -----, etc. and then it could be decoded later as desired. (I was thinking of masks for the combinations but then you'd have to predict all the combinations.)

If you ever get --PBJ then it is time for lunch. ;)

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lee,

I agree that earlier rather than later is "safer" but as the preamble most definitely does not mess with it I don't understand the suggested need for the complexity of putting it in .init3 (code that runs before the pre-amble) when:

uint8_t mcucr_copy;

int main(void) {
 mcucr_copy = MCUCR;
 MCUCR = 0;
...

just seems an awful lot simpler/easier.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
int main(void) {
 mcucr_copy = MCUCR;
 MCUCR = 0;
... 

This can be a quite "late" point when you have LOTS of initialized data (possibly with external memory). The watchdog can trigger before this point.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The only thing I can think of is my 2) above. For 3) head-of-main should be good as you say.It works for me in my apps, but I'm just looking for a way to "double-check" the reset cause in a problem controller in the field.

Normally with the if-else I just get the PORF. I've had a WDRF when a critical peripheral wasn't "ticking". I've had a couple BORF when there was too heavy a load on the power supply when an external device was energized. The weirdest one was EXTRF that I normally don't see except after ISP. It turned out that a wire bundle with a bare "ground strap" was dressed against the controller board, and when the machine started and vibrated a bit sometimes the bare wire came in contact with /RESET on the programming header...

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
gcc offers a big song and dance about reading the MCUSR really early in initialization AND copying that into a variable that is protected from the normal initialization process. I don't see that in the initial post. Nor any subsequent comments.

Is all that unnecessary?

As noted by others,
the watchdog timer can trigger before main.
To deal with such a possibility,
it's sometimes necessary to turn off the watchdog before main.
One should copy the MCUSR to ensure that one still can detect watchdog resets.
Dealing with the MCUSR and watchdog resets are the only
reason I've ever had to put something before main.
It strikes me as a candidate for a linker option.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
As noted by others,
the watchdog timer can trigger before main.
To deal with such a possibility,
it's sometimes necessary to turn off the watchdog before main.
One should copy the MCUSR to ensure that one still can detect watchdog resets.
Dealing with the MCUSR and watchdog resets are the only
reason I've ever had to put something before main.
It strikes me as a candidate for a linker option.

How exactly could the linker help with this?

You perhaps are talking about an alternative startup code, don't you?

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Regarding early reading/clearing of MCUSR - it's not just about detecting the reset cause as early as possible (for diagnostic purposes), it's also that while WDRF is set in MCUSR, the WDT cannot be disabled (the WDT settings "survive" reset), so you risk causing a subsequent WDR during lengthy initialization, thus entering an endless reset loop.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

8 years late but thanks. wink

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly