Forum: Compiler & IDEs Reset aus C auslösen möglich?


von beta-frank (Gast)


Lesenswert?

Hallo,

in einem Programm macht es Sinn, den AVR zu resetten. Wie kann man das
anstellen (ohne WatchDog;-)? Programmiere unter WinAVR.

Thx Frank

von A.K. (Gast)


Lesenswert?

Da die AVRs keinen RESET Befehl kennen, bleibt sonst nur die Möglichkeit
per Hardware. Direkt via Pin oder über 20 Ecken. Aber das hattest Du
wohl auch nicht im Auge, oder? Wenn man allerdings alle möglichen
Lösungen vorsorglich ausschliesst, landet man unweigerlich irgendwann
im Unlösbaren.

von Rufus T. Firefly (Gast)


Lesenswert?

Man könnte den Resetvektor in den PC laden. Allerdings wird dann die
Hardware nicht zurückgesetzt, aber das Programm liefe wieder "von
vorne" an.

von Peter D. (peda)


Lesenswert?

Z.B. so:

cli();
(((void(*)(void))0x0000)());

Allerdings mußt Du die neueste Version nehmen, ältere haben einen Bug,
dann geht es nur so:

cli();
__init();


Das hat auch den Vorteil, daß die Ausgänge nicht kurzzeitig floaten,
wie es bei einem echten Reset der Fall wäre.



Peter

von ---- (Gast)


Lesenswert?

Leider sind die oben beschriebenen Verfahren kein 100% korrekter Ersatz
für einen sauberen Reset (kein Register wird auf seinen Defaultwert
zurückgesetzt; bei manchen NichtAVR-Mikrocontrollern gibt auch sogen.
WriteOnce-Register - damit hättest du dann auch ein Problem ohne
richtigen Reset...).

Was spricht gegen den Einsatz des Watchdogs?

@Peter: Das mit dem Floaten darf ja bei einem 'normalen' Reset auch
nicht zum Problem werden...

----, (QuadDash).

von beta-frank (Gast)


Lesenswert?

Hmm, dachte, da gibts einen Trick 17. Wenn der AVR also neu anlaufen
soll, werd ich wohl doch den WatchDog von der Leine lassen.

Danke, Frank

von peter dannegger (Gast)


Lesenswert?

@QuadDash,

zu einem sauberen Programierstil gehört, daß man sämtliche verwendeten
Register initialisiert.

Wenn man dann noch Angst hat, das ein Programmirrläufer falsche
Interrupts freigibt, kann man zusätzlich noch sämtliche nicht benutzten
Interrupts sperren.

Und dann reicht durchaus ein simpler Restart aus.


"Das mit dem Floaten darf ja bei einem 'normalen' Reset auch
nicht zum Problem werden..."

Meistens wird ein Verückspielen angeschlossener Hardware beim
Einschalten toleriert oder durch eine Einschaltverzögerung verhindert.
Inmitten eines Programms will man sowas aber nicht haben.


Peter

von ---- (Gast)


Lesenswert?

> zu einem sauberen Programierstil gehört, daß man sämtliche verwendeten
Register initialisiert.

theoretisch schon - aber praktisch kann das beim guten Vorsatz bleiben,
wenn beispielsweise Fremdmodule in den Code eingebunden werden usw..
Was wenn aber ein Bit eines Configregisters fälschlicherweise gesetzt
wurde (z.B. durch Softwarebug), bzw. durch äußere Einflüsse sich
selbständig gesetzt hat, dann bist du evtl. nach dem selbstgestrickten
Reset noch genauso naß, da du dieses Register nicht initialisiert hast
- oder etwa doch?
Falls doch, dann ist es bedeutend weniger aufwendig einen Watchdogreset
auszulösen, als jedes (auch unbenutzte) (Config-)Register zu
initialisieren.

Für kleine selbstgestrickte AVR-Software trifft das alles zu was du
sagst - für größere Projekte nicht unbedingt.


Und wenn wir schon bei eher theoretischen Betrachtungen (fernab von
AVR) sind:
Manche Mikrocontroller haben einen bidirektionalen Resetpin, der im
Resetfall nach außen hin das ResetSignal treiben kann, sodaß daran
angeschlossene Resetcontroller oder sonstige externe Hardware (z.B.
SPI-Treiber) somit auch gleich zurückgesetzt werden kann.

-> Es gibt einige Punkte, die für einen richtigen Reset sprechen.

