XMega current measurements

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

I wanted to get some real world XMega current verses frequency
numbers. Don't read to much into the absolute values (need better
current meter), just relative compassion:

Base board with no XMega populated takes 5 uA.

Sleeping:
PDOWN/PSAVE/RTC Off: 5 uA
PSAVE/RTC on: 6 uA

Running empty NOP loop:

32 kHz External Osc. 180 uA

2 MHz/32 kHz External Osc Off: 2.31 mA
2 MHz/32 kHz External Osc On: 2.28 mA

Turning the 32 kHz Osc. on made the current go down.
Ran the test couple of times to confirm this.

4 MHz: 4.87 mA
8 MHz: 9.29 mA
16 MHz: 16.18 mA
32 MHz: 30.49 mA

More detailed numbers in the code below.

/*
 *
 * Atmel XMega 128A1 Current measurement Test harness, and PLL setup
 * example.
 *
 * V1.0 Bob Paddock Sep/1/2009
 *
 * Compile with WinAVR-200901313 GCC 4.3.2 or newer.
 *
 * Test configuration is power supply set to 3.7V, in series with
 * current meter on the positive lead, into a three volt regulator,
 * which is powering XMega 128A1.  Only XMega ports PQ0 and PQ1 are
 * connected to 32 kHz watch crystal, all other pins are floating,
 * except PK1->PK6 that have 1k external pull-ups.  Current meter
 * does not read below 1uA.
 *
 * A board with *no* XMega populated takes 5 uA for reset chip,
 * voltage regulator quiescent current, cap leakage etc.
 *
 * Test measurement currents are with Clock Out (PD7) disabled, and not
 * loaded.  Each measurement taken with JTAG unplugged, and power cycled.
 *
 * The set of defines below will allow running the XMega at
 * frequencies of 32 kHz, 2 MHz, 4 MHz, 16 MHz and 32 MHz, with
 * options for auto calibration, and RTC to be enabled.  With no
 * options test runs at default 2 MHz.
 *
 */

#include 
#include  /* _NOP() */

#include "ccpwrite.h"
#include "clksys_driver.h"
#include "rtc_driver.h" /* RTC_BUSY() */

/* Settings as shown run at 2 MHz: */
#define USE_CLOCK_OUT_ON_D7  (0) /* Non-zero for clock out on PD7.  Do not set when measuring current */

#define USE_SLEEP            (0) /* Non-Zero to enter sleep, otherwise use empty NOP loop */
#define USE_RTC              (0) /* Non-zero to enable RTC at 1 kHz */

#define ENABLE_16MHZ_PLL     (0) /* Non-zero to run at 16 MHz */
#define ENABLE_32MHZ_PLL     (0) /* Non-zero to run at 32 MHz */
#define ENABLE_PLL_DIV_4     (0) /* Non-zero to divide PLL by 4.  Will give 4 MHz with 16 MHz PLL, and 8 MHz with 32 MHz PLL */

#define USE_32kHz_CRYSTAL    (0) /* Non-zero to enable external 32.768 kHz Watch Crystal for auto calibration and running at 32 kHz */
#define USE_AUTO_CALIBRATION (0) /* Non-zero to use external crystal as reference for the internal 2 MHz Osc., not used at 32 kHz */
#define RUN_AT_32KHZ         (0)

/* Generate error message(s) if have incompatible options selected: */

#if( (ENABLE_16MHZ_PLL > 0) && (ENABLE_32MHZ_PLL > 0) )
#error Both 16 and 32 MHz settings may not be enabled simultaneously
#endif

#if( (ENABLE_PLL_DIV_4 > 0) && (0 == ENABLE_16MHZ_PLL) && (0 == ENABLE_32MHZ_PLL) )
#error ENABLE_16MHZ_PLL or ENABLE_32MHZ_PLL must be set to use ENABLE_PLL_DIV_4
#endif

#if( (USE_32kHz_CRYSTAL < 1) && (USE_AUTO_CALIBRATION > 0) )
#error USE_32kHz_CRYSTAL must be set to use Auto Calibration.
#endif

#if( RUN_AT_32KHZ > 0 )

#if( 0 == USE_32kHz_CRYSTAL )
#error USE_32kHz_CRYSTAL must be set to run at 32 kHz
#endif

#if( (ENABLE_16MHZ_PLL > 0) || (ENABLE_32MHZ_PLL > 0) )
#error 16 or 32 MHz PLL settings may not be enabled when running at 32 kHz
#endif

#if( ENABLE_PLL_DIV_4 > 0 )
#error ENABLE_PLL_DIV_4 may not be enabled when running at 32 kHz
#endif

#endif /* #if( RUN_AT_32KHZ > 0 ) */

