Forum: Mikrocontroller und Digitale Elektronik Probleme nach Watchdog Reset


von Philipp M. (lord-maricek)


Lesenswert?

Moin,

ich habe einen Atmega644p, mit einem Wi232 und GPS Modul an den Uarts, 
ein Kompass Modul und einen Arduino an der I2C Schnittstelle.
Ich habe einen Watchdog am laufen, den ich teilweise auch bewusst 
auslöse. Aber wenn der Controller neu startet, stürzt er immer ab und 
startet wieder neu und das bleibt auch so. Das gleiche passiert auch, 
wenn er nach dem Flashen neu startet. Er startet nur normal, wenn ich 
den die Spannung abnehmen und dann wieder anlege.
Hier ist die Main datei
1
#include "define.h"
2
#include "types.h"
3
#include "global.h"
4
5
#include "M_AVR_PROC/M_AVR_PROC.h"
6
#include "M_STEER_MANAGEMENT/M_STEER_MANAGEMENT.h"
7
#include "M_ROUTE_MANAGEMENT/M_ROUTE_MANAGEMENT.h"
8
#include "M_LSM303DLH/M_LSM_303DLH.h"
9
#include "M_GPS/M_GPS.h"
10
#include "M_PROTOCOL/M_PROTOCOL.h"
11
#include "M_PROTOCOL/fifo.h"
12
13
#include <avr/io.h>
14
#include <stdlib.h>
15
#include <stdio.h>
16
#include <avr/wdt.h>
17
18
19
//FIFO
20
fifo_t fifo_pc_in;
21
fifo_t fifo_pc_out;
22
fifo_t fifo_gps;
23
uint8_t fifo_buffer_in[60];
24
uint8_t fifo_buffer_out[60];
25
uint8_t fifo_buffer_gps[60];
26
27
//Timeouts
28
#define TIMEOUT_GPS 1000
29
#define TIMEOUT_WI232 1000
30
#define TIMEOUT_COMPASS 250
31
#define TIMEOUT_HEARTBEAT 500
32
#define TIMEOUT_PPM 75
33
34
//Timer Hardware
35
unsigned long timer_gps_lc;
36
unsigned long timer_wi232_lc;
37
unsigned long timer_compass_lc;
38
39
//Timer Software
40
unsigned long timer_heartbeat_lc;
41
unsigned long timer_ppm_lc;
42
43
//Checks Send
44
uint8_t timer_wi232_lc_send_check;
45
46
int main(void)
47
{
48
    fifo_init(&fifo_pc_in,fifo_buffer_in,60);
49
    fifo_init(&fifo_pc_out,fifo_buffer_out,60);
50
    fifo_init(&fifo_gps,fifo_buffer_gps,60);
51
52
    M_AVR_PROC_INIT();
53
    PORTB |= LED_RED|LED_GREEN;
54
55
    sei();
56
57
    delay_ms(20);
58
  
59
  PORTB &= ~ LED_GREEN;
60
  
61
    //Temporäre Kompass und Beschleunigungssensor Init
62
    uint8_t t = LSM303DLH_setup_acc();
63
    if(t!=M_LSM303DLH_ACC_OK)
64
    {
65
    device[E_T_DEVICE_COMPASS].valid = 0x00;
66
        uart_puts("ACC ERROR\n",M_USART_WI232);
67
    }
68
  else
69
  {
70
    device[E_T_DEVICE_COMPASS].valid = 0xff;
71
  }
72
73
    t = LSM303DLH_setup_mag();
74
    if(t!=M_LSM303DLH_MAG_OK)
75
    {
76
    device[E_T_DEVICE_COMPASS].valid = 0x00;
77
        uart_puts("MAG ERROR\n",M_USART_WI232);
78
    }
79
  else
80
  {
81
    device[E_T_DEVICE_COMPASS].valid = 0xff;
82
  }
83
  
84
  
85
  if( MCUSR &(1<<WDRF))
86
  {
87
    char a[10];
88
    uint8_t e =       protocol_msg_code(PROTOCOL_RESET,PROTOCOL_WATCHDOG_RESET,a);
89
    for(uint8_t i=0;i<e;i++)
90
    {
91
      fifo_put(&fifo_pc_out,a[i]);
92
      UCSR0B |= (1<<UDRIE0);  
93
    }
94
  }
95
  else
96
  {
97
    char a[10];
98
    uint8_t e = protocol_msg_code(PROTOCOL_RESET,PROTOCOL_NORMAL_RESET,a);
99
    for(uint8_t i=0;i<e;i++)
100
    {
101
      fifo_put(&fifo_pc_out,a[i]);
102
      UCSR0B |= (1<<UDRIE0);  
103
    }
104
  }
105
106
  wdt_enable(WDTO_8S);
107
  
108
  PORTB &= ~ LED_RED;
109
  
110
    while(1)
111
    {  
112
wdt_reset();
113
    /************************************************************************
114
    FIFO
115
    ************************************************************************/
116
    int tmp = fifo_get_nowait(&fifo_gps);
117
    if(tmp!=-1)
118
    {
119
      if(nmea_decode(tmp)==NMEA_DECODED)
120
      {
121
        timer_gps_lc = get_millis();
122
        device[E_T_DEVICE_GPS].valid = 0xff;
123
      }
124
      
125
    }
126
    
127
    tmp = fifo_get_nowait(&fifo_pc_in);
128
    if(tmp!=-1)
129
    {
130
      if(protocol_decode(tmp)==PROTOCOL_DECODED)
131
      {
132
        timer_wi232_lc = get_millis();
133
        timer_wi232_lc_send_check = 0x00;
134
        device[E_T_DEVICE_PC].valid = 0xff;
135
      }
136
    }
137
    //wdt_reset();
138
    /************************************************************************
139
    TIMER
140
    ************************************************************************/
141
    //WI232
142
    if(device[E_T_DEVICE_PC].valid!=0x00)
143
    {
144
      if((get_millis()>(timer_wi232_lc+TIMEOUT_WI232))&&(timer_wi232_lc_send_check!=0x00))
145
      {
146
        char buf[10];
147
        uint8_t t = protocol_msg_check_byte(buf);
148
        for(uint8_t i=0;i<t;i++)
149
        {
150
          fifo_put(&fifo_pc_out,buf[i]);
151
        }
152
        UCSR0B |= (1<<UDRIE0);
153
        
154
        device[E_T_DEVICE_PC].valid = 0x00;    
155
      }
156
      else if(get_millis()>(timer_wi232_lc+TIMEOUT_WI232))
157
      {
158
        char buf[10];
159
        uint8_t t = protocol_msg_check_byte(buf);
160
        for(uint8_t i=0;i<t;i++)
161
        {
162
          fifo_put(&fifo_pc_out,buf[i]);
163
        }
164
        UCSR0B |= (1<<UDRIE0);
165
        
166
        timer_wi232_lc = get_millis();
167
        timer_wi232_lc_send_check = 0xff;    
168
      }
169
    }
170
    //wdt_reset();
171
    //GPS
172
    if(device[E_T_DEVICE_GPS].valid!=0x00)
173
    {
174
      if(get_millis()>(timer_gps_lc+TIMEOUT_GPS))
175
      {
176
        device[E_T_DEVICE_GPS].valid = 0x00;
177
      }
178
    }
179
    //wdt_reset();
180
    //COMPASS
181
    if(get_millis()>(timer_compass_lc+TIMEOUT_COMPASS))
182
    {
183
      LSM303DLH_read();
184
      compass_course[E_T_COMPASS_COURSE].v = LSM303DLH_heading_calculate();
185
      timer_compass_lc = get_millis();  
186
    }
187
    //wdt_reset();
188
    //HEARTBEAT
189
    if(device[E_T_DEVICE_PC].valid!=0x00)
190
    {
191
      if(get_millis()>(timer_heartbeat_lc+TIMEOUT_HEARTBEAT))
192
      {
193
        char buf[40];
194
        uint8_t a = protocol_msg_heartbeat(buf);
195
        for(int i=0;i<a;i++)
196
        {
197
          fifo_put(&fifo_pc_out,buf[i]);  
198
        }
199
        UCSR0B |= (1<<UDRIE0);
200
        timer_heartbeat_lc = get_millis();  
201
      }  
202
    }
203
    //wdt_reset();
204
    //PPM
205
    if(get_millis()>(timer_ppm_lc+TIMEOUT_PPM))
206
    {
207
      //steer_management_ppm_update();
208
      steer_management_autopilot();
209
      route_management_update();
210
      steer_management_update();
211
      steer_management_send_data();
212
      timer_ppm_lc = get_millis();
213
    }    
214
    
215
    
216
    }
217
}