----, (QuadDash).

von ---- (Gast)


Lesenswert?

> Verückspielen angeschlossener Hardware [] durch eine
Einschaltverzögerung verhindert.

Stimmt, das ist auch eine Möglichkeit.

----, (QuadDash).

von Jörg Wunsch (Gast)


Lesenswert?

> zu einem sauberen Programierstil gehört, daß man sämtliche
> verwendeten Register initialisiert.

Nein, das ist Verschwendung.  Ein Register, für das mir der Hersteller
einen bestimmten Wert nach Reset garantiert (oder eine Variable, für
die mir der C-Standard das generiert), muss ich nicht nochmal selbst
auf ebendiesen Wert setzen.  Das vergeudet ROM und CPU-Zyklen, beides
teuer auf einem Controller.

Klar, wenn ich möchte, dass meine Applikation über einen Sprung auf 0
neu gestartet werden kann, dann muss ich all die IO-Register auf ihre
Initialwerte setzen, die ich selbst verändere, aber dann war ich das
auch selbst, der das so wollte.  (C-Variablen werden auch in diesem
Falle initialisiert.)

von peter dannegger (Gast)


Lesenswert?

@Jörg Wunsch

"Nein, das ist Verschwendung."

Na na !

Wer beim GCC Erbsen (Bytes) zählen will, muß schon was anderes nehmen.

Im GCC gibt es genügend anderen nicht optimalen Code, z.B. oft erzeugt
er für 8Bit Operationen 16Bittigen Code (Switches).

Da machen die paar Bytes Init-Code den Kohl auch nicht mehr fett.


Und wenn es für die Funktion wichtig ist, schreibe ich auch:

PORTB = 0x00;

Damit dann ein anderer weiß, wenn er daran dreht, könnte es Folgen
haben. Also bessere Lesbarkeit hat da den Vorrang.


Natürlich ist der Sprung nach 0x000 nur sinnvoll, wenn es ein regulärer
Zustand im Programm ist.
Um irgendwelche Bugs oder Irrläufer zu verschleiern, taugt er nicht.


Peter

von Jörg Wunsch (Gast)


Lesenswert?

Die Nichtoptimalitäten im GCC könnten sich aber reparieren lassen, die
in deinem Code nicht. ;-)

Für den gewünschten Dokumentationseffekt würde es genügen, die
entsprechenden Anweisungen als Kommentar zu schreiben mit der
Bemerkung, dass es sich um den Hardwarezustand handelt.  Aber ich
halte selbst das für überflüssig und würde es bestenfalls durch einen
globalen Satz ersetzen, dass die Hardware sich im für Reset
dokumentierten Zustand befinden muss.  Wofür ist der denn exakt
spezifiziert worden, wenn ich mich hinterher plötzlich nicht mehr
drauf verlassen können soll?

von MSE (Gast)


Lesenswert?

>> Im GCC gibt es genügend anderen nicht optimalen Code, z.B. oft
>> erzeugt er für 8Bit Operationen 16Bittigen Code (Switches).

Hab' ich auch neulich mit tiefer Trauer zur Kenntnis genommen. Ist
jemandem bekannt, ob geplant ist, diesen Umstand zu ändern?
Oder gibt es eine Compiler-Option, die in switch( char ) nur ein Byte
auswertet?

Gruß, Michael

von Thorsten (Gast)


Lesenswert?

@Jörg Wunsch

> Ein Register, für das mir der Hersteller einen bestimmten Wert nach
> Reset garantiert

Na du hast hast aber großes Vertrauen in die Hersteller.

> ...bestenfalls durch einen globalen Satz ersetzen, dass die Hardware

> sich im für Reset dokumentierten Zustand befinden muss

Genau, sowas liebe ich! Die große Frage ist: wie ist dieser Zustand
dokumentiert? Also Datenblatt raus, und alle Register nachlesen.
Blödsinn! Sehr schön für Leute, die mit einem Prozessor nicht soo
vertraut sind, die kriegen dann nämlich die Krise. Die Variante, alle
verwendeten Register zu initialisieren, finde ich sehr sinnvoll. So
weis jeder, welchen Zustand die Register haben. Spart viel Zeit und
Unklarheiten.

Thorsten

von Jörg Wunsch (Gast)


Lesenswert?

