ATmega resettet dauernd

OP #3601454
Lesenswert?

Morgen,

ich hab mal wieder mein Pollin-Board rausgekramt um ein wenig zu 
"spielen".
Dabei will ich mich mal bei IRMP + ENC28J60 versuchen.
Ich hab nun ein seltsames Verhalten, dass sich anscheinend der µC 
dauernd resettet. Ich hab mal ein Beispielcode geschrieben, womit das 
reproduzierbar ist. Das schnelle Blinken was am Anfang ist, macht er 
dauernd und das langsame Blinken in der Schleife macht er garnicht, da 
bleibt konstant die LED an. Achja es ist ein ATmega16 @ 16Mhz. 
Wahrscheinlich seh ich wieder den Wald vor lauter Bäumen nicht.
1
#ifndef F_CPU
2
    #define F_CPU 16000000UL
3
#endif
4

5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <avr/pgmspace.h>
8
#include <util/delay.h>
9
#include <stdlib.h>
10
#include <stdio.h>
11
#include "uart.h"
12
#include "irmpconfig.h"
13
#include "irmp.h"
14

15
#define BAUD 19200UL
16

17
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
18
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
19
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
20

21
#define US (1000000 / F_INTERRUPTS)
22

23

24
void timer1_init(void);
25

26
static int UARTsendstream(char c, FILE *stream);
27

28
static FILE uart_str = FDEV_SETUP_STREAM(UARTsendstream, NULL, _FDEV_SETUP_WRITE);
29

30

31
int main(void){
32
    IRMP_DATA irmp_data;
33

34
    uart_init(UART_BAUD_SELECT(BAUD, F_CPU));
35
    stdout = &uart_str;
36

37
    DDRD |= (1 << PD5)|(1 << PD6);
38

39
    PORTD |= (1 << PD5);
40
    _delay_ms(400);
41
    PORTD &= ~(1 << PD5);
42
    _delay_ms(200);
43
    PORTD |= (1 << PD5);
44
    _delay_ms(400);
45
    PORTD &= ~(1 << PD5);
46
    _delay_ms(1000);
47

48
    irmp_init();
49
    timer1_init();
50
    sei();
51

52
    while(1){
53
        PORTD |= (1 << PD6);
54
        _delay_ms(500);
55
        PORTD &= ~(1 << PD6);
56
        _delay_ms(500);
57
    }
58
}
59

60
void timer1_init(void){
61
    OCR1A = (F_CPU / F_INTERRUPTS) - 1;
62
    TCCR1B = (1 << WGM12)|(1 << CS10);
63

64
    TIMSK = 1 << OCIE1A;
65
}
66

67
static int UARTsendstream(char c , FILE *stream){
68
    uart_putc(c);
69
    return 0;
70
}
71

72
ISR(TIMER1_COMPA_vect){
73
    (void) irmp_ISR();
74
}
Gast #3601461
Lesenswert?

Kommentier diese Zeilen mal aus:

    irmp_init();
    (void) irmp_ISR();

Wenn es dann geht, liegt der Fehler im Code dieser Library bzw. 
irgendwelche Voraussetzungen sind nicht erfüllt, die sie zum 
Funktionieren benötigt.
Gast #3601537
Lesenswert?

Hi

>Wo kann man denn den Watchdog ausschalten?

Hast du den denn eingeschaltet?

>Wenn ich
>timer1_init();
>und
>sei();
>auskommentiere, funktioniert es.

Dann hat es auch nichts mit dem WD zu tun.

MfG Spess
Moderator Persönliche Seite #3601548
Lesenswert?

Mathias O. schrieb:
> Also es ist -mmcu=atmega16, somit stimmt das.
>
> Wo kann man denn den Watchdog ausschalten?

Ein ähnliches Problem hatte mal einer mit ATmega16 und STK500.

Schau mal hier:

  Beitrag "ATMega16: Interrupt mit Timer1"