Ich konnte nicht rausfinden, wo er abstürzt.
Habt ihr ne Idee, wo das Problem sein könnte?

MfG

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Normalerweise ist es üblich, beim Initialisieren den WD erstmal zu 
deaktivieren, um ihn dann vor der Hauptschleife anzuschalten. Ich denke, 
in deinem Fall wird er, da er nach dem WD Reset weiter aktiv ist, 
spätestens in der _delay_ms(20) Zeile triggern.

von holger (Gast)


Lesenswert?

>Aber wenn der Controller neu startet, stürzt er immer ab und
>startet wieder neu und das bleibt auch so. Das gleiche passiert auch,
>wenn er nach dem Flashen neu startet.

In deinem Programm findet da sicher keiner was;)
Das ist ein Schaltungsproblem. Also Schaltplan posten.

Als erstes kannst du mal versuchen die BODLEVEL Fuses
auf 4.3V zu stellen.

von holger (Gast)


Lesenswert?

Note: If the Watchdog is accidentally enabled, for example by a runaway 
pointer or brown-out
condition, the device will be reset and the Watchdog Timer will stay 
enabled. If the code is not
set up to handle the Watchdog, this might lead to an eternal loop of 
time-out resets. To avoid this
situation, the application software should always clear the Watchdog 
System Reset Flag
(WDRF) and the WDE control bit in the initialisation routine, even if 
the Watchdog is not in use.

