Hallo,
ich traue mich mit dem Problem ja fast nicht zu fragen.
Aber so langsam habe ich das Gefühl, der ATmega1284p bootet einfach
ständig neu und daher blinkt die LED scheinbar immer im gleichen Takt.
Selbst wenn ich die LED nur einfach einschalte, flackert diese ?!?!
Also Programm auf ein Minimum lesbar reduziert.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
#define LED_PIN (PD6)
5
#define LED_PORT (PORTD)
6
#define LED_DDR (DDRD)
7
8
#define SET_LED_ON (LED_PORT |= _BV(LED_PIN))
9
#define SET_LED_OFF (LED_PORT &= ~_BV(LED_PIN))
10
#define SET_LED_TOGGLE (LED_PORT ^= _BV(LED_PIN))
11
12
#define nop() asm("nop;")
13
14
int main(void)
15
{
16
LED_DDR|= _BV(LED_PIN);
17
while(1)
18
{
19
SET_LED_ON; // Testweise, aber auch flackert die LED
20
//SET_LED_TOGGLE;
21
_delay_ms(1000); // egal welchen Wert ich nehme 200,500,1000 Das Flackern ändert sich nicht
22
}
23
}
compiliert und geladen wird es mit (Zum test sogar ohne Makefile):
die Fuses sind wie folgt gesetzt:
avrdude: safemode: Fuses OK (E:FC, H:D1, L:FF)
Der ATmega1284 läuft mit einem externen 16MHz Quarz an 5V
Was habe ich übersehen ?!
Anfangs hatte ich for schleifen als delay eingebaut, selbes Ergebnis.
Wäre dankbar, wenn mir jemand das Brett vor dem Kopf weg nimmt.
Juergen
Der Aufbau geht.
Habe auch schon mehrere IO Pins versucht.
Die Prinzipielle Ansteuerung geht auch.
Schalte ich die LED am Anfang mit SET_LED_OFF aus, also nie an, bleibt
die Dunkel.
Erst wenn ich einen SET_LED_ON nutze geht die auch an, oder besser
flackert eben sehr schnell.
Ich denke eher ich bin in so einem Kompatibilitätsmodus und daher stürzt
das Program ab und der AVR bootet ständig neu, wodurch die Ports zurück
gesetzt werden und die LED ausgeht.
Juergen
Kuriose Sache.
hatten die Platine jetzt für ca. 5 Minuten abgeschaltet.
und seither geht alles wie erwartet.
Ich kann auch die Zeiten ändern, einspielen und tut.
WTF ? (sorry)
Jürgen
Teo D. schrieb:> Bei dem Fehlerbild, hat er entweder garnicht oder immer das selbe> Hex-File gebrannt.
Das kann ich 100% ausschließen.
1. Hatte ich das auch vermutet und daher genauer drauf geachtet
2. war das File immer unterschiedlich groß durch die tests
3. hat avrdude auch immer die passende Größe, also Unterschiedliche
Größe übertragen.
Reproduzieren läst es sich auch nicht mehr, es tut seither einfach, ich
kann einspielen, Änderungen vornehmen, es geht wie es soll....
Dachte auch schon an den STK200, habe aber den Reset abgezogen um sicher
zu sein. Hat aber keinen Unterschied gemacht.
Mich ärgert dabei immer die Zeit die man in den Sand setzt und nicht
weis warum.
Danke trotzdem.
Juergen
Jürgen S. schrieb:> hatten die Platine jetzt für ca. 5 Minuten abgeschaltet.> und seither geht alles wie erwartet.> Ich kann auch die Zeiten ändern, einspielen und tut.
Ohne ein einziges Byte am Code zu ändern? Dann werden wir es nie
erfahren.
Ähnlicher Fall: Was mich mal sehr sehr lange beschäftigt gehalten hatte:
Der Compiler hatte mein (selbstgeschriebenes) delay einfach
wegoptimiert.
Jürgen S. schrieb:> Teo D. schrieb:>> Bei dem Fehlerbild, hat er entweder garnicht oder immer das selbe>> Hex-File gebrannt.>> Das kann ich 100% ausschließen.> 1. Hatte ich das auch vermutet und daher genauer drauf geachtet> 2. war das File immer unterschiedlich groß durch die tests> 3. hat avrdude auch immer die passende Größe, also Unterschiedliche> Größe übertragen.
Dann haste nen echten Gremlin erwischt. ;)
Das lässt mich dann auch nicht mehr los. Wenn sie sich dann doch
zeigten, war's eigentlich immer, ein saudämlicher Fehler von mir. :D
Das ist wie ein eingebrannter Blinder-Fleck.
Nun, ich kann das ganze doch etwas Reproduzieren.
Und zwar, wenn ich Code in den Bereich des Bootloaders lade.
Der Bootloader Funktioniert wie erwartet (ist ja auch unverändert seit
Jahren, außer dass ich nun mit 16MHz, statt 8MHz CPU Takt fahre.
Soweit alles ok.
Lade ich nun per Bootloader den neuen Code in die CPU, habe ich das
Flackern wieder.
Ein Hardware Reset der CPU ändert nichts, ich muss jetzt wirklich einen
Power OFF=>On machen, dann läuft das eingespielte Programm wie erwartet.
Springe ich nun von meinem Programm aus in den Bootloader, bekomme ich
wieder das Flackern.
Ich meine mich Dunkel zu erinnern, dass man bei manchen ATmega nach
einen Software Reset manche Register nicht im gleichen Zustand hat wie
bei einem Power On ?!
Oder habe ich mich komplett verlaufen....
Sowohl Bootloader und Programm funktionieren so eigentlich schon auf
einer Baugleichen Platine.
Nur läuft da die CPU noch mit dem Internen 8MHz Takt (Taktteiler ist
aus).
Der Bootloader ist als normales eigenständiges Programm implementiert
und wird an die Start Adresse des Bootloaders geladen.
Einen Sprung dorthin löst also die Neuintialisierung per Code aus.
Der Gedanke ist eigentlich folgender:
Strom AN
AVR springt in den Bootloader
Bootloader macht eine Checksummen Prüfung des Flash
Ist die Checksumme ok, noch etwas Delay (damit man ein update starten
kann) und Sprung ins Hauptprogramm, was ein Sprung an Adresse 0x0000
bedeutet....
Der Bootloader läuft komplett ohne Interrupts, das Hauptprogramm
schon...
Interrupts werden natürlich im Bootloader sofort deaktiviert.
Aber genau so mache ich das schon seit Jahren.
Also kann es ja fast nur etwas mit den Fuses sein, die habe ich ja im
ersten Post aufgeführt.
Hoffe einer bringt mir die Erleuchtung.
Gruss
Jürgen
NACHTRAG:
ich habe sowohl im Hauptcode, als auch im Bootloader folgenden Code, der
wohl notwendig ist, um den Watchdog aus zu schalten:
ich kann nur sagen "Mea culpa", Asche auf mein Haupt...
Alles gut, alles geht.
In meinem Testcode hatte ich genau den obigen Code zum Initialisieren
des Watchdog nicht eingebaut, oder besser auskommentiert.
Nachdem dieser wieder im Bootloader und Hauptprogramm aktiv ist, ist
alles ok, bis jetzt.
Wenn ich das richtig verstehe, ist bei diesem ATmega der Watchdog aktiv
und man muss den sehr früh abschalten. Daher oberer Code, der im frühen
"Init" des Programms liegt, den noch der Compiler Automatisch erzeugt.
Ein wdt_disable(); im Hauptprogramm kommt da wohl zu spät.
Und herausgefunden habe ich das durch Subversion, womit ich mein
Projekte verwalte (Und Nein, ich nutze kein git :-) ). Einmal die
History durchsehen und TATA, da steht es doch direkt im Kommentar der
Revision :-)
Gruss
Juergen
Jürgen S. schrieb:> Wenn ich das richtig verstehe, ist bei diesem ATmega der Watchdog aktiv
Ist nicht meine Welt aber lässt er sich nicht auch per Fuses
deaktivieren?
KA, ob das bequemer ist.
Jürgen S. schrieb:> Wenn ich das richtig verstehe, ist bei diesem ATmega der Watchdog aktiv
Nicht ab Werk, nein.
Er muss also später aktiviert worden sein, entweder direkt durch dich
selber oder als "Nebenprodukt" durch das Flashen des Bootloaders. Also
auch wieder: durch dich selber, wenn auch vielleicht nicht absichtlich.
Vermutlich ist es so: Der Bootloader benutzt den Watchdog-Reset, um die
Anwendung garantiert mit dem Reset-Hardwarezustand zu starten, der im DB
steht.
Nötig ist das nicht wirklich. Ein anständiger Bootloader kann diesen
Zustand auch gezielt herstellen, ohne dazu den Watchdog benutzen zu
müssen. Er wird dann allerdings eine Handvoll Bytes größer ausfallen
müssen, was bei einem Mega1284P keine Rolle spielt (bei kleinen AVR8
aber eventuell wichtig sein kann).
Springen zwischen Bootloader und APP mache ich nicht durch den Watchdog,
der bringt mich nur zurück in den Bootloader :-)
Der Bootloader ist wie folgt definiert:
1
typedef void ( *bootloader_stub ) ( void );
2
bootloader_stub bootloader = (bootloader_stub)(BOOTLOADER_ADR / 2); // Need to be in WORD Address
Und so kann ich einfach mit "bootloader();" in den Bootloader springen.
Den Watchdog benutze ich aktuell nur, wenn ich den ATmega gezielt
Reseten möchte.
Wobei ich Praktisch als erstes in jedem Hauptprogramm ein wdt_disable()
stehen habe. Er sollte also in jedem Fall aus sein, wohl nur nicht
schnell genug.
Wieso flackerte dann die LED, obwohl ich nicht mal den Ausgang anmachen
konnte?
Spekulation:
- Portpin geht direkt auf den Eingang eines ULN2803, an dessen Ausgang
die LED hängt.
- Was mir nun auffällt ist, dass wenn der Pin noch ein Eingang ist,
Glimmt die LED bereits
- Dadurch das die LED bereits glimmt, kam es zur Fehlinterpretation, der
ATmega würde die LED bereits ansteuern, soweit kam er wohl nicht, wurde
resetet => LED AUS.
Nun denn, der Fehler ist gefunden und eingrenzbar.
Der Hintergrund zu dem Code ist etwas näher hier erläutert:
Beitrag "problem mit wdt zurücksetzen"
Gruss
Juergen
Jürgen S. schrieb:> Wenn ich das richtig verstehe, ist bei diesem ATmega der Watchdog aktiv> und man muss den sehr früh abschalten.
Nö, der ist nicht aktiv.
Wurde er jedoch gesetzt, läßt er sich nur durch Power off oder diese
spezielle Sequenz abschalten.
Ein anderes Reset oder Setzen der Fuses schaltet ihn nicht ab!
Das frühe Abschalten oder Setzen auf eine längere Zeit ist nur
notwendig, wenn viel externes RAM angeschlossen ist oder der CPU-Takt so
langsam, daß das RAM-Init nicht innerhalb 16ms abgeschlossen ist.
Aus den Tiefen der avr-libc
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). It is therefore required to turn off the watchdog early
during program startup, the datasheet recommends a sequence like
the following:
Da habe ich auch den Code her.
Ich verstehe das so, hat man den Watchdog einmal aktiv, kriegt man ihn
nur damit wieder aus.
Der ATmega1284p hat ja schon etwas mehr RAM. eventuell dauert das Init
deswegen zu lange.
Das ist auf alle Fälle die Lösung zu meinem Problem.
Und da dies selbst einen Reset überlebt, überlebt der Watchdog
vermutlich auch ein Programm upload per ISP.
Ist das "Problem", also Watchdog aktiv, einmal da, hilft nur noch der
Power Off.
Gruss
Juergen