AVR Goto Bootloader aus RXC_vect

OP #1708819
Lesenswert?
• ▲
▼
Hi,
Ich habe ein etwas größeres Projekt und will dabei im laufenden Betrieb 
zum Bootloader wechseln können. Der Bootloader ermittelt aus einer Reihe 
von 'U'-Chars seine Baudrate (Chip45boot2).
Damit der Reset schön einfach geht, frage ich im RXC-vect (der Uart wird 
auch sonst fleißig benutzt) einfach ab, ob 10-mal hintereinander ein 
solches 'U' kommt. Da mein restliches Protokoll keine Buchstaben 
enthält, sollte das auch nicht versehentlich ausgelöst werden.
Der Bootloader-Bereich ist 1k Words, die Startadresse 0x3C00. Das ganze 
ist ein Atmega32.
Mein Problem ist jetzt aber: Es funktioniert nicht. Der Controller 
resettet sich zwar, springt aber nicht in den Bootloader.
Der Bootloader an sich funktioniert, wenn ich die 'U's sende und den 
Controler per Reset-Pin bzw Power-Toggle resette, dann springt er 
problemlos in den Bootloader.

Fuses für Bootsize ist per AVR-Studio auf 1K Words gesetzt, Bootrst ist 
Programmed.

Hier das Empfangs-Interrupt. Die sonstige Abwicklung des Empfanges 
funktioniert einwandfrei...Hat jemand eine Idee?
(Bitte nicht: "Nimm doch einfach den Bootloader xyz", oder "Wozu soll 
das gut sein?")
1
/*Reset an die Bootloader-Adresse*/
2
void reset_to_bootloader(void)
3
{
4
  /*Interrupts deaktivieren*/
5
  cli();
6

7
  /*RXD Pin als Eingang*/
8
  DDRD &= ~(1 << PD0);
9

10
  /*Sprung zur Bootloaderstartadresse*/
11
  goto *0x7800;  
12
}
13

14

15
/*USART Empfangs Interrupt*/
16
ISR(USART_RXC_vect)
17
{  
18
  /*UDR leeren (damit UART wieder bereit), Zeichen zwischenspeichern*/
19
  uint8_t buffer = UDR;                      
20
  static uint8_t flag = ERR_NO_ERROR;
21
  static uint8_t ct_reset;
22

23
  /*Wenn Zeichen ein U ist*/
24
  if (buffer == 'U')                        
25
  {
26
    /*Reset für Bootloader nach dem 10. U*/
27
    if(++ct_reset==10)
28
    {
29
      reset_to_bootloader();                
30
    }
31
    /*wenn 10. U noch nicht erreicht, Vector verlassen*/
32
    else
33
    {
34
      return;
35
    }
36
  }
37

38
  else
39
  {
40
    /*Reset Counter zurücksetzen*/
41
    ct_reset = 0;
42
  }
43

44
  /*Wenn Endzeichen ankommt*/  
45
  if (buffer == RX_TERMINATOR)                  
46
  {  
47
    /*Wenn zuvor kein Fehler aufgetreten war, dann ist der Frame gültig*/
48
    if (flag == ERR_NO_ERROR)                    
49
    {
50
      /*und wird freigegeben*/
51
      release_last_frame(&rx_buffer);  
52
      
53
      /*Und Zähler wird erhöht*/
54
      number_rx_frames++;  
55
    }
56

57
    /*Wenn hingegen ein Fehler aufgetreten war, ist der Frame ungültig*/
58
    else
59
    {
60
      /*und wird verworfen*/
61
      dismiss_last_frame(&rx_buffer);
62

63
      /*Es wird eine Fehlermeldung ausgegeben*/
64
      send_status_message(PREFIX_ERROR, flag);
65

66
      /*Und Flag zurücksetzen*/
67
      flag = ERR_NO_ERROR;
68
    }
69
  }
70

71
  /*Alle anderen Zeichen*/
72
  else
73
  {
74
    /*Werden im Ringpuffer gespeichert und der Rückgabewert (Fehlermeldung) gespeichert*/
75
    flag = put_to_ringbuffer(&rx_buffer, buffer);
76
  }
77
  return;
78
}
OP #1709578
Lesenswert?
• ▲
▼
Hi Christian,
Momentan mache ich resets auch per Watchdog, allerdings möchte ich den 
zukünftig wirklich als "Wachhund" benutzen und möchte daher die 
goto-Anweisung verwenden. Laut Datenblatt und Beschreibung des 
Bootloaders sollte das ja eingetlich auch ohne weiteres funktionieren, 
leider tut es das einfach nicht, dh. höchst wahrscheinlich mache ich 
dabei noch irgendetwas falsch. Gibt es bei der goto-Anweisung etwas zu 
beachten, zB wenn sie aus einem Interrupt-Vector heraus aufgerufen wird?
Gast #1709600
Lesenswert?
• ▲
▼
Phillip Hommel schrieb:
> Momentan mache ich resets auch per Watchdog, allerdings möchte ich den
> zukünftig wirklich als "Wachhund" benutzen und möchte daher die
> goto-Anweisung verwenden.

Und warum kannst du den watchdog zukünftig nicht mehr dafür verwenden? 
Ob der nun zuschlägt, weil der Prozessor hängt, oder weil du absichtlich 
eine eine Endlosschleife eingebaut hast, ist dem völlig egal.

Damit bekommst du dann den echten Reset, mit definierten Zuständen aller 
Hardwaremodule. Ein Sprung auf die Resetadresse ist ja kein 
vollständiger Reset.

Phillip Hommel schrieb:
> ...die Startadresse 0x3C00.
>...
>   goto *0x7800;

Hm. Schon mal ins Disassembly geschaut?

Oliver

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.