Da war's jedenfalls der Watchdog, Lösung steht am Ende des (kurzen) 
Threads auch dabei.

Was mich aber wundert: Sobald Du timer1_init() und sei() rausnimmst, 
funktioniert es? Dann müsste es auch gehen, wenn Du nur sei() 
rausnimmst. Kannst Du das mal testen?

Bekommst Du beim Übersetzen irgendwelche Compiler-Warnungen?

Der Code ist ja nicht vollständig, es fehlen ja noch die uart-Routinen. 
Benutzen diese vielleicht Interrupts - eingeschaltet durch uart_init() - 
mit falschem Interrupt-Vektor? Dann solltest Du aber eine Warnung vom 
Compiler erhalten.
Gast #3601616
Lesenswert?

Oliver S. schrieb:
> Mathias O. schrieb:
>> Warum sollte auch die Lib ausgerechnet bei mir
>> nicht funktionieren. Bei Anderen läuft sie ja.
>
> Na ja, das könnte man jetzt kommentieren...
>
> Egal, häng halt mal eine kompletten kompilierbaren Code hier an.
>
> Oliver

Wenn es einfach funktionieren soll, dann füg das in den Code ein:
ISR(BADISR_vect) { }

und es wird funktionieren.

Es wird irgendein Interrupt ausgelöst bei dem keine ISR definiert ist, 
dann springt das Programm jedesmal an den Anfang wenn das entsprechende 
Interrupt ausgelöst wird.
OP #3601650
Lesenswert?

So hier ist mal ein kompilierbarer Code.
1
#ifndef F_CPU
2
    #define F_CPU 16000000UL
3
#endif
4

5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <util/delay.h>
8
#include "irmpconfig.h"
9
#include "irmp.h"
10

11

12
void timer1_init(void);
13

14
int main(void){
15
    DDRD |= (1 << PD5)|(1 << PD6);
16

17
    PORTD |= (1 << PD5);
18
    _delay_ms(400);
19
    PORTD &= ~(1 << PD5);
20
    _delay_ms(200);
21
    PORTD |= (1 << PD5);
22
    _delay_ms(400);
23
    PORTD &= ~(1 << PD5);
24
    _delay_ms(1000);
25

26
    timer1_init();
27
    sei();
28

29
    while(1){
30
        PORTD |= (1 << PD6);
31
        _delay_ms(500);
32
        PORTD &= ~(1 << PD6);
33
        _delay_ms(500);
34
    }
35
}
36

37
void timer1_init(void){
38
    OCR1A = (F_CPU / F_INTERRUPTS) - 1;
39
    TCCR1B = (1 << WGM12)|(1 << CS10);
40

41
    TIMSK = 1 << OCIE1A;
42
}
43

44
ISR(TIMER1_COMPA_vect){
45
    (void) irmp_ISR();
46
}
Angehängte Dateien:
Moderator Persönliche Seite #3601687
Lesenswert?

1
> #ifndef F_CPU
2
>     #define F_CPU 16000000UL
3
> #endif

Das ist schon mal Käse. Damit kannst Du nicht gewährleisten, dass die 
anderen Module (uart, irmp) mit der gleichen F_CPU compiliert werden.

Setz dies als Compiler-Option im Makefile oder Projekt für alle 
C-Dateien.
1
> #include "irmpconfig.h"
2
> #include "irmp.h"

Du benutzt hier einen 2 Jahre alten IRMP. Hole Dir bitte die aktuelle 
Version, siehe IRMP. Bei aktuellen Versionen darfst Du auch nur noch 
irmp.h "includieren".

Woran erkennst Du eigentlich, dass der ATmega resettet wird? Fängt er 
(wie am Anfang) an zu blinken?

Folgende Fragen hast Du vergessen, zu beantworten:

Reicht auch das Auskommentieren von sei() alleine, damit der ATmege 
läuft?

