Forum: Compiler & IDEs Interrupts im Bootloader


von Manuel Rass (Gast)


Lesenswert?

Hallo,
ich bin gerade über einen Bootloader für einen Mega16.

Soweit funktioniert alles.
Der Bootloader (primitiv, ohne Interrupts) funktioniert und startet
auch die normale Applikation.

Jetzt will ich aber im Bootloader Interrupts verwenden (Timer, Usart).
Die Interrupt-Vektortabelle hab ich in den Bootloader Bereich
verschoben, kann ich auch aus dem Map-File lesen.

Ohne die globale Interruptfreigabe läuft der Bootloader ganz normal.
Das kan nich an einer blinkenden LED erkennen.
Wenn ich aber die Interrupts freigebe, scheint es, als ob er beim
ersten Timer-Interrupt ins Nirvana läuft (LED-blinkt nicht mehr).

Ich habe mich schon durch verschieden Threads hier gelesen, doch leider
bekomme ich es dadurch auch nicht zum Laufen.


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include "main.h"

#define FCPU  14745600
#define TIMER_LOAD ((unsigned char) (256 - ((FCPU / 64) * 0.001)))  //
1ms-Timer


void main(void)
{
  static volatile unsigned int i, j, k;

  cli();              // Interrupts sperren

  GICR = 0x01;          // Interrupt Vektoren in den Bootloader bereich
verschieben
  GICR = 0x02;

    TIMSK = (1<<TOIE0);        //Timer 0 Overflow Interrupt aktivieren
    TCNT0 = TIMER_LOAD;        //Timer 0 Startwert setzen
    TCCR0 = 3;            //Timer 0 Prescaler = 64 -> Timer Taktfrequenz 
=
FCPU / 64

  DDRB = 0x07;
  PORTB |= 0x07;

//  sei();              // Interrupts freigeben

  PORTB &= ~0x02;          // LED 2 einschalten

  while(1)
  {
    for(j=0; j<10; j++)      // 10 Mal
    {
      k = 0;          // warten
      for(i=0; i<50000; i++)
        k++;

      if(PORTB & 0x01)    // LED 1 toggeln
        PORTB &= ~0x01;
      else
        PORTB |= 0x01;
    }

    PORTB |= 0x02;        // LED 2 ausschalten

    k = 0;            // warten
    for(i=0; i<65000; i++)
      k++;

    StartApp();          // Applikation starten
  }
}


void StartApp(void)
{
  GICR = 0x01;          // Interrupt Vektoren ins Flash verschieben
  GICR = 0x00;

  asm volatile   ("push r1" "\n\t"
          "push r1" "\n\t"
          "ret"     "\n\t"
          ::);
}


SIGNAL(SIG_OVERFLOW0)
{
  PORTB &= ~0x04;          // LED 3 einschalten
}

Kann mir irgendwer Tipps geben?

Gruß
Manuel

von Manuel Rass (Gast)


Lesenswert?

Problem hat sich erledigt.
Danke.
Manuel

von Peter D. (peda)


Lesenswert?

"Problem hat sich erledigt"

