Reputation: 11
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.
Upvotes: 0
Views: 1478
Reputation: 342
I used the following library once and it worked flawlessly. I am not sure if it would work with mbed 5 but its worth a try.
https://os.mbed.com/users/no2chem/code/PowerControl/
Upvotes: 0
Reputation: 826
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.
Upvotes: 1