von holger (Gast)


Lesenswert?

Dieses kleine Stück Code könnte evtl. hilfreich sein:

//---------------------------------------------------------------------- 
------
// wdt_init - Watchdog Init used to disable the CPU watchdog
//         placed in Startcode, no call needed
#include <avr/wdt.h>

void wdt_init(void) __attribute__((naked)) 
__attribute__((section(".init1")));

void wdt_init(void)
{
    MCUSR = 0;
    wdt_disable();
}

von Philipp M. (lord-maricek)


Lesenswert?

Ok, danke soweit. BODLEVEL ist auf 4,3V, hat aber nichts gebracht.
WDRF und WDE Flag gleich am anfang löschen brachte auch nichts.
Weder manuel noch mit wdt_disabel().

Der Schaltplan folgt, den hab brad leider nicht, weil ein Freund die 
gemacht hatte.

Könnte es ansonsten noch was mit den Fuses zutun haben? Besonders bei 
dem Quarz bin ich mir da nicht so sicher. Wir verwenden einen Quarz mit 
18.432Mhz, so ganz dahintergestiegen mit den Fuses fürn Quarz bin ich 
noch net.

BODLEVEL = 4V3
OCDEN = [X]
JTAGEN = [ ]
SPIEN = [X]
WDTON = [ ]
EESAVE = [X]
BOOTSZ = 4096W_7000
BOOTRST = [ ]
CKDIV8 = [ ]
CKOUT = [ ]
SUT_CKSEL = EXTXOSC_8MHZ_XX_16KCK_65MS

EXTENDED = 0xFC (valid)
HIGH = 0x51 (valid)
LOW = 0xFF (valid)


Das sin die Fuses.

MfG
philipp

von Philipp M. (lord-maricek)


Lesenswert?

@holger: zu spät gesehen: Mit dem Code gehts, danke :)

MfG
Philipp

von Philipp M. (lord-maricek)


Lesenswert?

EIn Problem hab ich jetzt noch, ich möchte ausgeben, obs ein WDT oder 
Normaler Reset war. Deswegen wollte ich das Register inner globalen 
Varibale speichern und in der Initfunktion dann auswerten, das scheint 
aber nicht zu gehen:
1
uint8_t _wdt_reset_flag;
2
3
void wdt_init(void) __attribute__((naked))
4
__attribute__((section(".init1")));
5
6
void wdt_init(void)
7
{
8
    _wdt_reset_flag = MCUSR;
9
  MCUSR = 0;
10
    wdt_disable();
11
}

