Forum: Mikrocontroller und Digitale Elektronik Interrupts umbiegen scheint nicht zu funktionieren


von Tobi (Gast)


Lesenswert?

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

von Chris D. (m8nix)


Lesenswert?

Würd jetzt mal spontan behaupten das deine Anwendung den Timer nicht 
richtig reinitiiert?
Poste doch mal....

von Tobi (Gast)


Lesenswert?

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

von Chris D. (m8nix)


Lesenswert?

Blöde Frage..... muss man den Timer nicht erst stoppen, bevor man den 
Prescaler ändert..... irgendwas war da doch.....

von Tobi (Gast)


Lesenswert?

wie willst den stoppen? Ist doch gestoppt indirekt durch cli() ?!?

von Chris D. (m8nix)


Lesenswert?

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...

von Tobi (Gast)


Lesenswert?

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?

von Stefan E. (sternst)


Lesenswert?

1
GICR &= ~_BV(IVSEL);

Datenblatt:
> Within four cycles, write the desired value to IVSEL
> while writing a zero to IVCE.

von Tobi (Gast)


Lesenswert?

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

von Stefan E. (sternst)


Lesenswert?

Kein Wunder, dass das alles nicht funktioniert.
Ich habe nicht umsonst einen Teil des Datenblatt-Zitats fett 
hervorgehoben.

von Tobi (Gast)


Lesenswert?

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 :)

von Stefan E. (sternst)


Lesenswert?

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.

von Tobi (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.