Forum: Mikrocontroller und Digitale Elektronik Atmega resetten


von Oz z. (ozzy)


Lesenswert?

Moin,

ich würde gerne beim Empfang eines bestimmten Zeichens über die serielle 
Schnittstelle meinen Atmega resetten. Dafür habe ich den Watchdog 
bemüht:

int main ( void ) {

   wdt_enable(WDTO_2S); // 2s
   wdt_disable();
   sei();
   ...
   case RESET :
      {
      cli();
      wdt_enable(WDTO_15MS);
      /* Warten, bis er anbeisst */
      while(1);
      break;
      }

Der Controller resettet sich auch, aber leider ständig... Habt Ihr eine 
Idee, woran das liegen könnte???

MfG und vielen Dank, Ozzy

von ... (Gast)


Lesenswert?

Wie wird denn die Switch Variable Initialisiert ?

von Oz z. (ozzy)


Lesenswert?

uint8_t c;
c = uart_receive();
switch( c )  {
   ...

Der ganze Rest funktioniert aber auch (also das Empfangen von anderen 
Befehlen)

von Volker S. (volkerschulz)


Lesenswert?

Check doch mal (anhand des entsprechenden Status-Bits) ob der Reset 
jeweils vom Watchdog kam. Wenn ja (und Du den Watchdog nirgendwo anders 
enablest), wird wohl case RESET oefter aufgerufen als geplant. ;)

Abgesehen davon, warum machst Du den geplanten Reset ueberhaupt ueber 
den Watchdog?

Volker

von Oz z. (ozzy)


Lesenswert?

Moin,

wie kann ich den Controller denn ohne watchdog resetten???
RESET dürfte aber nur einmal aufgerufen werden, da ich es vom PC auch 
nur einmal sende (per Hand)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Christoph O. schrieb:

>    ...
>    case RESET :

Steht vor dem case auch ein break vom vorherigen case? Zeig doch mal 
mehr von Deinem Code.

Gruß,

Frank

von Volker S. (volkerschulz)


Lesenswert?

Christoph O. schrieb:
> wie kann ich den Controller denn ohne watchdog resetten???

Ueber Reset-Pin auf I/O-Pin... Mit ist aber gerade in den Sinn gekommen, 
dass die LOW time da evtl. gar nicht ausreicht... Also vergiss das 
wieder. ;)


> RESET dürfte aber nur einmal aufgerufen werden, da ich es vom PC auch
> nur einmal sende (per Hand)

"Duerfte" ist nicht gut genug. Poste doch mal deinen ganzen Code.

Volker

von Karl H. (kbuchegg)


Lesenswert?

Volker Schulz schrieb:
> Christoph O. schrieb:
>> wie kann ich den Controller denn ohne watchdog resetten???
>
> Ueber Reset-Pin auf I/O-Pin... Mit ist aber gerade in den Sinn gekommen,
> dass die LOW time da evtl. gar nicht ausreicht... Also vergiss das
> wieder. ;)

Interessante Fragestellung

Angenommen PB0 ist mit Reset verbunden.
Was passiert bei
1
int main()
2
{
3
  PORTB = 1<<PB0;
4
  DDRB = 1<<PB0;
5
6
7
  PORTB &= ~(1<<PB0);    // Reset Pin auf Low ziehen
8
  while( 1 )
9
    ;
10
}

meiner Ansicht nach müsste das einen sauberen Reset ergeben. Was 
passiert, wenn der 'Puls' tatsächlich zu kurz ist? Geht der µC dann in 
einen 'Schwebezustand'?

von Oz z. (ozzy)


Lesenswert?

Von Außen will und kann ich ihn aber nicht resetten. Habe jetzt aber 
rausgefunden, dass es anscheindend an der Einstellung für den OSC liegt. 
Probiere gerade noch etwas mit der richtigen Einstellung rum (sut_cksel)

von nop (Gast)