/*
 * 2 MHz Osc. running, 32 kHz Osc. Off, Auto Calibration Off, RTC Off:
 * Empty loop, inputs floating:         Wondering around 3.00 mA
 * Empty loop, inputs pulled-up:        2.31 mA
 *
 * 2 MHz Osc. running, 32 kHz Osc. On, Auto Calibration Off, RTC Off:
 * Empty loop, inputs pulled-up:        2.28 mA [Went down?]
 *
 * 2 MHz Osc. running, 32 kHz Osc. On, Auto Calibration On, RTC Off:
 * Empty loop, inputs pulled-up:        2.29 mA
 *
 * 2 MHz Osc. running, 32 kHz Osc. On, Auto Calibration On, RTC On:
 * Empty loop, inputs pulled-up:        2.31 mA
 *
 * 2 MHz Osc. running, 32 kHz Osc. On, Auto Calibration On, RTC On, 16 MHz PLL:
 * Empty loop, inputs pulled-up:        16.18 mA
 *
 * 2 MHz Osc. running, 32 kHz Osc. On, Auto Calibration On, RTC On, 16 MHz PLL/4 (4 MHz):
 * Empty loop, inputs pulled-up:        4.87 mA
 *
 * 2 MHz Osc. running, 32 kHz Osc. On, Auto Calibration On, RTC On, 32 MHz PLL:
 * Empty loop, inputs pulled-up:        30.49 mA
 *
 * 2 MHz Osc. running, 32 kHz Osc. On, Auto Calibration On, RTC On, 32 MHz PLL/4 (8 MHz):
 * Empty loop, inputs pulled-up:        9.29 mA
 *
 * 2 MHz Osc. stopped, running at 32 kHz, Auto Calibration Off, RTC On:
 * Empty loop, inputs pulled-up:        180 uA
 *
 * At 2 MHz settings and 32 kHz Osc., stopped:
 *      RTC Off:
 *      PDOWN:                          5 uA
 *      PSAVE:                          5 uA
 *
 *      RTC On at 1024 Hz, 32 kHz *Off* (not useful):
 *      PSAVE:                          6 uA
 *
 *      RTC On at 1024 Hz, 32 kHz On:
 *      PSAVE:                          6 uA
 */

int main( void )
{

#if 0 /* Simple Empty loop.  Floating inputs, always bad design practice */
  for(;;)
    {
      _NOP();
    }
#endif

#if 1 /* Pull-ups enabled */
 /*
  * Reset has all port pins as inputs.
  * Set all pins to have internal pull-ups:
  */
  PORTCFG.MPCMASK = (uint8_t) -1; /* MPCMASK register is cleared automatically after the write operation to the pin configuration registers is finished. */
  PORTA.PIN0CTRL = PORT_OPC_PULLUP_gc;

  PORTCFG.MPCMASK = (uint8_t) -1;
  PORTB.PIN0CTRL = PORT_OPC_PULLUP_gc;

  PORTCFG.MPCMASK = (uint8_t) -1;
  PORTC.PIN0CTRL = PORT_OPC_PULLUP_gc;

  PORTCFG.MPCMASK = (uint8_t) -1;
  PORTD.PIN0CTRL = PORT_OPC_PULLUP_gc;

  PORTCFG.MPCMASK = (uint8_t) -1;
  PORTE.PIN0CTRL = PORT_OPC_PULLUP_gc;

  PORTCFG.MPCMASK = (uint8_t) -1;
  PORTF.PIN0CTRL = PORT_OPC_PULLUP_gc;

  PORTCFG.MPCMASK = (uint8_t) -1;
  PORTH.PIN0CTRL = PORT_OPC_PULLUP_gc;

  PORTCFG.MPCMASK = (uint8_t) -1;
  PORTJ.PIN0CTRL = PORT_OPC_PULLUP_gc;

  PORTCFG.MPCMASK = (uint8_t) -1;
  PORTK.PIN0CTRL = PORT_OPC_PULLUP_gc;

  PORTCFG.MPCMASK = (uint8_t) -1;
  PORTQ.PIN0CTRL = PORT_OPC_PULLUP_gc; /* PQ0 and PQ1 have 32.768 kHz Watch Crystal connected */

  PORTCFG.MPCMASK = (uint8_t) -1;
  PORTR.PIN0CTRL = PORT_OPC_PULLUP_gc;

#if( USE_CLOCK_OUT_ON_D7 > 0 )
  PORTD.DIRSET =  _BV(7);                   /* To output clock, port must be set as output */
  PORTCFG.CLKEVOUT = PORTCFG_CLKOUT_PD7_gc; /* Output the clock frequency on PD7 to measure on Counter/Scope */
#endif

#if( USE_32kHz_CRYSTAL > 0 )
  CLKSYS_XOSC_Config( 0, false, OSC_XOSCSEL_32KHz_gc );
  CLKSYS_Enable( (OSC_RC2MEN_bm|OSC_XOSCEN_bm) );        /* Does an OR with current Osc bits */
  do {} while ( CLKSYS_IsReady( OSC_XOSCRDY_bm ) == 0 ); /* 32 kHz Does AND of the bits */
#else
  CLKSYS_Enable( (OSC_RC2MEN_bm) );   /* Does an OR with current Osc bits */
#endif

  do {} while ( CLKSYS_IsReady( OSC_RC2MRDY_bm ) == 0 ); /* Wait for 2 MHz Osc. to stabilize */
  /* At Reset, the main clock source will already be the 2 MHz Osc. */

#if( (USE_32kHz_CRYSTAL > 0) && (USE_AUTO_CALIBRATION > 0) )
  CLKSYS_AutoCalibration_Enable( OSC_RC2MCREF_bm, true ); /* 2MHz Osc. True= external crystal used as reference */
#endif

#if( USE_RTC > 0 )
  CLKSYS_RTC_ClockSource_Enable( CLK_RTCSRC_TOSC_gc ); /* RTC source is 1024 Hz from 32kHz crystal oscillator on TOSC */
  while( RTC_Busy() )
    ;
  RTC.PER  = 2000;
  RTC.COMP = 1000;
  RTC.CNT  = 0;
  //  RTC.CTRL = RTC_PRESCALER_DIV1024_gc; /* Rollover in 18 hours and 12 minutes */
  RTC.CTRL = RTC_PRESCALER_DIV1_gc; /* Rollover at 64 seconds */
#endif

#if( ENABLE_16MHZ_PLL > 0 )
  CLKSYS_PLL_Config( OSC_PLLSRC_RC2M_gc, 8 );             /* 2MHz * 8 = 16 MHz.  PLL Min is 10 MHz */
#endif

#if( ENABLE_32MHZ_PLL > 0 )
  CLKSYS_PLL_Config( OSC_PLLSRC_RC2M_gc, 16 );            /* 2MHz * 16 = 32 MHz.  PLL Min is 10 MHz */
#endif

#if( ENABLE_PLL_DIV_4 > 0 )
  CLKSYS_Prescalers_Config( CLK_PSADIV_4_gc, CLK_PSBCDIV_1_1_gc ); /* CLKper = CLKcpu = PLL MHz/4.  PrescalerC drives CLKcpu */
#endif

#if( (ENABLE_16MHZ_PLL > 0) || (ENABLE_32MHZ_PLL > 0) )
  CLKSYS_Enable( OSC_PLLEN_bm );
  do {} while ( CLKSYS_IsReady( OSC_PLLRDY_bm ) == 0 );

  CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_PLL_gc );   /* Switch main clock PLL */