Funktioniert das Programm mit
1
ISR(BADISR_vect)
2
{
3
}

auch bei eingeschaltetem sei()?


P.S.
Du schriebst, dass der Fehler auch ohne Aufruf von irmp_init() und 
irmp_ISR() auftritt.

Dann hast Du aber nicht das minimalste Programm gepostet. Das wäre 
nämlich ohne die beiden Aufrufe und ohne die irmp-Includes und ohne 
irmp-Source-Dateien gewesen. Teste das bitte nochmal.
OP #3601730
Lesenswert?

Minimalistisch sieht es so aus.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
//#include "irmp.h"
5

6
#ifndef F_CPU
7
#error F_CPU unkown
8
#endif
9

10
#define F_INTERRUPTS 15000
11

12
void timer1_init(void);
13

14
int main(void){
15
    DDRD |= (1 << PD5)|(1 << PD6);
16

17
    PORTD |= (1 << PD5);
18
    _delay_ms(400);
19
    PORTD &= ~(1 << PD5);
20
    _delay_ms(200);
21
    PORTD |= (1 << PD5);
22
    _delay_ms(400);
23
    PORTD &= ~(1 << PD5);
24
    _delay_ms(1000);
25

26
    //IRMP_DATA irmp_data;
27

28
    //irmp_init();
29
    timer1_init();
30
    sei();
31

32
    while(1){
33
        PORTD |= (1 << PD6);
34
        _delay_ms(500);
35
        PORTD &= ~(1 << PD6);
36
        _delay_ms(500);
37
    }
38
}
39

40
void timer1_init(void){
41
    OCR1A = (F_CPU / F_INTERRUPTS) - 1;
42
    TCCR1B = (1 << WGM12)|(1 << CS10);
43

44
    TIMSK = 1 << OCIE1A;
45
}
46

47
ISR(TIMER1_COMPA_vect){
48
    //(void) irmp_ISR();
49
}
Funktioniert auch nicht.
Wenn ich sei(); auskommentiere funktioniert es.

Das resetten merke ich daran, dass er das schnelle Blinken vom Anfang 
(PD5) macht.

Das
1
ISR(BADISR_vect)
2
{
3
}
ändert auch nix.
OP #3601807
Lesenswert?

Na toll. Hab es jetzt geschafft. In Code::Blocks gibt man den mmcu in 
den Buildoptions an. Ich hab ihn allgemein beim Projekt angegeben, dann 
kann man ihn aber auch noch angeben bei debug und release. Ich hab ihn 
jetzt mal release auch noch angegeben, sowie F_CPU.
Und siehe da es funktioniert.
Der Output sieht nun so aus.
1
avr-gcc.exe -mmcu=atmega16 -DF_CPU=16000000UL  -mmcu=atmega16 -Os -DF_CPU=16000000UL     -c main.c -o obj\Release\main.o

Danke nochmal an alle für die Hilfe. Ich kam mir echt schon bescheuert 
vor.
Wenn es ne Kaffekasse geben würde, würde ich da jetzt was reinschmeissen 
;)
OP #3602947
Lesenswert?

Guten Morge,

so langsam fühle ich mich echt verarscht. Ich wollte jetzt den UART 
ansprechen und wollte die Lib von Fleury verwenden. Sobald ich wieder 
sei(); drin habe, macht er nur das Blinken vom Anfang und geht nicht in 
die Schleife rein.
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/pgmspace.h>
5
#include <util/delay.h>
6

7
#include "uart.h"
8

9
#define UART_BAUD_RATE 9600UL
10

11

12
int main(void){
13
    DDRD |= (1 << PD5)|(1 << PD6);
14

15
    PORTD |= (1 << PD5);
16
    _delay_ms(100);
17
    PORTD &= ~(1 << PD5);
18
    _delay_ms(300);
19
    PORTD |= (1 << PD5);
20
    _delay_ms(100);
21
    PORTD &= ~(1 << PD5);
22
    _delay_ms(300);
23
    PORTD |= (1 << PD5);
24
    _delay_ms(100);
25
    PORTD &= ~(1 << PD5);
26
    _delay_ms(800);
27

28
    uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));
