Power Management System for the eXPal Prototype A. More...
#include <avr/io.h>
#include "cb_list.h"
Go to the source code of this file.
Defines | |
#define | HL_PWR_ON 1 |
Parameter to switch things on. | |
#define | HL_PWR_OFF 0 |
Parameter to switch things off. | |
#define | HL_PWR_FAIL -1 |
Return value to indicate error conditions. | |
#define | HL_PWR_USB_ACTIVE 0x01 |
Power from USB is available. | |
#define | HL_PWR_3V3_ACTIVE 0x02 |
3.3V is active | |
#define | HL_PWR_5V_ACTIVE 0x04 |
5V regulator is active | |
#define | HL_PWR_LCD_ACTIVE 0x08 |
LCD High Voltage is active. | |
#define | HL_PWR_ST_RUNNING 0x00 |
PowerState 1 Running at full speed, no sleep at all allowed. | |
#define | HL_PWR_ST_IDLE 0x10 |
PowerState 2 Go into idle mode only. | |
#define | HL_PWR_ST_33SLEEP 0x20 |
PowerState 3 Go into power save mode but keep 3.3V ON. | |
#define | HL_PWR_ST_SLEEP 0x40 |
PowerState 3 Go into power save mode and switch 3.3V off. | |
#define | HL_PWR_ST_OFF 0x80 |
PowerState 3 Go into sleep mode. | |
#define | HL_PWR_ALLOW_NOSAVE 0x0000 |
No power saving allowed. | |
#define | HL_PWR_ALLOW_IDLE 0x0010 |
Power Down allowed. | |
#define | HL_PWR_ALLOW_33SLEEP 0x0020 |
Sleep Allowed but 3.3V untouched. | |
#define | HL_PWR_ALLOW_SLEEP 0x0040 |
Sleep Allowed. | |
#define | HL_PWR_ALLOW_OFF 0x0080 |
Power Off allowed. | |
#define | HL_PWR_OFF_TIME 600 |
inactivity seconds until power off | |
#define | HL_PWR_WAKE_BY_KEY 0x01 |
Key in COL0..2. | |
#define | HL_PWR_WAKE_BY_PWR_KEY 0x02 |
Key in COL3. | |
#define | HL_PWR_WAKE_BY_SYS_TMR 0x04 |
Timer2 COMPA. | |
#define | HL_PWR_WAKE_BY_1S_TMR 0x08 |
Timer2 OV. | |
#define | HL_PWR_WAKE_BY_EX232 0x10 |
USART 3. | |
#define | HL_PWR_WAKE_BY_MOD232 0x20 |
USART 2. | |
#define | HL_PWR_WAKE_BY_ADC 0x40 |
ADC. | |
#define | HL_PWR_WAKE_NO_SOURCE 0x00 |
Unknown Source or system was not in sleep (_NOSAVE). | |
Typedefs | |
typedef int8_t | hl_pwr_state_t |
typedef int8_t | pwr_info_t |
Functions | |
void | hl_pwr_InitBoard (void) |
Primary Hardware Init Function. | |
void | hl_pwr_InitPwrMan (void) |
Init power management system. | |
uint8_t | hl_pwr_EnterSleep (void) |
Try to switch system in the deepest allowed sleep mode. | |
void | hl_pwr_SetWakeSource (uint8_t ws) |
To be called in ISR to set wake-up source. | |
uint8_t | hl_pwr_GetWakeSource (void) |
return Wake-up source | |
void | hl_pwr_AppBusy (void) |
Keep System On. | |
void | hl_pwr_OffNow (void) |
Set off timer to zero. | |
uint16_t | hl_pwr_GetOffTime (void) |
Return the off timer value. | |
uint16_t | hl_pwr_fast (void *) |
fast system timer call (20ms) | |
uint16_t | hl_pwr_slow (void *) |
slow system timer call (1sec) | |
void | hl_pwr_3V3reg (hl_pwr_state_t state) |
Control the 3.3V regulator. | |
void | hl_pwr_5Vreg (hl_pwr_state_t state) |
Control the 5V regulator. | |
void | hl_pwr_LCDreg (hl_pwr_state_t state) |
Control the 15V regulator. | |
hl_pwr_state_t | hl_pwr_GetState (void) |
Return complete power state to application. | |
void | hl_RegisterPwrCb (cb_function_t fkt2call, void *PwrStAllowed) |
Register a call back function to request power down in higher SW layers. | |
Variables | |
volatile uint8_t | WakeUpSource |
Bitmap variable to indicate the wake-up source. | |
volatile uint16_t | PowerOffTimer |
Second timer until power off. | |
volatile hl_pwr_state_t | hl_pwr_state |
System power state (current setting). | |
volatile hl_pwr_state_t | hl_pwr_info |
Power States,the system is allowed to use. |
Power Management System for the eXPal Prototype A.
#define HL_PWR_ST_33SLEEP 0x20 |
PowerState 3 Go into power save mode but keep 3.3V ON.
This power state can be used when the system does not have to react on any communicatin channel. The system will wake up on any key interrupt or from the 1 sec interrupt and return from hl_pwr_EnterSleep(). After a key interrupt, the key scan module will keep the system in IDLE state until the key input is completed.
Power State with CPU in power save mode.
In this mode the CPU can not wake up from USART (no GPS operation possible)
#define HL_PWR_ST_IDLE 0x10 |
PowerState 2 Go into idle mode only.
This power state is intended to be used when the system is waiting for GPS or other external data. Every timer, USART or key iterrupt will cause the return from hl_pwr_EnterSleep().
Power State with CPU Idle mode.
#define HL_PWR_ST_OFF 0x80 |
PowerState 3 Go into sleep mode.
This state is the soft power off state with maximum power reduction, but the system time is still updated every second. The clock speed is reduced below 1MHz, the 5V regulator is off and the system will run on battery voltage. The wake-up procedure will take ~1ms to start the crystal, ramp the voltage up to 5V and start running at full speed again. The 1s ISR code is executed at low CPU speed. This has to be taken into account when functions like delay() are used.
Soft Power off state
System will only return from hl_pwr_EnterSleep() after a powerKey Interrupt (COL3)
#define HL_PWR_ST_RUNNING 0x00 |
PowerState 1 Running at full speed, no sleep at all allowed.
The system will operate without sleep and return immediately from from hl_pwr_EnterSleep(). This power state can be used to get the fastest main loop turn around time. This power state is default when powered from USB.
#define HL_PWR_ST_SLEEP 0x40 |
PowerState 3 Go into power save mode and switch 3.3V off.
This power state can be used when the system does not have to react on any communicatin channel. The system will wake up on any key interrupt or from the 1 sec interrupt and return from hl_pwr_EnterSleep(). After a key interrupt, the key scan module will keep the system in IDLE state until the key input is completed.
Power State with CPU in power save mode.
In this mode the CPU can not wake up from USART (no GPS operation possible)
void hl_pwr_3V3reg | ( | hl_pwr_state_t | state | ) |
Control the 3.3V regulator.
The function can be used to switch the 3.3V source ON or Off
[in] | state | HL_PWR_ON/HL_PWR_OFF |
Control the 3.3V regulator.
Switch the 3.3V reg. on or off
[in] | desired | state, HL_PWR_ON / HL_PWR_OFF |
{ if (state == HL_PWR_OFF){ /* power down 3.3 */ HL_PWR_VCC33_PORT &= ~(_BV(HL_PWR_VCC33)); hl_pwr_state &= ~HL_PWR_3V3_ACTIVE; }else{ /* power up 3.3 */ HL_PWR_VCC33_PORT |= _BV(HL_PWR_VCC33); hl_pwr_state |= HL_PWR_3V3_ACTIVE; } }
void hl_pwr_5Vreg | ( | hl_pwr_state_t | state | ) |
Control the 5V regulator.
The function can be used to switch the 5V source ON or Off When OFF, the Controller will run on Battery voltage minus ~0.2V.
[in] | state | HL_PWR_ON/HL_PWR_OFF |
Control the 5V regulator.
Switch the 5V reg. on or off
[in] | desired | state, HL_PWR_ON / HL_PWR_OFF |
{ if (state == HL_PWR_OFF){ /* power down 3.3 */ HL_PWR_VCC5_PORT &= ~(_BV(HL_PWR_VCC5)); hl_pwr_state &= ~HL_PWR_5V_ACTIVE; }else{ /* power up 3.3 */ HL_PWR_VCC5_PORT |= _BV(HL_PWR_VCC5); hl_pwr_state |= HL_PWR_5V_ACTIVE; } }
void hl_pwr_AppBusy | ( | void | ) | [inline] |
Keep System On.
The App has to call this function to avoid automatic power off otherwise the system will enter HL_PWR_ST_OFF when allowed and the timer has reached Zero
{ PowerOffTimer = HL_PWR_OFF_TIME; }
uint8_t hl_pwr_EnterSleep | ( | void | ) |
Try to switch system in the deepest allowed sleep mode.
Function to enter "PwrState". If a sleep power state is entered, the Control will stay within this function until wake-up
ZZZzzz...
{ // ************************************************************************* // Do OperatingSystem idle operations // Update battery display uint8_t BatState = hl_bat_GetBatStatus(); if((BatState & HL_BAT_NEWSTAT) != 0){ hl_stb_BattState(Empty + (BatState & HL_BAT_ST_MASK)); } // ************************************************************************* // Check what sleep mode is allowed uint16_t allowed_pwr_mode = 0xffff; // ask applications what's possible allowed_pwr_mode = callback_iterate_and_until0 (cbListPowerFirst); /* if(hl_pwr_state & HL_PWR_USB_ACTIVE){ // USB is active, stay in full on allowed_pwr_mode = HL_PWR_ALLOW_NOSAVE; } */ // reset system power state for update below hl_pwr_state &= ~(HL_PWR_ST_RUNNING | HL_PWR_ST_IDLE | HL_PWR_ST_33SLEEP | HL_PWR_ST_SLEEP | HL_PWR_ST_OFF); // ************************************************************************* // prepare for the individual sleep modes if ((allowed_pwr_mode & HL_PWR_ALLOW_OFF) && (PowerOffTimer == 0)){ // All registered applications did allow power off // and the shut off timer is zero too // Display status symbol hl_stb_PwrState(SLEEPsymbol); // update power state hl_pwr_state |= HL_PWR_ST_OFF; // for off use pwr-save to allow wake up from async timer set_sleep_mode (SLEEP_MODE_PWR_SAVE); // switch power sources off hl_pwr_LCDreg(HL_PWR_OFF); hl_pwr_3V3reg(HL_PWR_OFF); // LCD Controller off HL_LCD_PowerOff(); // enable wake up for power key hlRow3KeyWakeup(); // RAM interface disable and deselect RAM // ExtMemDisable(); // stop fast system timer hl_asyn_StopSysTimer(); // Stop ADC as well hl_adc_off(); // reduce clock and switch 5V reg off clock_prescale_set( clock_div_16 ); hl_pwr_5Vreg(HL_PWR_OFF); }else if (allowed_pwr_mode & HL_PWR_ALLOW_SLEEP){ // Display status symbol hl_stb_PwrState(SLEEPsymbol); // All registered applications did allow sleep hl_pwr_state |= HL_PWR_ST_SLEEP; // for off use pwr-save to allow wake up from async timer set_sleep_mode (SLEEP_MODE_PWR_SAVE); // switch power sources off hl_pwr_3V3reg(HL_PWR_OFF); // enable wake up for power key hlAllKeyWakeup(); // RAM interface disable and deselect RAM // ExtMemDisable(); // stop fast system timer hl_asyn_StopSysTimer(); // Stop ADC as well // ADC result will not be evaluated when SysTimer is off hl_adc_off(); }else if (allowed_pwr_mode & HL_PWR_ALLOW_33SLEEP){ // Display status symbol hl_stb_PwrState(SLEEPsymbol); // All registered applications did allow sleep hl_pwr_state |= HL_PWR_ST_33SLEEP; // for off use pwr-save to allow wake up from async timer set_sleep_mode (SLEEP_MODE_PWR_SAVE); // enable wake up for power key hlAllKeyWakeup(); // RAM interface disable and deselect RAM // ExtMemDisable(); // stop fast system timer hl_asyn_StopSysTimer(); // Stop ADC as well // ADC result will not be evaluated when SysTimer is off hl_adc_off(); }else if (allowed_pwr_mode & HL_PWR_ALLOW_IDLE){ // Display status symbol hl_stb_PwrState(IDLEsymbol); // All registered applications did allow idle hl_pwr_state |= HL_PWR_ST_IDLE; // Only idle mode to react on all sources set_sleep_mode (SLEEP_MODE_IDLE); } // ************************************************************************* // enter sleep mode if (allowed_pwr_mode != 0){ do{ // loop to stay in sleep for 1s timer in OFF mode WakeUpSource = HL_PWR_WAKE_NO_SOURCE; // Enter sleep mode sleep_enable (); sleep_cpu (); sleep_disable (); // Wait for ISR to set wake source if not done yet // while (WakeUpSource == HL_PWR_WAKE_NO_SOURCE); // we expect the ISR to be completed when WakeUpSource is set }while((WakeUpSource & HL_PWR_WAKE_BY_1S_TMR) && (hl_pwr_state & HL_PWR_ST_OFF)); // ************************************************************************* // manage wake up // System clock speed up when start from off if(hl_pwr_state & HL_PWR_ST_OFF){ hl_pwr_5Vreg(HL_PWR_ON); hl_pwr_LCDreg(HL_PWR_ON); HL_LCD_PowerOn(); // wait for 5V to rise // // While the voltage is rising up to 5V, the system is still running with // reduced speed. Since the delay time calculation works for 14.7456MHz, // the actual time had to be adjusted. In case of 1/16 of the original // clock, the value of 70us caused a delay of ~1.2ms. _delay_us (70); // Full speed ahead clock_prescale_set( clock_div_1 ); } // enable in case it was off or stay on // ExtMemEnable(); // do sys timer start in case it's off // hl_asyn_StartSysTimer(); }else{ // System is required to stay ON, // no sleep function called, // return without wakeup // Display status symbol if(hl_pwr_state & HL_PWR_USB_ACTIVE){ hl_stb_PwrState(USBsymbol); }else{ hl_stb_PwrState(RUNsymbol); } WakeUpSource = HL_PWR_WAKE_NO_SOURCE; hl_pwr_state |= HL_PWR_ST_RUNNING; } return WakeUpSource; }
uint16_t hl_pwr_fast | ( | void * | p | ) |
fast system timer call (20ms)
fast system timer call (20ms)
Do fast operations for power management:
{ // disable 5V reg. if Vusb available if ( (HL_USB_PWREN_PIN & _BV(HL_USB_PWREN)) == 0){ // device configured and active // Disable 5V reg. HL_PWR_VCC5_PORT &= ~(_BV(HL_PWR_VCC5)); hl_pwr_state &= ~HL_PWR_5V_ACTIVE; hl_pwr_state |= HL_PWR_USB_ACTIVE; }else{ // device not configured or in suspend // Enable 5V reg. HL_PWR_VCC5_PORT |= (_BV(HL_PWR_VCC5)); hl_pwr_state |= HL_PWR_5V_ACTIVE; hl_pwr_state &= ~HL_PWR_USB_ACTIVE; } return 0; }
uint16_t hl_pwr_GetOffTime | ( | void | ) | [inline] |
Return the off timer value.
The App can call this function to find out what time in seconds is left until soft power off.
{ return PowerOffTimer; }
hl_pwr_state_t hl_pwr_GetState | ( | void | ) | [inline] |
void hl_pwr_InitBoard | ( | void | ) |
Primary Hardware Init Function.
This function has to be called as the first action in main() It will ensure the correct setting of all processor IO lines and other board hardware. The function will only set everything in a defined, power saving state and not init any hardware unit to work.
{ /* Initialize the ports to avoid floating signals and excessive power consumption. To be complete it is more obvious to access the ports directly here. */ // Port A // can stay as is after reset // Port B PORTB= 0x80 | _BV(HL_SD_SS); // USB_RESET inakt, sauberer Pegel für SD Treiber DDRB = 0x87; // Port C DDRC = 0xFF; // Addr.Augaenge PORTC= 0xC0; // RAM Disable // Port D PORTD = 0xFF; // PullUp on for KeyLines // Port E PORTE = 0xFF; // PullUp on // Port F PORTF = 0x0F & ~_BV(PF0); // PullUp for unused AD Inputs // Port G DDRG = 0x07; PORTG = 0x07; // RD/WR disable // Port H PORTH = 0xFF; // PullUp on // Port J PORTJ = 0xFF; // PullUp on // Port K PORTK = 0xFF; // PullUp on // Port L DDRL = 0x07 | _BV(HL_EX232_FRCON) | _BV(HL_EX232_EN); // 5V ON, pull up at open pins PORTL = _BV(HL_PWR_VCC5) | _BV(PL3)|_BV(PL4) | 0*_BV(HL_EX232_FRCON) | 1*_BV(HL_EX232_EN); /* set power reduction registers */ PRR0 = _BV(PRTWI) /* | _BV(PRTIM2) | _BV(PRTIM0) */ | _BV(PRTIM1) | _BV(PRSPI) | _BV(PRUSART0) | _BV(PRADC) ; PRR1 = _BV(PRTIM5) | _BV(PRTIM4) | _BV(PRTIM3) | _BV(PRUSART3) | _BV(PRUSART2) | _BV(PRUSART1) ; }
void hl_pwr_InitPwrMan | ( | void | ) |
Init power management system.
Initialize
Initialize
{ hl_pwr_state = HL_PWR_5V_ACTIVE | HL_PWR_ST_RUNNING; hl_pwr_info = 0; // Stay in full on PowerOffTimer = HL_PWR_OFF_TIME; hl_asyn_Register1sTimer( (&hl_pwr_slow), NULL); hl_asyn_RegisterFastTimer( (&hl_pwr_fast), NULL); }
void hl_pwr_LCDreg | ( | hl_pwr_state_t | state | ) |
Control the 15V regulator.
The function can be used to switch the 15V LCD source ON or Off
[in] | state | HL_PWR_ON/HL_PWR_OFF |
Control the 15V regulator.
Switch the LCD High Voltage (~15V) reg. on or off
[in] | desired | state, HL_PWR_ON / HL_PWR_OFF |
{ if (state == HL_PWR_OFF){ /* power down 3.3 */ HL_PWR_VLCD_PORT &= ~(_BV(HL_PWR_VLCD)); hl_pwr_state &= ~HL_PWR_LCD_ACTIVE; }else{ /* power up 3.3 */ HL_PWR_VLCD_PORT |= _BV(HL_PWR_VLCD); hl_pwr_state |= HL_PWR_LCD_ACTIVE; } }
void hl_pwr_OffNow | ( | void | ) | [inline] |
Set off timer to zero.
The App has to call this function to set the off timer to Zero. The system will enter HL_PWR_ST_OFF when allowed.
{ PowerOffTimer = 0; }
void hl_pwr_SetWakeSource | ( | uint8_t | ws | ) | [inline] |
To be called in ISR to set wake-up source.
In some cases it might be desired to go back to sleep when the wake-up was caused by a certain source.
Example: Most of the background activities are done within the 20ms timer call. When the control is returned back to the main loop it might be desired to call hl_pwr_EnterSleep immediately.
[in] | ws | Wake-up source define HL_PWR_WAKE_BY_KEY HL_PWR_WAKE_BY_PWR_KEY HL_PWR_WAKE_BY_SYS_TMR HL_PWR_WAKE_BY_1S_TMR HL_PWR_WAKE_BY_EX232 HL_PWR_WAKE_BY_MOD232 HL_PWR_WAKE_NO_SOURCE |
{ WakeUpSource |= ws; }
uint16_t hl_pwr_slow | ( | void * | p | ) |
slow system timer call (1sec)
slow system timer call (1sec)
Do slow operations for power management:
{ if (PowerOffTimer > 0){ PowerOffTimer--; } return 0; }
void hl_RegisterPwrCb | ( | cb_function_t | fkt2call, | |
void * | PwrStAllowed | |||
) |
Register a call back function to request power down in higher SW layers.
The function will add an entry to the list of functions to be called when the power management tries to enter a lower power state. The new entry is added to the front of the list.
An Application routine can use the call back for the following actions:
The control should be returned as fast as pssible. Do not wait or complete any pending operations within the callback.
[in] | fkt2call | function pointer |
[in] | PwrStAllowed | pointer to power state bitmap |
{ cb_register_call (&cbListPowerFirst, fkt2call, PwrStAllowed); }
volatile uint16_t PowerOffTimer |
Second timer until power off.
If power off is allowed but the timer is not NULL, the system will only enter sleep mode.
volatile uint8_t WakeUpSource |
Bitmap variable to indicate the wake-up source.
WakeUpSource is a symmary of system actions that caused the system to wake up. It's cleared before entering sleep, any wake-up ISR will set the individual bit. When checked some time after wake-up, more than one source might be active