I want to create a low power application with mbed (LPC1768) and have been following tutorial by Jim Hamblen at: https://mbed.org/cookbook/Power-Management and also http://mbed.org/users/no2chem/notebook/mbed-power-controlconsumption/
I was able to wake the mbed from Sleep() by GPIO interrupt, UART interrupt, and Ticker. I use PowerControl library.
Here is my code:
#include "mbed.h"
#include "PowerControl/PowerControl.h"
#include "PowerControl/EthernetPowerControl.h"
// Need PowerControl *.h files from this URL
// http://mbed.org/users/no2chem/notebook/mbed-power-controlconsumption/
// Function to power down magic USB interface chip with new firmware
#define USR_POWERDOWN (0x104)
int semihost_powerdown() {
uint32_t arg;
return __semihost(USR_POWERDOWN, &arg);
}
DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
bool rx_uart_irq = false;
Serial device(p28, p27); // tx, rx
InterruptIn button(p5);
// Circular buffers for serial TX and RX data - used by interrupt routines
const int buffer_size = 255;
// might need to increase buffer size for high baud rates
char tx_buffer[buffer_size];
char rx_buffer[buffer_size];
// Circular buffer pointers
// volatile makes read-modify-write atomic
volatile int tx_in=0;
volatile int tx_out=0;
volatile int rx_in=0;
volatile int rx_out=0;
// Line buffers for sprintf and sscanf
char tx_line[80];
char rx_line[80];
void Rx_interrupt();
void blink() {
myled2 = !myled2;
}
int main() {
//int result;
device.baud(9600);
device.attach(&Rx_interrupt, Serial::RxIrq);
// Normal mbed power level for this setup is around 690mW
// assuming 5V used on Vin pin
// If you don't need networking...
// Power down Ethernet interface - saves around 175mW
// Also need to unplug network cable - just a cable sucks power
PHY_PowerDown();
myled2 = 0;
// If you don't need the PC host USB interface....
// Power down magic USB interface chip - saves around 150mW
// Needs new firmware (URL below) and USB cable not connected
// http://mbed.org/users/simon/notebook/interface-powerdown/
// Supply power to mbed using Vin pin
//result = semihost_powerdown();
// Power consumption is now around half
// Turn off clock enables on unused I/O Peripherals (UARTs, Timers, PWM, SPI, CAN, I2C, A/D...)
// To save just a tiny bit more power - most are already off by default in this short code example
// See PowerControl.h for I/O device bit assignments
// Don't turn off GPIO - it is needed to blink the LEDs
Peripheral_PowerDown( ~( LPC1768_PCONP_PCUART0 |
LPC1768_PCONP_PCUART2 |
0));
// use Ticker interrupt and Sleep instead of a wait for time delay - saves up to 70mW
// Sleep halts and waits for an interrupt instead of executing instructions
// power is saved by not constantly fetching and decoding instructions
// Exact power level reduction depends on the amount of time spent in Sleep mode
//blinker.attach(&blink, 0.05);
//button.rise(&blink);
while (1) {
myled1 = 0;
printf("bye\n");
Sleep();
if(rx_uart_irq == true) {
printf("wake from uart irq\n");
}
myled1 = 1;
}
}
// Interupt Routine to read in data from serial port
void Rx_interrupt() {
myled2 = !myled2;
rx_uart_irq = true;
uint32_t IRR0= LPC_UART2->IIR;
while ((device.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) {
rx_buffer[rx_in] = LPC_UART2->RBR;
rx_in = (rx_in + 1) % buffer_size;
}
}
Here is the problem: The Sleep() doesn't put the mbed to sleep when mbed-rtos library is added. Even when I don't use any function calls from the rtos library , Sleep() doesn't work.
My explanation: Probably the rtos has a timer running in the background and it generates an interrupt every now and then. (But it kinda doesn't make sense because I haven't use any function or object from rtos library)
My question:
Has any one made the Sleep() function work with rtos? if yes, please point me to the right direction or if you have the solution, please share.
I'm not sure if the Sleep() function is designed for RTOS use, but I doubt it. Someone with better knowledge in mbed-rtos could probably tell for sure, but I suspect that IRQ handling in the RTOS could cause the problem. If Sleep() relies on WFE then the MCU will sleep if there is no pending interrupt flag. In a super loop design you (should) have full control over this; with an RTOS you don't.
I suggest using Thread::wait() instead, which should have full knowledge about what the RTOS does. Can't tell if it causes a sleep, but I expect no less.