ATMega328p & GCC: Watchdog-Problem

Gast #4530631
Lesenswert?
• ▲
▼
In intWDT() wird der Watchdog initialisiert. Er soll alle 8 Sekunden 
(Flags:WDP0, WDP3 einen Interrupt auslösen.

Ausgelöst wird der Interrupt jedoch alle 16 ms.

Wo liegt der Fehler?

1
#include <avr/sleep.h>
2
#include <avr/wdt.h>
3
#include <util/delay.h>
4
#include <avr/io.h>
5
#include <util/atomic.h>
6

7
ISR  (WDT_vect, ISR_NAKED)
8
{
9
  PORTD |= (1 << PORTD5);
10
  _delay_ms(10);
11
  PORTD &= ~(1 << PORTD5);
12

13
  reti();
14
}
15

16
void intWDT(void)
17
{
18
  cli();
19
  wdt_reset() ;
20
  WDTCSR = (1 << WDCE) | (1 << WDIE);
21
  WDTCSR = (1 << WDIE) | (1 << WDP3) | (1 << WDP0);
22
  sei();
23
}
24

25
int main(void)
26
{
27
  DDRD = (1 << PORTD5);
28

29
  intWDT();
30

31
  while (1)
32
  {
33
  }
34
  
35
  return (0);
36
}
Gast #4530835
Lesenswert?
• ▲
▼
Nun,

dies macht man auch nicht in einer ISR!
1
ISR  (WDT_vect, ISR_NAKED)
2
{
3
  PORTD |= (1 << PORTD5);
4
  _delay_ms(10);
5
  PORTD &= ~(1 << PORTD5);
6

7
  reti();
8
}

Setze ein (Event-)Flag und arbeite es in der Mainloop ab.
Gast #4530846
Lesenswert?
• ▲
▼
Karl M. schrieb:
> dies macht man auch nicht in einer ISR!

Zum Testen ist das wurscht, ich würde mir eher Gedanken machen, ob das 
reti() dem Compiler bei der Restaurierung der Register in die Suppe 
spuckt und für Stacküberlauf sorgt, weil die Register nicht mehr vom 
Stack gePOPpt werden.

Das sollte raus, vom Compiler wird in einer ISR das RETI nach dem 
{}-Block automatisch erzeugt.
Gast #4530908
Lesenswert?
• ▲
▼
Bei ISR_NAKED werden keinerlei Register gesichert. Wenn irgendwann in 
Deinem main() mal richtiger Cde steht, wirst Du so merkwürdige Fehler 
bekommen.

bdw.:
Warum ein paar ns durch ISR_NAKED sparen und danach _delay_ms(10) 
aufrufen???

Gruß, Stefan

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