Lesenswert?

>Von Außen will und kann ich ihn aber nicht resetten.

Wozu auch, die Methode mit dem Watchdog ist schon ok.

von P. S. (Gast)


Lesenswert?

Kannst du Bescheid geben, wenn du das Problem geloest hast? Ich habe das 
gleiche Problem, bin aber noch nicht dazu gekommen, das auf ein 
postbares Beispiel zu reduzieren :-)

von Volker S. (volkerschulz)


Lesenswert?

Karl heinz Buchegger schrieb:
> Interessante Fragestellung
>
> Angenommen PB0 ist mit Reset verbunden.
> Was passiert bei
>
>
1
> int main()
2
> {
3
>   PORTB = 1<<PB0;
4
>   DDRB = 1<<PB0;
5
> 
6
> 
7
>   PORTB &= ~(1<<PB0);    // Reset Pin auf Low ziehen
8
>   while( 1 )
9
>     ;
10
> }
11
>
>
> meiner Ansicht nach müsste das einen sauberen Reset ergeben. Was
> passiert, wenn der 'Puls' tatsächlich zu kurz ist? Geht der µC dann in
> einen 'Schwebezustand'?

Ich meine irgendwo mal gelesen zu haben, dass die I/O-Pins schon nach 
der HALBEN minimalen Reset-Zeit auf Tri-Stated gehen. Und daran 
erinnerte ich mich dann nach meinem Beitrag spontan wieder.

An einen 'Schwebezustand' glaube ich eher nicht, eher dass entweder 
generell kein Reset stattfindet, oder eben pseudo zufaellig mal ja und 
mal nein.

Volker

von Volker S. (volkerschulz)


Lesenswert?

Hab's gefunden und zitiere:

If you want to perform a software reset of your AVR you should use the 
internal Watchdog. Simply enable it and let it time out. When the 
Watchdog triggers it resets the program counter back to 0, clears all 
the registers and performs all the other tasks. This operation gives the 
same result as pulling the RESET line low.

You should not try to:
- Use another pin of the AVR to pull the external RESET line. The pins 
of the AVR are tristated halfway through the minimum reset time, this 
releases the RESET line and hence nothing happens.
- Jump to program location 0. Jumping to program location 0 does not 
clear all the registers and hence you do not have a "clean" reset.


Example Code (GCC) Resetting the AVR every 30mS:
1
#include <avr/io.h>
2
#include <avr/wdt.h>
3
4
int main(void)
5
{
6
wdt_enable(WDTO_30MS);
7
while(1) {};
8
}

Alternatively you can create a macro:

Code:
1
#include <avr/io.h>
2
#include <avr/wdt.h>
3
4
#define Reset_AVR() wdt_enable(WDTO_30MS); while(1) {}
5
6
int main(void)
7
{
8
Reset_AVR();
9
}


Die "Loesung" mit dem Pin bringt also gar nichts. Ich entschuldige mich 
fuer die gestiftete Verwirrung! ;)

Volker

von maveric00 (Gast)


Lesenswert?

Hallo,

wird der Watchdog nach dem Reset denn wieder ausgeschaltet? Sonst bleibt 
der nämlich aktiv - und löst dementsprechend wieder aus. Siehe auch 
Manual z.B. vom PWM3:

> 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.

Schöne Grüße,
Martin

von Fallout-Girl (Gast)


Lesenswert?

Dreh ihn mal um. Da gibt es irgendwo eine kleine Taste die du mit einem 
spitzen Gegenstand (ich nehme einen Zahnstocher) drücken kannst...

scrn

von Rolf Magnus (Gast)


Lesenswert?

>> wie kann ich den Controller denn ohne watchdog resetten???
>
> Ueber Reset-Pin auf I/O-Pin... Mit ist aber gerade in den Sinn
> gekommen, dass die LOW time da evtl. gar nicht ausreicht... Also
> vergiss das wieder. ;)

