Here is what I have found so far.
Looking through the docs, it seems that normal sleep mode is a bit of a waste of time, as at best it will save 2ma.
Moving onto stop mode which seems the best option (standby resets sram?) I managed to get the current down to 3ma (incl regulator) with everything in it's default state and about 5ma with the built in LED on. Not bad. This is a Olimexino running off a 3.7V li-ion battery.
Here is some rough code, if someone with more knowledge than me could look through it and point out any mistakes/suggestions:-
// Engages stop mode on the cpu, wakes up when the onboard button is briefly pressed
// Toggles pin 3 and pin 13 every time the button is pressed/released
// Pin 3 is used to indicate that the main loop has run. It is toggled every time loop() is called.
// Normally this would be constantly flashing on/off so fast it would appear on all the time
// In this case, the loop is only finished when the button has been pressed/released.
// PROBLEMS so far : works as expected,
// : note that because it's in stop mode, you may have to
// : reset to reprogram.
// : SerialUSB.print : NOT WORKING.
#include <stdint.h>
#include <pwr.h>
#include <scb.h>
// These are possibly defined somewhere but I couldn't find them. System Control Register
#define SCB_SCR_SLEEPDEEP 4 // Controls deepsleep(1) or sleep(0)
#define SCB_SCR_SLEEPONEXIT 2 // Controls sleeponexit (not used here)
volatile bool ledState = LOW; // Used in ISR blinkState()
void setup()
{
pinMode(BOARD_LED_PIN, OUTPUT);
pinMode(3,OUTPUT);
pinMode(BOARD_BUTTON_PIN, INPUT);
// Just to show that the board has reset (wdt or possibly standby mode(not used here))
for (int i=0; i<20; ++i)
{
delay(200);
toggleLED();
}
togglePin(3);
// Wake up cpu on button press.
attachInterrupt(BOARD_BUTTON_PIN, blinkState, FALLING);
}
void loop()
{
//SerialUSB.println("HI!"); delay(100); // Only works on first iteration, before stop mode
// Clear PDDS and LPDS bits
PWR_BASE->CR &= PWR_CR_LPDS | PWR_CR_PDDS;
// set sleepdeep in the system control register
SCB_BASE->SCR |= SCB_SCR_SLEEPDEEP;
// Now go into stop mode, wake up on interrupt
asm(" wfi");
digitalWrite(BOARD_LED_PIN, ledState);
togglePin(3);
}
// Interrupt Service Routine (ISR)
void blinkState()
{
ledState=!ledState;
waitForButtonPress(); // Dangerous in ISR, I know, but quick demo only so blah.
}
It pretty much came down 2 lines of code in the end. Doesn't seem like much, but it took 30 pages of docs to get there. I'm guessing it's not in any way robust, but at least it's a starting point. It should work with the RTC as Rod mentioned or any external interrupt. I'm not sure whether I have to clear flags in the ISR or not.
The main problem is that the SerialUSB goes down, I don't know whether re-init it would help.