The case of the missing microamps...

Thanks for the clarification on delay() being the culprit for interrupts; I figured it was just a counter loop... in case of a timer interrupt, the trouble I was having with noInterrupts() and/or disabling timers make perfect sense now.

I know the power_xxx_disable() functions are indeed doing nothing now that I write to the PRR directly - I figured they couldn't hurt anything :slight_smile:

But nevermind that... I have some new information!

It is definitely something in the Arduino environment - not the fuse configuration or bootloader - that is twiddling the "mystery resource(s)" that draws (or totals) 100uA. I compiled and uploaded the essentially identical code directly using avrdude to the bootloader:

Now it draws only 17uA!

Now to track down those 17uA... after more careful reading of the datasheet/forums, I was not disabling the BOD correctly: even after setting BOD disable during sleep using a magic incantation, the sleep() has to be executed within three cycles, or BOD re-enables!

After fixing this, the sleep current is now too low to measure on my meter (<1uA).

Going thru avr-gcc directly like this is not really a solution (the point of this is to be an Arduino, afterall), but it should at least rule out the fuses/bootloader and help narrow down what's going on. If anyone reading this is familiar with the bowels of the Arduino source, any suggestions to narrow the search further would be most appreciated!

#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
//#include <avr/boot.h>
#include <avr/power.h>
#include <avr/sleep.h>

#define LED_DDR  DDRC
#define LED_PORT PORTC
#define LED_PIN  PINC
#define LED      PINC2

void flash_led(uint8_t);

// fished from a newer avr/sleep.h on the internet
#define sleep_bod_disable() \
do { \
   uint8_t tempreg; \
   __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \
                        "ori %[tempreg], %[bods_bodse]" "\n\t" \
                        "out %[mcucr], %[tempreg]" "\n\t" \
                        "andi %[tempreg], %[not_bodse]" "\n\t" \
                        "out %[mcucr], %[tempreg]" \
                        : [tempreg] "=&d" (tempreg) \
                        : [mcucr] "I" _SFR_IO_ADDR(MCUCR), \
                          [bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \
                          [not_bodse] "i" (~_BV(BODSE))); \
 } while (0)

void main(void)
{
  asm volatile("nop\n\t");


    /* set LED pin as output */
  LED_DDR |= _BV(LED);


  flash_led(NUM_LED_FLASHES);


  DDRA = 0;
  DDRB = 0;
  DDRC = 0;
  DDRD = 0;

  PORTA=0;
  PORTB=0;
  PORTC=0;
  PORTD=0;

  while (ASSR & ((1<<TCN2UB)|(1<<OCR2AUB)|(1<<OCR2BUB)|(1<<TCR2AUB)|(1<<TCR2BUB))) {  }


  
  
  MCUCR |= 0b00010000; // disable pullups - no change





  // Shutdown ADC related stuff
  ACSR = ACSR & 0b11110111 ; // clearing ACIE prevent analog interupts happening during next command
  ACSR = 0b10000000; // set ACD bit powers off analog comparator; disable bandgap ref too
  ADCSRA = 0b00000000;  // clearing ADEN turns off analog digital converter
  ADMUX &= 0b00111111;  // Comparator uses AREF/GND and not internally generated references
  // Digital Input Disable
  DIDR1 = 0b00000011;
  DIDR0 = 0b11111111;


    // kill WDT if running
  MCUSR = 0;
  WDTCSR |= _BV(WDCE) | _BV(WDE);
  WDTCSR = 0;

  TCCR0B = 0b00000000; // ensure timer 0 not clocked
  TCCR1B = 0b00000000; // ensure timer 1 not clocked
  TCCR1B = 0b00000000; // ensure timer 2 not clocked
  PRR = 0b11111111 ; // Bit 6, 5 are timers...
  PRR0 = 0b11111111 ; // probably an alias for PRR

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_bod_disable();
  sleep_cpu();


    /* forever loop */
    for (;;)
      {
            flash_led(2);
      }
    /* end of forever loop */
}

void flash_led(uint8_t count)
{
    /* flash onboard LED three times to signal entering of bootloader */
      /* l needs to be volatile or the delay loops below might get
      optimized away if compiling with optimizations (DAM). */
    volatile uint32_t l;

    if (count == 0) {
      count = 3;
    }

      int8_t i;
    for (i = 0; i < count; ++i) {
            LED_PORT |= _BV(LED);
            for(l = 0; l < (F_CPU / 1000); ++l);
            LED_PORT &= ~_BV(LED);
            for(l = 0; l < (F_CPU / 1000); ++l);
      }

}