Es hätte auch den Nachteil, daß man einen I/O-Pin dafür zusätzlich 
verbraucht (oder zwei, wenn man den RESET-Anschluß auch als I/O 
verwenden wollte). Der Watchdog ist doch eh da, warum sollte man den 
nicht dafür einsetzen?

von Andreas F. (aferber)


Lesenswert?

Wie wäre es damit, einfach die Dokumentation zu den Werkzeugen, die man 
einsetzt, zumindest mal kurz zu überfliegen? Siehe 
http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html, da 
ist genau beschrieben (sogar mit fertigem Code), was man machen muss, 
damit man nicht im Endlos-Reset endet.

Andreas

von P. S. (Gast)


Lesenswert?

Andreas Ferber schrieb:
> Wie wäre es damit, einfach die Dokumentation zu den Werkzeugen, die man
> einsetzt, zumindest mal kurz zu überfliegen?

Koenntest du auch noch verraten, wo der Code von Christoph sich - 
fehlerhaft - nicht an die Dokumentation haelt?

von Andreas F. (aferber)


Lesenswert?

Peter Stegemann schrieb:
> Andreas Ferber schrieb:
>> Wie wäre es damit, einfach die Dokumentation zu den Werkzeugen, die man
>> einsetzt, zumindest mal kurz zu überfliegen?
> Koenntest du auch noch verraten, wo der Code von Christoph sich -
> fehlerhaft - nicht an die Dokumentation haelt?

Er schaltet den Watchdog halt nach dem Reset nicht wieder aus, deshalb 
gibt's nach 15ms dann gleich den nächsten. Sowohl in der Atmel- als auch 
der AVR-libc-Doku steht aber (bei allen neueren ATmegas) drin, dass man 
das muss.

Am Anfang von main() ist BTW zu spät, das kann man auch der 
avr-libc-Doku entnehmen.

Andreas

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Andreas Ferber schrieb:

> Er schaltet den Watchdog halt nach dem Reset nicht wieder aus, deshalb
> gibt's nach 15ms dann gleich den nächsten.

Macht er doch:
1
int main ( void ) {
2
3
   wdt_enable(WDTO_2S); // 2s
4
   wdt_disable();

Ich weiß zwar nicht, wozu der anfängliche Enable (von 2 Sekunden) da 
ist, aber da passiert direkt darauf ein wdt_disable().

> Sowohl in der Atmel- als auch der AVR-libc-Doku steht aber (bei allen
> neueren ATmegas) drin, dass man das muss.

Ja, muss man auch.

> Am Anfang von main() ist BTW zu spät, das kann man auch der
> avr-libc-Doku entnehmen.

Am Anfang von main() ist das zu spät??? Wann könnte man das denn noch 
früher machen als am Anfang von main? 15 msec sind doch eine Ewigkeit...

Gruß,

Frank

P.S.
Ich nehme jetzt mal an, dass da kein Bootloader vorgeschaltet ist, der 
natürlich den Aufruf von main() beträchtlich verzögern könnte.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Frank M. schrieb:

> Am Anfang von main() ist das zu spät??? Wann könnte man das denn _noch_
> früher machen als am Anfang von main? 15 msec sind doch eine Ewigkeit...

In .init3 steht doch im Link oben

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Stefan B. schrieb:
> Frank M. schrieb:
>
>> Am Anfang von main() ist das zu spät??? Wann könnte man das denn _noch_
>> früher machen als am Anfang von main? 15 msec sind doch eine Ewigkeit...
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> In .init3 steht doch im Link oben

Du meinst, dass zwischen .init3 und main() 15msec vergehen? Mit welchem 
Takt läuft denn da der µC?

Wenn dem tatsächlich so wäre, müsste man beim Reset über

    wdt_enable(WDTO_500MS);    // 500msec statt 15msec

ja locker viel Zeit haben und das Problem würde sich von selbst 
erledigen.

Gruß,

Frank

von P. S. (Gast)


Lesenswert?

Frank M. schrieb:

> Wenn dem tatsächlich so wäre, müsste man beim Reset über
>
>     wdt_enable(WDTO_500MS);    // 500msec statt 15msec
>
> ja locker viel Zeit haben und das Problem würde sich von selbst
> erledigen.

Wird keinen Unterschied machen, wenn der Watchdog "von selbst" auf 15ms 
wechselt:

"Note that for newer devices (ATmega88 and newer, effectively any AVR 
that has the option to also generate interrupts), the watchdog timer 
remains active even after a system reset (except a power-on condition), 
using the fastest prescaler value (approximately 15 ms)."

