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() */