29

30
    sei();
31

32
    uart_puts_P("Hallo\n");
33

34
    while(1){
35
        uart_puts_P("Test\n");
36
        PORTD |= (1 << PD6);
37
        _delay_ms(500);
38
        PORTD &= ~(1 << PD6);
39
        _delay_ms(500);
40
    }
41
}
Ich frage mich warum das so ein Krampf ist. Als ich das zuletzt vor 
Monaten mit einem mega8 gemacht habe funktionierte alles.
Ich hab jetzt auch nochmal einen anderen mega16 genommen, aber der zeigt 
das selbe Verhalten.
Ich bin echt ratlos.
Gast #3603050
Lesenswert?

Mathias O. schrieb:
> würde es doch auch nicht im richtigen Takt blinken oder?

Auch richtig. Kannst Du den Code simulieren und die Register 
untersuchen? So wie jetzt stocherst Du im Nebel.

In der uart.c der Fleury Lib sind conditional defines drin, um auf die 
verschiedenen µCs anzupassen. Wenn da das Symbol des Prozessors (s.o.) 
nicht klar ist, könnt's zu Problemen kommen.

Da sollten aber Meldungen vom Compiler kommen, was steht in der Ausgabe?
OP #3603060
Lesenswert?

lmao schrieb:
> Mathias O. schrieb:
>> Guten Morge,
>>
>> so langsam fühle ich mich echt verarscht.
>
> Das Problem sitzt meist vorm Rechner
Soweit bin ich auch schon gekommen.


Ausgabe sieht so aus:
1
-------------- Build: Release in IRMP (compiler: GNU AVR GCC Compiler)---------------
2

3
avr-gcc.exe  -mmcu=atmega16 -Os -DF_CPU=16000000UL     -c main.c -o obj\Release\main.o
4
avr-gcc.exe  -mmcu=atmega16 -Os -DF_CPU=16000000UL     -c uart.c -o obj\Release\uart.o
5
avr-g++.exe -LD:\opencv\build\x86\mingw\lib  -o bin\Release\IRMP.elf obj\Release\main.o obj\Release\uart.o   -Wl,-Map=bin\Release\IRMP.map,--cref  
6
Output size is 2.98 KB
7
Running project post-build steps
8
cmd /c "avr-objdump -h -S bin\Release\IRMP.elf > bin\Release\IRMP.lss"
9
avr-objcopy -R .eeprom -R .fuse -R .lock -R .signature -O ihex bin\Release\IRMP.elf bin\Release\IRMP.hex
10
avr-objcopy --no-change-warnings -j .eeprom --change-section-lma .eeprom=0 -O ihex bin\Release\IRMP.elf bin\Release\IRMP.eep
11
avr-objcopy --no-change-warnings -j .lock --change-section-lma .lock=0 -O ihex bin\Release\IRMP.elf bin\Release\IRMP.lock
12
avr-objcopy --no-change-warnings -j .signature --change-section-lma .signature=0 -O ihex bin\Release\IRMP.elf bin\Release\IRMP.sig
13
avr-objcopy --no-change-warnings -j .fuse --change-section-lma .fuse=0 -O ihex bin\Release\IRMP.elf bin\Release\IRMP.fuse
14
srec_cat bin\Release\IRMP.fuse -Intel -crop 0x00 0x01 -offset  0x00 -O bin\Release\IRMP.lfs -Intel
15
srec_cat: bin\Release\IRMP.fuse: 1: file contains no data
16
Process terminated with status 1 (0 minutes, 0 seconds)
17
0 errors, 0 warnings (0 minutes, 0 seconds)
#3603067
Lesenswert?

