Heyho.
Ich hab zwar hier schon viel gesucht, aber leider nichts passendes
gefunden. Ich hab einen watchdog in auf meinem Tiny85 am laufen. Wenn es
aber von dem einen reset gab, will ich das herausfinden:
1
voidwdt_init(void)
2
{
3
4
uint8_tbuffer;
5
buffer=MCUSR&(1<<WDRF);
6
7
if(buffer==1){
8
IsWatchdogReset=true;
9
}else{
10
IsWatchdogReset=false;
11
};
12
13
MCUSR=0;
14
wdt_disable();
15
16
return;
17
}
Nur ist bei mir IsWatchdogReset immer false. Was mache ich falsch?
Danke für die Hilfe :-)
Eventuell ein simpler Fehler: WDRF ist Bit 3 im Register.
Wenn das Bit gesetzt war steht daher dezimal 8 im Buffer, du prüfst
allerdings auf 1. Ein simples "if(buffer)" wäre hier richtig, das prüft
ob ein beliebiges Bit gesetzt ist.
Probier mal so:
Ooh schon wieder zu langsam :(
Eine kleine Anmerkung habe ich noch. Leg in so einen allgemeinen Puffer
immer das vollständige Register. Wenn du irgendwann mal auf Power-On
Reset prüfen willst wunderst du dich sonst wieso das Bit nicht kommt,
hattest doch sogar gepuffert. Bei einer größeren Funktion geht dann die
Sucherei und Umbau los.
Panorama schrieb:> Ooh schon wieder zu langsam :(>> Eine kleine Anmerkung habe ich noch. Leg in so einen allgemeinen Puffer> immer das vollständige Register. Wenn du irgendwann mal auf Power-On> Reset prüfen willst wunderst du dich sonst wieso das Bit nicht kommt,> hattest doch sogar gepuffert. Bei einer größeren Funktion geht dann die> Sucherei und Umbau los.
Der bessere Tipp wäre auf solch "allgemeine Puffer" komplett zu
verzichten. Variabeln und Funktionen sprechend benennen. Namen wie
"buffer","x","a" usw. einfach weg lassen.
Ach mist, da hatte ich einen denkfehler. Ich hatte das shift genau
falsch herum gelesen - dann käme da eine 1 raus.
wenn ich jetzt aber nach einen watchdog reset prüfe:
1
intmain(){
2
// Gab es einen Watchdog-Reset?
3
if(IsWatchdogReset){
4
5
// Blinken
6
for(inti=0;i<10;i++){
7
8
PB1_on();
9
_delay_ms(100);
10
PB1_off();
11
_delay_ms(500);
12
};
13
};
14
};
Dann blinkt die led nie, auch wenn der watchdog einen reset gemacht
hat??!!
Weis einer wieso? Vielen Dank :-)
Wo setzt Du denn IsWatchdogReset? Ich sehe in main() lediglich die
Abfrage der Variable. Deine Funktion wdt_init() wird auch nirgendwo
aufgerufen.
Zeig Deinen kompletten Code. So ist das sinnfrei.
Watchdog Reset schrieb:> void wdt_init(void) __attribute__((naked))> __attribute__((section(".init1")));
Aha. Wo ist die Definition von IsWatchdogReset? Wann werden globale
Variablen mit 0 initialisiert? Vor oder nach der init1-Section?
Michael Strosche schrieb:> Und an welcher Stelle wird wdt_init überhaupt aufgerufen?
Das passiert durch die Platzerung der Funktion in die Section namens
"init1". Aber ich nehme mal nicht an, dass der Compiler dadurch
automatisch weiß, dass wdt_init() vor main() aufgerufen werden könnte
und zudem auch noch eine globale Variable setzt - Stichwort: volatile.
Aber gerade die Definition der globalen Variablen hat der TO
unterschlagen.... damit die Kristallkugeln weiterhin brav poliert
werden...
Diese merkwürdige Verlagerung der Init Funktion in die init1 Sektion ist
mir nicht so ganz klar. Nötig ist sie für das was wir hier sehen
jedenfalls nicht. Das ganze Spiel geht auch direkt aus der main heraus.
Sollte man solche Handstände machen, wenn man grade noch mit einem
"bitwise and" gekämpft hat? Ich glaube nicht Tim.
Cyblord ---- schrieb:> Diese merkwürdige Verlagerung der Init Funktion in die init1 Sektion ist> mir nicht so ganz klar.
Es gab hier in der Vergangenheit schon diverse Threads, wo wdt_disable()
als erster Aufruf in main() zu spät kam und man dadurch den µC in eine
Art Dauer-Watchdog-Reset versetzt hat.
Die Lösung, die dann immer angeboten wurde, war, den Aufruf von
wdt_reset() in die init1-Section zu verlagern.
Ich habe aber gerade mal die Funktionen des TOs kompiliert und gesehen,
dass standardmäßig erstmal wdt_init() komplett wegoptimiert wird. Es
landet schon gar nicht mehr im lss-File.
Hallo,
ich glaube das Verlagern der Funktion hat etwas damit zu tun, dass der
Watchdog bei einigen AVRs nach einem Reset weiterhin aktiv ist. Dadurch
kann es passieren, dass der Watchdog in der main() evt. nicht
rechtzeitig deaktiviert werden kann. Aber ich bin mir bei init1 auch
nicht sicher.
CU,
Jay
Frank M. schrieb:> Watchdog Reset schrieb:>> void wdt_init(void) __attribute__((naked))>> __attribute__((section(".init1")));>> Aha. Wo ist die Definition von IsWatchdogReset? Wann werden globale> Variablen mit 0 initialisiert? Vor oder nach der init1-Section?
Ach entschuldigung, das vergaß ich tatsächlich:
Jay schrieb:> ich glaube das Verlagern der Funktion hat etwas damit zu tun, dass der> Watchdog bei einigen AVRs nach einem Reset weiterhin aktiv ist
Vollkommen richtig. Beim Tiny85 resettet sich sogar der vorteiler sodass
er in den kürzesten interrupt von 16ms fällt. Dann kommt er nichteinmal
bis zum wdt_disable(); selbst wenn es an derster stelle steht.
Watchdog Reset schrieb:> Ach mist jetzt hat er was beim kopieren verloren:
Ohne das auszuprobieren: Funktioniert der Code so wie beschrieben, wenn
du es schaffst, beim Einfachen Copy & Paste eines gesamten
Codeschnippsels eine einzelne Zeile dazwischen zu verlieren? Jede
Zwischenablage, die ich kenne, kann das nicht...
Das hilft insofern, dass ich so nicht ganz glauben kann, dass der Code
ein vollständiges Beispiel darstellt bzw. scheinbar ja nicht so
ausprobiert wurde (sonst wäre die Variablendeklaration ja im ersten
Copy&Paste-Vorgang mitgekommen). Deshalb auch die Frage, ob der Code so
wirklich funktioniert? (oder halt nicht, aber mit beschriebenem Symptom)
Vielen Dank Fritz, Dein Ansatz funktioniert.
Dem verständnis nach muss man also die globale Variable dann in den
Noinit-Block schieben, damit sie nicht beim Startvorgang des µC
überschrieben wird, oder?
Und woher weiß der Controller, dass get_mcusr() vor wdt_init()
aufgerufen werden muss? Eine Hirarchie kann ich nicht erkennen. Oder
liegt das nur daran, da das mcusr vor dem init steht und das ganze
sequenziell abgearbeitet wird?
Watchdog Reset schrieb:> Eine Hirarchie kann ich nicht erkennen. Oder> liegt das nur daran, da das mcusr vor dem init steht und das ganze> sequenziell abgearbeitet wird?
Nehme ich mal an. Ich glaube den Code habe ich hier im Forum gefunden.