Atmega48 wacht nicht durch INT1 auf (sleep_mode(), interrupt)

Gast #4217389
Lesenswert?

Folgender Code geht erwartungsgemäß in den Power-Down Modus, lässt sich 
dann aber durch einen low-Pegel an PD3 nicht mehr "wecken".
1
#include <stdint.h>
2
#include <avr/io.h>
3
#include <avr/wdt.h>
4
#include <avr/sleep.h>
5
#include <avr/interrupt.h>
6

7
int main(void)
8
{
9
  wdt_disable();
10
  ACSR = (1<<ACD);
11
  PORTD = 0xFF; 
12
  DDRD  = 0xFF; 
13
  TCCR0A =   0;
14
  TCCR0B = (1<<CS01);
15
  OCR0A  =  124;
16
  TIMSK0 = (1<<OCIE0A);
17
  TCCR1A =   0;
18
  TCCR1B =  (1<<CS12) | (1<<CS10);
19
  OCR0A  =   65535;
20
  TIMSK1 = (1<<OCIE1A);
21
  LEDpattern = 0;
22
  sei();
23
  while(1)
24
  {
25
    LEDpattern++;
26
    set_sleep_mode(SLEEP_MODE_IDLE);
27
    sleep_mode();
28
  }
29
}
30

31
ISR( TIMER0_COMPA_vect ) 
32
{
33
  OCR1A += 124;
34
  PORTD = LEDpattern;
35
}
36

37
ISR( TIMER1_COMPA_vect ) 
38
{
39
  PORTD  = 0xFF;
40
  DDRD  &= ~(1<<PD3);
41
  EICRA = 0;
42
  EIFR = 0;
43
  EIMSK = (1<<INT1);
44
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
45
  sleep_mode();
46
}
47

48
ISR( INT1_vect ) 
49
{
50
  EIMSK = 0;
51
  DDRD  |= (1<<PD3);
52
  PORTD  = 0x00;
53
}

Es ist vermutlich der Aufruf von sleep_mode() im interrupt - wieso?

http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html
http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf
Gast #4217415
Lesenswert?

Denis schrieb:
> was als erstes, beim Anspringen der Interrupt routine
> passiert,

Meinst du einen spezifischen? In beiden schalte ich den Interrupt aus, 
den Pin um, und den anderen Interrupt ein. Wo genau ist das Problem?

Jetzt N. schrieb:
> Aaaaahhhhhhh....
>
> ein sleep() in einem timer interrupt ....

Genau das ist die Frage: ist das das Problem, und wieso? Du musst es mir 
ja nicht erklären, aber hilfreicher wäre ein Verweis!
Gast #4217432
Lesenswert?

Aha, danke! Schon lange nichts mehr mit AVR gemacht (Gruß in den 
Wedding).
1
7.7 Reset and Interrupt Handling
2
...
3
When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The user 
4
software can write logic one to the I-bit to enable nested interrupts. All enabled interrupts can then interrupt the 
5
current interrupt routine. The I-bit is automatically set when a Return from Interrupt instruction – RETI – is 
6
executed. 
7

8
...
9

10
if one or more interrupt conditions occur while the Global 
11
Interrupt Enable bit is cleared, the corresponding Interrupt Flag(s) will be set and remembered until the Global 
12
Interrupt Enable bit is set, and will then be executed by order of priority. 
13

14
..
15

16
When the AVR exits from an interrupt, it will always return to the main program and execute one more 
17
instruction before any pending interrupt is served.
#4217465
Lesenswert?

Du kannst ja nur das "set_sleep_mode(SLEEP_MODE_PWR_DOWN);" im Interrupt 
lassen, darfst es dann aber in der Mainloop nicht sofort wieder 
rücksetzen.

Das "sleep_mode();" sollte man generell nicht verwenden, es bewirkt eine 
Race Condition (siehe Erläuterung in <sleep.h>).
Gast #4217646
Lesenswert?

OK, danke.

Habe zwischenzeitlich die set_sleep_mode() in die jeweiligen ISRs 
gesetzt und in der Endlosschleife (noch) das sleep_mode().

1
    As the \c sleep_mode() macro might cause race conditions in some
2
    situations, the individual steps of manipulating the sleep enable
3
    (SE) bit, and actually issuing the \c SLEEP instruction, are provided
4
    in the macros \c sleep_enable(), \c sleep_disable(), and
5
    \c sleep_cpu().  This also allows for test-and-sleep scenarios that
6
    take care of not missing the interrupt that will awake the device
7
    from sleep.
8

9
    Example:
10
    \code
11
    #include <avr/interrupt.h>
12
    #include <avr/sleep.h>
13

14
    ...
15
      set_sleep_mode(<mode>);
16
      cli();
17
      if (some_condition)
18
      {
19
        sleep_enable();
20
        sei();
21
        sleep_cpu();
22
        sleep_disable();
23
      }
24
      sei();
25
    \endcode
26

27
    This sequence ensures an atomic test of \c some_condition with
28
    interrupts being disabled.  If the condition is met, sleep mode
29
    will be prepared, and the \c SLEEP instruction will be scheduled
30
    immediately after an \c SEI instruction.  As the intruction right
31
    after the \c SEI is guaranteed to be executed before an interrupt
32
    could trigger, it is sure the device will really be put to sleep.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren