Hallo zusammen, versuche Interrupts die ich im Bootloader über: GICR = _BV(IVCE); GICR = _BV(IVSEL); auf die Bootloadersection umbiege am Ende beim Sprung in die Anwendung nach Adresse 0x0000 wieder zurückzubiegen über: GICR = _BV(IVCE); GICR &= ~_BV(IVSEL); Leider funktioniert das scheinbar nicht, da der Timer nicht läuft. Ich nutze in beiden Sektionen einen Timer. Muss ich im Bootloader sonst noch etwas zurückbiegen bevor das funktioniert? BOOTRST ist gesetzt. Fuses: high: 0xff und low: 0xd8 Wenn ich das Anwendungsprogramm nicht per Bootloader flashe, dann funktioniert es. Das Programm wird durch den Bootloader auch richtig geflashed, da es prinzipiell funktioniert. Displayausgaben funktionieren soweit. Nur wenn über Timer gesteuert etwas auf das Display ausgegeben wird funktioniert dies nicht. Laut Docu müsste IVSEL alles sein um die Interrupts richtig zu biegen. Was könnte da noch fehlen?? Mfg Tobi
Würd jetzt mal spontan behaupten das deine Anwendung den Timer nicht richtig reinitiiert? Poste doch mal....
1 | void timer_init(void) |
2 | {
|
3 | global_Timer = 0; |
4 | global_sec_Timer = 0; |
5 | |
6 | cli(); |
7 | |
8 | // Initialisierung:
|
9 | TCCR0 = (1<<CS00) | (1<<CS02) | (1<<WGM01); // Prescaler von 1024 | CTC-Modus (siehe unten für Beschreibung) |
10 | OCR0 = 53; // Vergleichswert (11059200 * 0,005s / 1024)-1 |
11 | TIMSK |= (1<<OCIE0); // Interrupts aktivieren und damit Timer starten |
12 | sei(); |
13 | |
14 | return; |
15 | }
|
in beiden Fällen.. also Bootloader und Anwendung
Blöde Frage..... muss man den Timer nicht erst stoppen, bevor man den Prescaler ändert..... irgendwas war da doch.....
wie willst den stoppen? Ist doch gestoppt indirekt durch cli() ?!?
Ne ne ... CLI stoppt den Timer nicht..... verhindert nur dessen Interrupt... Aber ich glaub ich bin grad auf dem Holzweg .... was das stoppen bevor man den Prescaler ändert betrifft. Ich glaub das hatte was mit dem Watchdog zu tun...
hm.. also ich habe nun versucht das TIMSK Register vor dem Sprung nach 0x0000 auf 0 zu setzen .. bewirkt aber auch nichts... Ansich müsste der Timer doch einfach neu initialisiert werden mit der o.g. Routine.. aber irgendwas mit Timern / Interrupts muss da wohl noch falsch sein... ich komm nur nicht drauf... Keiner ne Idee?
1 | GICR &= ~_BV(IVSEL); |
Datenblatt: > Within four cycles, write the desired value to IVSEL > while writing a zero to IVCE.
hm.... ok.. also
1 | uint8_t tmp1 = GICR | _BV(IVCE); |
2 | uint8_t tmp2 = tmp1 & (~_BV(IVSEL)); |
3 | GICR = tmp1; |
4 | GICR = tmp2; |
oder direkt:
1 | GICR = 1; |
2 | GICR = 3; |
funktionieren beide nicht... sollten doch nun aber innerhalb vire Zyklen passieren.. schneller kann ich das doch nicht mehr realisieren?!? eigendlich solte doch sogar
1 | GICR = _BV(IVCE); |
reichen da damit doch auch IVSEL richtig gesetzt ist? geht aber auch nicht
Kein Wunder, dass das alles nicht funktioniert. Ich habe nicht umsonst einen Teil des Datenblatt-Zitats fett hervorgehoben.
Ja habs auch gerade gemerkt... bei meinen "tmp1/2" versuchen habe ich nicht berücksichtigt, dass IVCE gleichzeitig wieder auf "0" geschrieben werden muss und bei meiner direkten zuweisung mit den Zahlen muss das natürlich ne 1 und dann ne 0 sein... Denkfehler.. Jetzt gehts auch :) danke für den Stups Stefan. Da wäre ich, trotz dessen dass ich das Datenblatt gelesen hatte!! nicht so schnell drauf gekommen, da ich blind vermutete das meine ursprüngliche Variante
1 | GICR = _BV(IVCE); |
2 | GICR &= ~_BV(IVSEL); |
sicherlich innerhalb der 4 Zyklen sein sollte... Ist auch recht knapp bemessen diese Zeit.. Der Codeteil wäre sicher gut für inlien Assembler... wenn mans beherrschen würde :)
Tobi schrieb: > Da wäre ich, trotz dessen dass ich das Datenblatt gelesen hatte!! nicht > so schnell drauf gekommen, da ich blind vermutete das meine > ursprüngliche Variante
1 | GICR = _BV(IVCE); |
2 | GICR &= ~_BV(IVSEL); |
> > sicherlich innerhalb der 4 Zyklen sein sollte... Aber auch da ist der Knackpunkt nicht die 4 Zyklen, sondern die Tatsache, dass du in der 2. Zeile eine 1 nach IVCE schreibst.
hm.. jetzt wo dus sagst :) Man sollte eben nicht immer allem was man aus dem Netz kopiert blind vertrauen :) Also so funktionierts jetzt auch:
1 | GICR = _BV(IVCE); |
2 | GICR &= ~(_BV(IVSEL)|_BV(IVCE)); |
Danke!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.