XMEGA Application Note


sleepmgr.c File Reference

Sleep manager source file. More...

#include <stdint.h>
#include "avr_compiler.h"
#include "sleepmgr.h"
#include "config_sleepmgr.h"

Include dependency graph for sleepmgr.c:

Go to the source code of this file.

Functions

void SLEEPMGR_CancelSleep (void)
 Cancel pending sleep attempt, e.g. when work is added from a device driver.
void SLEEPMGR_Init (void)
 Initialize sleep manager. Call this before any other manager function.
void SLEEPMGR_Lock (SLEEPMGR_mode_t mode)
 Increase lock for a mode, i.e. you need at least this awareness.
void SLEEPMGR_Sleep (void)
 Enter the deepest possible sleep mode possible with current lock state.
void SLEEPMGR_Unlock (SLEEPMGR_mode_t mode)
 Decrease lock for a mode, i.e. you no longer need this awareness.

Variables

 SLEEPMGR_DEFINE_MODES
SLEEPMGR_lock_t SLEEPMGR_locks [SLEEPMGR_NUM_MODES]
 Sleep mode lock counters.


Detailed Description

Sleep manager source file.

This file contains the function implementations of the sleep manager.

Application note:
AVR1010: Minimizing the power consumption of XMEGA devices
Documentation
For comprehensive code documentation, supported compilers, compiler settings and supported devices see readme.html
Author:
Atmel Corporation: http://www.atmel.com
Support email: avr@atmel.com
Revision
2770
Date
2009-09-11 10:55:22 +0200 (fr, 11 sep 2009)

Copyright (c) 2008, Atmel Corporation All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. The name of ATMEL may not be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Definition in file sleepmgr.c.


Function Documentation

void SLEEPMGR_CancelSleep ( void   ) 

Cancel pending sleep attempt, e.g. when work is added from a device driver.

This function cancels a sleep attempt, if called from a handler that interrupted the SLEEPMGR_Sleep() function. This function has no effect if called from elsewhere. It is intended to be called from interrupt domain whenever an interrupt causes more work, which means that sleeping is not ok. Normally, this function will be called from within WORKQUEUE_AddWork() and SOFTIRQ_Raise(), which in turn are called from device driver ISRs.

Definition at line 196 of file sleepmgr.c.

References SLEEPMGR_DISABLE_SLEEP.

00197 {
00198         // Disable sleep, so that any SLEEP instruction will fail.
00199         SLEEPMGR_DISABLE_SLEEP();
00200 }

void SLEEPMGR_Init ( void   ) 

Initialize sleep manager. Call this before any other manager function.

This function initializes the sleep manager. The sleep manager must be initialized before any other modules can use it.

Definition at line 74 of file sleepmgr.c.

References SLEEPMGR_locks, and SLEEPMGR_NUM_MODES.

Referenced by ISR(), and main().

00075 {
00076         // Set all mode locks to zero, except the last one, which is handled below.
00077         for (uint8_t index = 0; index < (SLEEPMGR_NUM_MODES - 1); ++index) {
00078                 SLEEPMGR_locks[index] = 0;
00079         }
00080         
00081         // Lock the deepest sleep mode once and for all, to ease the search
00082         // implementation in SLEEPMGR_Sleep() later.
00083         SLEEPMGR_locks[SLEEPMGR_NUM_MODES - 1] = 1;
00084 }

void SLEEPMGR_Lock ( SLEEPMGR_mode_t  mode  ) 

Increase lock for a mode, i.e. you need at least this awareness.

This function increases the lock count for one particular sleep mode. This essentially tells the sleep manager that it should not enter deeper sleep modes than that.

It is ok to lock several modes from one module, and locking and unlocking need not be done in any particular order. However, it is important to unlock all modes previously locked.

If you want to change your requirements to a deeper sleep mode, it is not sufficient to just lock the deeper mode. You also need to unlock the shallower mode.

Parameters:
mode The sleep mode to lock.

Definition at line 102 of file sleepmgr.c.

References ENTER_CRITICAL_REGION, LEAVE_CRITICAL_REGION, and SLEEPMGR_locks.

Referenced by ISR(), and main().

