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