mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik attiny25 reset nach power down


Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
ich will etwas bauen, dass statt ausgeshcalten zu werden in den power 
down geht und mit einem pin change dann wieder aufwacht, dann jedoch 
einen Reset durchführt.

in einem Anderen Projekt hab ich das schonmal mit int0 gemacht.
da ich im Programm den Interupt aber nicht brauchte (und Platzmangel 
war) hab ich die ISR einfach weggelassen. Das hat funktioniert.


den PCINT, den ich benutzen möchte benötige ich jetzt jedoch im 
Programm.

Bei AVR bin ich auf etwas gestoßen mit dem WDT.
http://support.atmel.no/bin/customer?=&action=view...
Das scheint nur leider nicht zu funktionieren.


Das ist der code:

static inline void powerDown(void)
{
  set_sleep_mode( SLEEP_MODE_PWR_DOWN);
  TCCR0B = 0;
  TCCR1 = 0;

  sleep_enable();
  sei();    // enable because called from timer ISR
  sleep_cpu();

  /* bis hier hin funktionierts */

  /*reset*/
  wdt_enable(WDTO_30MS);
  while(1) {};
}


die CPU legt sich schlafen, wacht auch wieder auf (getestet mit 
led-gewackel nach dem sleep_cpu() , aber der reset klappt nicht.

Jemand von euch ne idee?

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hat niemand einen Hinweis, wie man einen Software-rest auslöst.

Autor: Gast 57 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Software-Reset:

Auslösen mit Watch-Dog? -> Braucht halt die WD-Time
Jump to Reset bzw. Programm-Beginn. (Dann alle Regs initialisieren!)

Nicht elegant, aber wirkungsvoll

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mit dem WD das schlägt ja atmel vor mit folgendem Codebispiel:
  /*reset*/
  wdt_enable(WDTO_30MS);
  while(1) {};

Allerdings passiert dabei gar nix.
Er scheint danach in der Whileschleife zuhängen.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Er scheint danach in der Whileschleife zuhängen.

Dann aktiviere den Watchdog doch mal.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn's nur um den Sprung zum Reset-Vektor geht und nicht um das Löschen 
von Registern etc., was ein Hardware-Reset ja zusätzlich macht:
asm volatile ( "jmp 0x0" )

Autor: R. Max (rmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:

> Allerdings passiert dabei gar nix.
> Er scheint danach in der Whileschleife zuhängen.

Kannst Du mal noch den Anfang von main() posten? Evtl. hängt er nicht in 
der Schleife, sondern führt einen Reset nach dem anderen aus, weil Du 
den Watchdog nach dem Reset nicht oder zu spät abschaltest.

Alternativ könntest Du die Taste zum ein- und ausschalten an den 
Reset-Pin hängen und in main() unterscheiden, ob der Reset aus dem Wach- 
oder Schlafzustand ausgelöst wurde.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal WDTCR[WDE] auf 1 bevor hier weiter rumgerätselt wird

Autor: R. Max (rmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timmo H. schrieb:
> Erstmal WDTCR[WDE] auf 1 bevor hier weiter rumgerätselt wird

wdt_enable() tut genau das.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
R. Max schrieb:
> Vlad Tepesch schrieb:
>
>> Allerdings passiert dabei gar nix.
>> Er scheint danach in der Whileschleife zuhängen.
>
> Kannst Du mal noch den Anfang von main() posten? Evtl. hängt er nicht in
> der Schleife, sondern führt einen Reset nach dem anderen aus, weil Du
> den Watchdog nach dem Reset nicht oder zu spät abschaltest.
Kann ich heut abend noch mal schauen, ich bin mir aber fast sicher, dass 
ich vordichtshalber eine Routine eingebaut hatte, die noch vor der 
runtime-Initialisierung läuft und den wdt abschaltet.
In der Atmel Appnote steht davon ja aber auch nix.

>
> Alternativ könntest Du die Taste zum ein- und ausschalten an den
> Reset-Pin hängen und in main() unterscheiden, ob der Reset aus dem Wach-
> oder Schlafzustand ausgelöst wurde.

hab keinen taster dafür.
Hab nen primitven bewegungssenso gebaut, der wenn er bewegt wird gegen 
Masse schaltet.

wurde das gerät eine Weile nicht bewegt, dann wird alles abgeschalteten.
Wird das ding wieder bewegt soll alles wieder an gehen - mit einem 
kompletten neustart, was gegen einen Sprung nach 0 spricht.

>asm volatile ( "jmp 0x0" )
hatte ich übrigens auch probiert, der meckert der assembler, dass der 
atmega25 diesen opcode nicht hat. Laut reference kann der nur relative 
sprünge.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahh, stimmt
(_BV(_WD_CHANGE_BIT) | _BV(WDE)
sagt der name ja auch schon. Hatte angenommen, dass da so nur der Timer 
angefasst wird. Dann sollte es aber ja eigentlich auch funzen

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde ja zu einer ordentlichen Entprellung raten, damit ist 
Power-Down ein Kinderspiel:

http://www.avrfreaks.net/index.php?module=Freaks%2...


Und ein Reset ist immer ein Dirty Hack.
Mach besser einfach in das Main noch ne äußere Loop, die nach dem 
Power-Down durchlaufen wird und die Initialisierung + innere Loop neu 
startet.


Peter

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
>>asm volatile ( "jmp 0x0" )
> hatte ich übrigens auch probiert, der meckert der assembler, dass der
> atmega25 diesen opcode nicht hat. Laut reference kann der nur relative
> sprünge.
meine natürlich attiny25

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Ich würde ja zu einer ordentlichen Entprellung raten, damit ist
> Power-Down ein Kinderspiel:
>
> 
http://www.avrfreaks.net/index.php?module=Freaks%2...


Zitat:
>wurde das gerät eine Weile nicht bewegt, dann wird alles abgeschalteten.
wenn etwas nicht geschaltet wird, brauchs auch nicht entprellt werden

>
>
> Und ein Reset ist immer ein Dirty Hack.
> Mach besser einfach in das Main noch ne äußere Loop, die nach dem
> Power-Down durchlaufen wird und die Initialisierung + innere Loop neu
> startet.
>
>
> Peter

Was ist ein dirty hack daran, wenn ein System ausgeschalten wird und vor 
weiteren Gebrauch mit der Standard-Prozedur neu startet?

eine weitere äußere Loop ist für mich der dirty hack, da hier 
zusätzliche kommunikation zwischen ISR und main benötigt wird und das 
System länger arbeitet, als es sollte.

Autor: R. Max (rmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:

> In der Atmel Appnote steht davon ja aber auch nix.

Ich weiß nicht, welche Appnote Du meinst, aber im Manual zum 
ATtiny25/45/85 sind im Kapitel 8.4.2 auf Seite 45 Beispiele in Assembler 
und C zum Abschalten des Watchdog. Wichtig ist, daß man das MCUSR zuerst 
nullt, sonst schaltet sich der WDT nicht ab.

Falls Du die Ursache für den Reset später nochmal brauchst, findest Du 
in avr/wdt.h ein Beispiel, wie man das in Verbindung mit wdt_disable() 
macht.

> wurde das gerät eine Weile nicht bewegt, dann wird alles abgeschalteten.
> Wird das ding wieder bewegt soll alles wieder an gehen - mit einem
> kompletten neustart, was gegen einen Sprung nach 0 spricht.

Kannst Du den Spieß nicht umdrehen und gleich den Watchdog-Reset als 
Timeout zum Abschalten nehmen? Im Tiny25 kann der immerhin bis zu 8 
Sekunden. Im Reset schaltest Du dann als erstes den Watchgog aus und 
schickst den Tiny in den Power-Down. Wenn er durch den PCINT wieder 
aufwacht, ist die CPU immer noch im "gerade resetteten" Zustand, und Du 
kannst die Initialisierung fortsetzen.

Falls Deine "Weile" bis zum Abschalten länger als 8 Sekunden dauern 
soll, kannst Du den WDT auch erstmal einen Iterrupt statt eines Resets 
auslösen lassen und nach einer bestimmten Anzahl von Interrupts auf 
Reset umschalten.

Andererseits: Ist dierer komplette Neustart wirklich nötig? Kann das 
Programm nicht einfach da weitermachen, wo es sich vorher schlafengelegt 
hat?

>>asm volatile ( "jmp 0x0" )
> hatte ich übrigens auch probiert, der meckert der assembler, dass der
> atmega25 diesen opcode nicht hat. Laut reference kann der nur relative
> sprünge.

Er hat auch einen absoluten Sprung (IJMP), nur kann die Zieladresse halt 
nicht unmittelbar im Code stehen, sondern muß vorher ins Z-Register 
geladen werden.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
R. Max schrieb:
> Vlad Tepesch schrieb:
>
>> In der Atmel Appnote steht davon ja aber auch nix.
>
> Ich weiß nicht, welche Appnote Du meinst,
siehe eingangspost
ok, ist keine Appnote, ist ein FAQ-Eintrag

> Falls Du die Ursache für den Reset später nochmal brauchst>> wurde das gerät eine Weile nicht bewegt, dann wird alles abgeschalteten.
>> Wird das ding wieder bewegt soll alles wieder an gehen - mit einem
>> kompletten neustart, was gegen einen Sprung nach 0 spricht.
>
> Kannst Du den Spieß nicht umdrehen und gleich den Watchdog-Reset als
> Timeout zum Abschalten nehmen? Im Tiny25 kann der immerhin bis zu 8
> Sekunden. Im Reset schaltest Du dann als erstes den Watchgog aus und
> schickst den Tiny in den Power-Down. Wenn er durch den PCINT wieder
> aufwacht, ist die CPU immer noch im "gerade resetteten" Zustand, und Du
> kannst die Initialisierung fortsetzen.
>
> Falls Deine "Weile" bis zum Abschalten länger als 8 Sekunden dauern
> soll, kannst Du den WDT auch erstmal einen Iterrupt statt eines Resets
> auslösen lassen und nach einer bestimmten Anzahl von Interrupts auf
> Reset umschalten.


wär eine Möglichkeit, man würde sich den timer sparen, das eigendliche 
Problem, behebt es nicht.
Das ist ja momentan, dassd er WD nicht zu funktionieren scheint und 
scheinbar kein reset auslöst.


>
> Andererseits: Ist dierer komplette Neustart wirklich nötig? Kann das
> Programm nicht einfach da weitermachen, wo es sich vorher schlafengelegt
> hat?
es soll neu gestartet werden.

>
>>>asm volatile ( "jmp 0x0" )
>> hatte ich übrigens auch probiert, der meckert der assembler, dass der
>> atmega25 diesen opcode nicht hat. Laut reference kann der nur relative
>> sprünge.
>
> Er hat auch einen absoluten Sprung (IJMP), nur kann die Zieladresse halt
> nicht unmittelbar im Code stehen, sondern muß vorher ins Z-Register
> geladen werden.
Ach stimmt, das hatte ich dannach gelesen, aber wieder verworfen,
weil ich mir nicht sicher war, was bei einem sprungnach 0 passiert.
werden die register und der vor allem der stack von der runtime 
intialisiert?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
> wenn etwas nicht geschaltet wird, brauchs auch nicht entprellt werden

Das ist ein Irrtum.
Entprellen ist auch beim Einschalten äußerst nützlich. Man will ja 
nicht, daß Geräte sofort durch irgendwelche Störimpulse von alleine 
angehen (Handy, Staubsauger einschalten, gehen mit Gummisohlen usw.).


> Was ist ein dirty hack daran, wenn ein System ausgeschalten wird und vor
> weiteren Gebrauch mit der Standard-Prozedur neu startet?

Ein Gerät, welches einen Resettaster benötigt oder sich selbst resettet, 
hinterläßt immer das ungute Gefühl, in der Software wurde gepfuscht.

Du weißt ja, in welchem Zustand alle Register und Pins nach einem 
Aufwachen sind, nämlich in genau dem Zustand vor dem Power-Down. Warum 
also unnötige Aktionen durchführen?

Einen PC möchte man ja auch nicht neu booten müssen, nur weil zum 
Stromsparen nach ner Weile Bildschirm und Festplatte abschalten.
Man möchte dort weitermachen, wo man aufgehört hat.

Ein Reset ohne Not ist ein Dirty Hack, da man damit zugibt, die 
Kontrolle über sein Programm verloren zu haben.
Es ist unsauberer Programmierstil. Wenn Deine Programme mal größer und 
komplexer werden, wirst Du das schnell selber merken, es wird Dir 
irgendwann auf die Füße fallen.


Peter

Autor: R. Max (rmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:

> ok, ist keine Appnote, ist ein FAQ-Eintrag

Da heißt es "Example Code (GCC) Resetting the AVR every 30mS:", Du 
willst ihn aber nicht alle 30ms resetten, sondern nur einmal, also musst 
Du den Watchdog nach dem Reset innerhalb von 30ms wieder abschalten.

>> Kannst Du den Spieß nicht umdrehen und gleich den Watchdog-Reset als
>> Timeout zum Abschalten nehmen?
>
> wär eine Möglichkeit, man würde sich den timer sparen, das eigendliche
> Problem, behebt es nicht.
> Das ist ja momentan, dassd er WD nicht zu funktionieren scheint und
> scheinbar kein reset auslöst.

Also wenn Dein Exemplar nicht gerade einen Hau hat, dann gibt es keinen 
Grund, warum der WDT mit dem Code, den Du gepostet hast, nicht 
funktionieren sollte. Das Problem dürfte also woanders liegen, als da, 
wo Du es vermutest. Ohne mehr von Deinem Code gesehen zu haben, sehe ich 
leider keine Möglichkeit, Dir weiter zu helfen.

> werden die register und der vor allem der stack von der runtime
> intialisiert?

Der Stack und die Variablen werden von der Runtime initialisiert. Ob die 
auch von definierten Registerinhalten ausgeht oder einen undefinierten 
Zustand annimmt, weiß ich nicht auswendig. Ich wollte ja auch nicht die 
JMP-Variante propagieren, sondern nur festhalten, daß es durchaus einen 
absoluten Sprung gibt.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
R. Max schrieb:
> Vlad Tepesch schrieb:
>
>> ok, ist keine Appnote, ist ein FAQ-Eintrag
>
> Da heißt es "Example Code (GCC) Resetting the AVR every 30mS:", Du
> willst ihn aber nicht alle 30ms resetten, sondern nur einmal, also musst
> Du den Watchdog nach dem Reset innerhalb von 30ms wieder abschalten.

das der alle 30ms resettet liegt ja aber eher da ran, dass nach dem 
reset in der main gleich wieder der timer gestartet wird.

>
>>> Kannst Du den Spieß nicht umdrehen und gleich den Watchdog-Reset als
>>> Timeout zum Abschalten nehmen?
>>
>> wär eine Möglichkeit, man würde sich den timer sparen, das eigendliche
>> Problem, behebt es nicht.
>> Das ist ja momentan, dassd er WD nicht zu funktionieren scheint und
>> scheinbar kein reset auslöst.
>
> Also wenn Dein Exemplar nicht gerade einen Hau hat, dann gibt es keinen
> Grund, warum der WDT mit dem Code, den Du gepostet hast, nicht
> funktionieren sollte. Das Problem dürfte also woanders liegen, als da,
> wo Du es vermutest. Ohne mehr von Deinem Code gesehen zu haben, sehe ich
> leider keine Möglichkeit, Dir weiter zu helfen.

naja, ich wollte euch den Code nicht zumuten.
Habs jetzt aber so gelöst, wie peda es vorgeschalgen hatte, ohne reset, 
mit ner großen schleife ums gesammte programm.

Ist zwar nicht sehr befriedigend, die Ursache des Problems mit dem nicht 
funktionierneden reset nicht gefunden zu haben, aber ich hab keine Zeit 
und Lust mich ewig damit aufzuhalten.

Ich werd das bei gelegenheit nochmal mit nem frischen tiny und nem 
leeren Minimal-Programm testen.

Danke euch allen nochmal.

Autor: R. Max (rmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So habe ich das kürzlich (auch mit einem Tiny25) gemacht, um das Gerät 
mit Watchdog-Reset und dem Pin-Change-Interrupt an PB0 ein- und 
auszuschalten. Die Entprellung und den Code für die eigentliche Funktion 
(simuliertes Kerzenflackern an PB1..PB4) habe ich der Übersichtlichkeit 
halber weggelassen.
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#define F_CPU 8000000UL
#include <util/delay.h>

#define BUTTON (!(PINB & 1<<PB0))

EMPTY_INTERRUPT(PCINT0_vect);

int main(void)
{
    MCUSR = 0;
    wdt_disable();

    PORTB |= 1<<PB0; // Pullup on PB0

    // Pin change interrupt on PB0
    GIMSK = 1<<PCIE;
    PCMSK = 1<<PCINT0;

    while(BUTTON);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sei();
    sleep_cpu();
    sleep_disable();
    cli();
    while(BUTTON);

    for (;;) {
        if (BUTTON) {
            wdt_enable(WDTO_500MS);
            while(BUTTON);
            wdt_disable();
        }
    }
}

Nach dem Reset schaltet der AVR den Watchdog-Timer aus, den PCINT ein, 
wartet ggf. bis der Taster losgelassen wird und geht in den Power-Down. 
Beim Erwachen wartet er wieder auf den Taster und geht dann in die 
Hauptschleife.

Dort wird der Watchdog beim Drücken des Tasters ein- und nach dem 
Loslassen wieder abgeschaltet. Ein Halten der Taste über den 
Watchdog-Timeout hinaus löst den Reset aus und führt zur Abschaltung.

Falls Du Dich über den langen Timeout wunderst: Im vollständigen 
Programm schaltet ein kurzer Tastendruck zwischen verschiedenen 
Betriebsmodi um. Das war auch der Grund, warum ich zum Abschalten den 
Watchdog genommen habe.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so hab ichs in dem adneren Projekt gemacht, einen PCInt ohne ISR.
das geht hier nicht, da ich den PCINT im Programm brauche.

habs jetz aber wie gesagt anders gelöst.

das
    MCUSR = 0;
    wdt_disable();

sollt eaber in code der direkt nach dem start ausgeführt wird.
Wobei das bei deinem großen timeout unkritisch ist.

Autor: R. Max (rmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
> so hab ichs in dem adneren Projekt gemacht, einen PCInt ohne ISR.
> das geht hier nicht, da ich den PCINT im Programm brauche.

Es spricht ja nichts dagegen, den PCINT mit ISR auch zum Aufwecken zu 
benutzen, ggf. halt mit einem zusätzlichen Flag, an dem die ISR erkennen 
kann, ob die CPU gerade aufgewacht ist oder sich im normalen Betrieb 
befindet.

> sollt eaber in code der direkt nach dem start ausgeführt wird.
> Wobei das bei deinem großen timeout unkritisch ist.

Klar, bei extrem kurzen Timeouts kann es in main() schon zu spät sein.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab das
EMPTY_INTERRUPT(PCINT0_vect);
missverstanden, ich dachte das markiert einen Interupt der nicht 
implementiert ist, wodurch ein reset (jmp 0) ausgelöst wird.

aber das wär quatsch.

Aber wie gesagt, mein Problem ist erst mal auf dem pragmatischen weg 
gelöst.

Ob das mit dem wdt-reset in einem Minimalbeispiel klappt, oder mit dem 
selbe COde auf einem anderen Tiny25, probier ishc ein anderes Mal.

Nochmal Danke,
Vlad

Autor: R. Max (rmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
> Ich hab das
> EMPTY_INTERRUPT(PCINT0_vect);
> missverstanden, ich dachte das markiert einen Interupt der nicht
> implementiert ist, wodurch ein reset (jmp 0) ausgelöst wird.

Nein, jmp 0 bekommt man, wenn man gar keine ISR definiert. 
EMPTY_INTERRUPT() baut eine ISR, die nur aus RETI besteht, wobei ich 
mich frage, warum gcc bzw. avr-libc das RETI nicht gleich in die 
Interrupt-Tabelle setzen, sondern zuerst noch einen jmp machen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.