mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AT89- bzw. 8051-Bootloader anspringen


Autor: Patrick G. (pgr8051)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich nutze den Atmel AT89*CC02 Controller mit CAN. Ich möchte den 
Bootloader (wohl Adresse 0xf800) gerne durch Umbiegen eines 
Funktionszeigers anspringen, z. B. so:

  void (*func)(void) = 0xf800; // Pointer auf Bootloader klarmachen
  (*func)(); // Pointer anspringen

Mit dem Keil-Kompiler klappte das fast. Eine Connection zum 
CAN-Bootloader gelang, nur das Hochladen blieb immer irgendwo bei 90 % 
stecken. Mit dem freien SDCC geht's gar nicht mehr.

Ziel ist das Starten des Bootloaders über eine bestimmte CAN-Nachricht. 
Ist die Vorgehensweise hier total unorthodox? Kann ich das auch anders 
realisieren, und zwar nur auf Softwareebene?

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Hm, dass er sich aufhängt, ist komisch... AUXR1-Flag vorher gesetzt?

Ich arbeite mit dem AT89C51ED2, also auch einer mit Bootloader. Ich 
hab's dort so gelöst, dass ich nicht den Bootloader direkt anspringe, 
sondern das BLJB-Flag setze, dann den Watchdog aktiviere, und den dann 
den Reset triggern lasse. Das heisst, alle Register haben dann auch ihre 
Reset-Werte, wenn der Bootloader startet, evtl. liegt dein Aufhänger ja 
darin begründet. Das könntest du ja auch so machen.

Ralf

Autor: Patrick G. (pgr8051)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AUXR1 habe ich vorher nicht gesetzt, die Watchdog-Sache hört sich aber 
gut an. ENBOOT in AUXR1 setzen geht in Ordnung. Den Watchdog aktiviert 
man in WDTRST durch Schreiben einer Sequenz von Werten (0x1e und 0xe1). 
Wie kann ich das Jump Bit aber setzen? Im Atmel-Data-Sheet steht nur was 
von "Hardware Security Byte", aber keine Register-Adresse, wo sich das 
BLJB befindet.

PS: "und den dann den Reset triggern lasse" -- wie ist das gemeint? Geht 
es hier um die Hardware-Condition/Reset, den ich sonst mache, um den 
Bootloader zurückzuholen?

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Stichwort ist API. Mit den API-Befehlen kannst du das BLJB setzen 
(zumindest beim ED2). Wie du die API aktivierst, steht im Datenblatt. 
Ausserdem gibts von Atmel bzw. Keil entsprechende C/H-Files, mit denen 
du die API-Befehle realisieren kannst, also nicht alles selber 
entwickeln musst.

Mit Reset triggern meinte ich, den Watchdog zu aktivieren, ihn aber 
nicht zu bedienen. Das löst einen "richtigen" Reset aus. Je nach Derivat 
ist der Resetpin bidirektional, d.h. du musst nachsehen, ob der Resetpin 
bei einem WD-Reset bedient wird, und ob das Probleme mit deiner externen 
Reset-Schaltung geben könne...

Ralf

Autor: Patrick G. (pgr8051)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, mal gestestet:

ENBOOT in AUXR1 habe ich vor dem Sprung gesetzt. Klappt nicht. Ein 
zyklischer Sende-Interrupt läuft sogar weiter nach dem "Sprung". Der 
Code wird auf jeden Fall ausgeführt, da ich eine CAN-Quittung 
programmiert habe. Diese Nachricht bestätigt, daß der Code-Zweig mit dem 
Sprung auch genommen wird.

AUXR1 auf ENBOOT, dann HSB (Register 0xBB) auf 0x40 und anschließend die 
beiden Werte in WDTRST für die Watchdog-Aktivierung. Es scheint sich 
nichts zu tun. Fehlt noch was?

PS: Gerade deine Antwort gelesen: Habe Sfr 0xBB angelegt und wie ein 
übliches Register angesprochen, eine API habe ich nicht genutzt. Ich 
schau nochmal.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf meinem AT89C51CC01:

#define CALL(addr)      (((void(*)(void))(char code *)addr)())
#define AUXR1_ENBOOT_   0x20

void flash(void)               // enter bootloader to reprogram
{
    EA = 0;
    AUXR1 |= AUXR1_ENBOOT_;     // enable boot
    PSW = 1 << 3;               // Bank 1
    *(char data*)0 = 20;        // R0: oscillator freq
    *(char data*)1 = 0x0A;      // R1: program BLJB
    PSW = 0;
    DPTR = 4;                   // specify BLJB
    ACC = 0x00;                 // set BLJB
    CALL( 0xFFF0 );             // API call

    WDTPRG = 0;                 // force watchdog reset
    WDTRST = 0x1E;
    WDTRST = 0xE1;
    for(;;);
}


Peter

Autor: Patrick G. (pgr8051)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Peter

Es scheint nicht zu gehen. DPTR ist in meinem Include unbekannt. Laut 
Oszi kommt aber wegen Setzen der WDT-Register eine RESET-Signal über den 
Pin, so daß ich nur noch PORT1 extern auf 0xFE (Hardware Condition) 
ziehen muß. Dann kommt der Bootloader.

Pin 1.6 ist auf Masse gezogen. Ich weiß nicht, ob das ein Problem ist...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.