Da haste aber bei den neueren ATmegas mit ihren vielen Registern
mächtig was vor...  Davon abgesehen, eigentlich habe ich bei AVR
bisher noch keine Verleztung des POLA (principle of least
astonishment) bei den Initialwerten erlebt, d.h. die IO-Register
kommen mit einer Voreinstellung daher, die man auch so erwarten würde.
Portregister stehen alle auf Eingabe, Timer sind im Stop-Zustand,
UARTs generieren, nachdem man ihnen die Baudrate auf die Reihe gibt
8N1-Frames, ...  Ich habe wirklich noch keine Überraschung erlebt.

Die Erweiterung vieler Werte auf einen `int' hat einfach erstmal den
Grund, dass der C-Standard das so verlangt.  Klar, der Compiler darf
danach auch noch so intelligent sein festzustellen, dass sich nichts
ändern würde, wenn man den Wert anschließend wieder auf ein Byte
verkürzt, aber hier zeigt sich, dass der AVR als 8-Bit-Plattform
einfach in der Entwicklerkapazität bei GCC völlig unterrepräsentiert
ist.  Die Hauptarchitekturen des GCC stört das überhaupt nicht, dass
die Daten auf einen int erweitert werden, im Gegenteil, deren
Prozessoren arbeiten typischerweise mit Registern, die selbst einen
int (oder gar noch mehr) fassen können.

> ,,...ob geplant ist, diesen Zustand zu ändern?''

Weiß nicht, planst du es denn, Michael?

Mir dünkt, du hast noch nicht ganz verstanden, wie eine Opensource-
Entwicklung so abläuft...  Nein, wenn es keiner macht, wird es auch
nicht passieren.  Oder: wenn du es nicht machst, ich es nicht mache,
... es nicht macht -- dann macht es niemand.

von A.K. (Gast)


Lesenswert?

@MSE:

Nu, das gibt es doch schon. -mint8. Nur warum derjenige, dem wird die
AVR-Portierung zu verdanken haben, dennoch in Version 3 unbedingt
64-Bit Datentypen brauchte (wodurch dann 32 Bit im schwarzen Loch
verschwinden), erschliesst sich mir nicht.

Wozu der GCC fähig ist, zeigt er erst mit -mint8. Nur die Lib kommt da
teilweise nicht mit, aber wer benutzt schon printf wenn's arg auf die
Grösse ankommt. Aber verwendbar ist es durchaus, man muss halt nur
genau wissen was man von der Lib verwendet.

von Peter D. (peda)


Lesenswert?

"Da haste aber bei den neueren ATmegas mit ihren vielen Registern
mächtig was vor..."


Ich initialisiere natürlich nur die IO-Register, die ich auch benutze.
Bei allen anderen (z.B. AD-Wandler) gehe ich davon aus, daß sie nach
dem Reset im inaktiven Zustand sind.


Peter

von Jörg Wunsch (Gast)


Lesenswert?

> Bei allen anderen (z.B. AD-Wandler) gehe ich davon aus, daß sie nach
> dem Reset im inaktiven Zustand sind.

Das ist aber nach deinem sonstigen Misstrauen gegenüber dem Hersteller
eine sehr mutige Annahme. :-))

von peter dannegger (Gast)


Lesenswert?

Ich habe nirgends Mißtrauen geäußert.

Ich habe nur gesagt:

Wenn ich für eine Funktion benötige, daß Register X den Wert Y haben
muß, dann schreibe ich das hin, um es zu dokumentieren, unabhängig
davon, ob der Wert Y zufällig auch der Resetzustand ist.

Wie gesagt, wirkt sich das nicht signifikant auf die Codegröße aus, und
auf die Ausführungszeit schon gar nicht.


Peter

von Jörg Wunsch (Gast)


Lesenswert?

Tja, und ich finde es eben völlig überflüssig.  Schließlich setze ich
auch nicht den PC extra auf 0, sondern vertraue darauf, dass der
Hersteller ihn wirklich auf 0 gesetzt hat nach einem Reset.

Da können wir uns halt nicht einigen, macht nix.

von peter dannegger (Gast)


Lesenswert?

"Schließlich setze ich auch nicht den PC extra auf 0"


.org irgendwo
rjmp 0


Das ist wohl das einzige Register, welches man nicht in Software von
einem unbekannten Wert auf einen bekannten setzen kann.


"Da können wir uns halt nicht einigen"

Zwingt uns ja niemand dazu.


Peter

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.