avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-libc-dev] [RFC] Patch to fix various sleep bugs.


From: E. Weddington
Subject: [avr-libc-dev] [RFC] Patch to fix various sleep bugs.
Date: Tue, 28 Dec 2004 17:33:51 -0700
User-agent: Mozilla Thunderbird 0.7.3 (Windows/20040803)

Hello!

Attached is a patch that I think will fix the following bugs regarding sleep.h:
#6352
#10489
#11425

It's a bit of a gory change. I would appreciate any looking over to see if I've missed anything before I commit.

Thanks
Eric
Index: include/avr/sleep.h
===================================================================
RCS file: /cvsroot/avr-libc/avr-libc/include/avr/sleep.h,v
retrieving revision 1.8
diff -u -r1.8 sleep.h
--- include/avr/sleep.h 2 Nov 2004 18:16:07 -0000       1.8
+++ include/avr/sleep.h 29 Dec 2004 00:31:52 -0000
@@ -1,4 +1,5 @@
-/* Copyright (c) 2002,2004 Theodore A. Roth
+/* Copyright (c) 2002, 2004 Theodore A. Roth
+   Copyright (c) 2004 Eric B. Weddington
    All rights reserved.
 
    Redistribution and use in source and binary forms, with or without
@@ -35,38 +36,63 @@
 
 #include <avr/io.h>
 
-/* Figure out which type of sleep mode the selected device uses (1, 2 or 3
-   bits) */
 
-#if defined(SM) && ! defined(SM0) && ! defined(SM1) && ! defined(SM2)
-#  define _SLEEP_TYPE 1
-#elif ! defined(SM) && defined(SM0) && defined(SM1) && ! defined(SM2)
-#  define _SLEEP_TYPE 2
-#elif ! defined(SM) && defined(SM0) && defined(SM1) && defined(SM2)
-#  define _SLEEP_TYPE 3
+
+/* Define internal sleep types for the various devices. */
+/* Also define some internal masks for use in set_sleep_mode() */
+#if defined(__AVR_ATmega161__)
+
+#define _SLEEP_TYPE 5
+
+#elif defined(__AVR_ATmega162__) || defined(__AVR_ATmega8515__)
+
+#define _SLEEP_TYPE 4
+
+#elif defined(SM) && !defined(SM0) && !defined(SM1) && !defined(SM2)
+
+#define _SLEEP_TYPE 1
+#define _SLEEP_MODE_MASK _BV(SM)
+
+#elif !defined(SM) && defined(SM0) && defined(SM1) && !defined(SM2)
+
+#define _SLEEP_TYPE 2
+#define _SLEEP_MODE_MASK (_BV(SM0) | _BV(SM1))
+
+#elif !defined(SM) && defined(SM0) && defined(SM1) && defined(SM2)
+
+#define _SLEEP_TYPE 3
+#define _SLEEP_MODE_MASK (_BV(SM0) | _BV(SM1) | _BV(SM2))
+
+#else
+
+#error "No SLEEP mode defined for this device."
+
+#endif
+
+
+
+/* Define the internal control register to use for sleep_mode(). */
+#if defined(SMCR)
+
+#define _SLEEP_CONTROL_REG SMCR
+
+#else
+
+#define _SLEEP_CONTROL_REG MCUCR
+
 #endif
 
+
+
 /** \defgroup avr_sleep Power Management and Sleep Modes
 
     \code #include <avr/sleep.h>\endcode
 
     Use of the \c SLEEP instruction can allow your application to reduce it's
     power comsumption considerably. AVR devices can be put into different
-    sleep modes by changing the \c SMn bits of the \c MCU Control Register (
-    \c MCUCR ). Refer to the datasheet for the details relating to the device
+    sleep modes. Refer to the datasheet for the details relating to the device
     you are using. */
 
-/* Mask of all the sleep mode bits. */
-
-#if _SLEEP_TYPE == 1
-#  define _SLEEP_MODE_MASK _BV(SM)
-#elif _SLEEP_TYPE == 2
-#  define _SLEEP_MODE_MASK (_BV(SM0) | _BV(SM1))
-#elif _SLEEP_TYPE == 3
-#  define _SLEEP_MODE_MASK (_BV(SM0) | _BV(SM1) | _BV(SM2))
-#else
-#  error "No SLEEP mode defined for device."
-#endif
 
 /** \name Sleep Modes
 
@@ -75,49 +101,69 @@
 
 /* @{ */
 
-/** \ingroup avr_sleep
-    \def SLEEP_MODE_IDLE
-    Idle mode. */
-#define SLEEP_MODE_IDLE         0
 
+/* Define the sleep modes according to the internal sleep types. */
 #if _SLEEP_TYPE == 1
+#define SLEEP_MODE_IDLE         0
+#define SLEEP_MODE_PWR_DOWN     _BV(SM)
+#endif
 
-#  define SLEEP_MODE_PWR_DOWN   _BV(SM)
-
-#elif _SLEEP_TYPE == 2
 
-#  define SLEEP_MODE_ADC        _BV(SM0)
-#  define SLEEP_MODE_PWR_DOWN   _BV(SM1)
-#  define SLEEP_MODE_PWR_SAVE   (_BV(SM0) | _BV(SM1))
+#if _SLEEP_TYPE == 2
+#define SLEEP_MODE_IDLE         0
+#define SLEEP_MODE_ADC          _BV(SM0)
+#define SLEEP_MODE_PWR_DOWN     _BV(SM1)
+#define SLEEP_MODE_PWR_SAVE     (_BV(SM0) | _BV(SM1))
+#endif
 