Und
1
if( _wdt_reset_flag &(1<<WDRF))
2
  {
3
    char a[10];
4
    uint8_t e = protocol_msg_code(PROTOCOL_RESET,PROTOCOL_WATCHDOG_RESET,a);
5
    for(uint8_t i=0;i<e;i++)
6
    {
7
      fifo_put(&fifo_pc_out,a[i]);  
8
    }
9
    UCSR0B |= (1<<UDRIE0);
10
  }
11
  else
12
  {
13
    char a[10];
14
    uint8_t e = protocol_msg_code(PROTOCOL_RESET,PROTOCOL_NORMAL_RESET,a);
15
    for(uint8_t i=0;i<e;i++)
16
    {
17
      fifo_put(&fifo_pc_out,a[i]);
18
    }
19
    UCSR0B |= (1<<UDRIE0);
20
  }

Ich bekomme aber immer Normaler Reset angezeigt, obwohls ein Watchdog 
reset war.

MfG
Philipp

von holger (Gast)


Lesenswert?

>Ich bekomme aber immer Normaler Reset angezeigt, obwohls ein Watchdog
>reset war.

Versuch es doch einfach mal so:

void wdt_init(void)
{
    wdt_disable();
}

von Philipp M. (lord-maricek)


Lesenswert?

Moin,

void wdt_init(void)
{
    wdt_disable();
}

so gehts leider auch nicht, auch nicht wenn ich:
_wdt_reset_flag = MCUSR;
MCUSR = 0;
ganz als erstes in die main Funktion packe, stürtzt er auch wieder ab.

Ich habs auch einmal so versucht, dass das MCUSR in einer weiteren 
FUnktion gespeichert wird, der controller startet zwar normal, aber der 
WDT Reset wird nicht angezeigt.
1
uint8_t _wdt_reset_flag;
2
3
void wdt_init(void) __attribute__((naked))
4
__attribute__((section(".init1")));
5
6
void _wdt_init(void)
7
{
8
  _wdt_reset_flag = MCUSR;
9
  MCUSR = 0;
10
}
11
12
void wdt_init(void)
13
{
14
  _wdt_init();
15
    wdt_disable();
16
}

MfG
Philipp

von Philipp M. (lord-maricek)


Lesenswert?

Hi,

nach vielen Versuchen funktioniert es weiterhin nur so wie in meinem 
letzten Beitrag. Problem ist immernoch, dass das Registern nicht in der 
Varibale gespeichert wird, gibt es vielleicht irgenteine Möglichkeit, an 
dieser Stelle den Wert vom MCUSR in irgentein vorher definiertes 
Register zu schreiben, oder ans ende des Flashs zu setzten?

MfG
Philipp

von holger (Gast)


Lesenswert?

So müsste das gehen.

uint8_t mcusr_mirror _attribute_ ((section (".noinit")));

void get_mcusr(void) __attribute__((naked)) 
_attribute__((section(".init1")));
void get_mcusr(void)
{
  mcusr_mirror = MCUSR;

  MCUSR = 0;
  wdt_disable();
}

von holger (Gast)


Lesenswert?

Grr, attribute unterstrichen;)

So nochmal richtig:
1
uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
2
3
void get_mcusr(void) __attribute__((naked)) _attribute__((section(".init1")));
4
void get_mcusr(void)
5
{
6
  mcusr_mirror = MCUSR;
7
8
  // disable the dog
9
  MCUSR = 0;
10
  wdt_disable();
11
}

von holger (Gast)


Lesenswert?

Grr, ein Unterstrich verloren gegangen):

Und nochmal:
1
uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
2
3
void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init1")));
4
void get_mcusr(void)
5
{
6
  mcusr_mirror = MCUSR;
7
8
  // disable the dog
9
  MCUSR = 0;
10
  wdt_disable();
11
}

Es müssen zwei Unterstriche vor und hinter jedes attribute.

von Philipp M. (lord-maricek)


Lesenswert?

Danke :) jetzt gehts.

von Leo B. (luigi)


Lesenswert?

Da ich gerade vor einem ähnlichen Problem stand finde ich es interesant, 
dass es funktioniert, da erst in der .init2 das zero_reg zur Verfügung 
steht...

Quelle: http://www.nongnu.org/avr-libc/user-manual/mem_sections.html
########################################
[...]
.init2:
In C programs, weakly bound to initialize the stack, and to clear 
_zero_reg_ (r1).
[...]
########################################

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.