Muss ich zuhause mal ausprobieren...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter Stegemann schrieb:
> "Note that for newer devices (ATmega88 and newer, effectively any AVR
> that has the option to also generate interrupts), the watchdog timer
> remains active even after a system reset (except a power-on condition),
> using the fastest prescaler value (approximately 15 ms)."

Okay, das überzeugt mich... aber stellt mich nicht zufrieden. Ich kann 
mir kaum vorstellen, dass zwischen einem Aufruf in .init3 und einem 
Aufruf direkt als erstes im main() die entscheidenden 15msec abgelaufen 
sind - immer noch vorausgesetzt, dass da kein Bootloader 
dazwischenfunkt.

> Muss ich zuhause mal ausprobieren...

Bin gespannt.

Gruß,

Frank

von Andreas F. (aferber)


Lesenswert?

Frank M. schrieb:
>> Am Anfang von main() ist BTW zu spät, das kann man auch der
>> avr-libc-Doku entnehmen.
> Am Anfang von main() ist das zu spät??? Wann könnte man das denn _noch_
> früher machen als am Anfang von main? 15 msec sind doch eine Ewigkeit...

Schau dir mal im Disassembler an, was die libc vor dem Start von 
main() schon so alles veranstaltet. Da werden Stackpointer 
initialisiert, Variablen vom Flash ins RAM geladen etcpp. Ausserdem 
läuft meines Wissens der Watchdog-Timer beim Reset einfach durch, d.h. 
von deinen 15ms geht die Zeit, die der eigentliche Reset des AVR dauert, 
auch noch runter.

Wenn der dann auch nur mit den Werks-1MHz (oder gar noch langsamer, um 
Strom zu sparen) läuft, dann sind die 15ms auf einmal keine Ewigkeit 
mehr. Die avr-libc empfiehlt nicht zum Spass, das Watchdog-Disablen in 
eine Init-Routine zu packen, statt bis zum Anfang von main() drauf zu 
warten.

Viel schöner ist das mit C++ auf einem grossen Rechner, da braucht der 
Prozess ggf. dank Konstruktoren und Destruktoren den grösseren Teil der 
Rechenzeit vor und nach main() anstatt im Hauptprogramm ;-)

> Ich nehme jetzt mal an, dass da kein Bootloader vorgeschaltet ist, der
> natürlich den Aufruf von main() beträchtlich verzögern könnte.

Garnicht nötig, langsamer Takt und viele Variablen können da locker 
reichen.

Andreas

von Volker S. (volkerschulz)


Lesenswert?

Rolf Magnus schrieb:
>>> wie kann ich den Controller denn ohne watchdog resetten???
>>
>> Ueber Reset-Pin auf I/O-Pin... Mit ist aber gerade in den Sinn
>> gekommen, dass die LOW time da evtl. gar nicht ausreicht... Also
>> vergiss das wieder. ;)
>
> Es hätte auch den Nachteil, daß man einen I/O-Pin dafür zusätzlich
> verbraucht (oder zwei, wenn man den RESET-Anschluß auch als I/O
> verwenden wollte). Der Watchdog ist doch eh da, warum sollte man den
> nicht dafür einsetzen?