-#else /* _SLEEP_TYPE == 3 */
 
+#if _SLEEP_TYPE == 3
+/** \ingroup avr_sleep
+    \def SLEEP_MODE_IDLE
+    Idle mode. */
+#define SLEEP_MODE_IDLE         0
 /** \ingroup avr_sleep
     \def SLEEP_MODE_ADC
     ADC Noise Reduction Mode. */
 #define SLEEP_MODE_ADC          _BV(SM0)
-
 /** \ingroup avr_sleep
     \def SLEEP_MODE_PWR_DOWN
     Power Down Mode. */
 #define SLEEP_MODE_PWR_DOWN     _BV(SM1)
-
 /** \ingroup avr_sleep
     \def SLEEP_MODE_PWR_SAVE
     Power Save Mode. */
 #define SLEEP_MODE_PWR_SAVE     (_BV(SM0) | _BV(SM1))
-
 /** \ingroup avr_sleep
     \def SLEEP_MODE_STANDBY
     Standby Mode. */
 #define SLEEP_MODE_STANDBY      (_BV(SM1) | _BV(SM2))
-
 /** \ingroup avr_sleep
     \def SLEEP_MODE_EXT_STANDBY
     Extended Standby Mode. */
 #define SLEEP_MODE_EXT_STANDBY  (_BV(SM0) | _BV(SM1) | _BV(SM2))
+#endif
+
+
+#if _SLEEP_TYPE == 4
+#define SLEEP_MODE_IDLE         0
+#define SLEEP_MODE_PWR_DOWN     1
+#define SLEEP_MODE_PWR_SAVE     2
+#define SLEEP_MODE_ADC          3
+#define SLEEP_MODE_STANDBY      4
+#define SLEEP_MODE_EXT_STANDBY  5
+#endif
+
+
+#if _SLEEP_TYPE == 5
+#define SLEEP_MODE_IDLE         0
+#define SLEEP_MODE_PWR_DOWN     1
+#define SLEEP_MODE_PWR_SAVE     2
+#endif
+
+
+
 
-#endif /* _SLEEP_TYPE == 3 */
 
 /* @} */
 
@@ -127,37 +173,59 @@
 
 /** \ingroup avr_sleep 
 
-    Set the bits in the \c MCUCR to select a sleep mode. */
+    Select a sleep mode. */
 
 #if defined(DOXYGEN)
+
 extern void set_sleep_mode (uint8_t mode);
-#else
-# if defined (SMCR)
-#  define set_sleep_mode(mode) do { \
-       (SMCR = ((SMCR & ~_SLEEP_MODE_MASK) | (mode))) \
-} while (0)
-# else
-#  define set_sleep_mode(mode) do { \
-       (MCUCR = ((MCUCR & ~_SLEEP_MODE_MASK) | (mode))) \
-} while (0)
-# endif
+
+#elif _SLEEP_TYPE == 5
+
+#define set_sleep_mode(mode) \
+do { \
+    MCUCR = ((MCUCR & ~_BV(SM1)) | ((mode) == SLEEP_MODE_PWR_DOWN || (mode) == 
SLEEP_MODE_PWR_SAVE ? _BV(SM1) : 0)); \
+    EMCUCR = ((EMCUCR & ~_BV(SM0)) | ((mode) == SLEEP_MODE_PWR_SAVE ? _BV(SM0) 
: 0)); \
+} while(0)
+
+#elif _SLEEP_TYPE == 4
+
+#define set_sleep_mode(mode) \
+do { \
+    MCUCR = ((MCUCR & ~_BV(SM1)) | ((mode) == SLEEP_MODE_IDLE ? 0 : 
_BV(SM1))); \
+    MCUCSR = ((MCUCSR & ~_BV(SM2)) | ((mode) == SLEEP_MODE_STANDBY  || (mode) 
== SLEEP_MODE_EXT_STANDBY ? _BV(SM2) : 0)); \
+    EMCUCR = ((EMCUCR & ~_BV(SM0)) | ((mode) == SLEEP_MODE_PWR_SAVE || (mode) 
== SLEEP_MODE_EXT_STANDBY ? _BV(SM0) : 0)); \
+} while(0)
+
+#elif _SLEEP_TYPE == 3 || _SLEEP_TYPE == 2 || _SLEEP_TYPE == 1
+
+#define set_sleep_mode(mode) \
+do { \
+    _SLEEP_CONTROL_REG = ((_SLEEP_CONTROL_REG & ~_SLEEP_MODE_MASK) | (mode)); \
+} while(0)
+
 #endif
 
+
+
+
 /** \ingroup avr_sleep 
 
     Put the device in sleep mode. How the device is brought out of sleep mode
     depends on the specific mode selected with the set_sleep_mode() function.
     See the data sheet for your device for more details. */
-
 #if defined(DOXYGEN)
+
 extern void sleep_mode (void);
+
 #else
-#define sleep_mode() \
+
+#define sleep_mode()                           \
 do {                                           \
-    MCUCR |= _BV(SE);                          \
+    _SLEEP_CONTROL_REG |= _BV(SE);            \
     __asm__ __volatile__ ("sleep" "\n\t" :: ); \
-    MCUCR &= ~_BV(SE);                         \
+    _SLEEP_CONTROL_REG &= ~_BV(SE);           \
 } while (0)
+
 #endif
 
 /address@hidden/

reply via email to

[Prev in Thread] Current Thread [Next in Thread]