#endif

#if( RUN_AT_32KHZ > 0 )

#if( USE_AUTO_CALIBRATION > 0 )
  CLKSYS_AutoCalibration_Disable( DFLLRC2M ); /* Turn off the 2MHz Auto Calibration so we can switch Osc. to 32 kHz */
#endif

  CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_XOSC_gc );  /* Switch external 32 kHz watch crystal */

  (void) CLKSYS_Disable( OSC_RC2MEN_bm );/* Disable the 2 MHz osc now that we are not using it */
#endif

#if( USE_SLEEP > 0 )
  CCPWrite(&MCU.MCUCR, MCU_JTAGD_bm);    /* Disables JTAG during sleep */

  SLEEP.CTRL  = (SLEEP_SMODE_PSAVE_gc|SLEEP_SEN_bm);    /* Set sleep mode to Power Save, asynchronous I/O wakeup, RTC runs if enabled, enable Sleep instruction */
#endif

  for(;;)
    {
#if( USE_SLEEP > 0 )
      sleep_cpu();                           /* AVR Sleep instruction */
#else
      _NOP();
#endif
    }


#endif /* Pull-ups enabled */

}/* main() */
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

* Test configuration is power supply set to 3.7V, in series with
* current meter on the positive lead, into a three volt regulator,
* which is powering XMega 128A1.

While the test setup and tests run are quite "practical", measuring the input to the regulator doesn't truly reflect the Xmega's draw as the regulator's loss could be different at different draws.

But as a practical guide we now know it is "a mA per MHz" for Xmega CPU draw. That is about 2x the value in the datasheet, and 2x that of a Mega[88P]. Given that, I'd look at your test conditions again, and measure the current coming from the regulator to the Xmega.

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

I can independently confirm that while running at 32MHz on an XMEGA64A3 on both the STK600 and on a separate board I measure 35mA of current. This is twice the datasheet current, and quite surprising.

My STK600 measurement is at the VTARGET pin, and my second board measurement is at a jumper that switches between FT232R and external 3.3V.

The program is just one I happen to be running, and I haven't configured the fuses in any special way (JTAGEN is on, although turning it off has very little impact on total current consumption).

Since my FT232R can only source 50mA, I'm kind of up against a wall for my power consumption.