Mathias O. schrieb:
> avr-gcc.exe  -mmcu=atmega16 -Os -DF_CPU=16000000UL     -c main.c -o
> obj\Release\main.o
> avr-gcc.exe  -mmcu=atmega16 -Os -DF_CPU=16000000UL     -c uart.c -o
> obj\Release\uart.o
> avr-g++.exe -LD:\opencv\build\x86\mingw\lib  -o bin\Release\IRMP.elf
> obj\Release\main.o obj\Release\uart.o
> -Wl,-Map=bin\Release\IRMP.map,--cref

Für einen avr ist der Lib-Pfad völlig unsinnig, dafür fehlen da ein paar 
der sonst üblichen Optionen. Bist du sicher, daß deine IDE auch 
tatasächlich AVR-Programme erezugen kann, und dafür richtig eingestellt 
ist?

Lass dir mal mit MFile ein makefile erezugen, und compiler damit. Oder 
pack deine Sourcen ins AVR-Studio, und lass das mal kompilieren.

Oliver
OP #3603085
Lesenswert?

Habs es entfernt. Hab nun
1
-------------- Build: Release in IRMP (compiler: GNU AVR GCC Compiler)---------------
2

3
avr-gcc.exe  -mmcu=atmega16 -Os -DF_CPU=16000000UL     -c main.c -o obj\Release\main.o
4
avr-gcc.exe  -mmcu=atmega16 -Os -DF_CPU=16000000UL     -c uart.c -o obj\Release\uart.o
5
avr-g++.exe  -o bin\Release\IRMP.elf obj\Release\main.o obj\Release\uart.o   -Wl,-Map=bin\Release\IRMP.map,--cref  
6
Output size is 2.78 KB
7
Running project post-build steps
8
cmd /c "avr-objdump -h -S bin\Release\IRMP.elf > bin\Release\IRMP.lss"
9
avr-objcopy -R .eeprom -R .fuse -R .lock -R .signature -O ihex bin\Release\IRMP.elf bin\Release\IRMP.hex
10
avr-objcopy --no-change-warnings -j .eeprom --change-section-lma .eeprom=0 -O ihex bin\Release\IRMP.elf bin\Release\IRMP.eep
11
avr-objcopy --no-change-warnings -j .lock --change-section-lma .lock=0 -O ihex bin\Release\IRMP.elf bin\Release\IRMP.lock
12
avr-objcopy --no-change-warnings -j .signature --change-section-lma .signature=0 -O ihex bin\Release\IRMP.elf bin\Release\IRMP.sig
13
avr-objcopy --no-change-warnings -j .fuse --change-section-lma .fuse=0 -O ihex bin\Release\IRMP.elf bin\Release\IRMP.fuse
14
srec_cat bin\Release\IRMP.fuse -Intel -crop 0x00 0x01 -offset  0x00 -O bin\Release\IRMP.lfs -Intel
15
srec_cat: bin\Release\IRMP.fuse: 1: file contains no data
16
Process terminated with status 1 (0 minutes, 0 seconds)
17
0 errors, 0 warnings (0 minutes, 0 seconds)
Wenn er keine AVR-Programme erzeugen würde, warum blinkt dann die Led 
wie im Programm vorgegeben?
Irgendwas scheint mit dem Interrupt im UART nicht zu funktionieren.

Wenn ich statt
1
void uart_putc(unsigned char data)
2
{
3
    unsigned char tmphead;
4

5

6
    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
7

8
    while ( tmphead == UART_TxTail ){
9
        ;/* wait for free space in buffer */
10
    }
11

12
    UART_TxBuf[tmphead] = data;
13
    UART_TxHead = tmphead;
14

15
    /* enable UDRE interrupt */
16
    UART0_CONTROL    |= _BV(UART0_UDRIE);
17

18
}/* uart_putc */
das so verwende
1
void uart_putc(unsigned char data)
2
{
3
    while
4
    (!(UCSRA & (1<<UDRE)))
5
    {
6
    }
7
    UDR = data;
8

9
}/* uart_putc */
funktioniert es.
Moderator Persönliche Seite #3603246
Lesenswert?