Weil es zeitkritische Anwendungen fuer Mikrocontroller gibt und man die 
17ms vielleicht nicht verschenken moechte... Wie schon erwaehnt, geht's 
aber per I/O-Pin ohnehin nicht.

Volker

von P. S. (Gast)


Lesenswert?

Volker Schulz schrieb:

> Weil es zeitkritische Anwendungen fuer Mikrocontroller gibt und man die
> 17ms vielleicht nicht verschenken moechte... Wie schon erwaehnt, geht's
> aber per I/O-Pin ohnehin nicht.

Du kannst auch den hier machen:

  // Jump into reset vector.
  goto *(( void**) NULL);

Aber den Beipackzettel lesen:

"The canonical way to perform a software reset of the AVR is to use the 
watchdog timer. Enable the watchdog timer to the shortest timeout 
setting, then go into an infinite, do-nothing loop. The watchdog will 
then reset the processor.
The reason why this is preferable over jumping to the reset vector, is 
that when the watchdog resets the AVR, the registers will be reset to 
their known, default settings. Whereas jumping to the reset vector will 
leave the registers in their previous state, which is generally not a 
good idea."

http://www.nongnu.org/avr-libc/user-manual/FAQ.html

Ich habe nun uebrigens auf dem 2560 rumprobiert, ohne init-Funktion 
geht's einfach nicht, auch wenn der Code nur aus ein bisschen Blinken 
besteht. (Wobei ich nach wie vor mit dem g++ arbeite, fuer gcc bin ich 
zu faul).

von Frank B. (frank501)


Lesenswert?

Wie wäre es, um allen Unbilden aus dem Weg zu gehen, einen Pin als 
Resetauslöser zu verwenden und den Impuls mit einem NE555 als Monoflop 
einfach zu verlängern?

Frank

von Volker S. (volkerschulz)


Lesenswert?

Peter Stegemann schrieb:
> Du kannst auch den hier machen:
>
>   // Jump into reset vector.
>   goto *(( void**) NULL);
>
> Aber den Beipackzettel lesen:

1.) Zum Reset Vektor springen ist eben KEIN sauberer Reset.

2.) Das stand auch im Beipackzettel, den ich viel weiter oben gepostet 
habe. ;)


Frank B. schrieb:
> Wie wäre es, um allen Unbilden aus dem Weg zu gehen, einen Pin als
> Resetauslöser zu verwenden und den Impuls mit einem NE555 als Monoflop
> einfach zu verlängern?

Yeah... aber das sollte man dann wirklich nur in Betracht ziehen, wenn 
man die 17ms nicht mehr verschmerzen kann. ;)


Volker

von spess53 (Gast)


Lesenswert?

Hi

>1.) Zum Reset Vektor springen ist eben KEIN sauberer Reset.

Wenn das ein Problem ist, dann wird der Controller vom Programm nicht 
ordentlich initialisiert.

>2.) Das stand auch im Beipackzettel, den ich viel weiter oben gepostet
>habe. ;)

Das ist maximal ein Hinweis von Atmel. Kein Verbot.

MfG Spess

von Volker S. (volkerschulz)


Lesenswert?

spess53 schrieb:
> Hi
>
>>1.) Zum Reset Vektor springen ist eben KEIN sauberer Reset.
>
> Wenn das ein Problem ist, dann wird der Controller vom Programm nicht
> ordentlich initialisiert.
>
>>2.) Das stand auch im Beipackzettel, den ich viel weiter oben gepostet
>>habe. ;)
>
> Das ist maximal ein Hinweis von Atmel. Kein Verbot.

Hab ja auch nicht von einem Verbot gesprochen, sondern von "KEINEM 
sauberen Reset". Und viel mehr Uebersetzungsmoeglichkeiten fallen mir 
fuer

"Jumping to program location 0 does not clear all the registers and 
hence you do not have a "clean" reset."

auch nicht ein. ;)


Volker

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.