Diese Antworten liebe ich :-(

Wäre es nicht besser, sich nicht als Egoist zu outen ?

Wenn Du willst, daß alle sich mit Deinem Problem beschäftigen, dann
sollte man doch auch die gefundenen Lösungen öffentlich machen.


Peter

von Manuel Rass (Gast)


Lesenswert?

Ich hatte im Makefile den Bootloader an eine andere Stelle verschoben
als in den Fuses angegeben.
So wurde das Programm zwar ausgeführt, als aber dann ein Interrupt
ausgelöst wurde landete der Sprung im Nirvana und der Bootloader wurde
von vorne ausgeführt. Dadurch war auch kein Blinken der LED mehr zu
erkennen.

Also:
Achtung beim verschieben des Bootloaders im Makefile.
Im Makefile werden Byte-Adressen verwendet und bei den Fuses
Word-Adressen.
Beim mega16 und 1024 Word Bootloader entspricht die Startadresse 0x1C00
(Word) bzw. 0x3800 (Byte). Bei 512 Word Bootloader entspricht die
Startadresse 0x1E00 (Word) bzw. 0x3C00 (Byte).

Ich hatte die Einstellungen versehentlich vermischt. In den Fuses auf
0x1C00 (Word) und im Makefile auf 0x3C00 (Byte).

Gruß
mrMR

von ape (Gast)


Lesenswert?

Hallo!
Ich sitze gerade an einem ganz ähnlichen Problem.
Und zwar möchte ich auch einen Bootloader im mega16 zu implementieren.
Funktioniert soweit ganz gut. Hänge jetzt aber auch an den Interrupts.
Ist ja im Prinzip kein großes Problem aber wie sag ich nun dem avr-gcc
das er die Interrupt-Sprungtabelle an den Anfang des
Bootloaderbereiches schreiben soll?

mfg
ape

von ape (Gast)


Lesenswert?

mhmm also hab nochmal ein wenig gesucht und ein beispiel gefunden wo im
makefile schon die .text section in den bootloader bereich geschoben
wird dann stehen auch interruptvektoren im bootloader bereich aber
irgendwie müsste man doch auch 2 tabellen anlegen können eine im
application bereich und eine im bootloader...

von mthomas (Gast)


Lesenswert?

Erstmal ein wenig "Eigenwerbung":
http://www.siwawi.arubi.uni-kl.de/avr_projects/#avrprog_boot
Dort findet sich ein Bootloader in avr-gcc fuer den ATmega16. Code und
Makefile sind so gestaltet, dass auch fuer den Bootloader eine
"Interrupttabelle" erzeugt wird, obwohl dieser Bootloader selbst
keine Interrupts nutzt (wuesst auch nicht wirklich warum - aber
einerlei). Ist in meinem Code eher eine "parnoia"-Einstellung um
sicherzustellen, das nicht irgendein Seiteneffekt aus der Applikation
auftritt.
Wichtig ist, dem uC mitzuteilen welcher Interruptvektor zu verwenden
ist. Nehme an, das ist das Problem. Dazu setzt man IVCE im MCUCR des
Mega16. Hierbei ist eine bestimmte "timed sequence" inzuhalten.
Erlaeuterungen im Datenblatt, Beispiel im og. Bootloader.
HTH, Martin

von Ralf Kummetat (Gast)


Lesenswert?

Hallo,
leider läßt sich das Bootprogramm von Martin nicht mit dem AVR-Studio4
debuggen, obwohl Fuse-bit Boot Reset enabled ist.
Gruß Ralf

von mthomas (Gast)


Lesenswert?

Wenn recht erinnert, gibt es zu "Bootloader simulieren" im Studio4
einige Threads in den avrfreaks.net Foren. Funktioniert wohl nicht so
einfach, aber mglw. gibts auch neuere Information in diesen Threads.
BTW: warum noch debuggen, bzw. was fehlt dem Bootloader?
Martin

von Ralf Kummetat (Gast)


Lesenswert?

Hallo Martin,
weil ich ein anderes Bootprogramm benötige, welches in einem Bussystem
einzelne Stationen updaten kann.
Gruß Ralf

von mthomas (Gast)


Lesenswert?

Ah ok, sowas hab' ich auch in Planung, verteiltes "Flash Update ueber
RS485". Ist aber noch in den "Kinderschuhen".
Viel Erfolg bei dem Projekt.
Martin

von Stefan Bachmaier (Gast)


Lesenswert?

Hallo,

ich bin auch grad auf der Suche nach Informationen betreffend "Flash
Update ueber RS485", finde aber keine Möglichkeit

a) den Atmega vom Programm aus zu resetten
b) vom Programm aus den Bootloader zu starten

Könnt ihr mir da helfen?

von Jörg Wunsch (Gast)


Lesenswert?

> ...finde aber keine Möglichkeit

> a) den Atmega vom Programm aus zu resetten

Einen wirklichen Reset kannst du nur über ein mit /RESET verbundenes
Port-Pin oder über den Watchdog erreichen.

Falls es dir auf den Zustand der Hardware (IO-Register) nicht ankommt,
kannst du natürlich auch einen Sprung zur Adresse 0 ausführen.

> b) vom Programm aus den Bootloader zu starten

Ein ganz normaler Sprungbefehl, oder was meinst du?

von Stefan Bachmaier (Gast)


Lesenswert?

a) Ist klar..

b) Ok, habs grad eben in der AN von Atmel gelesen wie's geht.
Dankeschön!

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.