Mathias O. schrieb:
>     UART0_CONTROL    |= _BV(UART0_UDRIE);

Das sieht so aus, als ob der Interrupt zu UART0_UDRIE nicht passt. Der 
müsste eigentlich so aussehen:

ISR(USART_UDRE_vect)
{
  ....
}

Aber: Wenn er denn wirklich falsch wäre, dann müsste der Compiler auch 
eine Warnung ausgeben, dass der Interrupt-Handler-Name falsch wäre (so 
ähnlich jedenfalls). Ausserdem glaube ich nicht, dass ein derartiger 
Schnitzer im Fleury-Source ist.

Sehr merkwürdig das ganze.
Gast #3603355
Lesenswert?

Frank M. schrieb:
> Die ersten paar Zeilen aus der lss-Datei (Interrupt-Vektor-Tabelle)
> wären lesbarer und deshalb interessanter ;-)

Die Tabelle seh' ich auch so und die ist Murks, da stehen an den 
Vektoren RJMPs statt JMPs drin, der letzte Teil der IVT ist Müll. Der 
Stackpointer wird auf 0x025F initialisiert, müsste beim ATM16 auf 0x045F 
sein. Da stimmt das Target nicht.
#3603438
Lesenswert?

?
1
avr-gcc.exe  -mmcu=atmega16 -Os -DF_CPU=16000000UL     -c main.c -o obj\Release\main.o
2
avr-gcc.exe  -mmcu=atmega16 -Os -DF_CPU=16000000UL     -c uart.c -o obj\Release\uart.o
3
avr-g++.exe -LD:\opencv\build\x86\mingw\lib  -o bin\Release\IRMP.elf obj\Release\main.o obj\Release\uart.o   -Wl,-Map=bin\Release\IRMP.map,--cref

einmal avr-gcc und dann avr-g++ ?
Auch fehlt mir in der Linker Anweisung die Angabe vom Mega16

Poste doch mal dein makefile. Da scheint ein ordentlicher Wurm drinnen 
zu sein.
Gast #3603477
Lesenswert?

Mathias O. schrieb:
> Ich arbeite mit Code::Blocks.

Das hab' ich gelesen, kenn' mich mit Codeblocks aber nicht aus.

Vielleicht compilierst Du auch etwas anderes, als dass Du auf den µC 
brennst, vergleich' dich mal die Erstellungs-/Änderungszeiten der 
beteiligten Dateien. Im Hex-Code werden Befehle ausgeführt, die nicht im 
C-Code wie oben zu finden sind:
1
in  r24,p11
2
ori  r24,k60
3
out  p11,r24 --> DDRD |= (1 << PD5)|(1 << PD6);
4

5
cbi  p11,b3 --> ? (löscht Bit3 in DDRD)
6

7
sbi  p12,b5 --> PORTD |= (1 << PD5);
8

9
ldi  r24,kFF
10
ldi  r25,kE1
11
ldi  r26,k04
12
L002E:
13
subi  r24,k01
14
sbci  r25,k00
15
sbci  r26,k00
16
brne  L002E --> _delay_ms(100);
#3603735
Lesenswert?

Mathias O. schrieb:
> Super endlich. Hab in den Linker settings noch -mmcu=atmega16 angegeben
> und nun funktioniert es endlich richtig alles.

Das hättest du schon gestern haben können. :-)

Konrad S. schrieb im Beitrag #3601753:
> Oder evtl. unterschiedliche µCs für Kompilieren und Linken angegeben?

Konrad S. schrieb im Beitrag #3602476:
> Es wäre noch interessant zu wissen, wie die Aufrufe vorher aussahen,
> einmal beim Kompilieren von main.c und einmal beim Linken des Programms.

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