00103 {
00104         // The following must be an atomic operation, to avoid race conditions.
00105         ENTER_CRITICAL_REGION();
00106         
00107                 // Check that lock has not reached max value for its datatype.
00108                 // By casting "-1L" to the correct datatype, we always get max value.
00109 //              assert( SLEEPMGR_locks[mode] != (SLEEPMGR_mode_t) -1L );
00110                 // Now it's safe to increase the lock counter.
00111                 ++SLEEPMGR_locks[mode];
00112         
00113         LEAVE_CRITICAL_REGION();
00114 }

void SLEEPMGR_Sleep ( void   ) 

Enter the deepest possible sleep mode possible with current lock state.

This function computes the deepest sleep mode possible and enters that. If interrupt handlers want to cancel the sleep attempt, it can only be canceled by called SLEEPMGR_CancelSleep().

Definition at line 152 of file sleepmgr.c.

References SLEEPMGR_DISABLE_SLEEP, SLEEPMGR_locks, and SLEEPMGR_PREPARE_SLEEP.

Referenced by main().

00153 {
00154         // The following must be an atomic operation, to avoid race conditions.
00155         // No need to save the interrupt state, as we must enable global interrupts
00156         // anyway to be able to wake up from sleep.
00157         cli();
00158         
00159         // Make sure the deepest sleep mode is actually locked, which should have
00160         // been done in SLEEPMGR_Init at least. This ensures that the search
00161         // below will succeed.
00162 //      assert( SLEEPMGR_locks[SLEEPMGR_NUM_MODES - 1] > 0 );
00163         
00164         // Search from shallowest sleep mode until a non-zero lock is found.
00165         SLEEPMGR_lock_t const * lockPtr = SLEEPMGR_locks;
00166         uint8_t PROGMEM_PTR_T modePtr = SLEEPMGR_modes;
00167         while (*lockPtr == 0) {
00168                 ++lockPtr;
00169                 ++modePtr;
00170         }
00171         
00172         // Prepare sleep configuration, not touching other fields in register.
00173         uint8_t modeConfig = PROGMEM_READ_BYTE( modePtr );
00174         SLEEPMGR_PREPARE_SLEEP( modeConfig );
00175 
00176         // Enable interrupts before sleeping, otherwise we won't wake up.
00177         sei();
00178 
00179         // Now, enter sleep mode. Any pending interrupts will cause the device
00180         // to instantaneously wake up.
00181         cpu_sleep();
00182         
00183         // After waking up, we disable sleep.
00184         SLEEPMGR_DISABLE_SLEEP();
00185 }

void SLEEPMGR_Unlock ( SLEEPMGR_mode_t  mode  ) 

Decrease lock for a mode, i.e. you no longer need this awareness.

This function decreases the lock count for one particular sleep mode. This essentially tells the sleep manager that you are ok with deeper sleep modes, as long as no more locks exist on this or shallower sleep modes.

It is ok to lock several modes from one module, and locking and unlocking need not be done in any particular order. However, it is important to unlock all modes previously locked.

If you want to change your requirements to a deeper sleep mode, it is not sufficient to just lock the deeper mode. You also need to unlock the shallower mode.

Parameters:
mode The sleep mode to unlock.

Definition at line 132 of file sleepmgr.c.

References ENTER_CRITICAL_REGION, LEAVE_CRITICAL_REGION, and SLEEPMGR_locks.

Referenced by ISR().

00133 {
00134         // The following must be an atomic operation, to avoid race conditions.
00135         ENTER_CRITICAL_REGION();
00136         
00137                 // Check that lock is not already zero,
00138                 // which would mean lock/unlock has not been handle correctly.
00139 //              assert( SLEEPMGR_locks[mode] != 0 );
00140                 // Now it's safe to decrease the lock counter.
00141                 --SLEEPMGR_locks[mode];
00142         
00143         LEAVE_CRITICAL_REGION();
00144 }


Variable Documentation

Definition at line 62 of file sleepmgr.c.

SLEEPMGR_lock_t SLEEPMGR_locks[SLEEPMGR_NUM_MODES]

Sleep mode lock counters.

Definition at line 64 of file sleepmgr.c.

Referenced by SLEEPMGR_Init(), SLEEPMGR_Lock(), SLEEPMGR_Sleep(), and SLEEPMGR_Unlock().

@DOC_TITLE@
Generated on Mon Nov 9 13:44:35 2009 for XMEGA power consumption evaluation code by doxygen 1.5.9