Pages: [1]   Go Down
Author Topic: Help me sleep :)  (Read 581 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 0
Posts: 158
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am working with an ATMEGA8 in a standalone application and need to get it into one of the different sleep modes.

I am trying not to use the avr/sleep.h library as I frankly don't understand what it is doing.  Plus, it is a good opportunity to learn the code and microcontroller better. 

In the code snippet below I am trying to put the part into ADC Noise Reduction mode:

Code:
MCUCR |= (1<<SE) | (1<<SM1);

In tutorials I have read, they mention a "sleep command".   However, in inspecting sleep.h in the avr library, I don't see any assembly code representing such a command so I am confused.   


Thanks for your time
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

From sleep.h:
Code:
#define sleep_enable()             \
do {                               \
  _SLEEP_CONTROL_REG |= (uint8_t)_SLEEP_ENABLE_MASK;   \
} while(0)
Code:
#if defined(SLEEP_CTRL)

    /* XMEGA devices */
    #define _SLEEP_CONTROL_REG  SLEEP_CTRL
    #define _SLEEP_ENABLE_MASK  SLEEP_SEN_bm

#elif defined(SMCR)

    #define _SLEEP_CONTROL_REG  SMCR
    #define _SLEEP_ENABLE_MASK  _BV(SE)

#elif defined(__AVR_AT94K__)

    #define _SLEEP_CONTROL_REG  MCUR
    #define _SLEEP_ENABLE_MASK  _BV(SE)

#else

    #define _SLEEP_CONTROL_REG  MCUCR
    #define _SLEEP_ENABLE_MASK  _BV(SE)

#endif

Can you be more specific about what your problem is?
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 158
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

From sleep.h:
Code:
#define sleep_enable()             \
do {                               \
  _SLEEP_CONTROL_REG |= (uint8_t)_SLEEP_ENABLE_MASK;   \
} while(0)
Code:
#if defined(SLEEP_CTRL)

    /* XMEGA devices */
    #define _SLEEP_CONTROL_REG  SLEEP_CTRL
    #define _SLEEP_ENABLE_MASK  SLEEP_SEN_bm

#elif defined(SMCR)

    #define _SLEEP_CONTROL_REG  SMCR
    #define _SLEEP_ENABLE_MASK  _BV(SE)

#elif defined(__AVR_AT94K__)

    #define _SLEEP_CONTROL_REG  MCUR
    #define _SLEEP_ENABLE_MASK  _BV(SE)

#else

    #define _SLEEP_CONTROL_REG  MCUCR
    #define _SLEEP_ENABLE_MASK  _BV(SE)

#endif

Can you be more specific about what your problem is?

My apologies for the lack of detail.  My problem is, when I execute the following code to go into powerdown mode:

Code:
MCUCR = ((MCUCR & ~(_BV(SM0) | _BV(SM1) | _BV(SM2))) | _BV(SM1));
MCUCR |= (uint8_t)_BV(SE);

I don't see any change in behavior in my program.  In otherwords, it does not behave as if it actually is in powderdown mode as it is still performing ADC conversions, responding to inputs, etc.

Logged

Offline Offline
God Member
*****
Karma: 19
Posts: 785
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I apologize for derailing this a little, but why is that code put into a do{} while(0) loop.  That looks really odd to me and I'm sure there's a real good reason why it's done there.  Isn't that the same as just executing the line of code once?  Or is that just to add one more instruction (the comparison) so it doesn't return before it falls asleep?
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I apologize for derailing this a little, but why is that code put into a do{} while(0) loop.  That looks really odd to me and I'm sure there's a real good reason why it's done there.  Isn't that the same as just executing the line of code once?  Or is that just to add one more instruction (the comparison) so it doesn't return before it falls asleep?
It's a "standard" convention to do that in macros so that it behaves as much like a function as possible. Without the do{}while(0), you could get errors like:
Code:
#define bar(x) y = x; y++;
if (foo) bar(3);
which would unconditionally execute y++, and if you do
Code:
#define bar(x) {y = x; y++;}
if (foo) bar(3);
then this would be legal:
Code:
#define bar(x) {y = x; y++;}
if (foo) bar(3)
... etc. All to get around the overhead of a function call that would be optimized out anyway.

Anyway, I'm no expert in sleeping and I can't spend the time to look up the registers. However, remember that the chip will wake up whenever there's an interrupt, and if you keep timer0 enabled, there's an interrupt every 1ms to update the millia() timer. You also have to think about what you want to take up the chip, and if that's getting triggered prematurely.
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 158
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I apologize for derailing this a little, but why is that code put into a do{} while(0) loop.  That looks really odd to me and I'm sure there's a real good reason why it's done there.  Isn't that the same as just executing the line of code once?  Or is that just to add one more instruction (the comparison) so it doesn't return before it falls asleep?
It's a "standard" convention to do that in macros so that it behaves as much like a function as possible. Without the do{}while(0), you could get errors like:
Code:
#define bar(x) y = x; y++;
if (foo) bar(3);
which would unconditionally execute y++, and if you do
Code:
#define bar(x) {y = x; y++;}
if (foo) bar(3);
then this would be legal:
Code:
#define bar(x) {y = x; y++;}
if (foo) bar(3)
... etc. All to get around the overhead of a function call that would be optimized out anyway.

Anyway, I'm no expert in sleeping and I can't spend the time to look up the registers. However, remember that the chip will wake up whenever there's an interrupt, and if you keep timer0 enabled, there's an interrupt every 1ms to update the millia() timer. You also have to think about what you want to take up the chip, and if that's getting triggered prematurely.

Ahh, I didn't realize the chip wakes on an interrupt.  That may explain what is occurring.

Thanks!
Logged

Pages: [1]   Go Up
Jump to: