Pages: [1]   Go Down
Author Topic: MCUSR on ATtiny85 (HLT cores)?  (Read 737 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 3
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to use the MCUSR register to determine whether the MCU came up from PORF or WXTRF, but it's not quite doing what I expect:

Code:

volatile byte last_mode;

void setup() {
  light_led(MCUSR-1);  delay(250);  leds_off();  delay(250); // What are the contents of the MCUSR?

  if(bit_is_set(MCUSR, PORF)) {
    MCUSR = 0;
    last_mode = 0; // I just powered on!                                                                                                     
    light_led(10); delay(250); leds_off(); delay(250);
  }
  else if(bit_is_set(MCUSR, EXTRF)) {
    MCUSR = 0;
    last_mode++; // advance mode because I just reset                                                                         
    light_led(11); delay(250); leds_off(); delay(250);

    if(last_mode > MAX_MODE) {
      last_mode = 0; // reset mode                                                                     
    }
  }

(light_led just lights the appropriate LED, in lieu of getting SoftwareSerial running)

In practice, on cold boot, last_mode is 0 and lights up LED 10.  I hit the reset switch and last_mode is 1 and it lights up LED 11.  And every time after that, last_mode is 1.  I was under the impression that memory isn't explicitly reinitialized after EXTRF, but it sure seems that last_mode is getting reinitialized every time, and only the increment in the EXTRF elsif is updating it from 0.  Is there a trick to ensuring that variables aren't overwritten?  It's my understanding that the HLT "bootloader" just flashes the appropriate fuses, so there isn't actually a bootloader mucking around with MCUSR like happens on the ATmegas.  MCUSR seems to contain the right bits after PORF and EXTRF are asserted, so I'm getting into the conditionals that I expect.

(Actually, typing this up gave me the idea to monitor last_mode via blinking the appropriate LED, and that confirms that last_mode is getting reset to 0 after I hit the reset switch.  Hrmph.)

Any ideas?  Googling around has a few suggestions that imply that this ought to work, but none of them are in the Arduino environment, so I half suspect there's some basic assumption stomping on it at compile time.

Thanks!

(mostly the references are along the lines of http://www.sparkfun.com/datasheets/Kits/tinyCylon2.c which is close to what I'm aiming to do.  Start at mode 0 from power on, advance to additional modes on reset.)

Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12283
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is there a trick to ensuring that variables aren't overwritten?

No trick.  Use the EEPROM.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is there a trick to ensuring that variables aren't overwritten? 

There is a compiler attribute, example:

Code:
long __attribute__ ((section (".noinit"))) resetCount;

The tricky bit now is to have it initialized the first time. Something like this:

Code:
// some stuff that shouldn't be there randomly
const char wantedSig [5] = { 'f', 'o', 'b', 'a', 'r' };

// compiler not to initialize these two variables
char __attribute__ ((section (".noinit"))) magicSig [5];
long __attribute__ ((section (".noinit"))) resetCount;

void setup ()
{
 
  // if signature there, we have restarted
  if (memcmp (wantedSig, magicSig, sizeof magicSig) == 0)
    resetCount++;
  else
    {
    resetCount = 0;
    // put signature there
    memcpy (magicSig, wantedSig, sizeof magicSig);
    }

 // other setup

 }  // end of setup

void loop ()
  {
  // whatever
  }

The idea is that magicSig will have random data in it after a power on (and thus, not "fobar"). So if the signature is random, we set initialize it and set the resetCount to zero.
Logged

Offline Offline
Newbie
*
Karma: 3
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


There is a compiler attribute, example:

Code:
long __attribute__ ((section (".noinit"))) resetCount;

The tricky bit now is to have it initialized the first time. Something like this:
(...snip...)

Ah yeah, I tried simplifying the .noinit from the tinycylon code to be a straightforward variable, but I must have missed it by a hair, because when I tried it it ended up generating Java errors, not even avr-gcc errors.  I know emacs' gcc mode was puzzled by it, but in my 2 hours past bedtime fog I didn't commit it so I couldn't even say how I screwed it up.

For future reference, this works like a charm:

Code:
byte __attribute__ ((section (".noinit"))) last_mode;

void setup() {
  if(bit_is_set(MCUSR, PORF)) {
    MCUSR = 0;
    last_mode = 0; // power on!                                                                                                     
  }
  else if(bit_is_set(MCUSR, EXTRF)) {
    MCUSR = 0;
    last_mode++; // advance mode                                                                                                   

    if(last_mode > MAX_MODE) {
      last_mode = 0; // reset mode                                                                                                 
    }
  }
// rest of setup
}

I had been using eeprom previously, and I might go back to it.  But while previously I had been writing after every reset, now I can use resets as a mode selector until it times out, then it writes the selected mode to eeprom.  Even though the various flash destroyers have convinced me that Atmel's 100,000 write claim is highly pessimistic, I may as well limit how often I'm beating it up - there's always crib death.

And I see the difference between monitoring for a cold boot via PORF versus checking for uninitialized garbage.  Belt and suspenders.  I'll see about implementing that after work.

Thanks again, though - that was the nudge in the right direction!
Logged

Pages: [1]   Go Up
Jump to: