G120 Power Tests
I really need a descent low power state for my application. I was hoping that the last Firmware drop would provide something useful, but alas no luck. In desperation I have been conducting some experiments to try and reduce the power to the as much as possible. I haven’t played with the hardware Deep Sleep modes yet as I was concerned that NETMF might not recover. So far my results seem promising, but I would still really like to get down to the microAmp sleep level.
WARNING:- Do not try any of this unless you are prepared to brick your module. I expect some of the changes here to interfere with various parts of NETMF and cause stability problems for your application. Also I advise putting a Thread.Sleep(5000); at the start of your code to make it easier to recover.
[em]Fresh firmware flash 4.2.11.0
Lets measure the idle current.[/em]
Current = 152mA
Now the current under load.
a = System.Math.Sin(1.1f); //Infinite loop
Current = 161mA
Power.EthernetOscillatorEnable(false);
Current = 140mA //But seems to cause crash
[em]Scrub that. We can turn it off using the PCONP register anyway.
[/em]
Hibernate
[em]Lets See what hibernate does[/em]
Debug.Print("Hibernating");
Thread.Sleep(100);
Power.Hibernate(Power.WakeUpInterrupt.InterruptInputs); //Only mode that seems to work
Current = 106mA
Peripheral Control
[em]Note:- some of the changes below cause problems with debugging. You may need to press reset before you load your application. Other than that it seems totally reversible.
Lets see how much we can save by turning various peripherals off. Im going to do it in blocks to save time.
First lets create the PCONP register.[/em]
Register PCONP = new Register(0x400fc0c4);
[em]Default PCONP = 0xFFFEFFFF. In other words everything is on bar SPI Flash(PCSPIFI)
[/em]
Current = 152mA
[em]Now we will start turning some stuff off[/em]
PCONP.ClearBits(0x40000000);//Turn Off Ethernet
Current = 147mA
PCONP.ClearBits(0x00001000);//Turn Off ADC
Current = 147mA
PCONP.ClearBits(0x0Cf00000);//Turn Off PCI2S PCIC2 PCTIM3 PCTIM2 PCSSP0 PCSSP2
Current = 145mA
PCONP.ClearBits(0x000f0000);//Turn Off PCI2C1 PCQEI PCMCPWM PCSPIFI
Current = 143mA
PCONP.ClearBits(0x0000f000);//Turn Off PCGPIO PCCAN2 PCCAN1 PCADC
Current = 135mA
PCONP.ClearBits(0x00000700);//Turn Off not(PCEMC) PCSSP1 PCRTC PCUART4
Current = 133mA
[em]All these seem to cause problems with deploying unless a hard reset is pressed.[/em]
PCONP.ClearBits(0x000000E0);//Turn Off PCI2C0 PCPWM1 PCPWM0 NOT(PCUART1)
Current = 131mA
PCONP.ClearBits(0x00000004);//Turn Off NOT(PCUART0) PCTIM1 NOT(PCTIM0) NOT(PCLCD)
Current = 131mA
[em]PC Timer 0 seems to be needed for G120 to run. It doesnt take less than a mA anyway. It later turns out that all the PCTIM seem important so dont turn them off.[/em]
[em]PCONP.ClearBits(0x00000001);//Turn Off PCLCD[/em]
Current = 121mA
[em]The LCD controller is a big power draw. According to the release notes for this update the LCD should be off anyway, but it doesnt appears so.
[/em]
[em]Turn off the last 2 UARTS[/em]
PCONP.ClearBits(0x03000000);//Turn Off PCUART3 PCUART2
Current = 119mA
PCONP.ClearBits(0x20000000);//Turn Off PCGPDMA
Current = 108mA
[em]Ok, with all that done lets try the hibernate function again.[/em]
Debug.Print("Hibernating");
Thread.Sleep(100);
Power.Hibernate(Power.WakeUpInterrupt.InterruptInputs); //Only mode that seems to work
Current = 59mA
CPU Clock etc
PCONP = 90C00F1E
Initial current = 111mA
Register PBOOST = new Register(0x400FC1B0);
PBOOST.ClearBits(3);//POWER BOOST OFF TOP CPU CLOCK 100MHz Saves a few mA
Current = 102mA
[em]Now try and underclock the G120 to 60MHz[/em]
Register PLL0CFG = new Register(0x400FC084); //Default to 9 //MSEL=9,PSEL=0
Debug.Print("PLL0CFG = " + PLL0CFG.Read().ToString());
PLL0CFG.Write(0x24); //Set MSEL=4,M= 5,PSEL = 1(div by 2) CLK = 5*12/= 60MHz
Register PLL0FEED = new Register(0x400FC08C);//Need to write AA55 here to commit change
PLL0FEED.Write(0xAA);
PLL0FEED.Write(0x55);//Make it happen
Debug.Print("PLL0CFG = " + PLL0CFG.Read().ToString());
Current = 68mA
PLL0CFG.Write(0x23); //Set MSEL=3,M=4,PSEL=1(div by 2) CLK=4*12/=48MHz
Current = 60mA
PLL0CFG.Write(0x60); //Set MSEL=0,M= 1,PSEL=3(div by 8) CLK = 1*12/= 12MHz
Current = 39mA
[em]Other CPU speed settings are as follows:-[/em]
PLL0CFG.Write(0x09); //Set MSEL=6, M=5,PSEL = 0(div by 1) CLK = 10*12/= 120MHz
PLL0CFG.Write(0x06); //Set MSEL=6, M=7,PSEL = 0(div by 1) CLK = 7*12 = 84MHz
PLL0CFG.Write(0x25); //Set MSEL=5, M=6,PSEL = 1(div by 2) CLK = 6*12/= 72MHz
PLL0CFG.Write(0x24); //Set MSEL=4, M=5,PSEL = 1(div by 2) CLK = 5*12/= 60MHz
PLL0CFG.Write(0x23); //Set MSEL=3, M=4,PSEL = 1(div by 2) CLK = 4*12/= 48MHz
PLL0CFG.Write(0x41); //Set MSEL=1, M=2,PSEL = 2(div by 4) CLK = 2*12/= 24MHz PLL0CFG.Write(0x60); //Set MSEL=0, M=1,PSEL = 3(div by 8) CLK = 1*12/= 12MHz
[em]Note:- I havent tried running any applications while running at these clock rates. I have noticed that it slows down the Thres.Sleep() timer. I assume this converts milliseconds into CPU ticks internally.
Now hibernating while at 12MHz[/em]
Current = 24mA
[em]I have also tested recovering from this low power mode and getting back to the full power state. Obviously you need the GPIO enabled to give you an interrupt to get out of hibernate. This seems to work reliably. [/em]
PLL0CFG.Write(0x09); //Set MSEL = 6, M = 5,PSEL = 0(div by 1) CLK = 10*12/= 120MHz PLL0FEED.Write(0xAA);
PLL0FEED.Write(0x55);//Make it happen
PCONP.Write(0xFFFEFFFF);//Back to normal