Hallo, ich hab den GCC-Port der Butterfly-Software verwendet und hab ein sehr merkwürdiges Problem, das ich mir überhaupt nicht erklären kann. Und zwar nutze ich die Minimal-Version mit der Laufschrift und LCD_puts(...) funktioniert auch wunderbar und die Laufschrift läuft auch wie sie soll, aber wenn ich jetzt in eine Schleife wie while (...) { } reinkomme, quasi auf irgendwas warte, dann bleibt die Laufschrift stehen und die läuft dann erst weiter, wenn die Schleife verlassen wurde. Das wundert mich sehr, da ja die Laufschrift über den LCD-Frame-Interrupt realisiert wird und aus meinen bisherigen Erfahrung mit Interrupts werde ich daraus nicht ganz schlau. Es werden jedenfalls keine Interrupts gesperrt, die den LCD-Frame-Int verhindern könnten. Hat da jemand ähnliche Erfahrungen gemacht? Mfg Thomas
Und meine bisherigen Erfahrungen hatten Recht ... Der GCC hat - aus einem mir unbekannten Grund - in eine Funktion die von der Main-Loop aufgerufen wird und die die empfangenen RS232-Kommandos dekodiert ein cli in den Assemblercode gebaut. Weiß jemand, warum er das gemacht hat? Bsp:
1 | void Usart_Clear(void) |
2 | {
|
3 | while (UCSRA & (1<<RXC)) |
4 | {
|
5 | volatile char dummy = UDR; |
6 | }
|
7 | }
|
wird zu:
1 | 00000c48 <Usart_Clear>: |
2 | c48: cf 93 push r28 |
3 | c4a: df 93 push r29 |
4 | c4c: cd b7 in r28, 0x3d ; 61 |
5 | c4e: de b7 in r29, 0x3e ; 62 |
6 | c50: 21 97 sbiw r28, 0x01 ; 1 |
7 | c52: 0f b6 in r0, 0x3f ; 63 |
8 | c54: f8 94 cli |
9 | c56: de bf out 0x3e, r29 ; 62 |
10 | c58: 0f be out 0x3f, r0 ; 63 |
11 | c5a: cd bf out 0x3d, r28 ; 61 |
12 | c5c: 80 91 c0 00 lds r24, 0x00C0 |
13 | c60: 87 ff sbrs r24, 7 |
14 | c62: 07 c0 rjmp .+14 ; 0xc72 <Usart_Clear+0x2a> |
15 | c64: 80 91 c6 00 lds r24, 0x00C6 |
16 | c68: 89 83 std Y+1, r24 ; 0x01 |
17 | c6a: 80 91 c0 00 lds r24, 0x00C0 |
18 | c6e: 88 23 and r24, r24 |
19 | c70: cc f3 brlt .-14 ; 0xc64 <Usart_Clear+0x1c> |
20 | c72: 21 96 adiw r28, 0x01 ; 1 |
21 | c74: 0f b6 in r0, 0x3f ; 63 |
22 | c76: f8 94 cli |
23 | c78: de bf out 0x3e, r29 ; 62 |
24 | c7a: 0f be out 0x3f, r0 ; 63 |
25 | c7c: cd bf out 0x3d, r28 ; 61 |
26 | c7e: df 91 pop r29 |
27 | c80: cf 91 pop r28 |
28 | c82: 08 95 ret |
Das sieht nur so aus: c52: 0f b6 in r0, 0x3f ; 63 c54: f8 94 cli c56: de bf out 0x3e, r29 ; 62 c58: 0f be out 0x3f, r0 ; 63 c5a: cd bf out 0x3d, r28 ; in Zeile c52 wird das Status Register gesichert, indem sich auch das Interrupt Status Register befindet. In Zeile c54 wird der Interrupt kurzzeitig abgeschaltet um in Zeile c58, durch Rückspeicherung des gesicherten Wertes des Status Registers wieder aktiviert zu werden. Der Grund ist einfach: Während der Stackpointer in den Zeilen c56 und c5a manipuliert wird, sollte tunlichst kein Interrupt auftreten. Die Speicherung der Return-Adresse geht sonst schief.
Ja richtig! 0x3f ist das SREG und das wird einfach nur gesichert und dann wieder hergestellt, also sind die Interrupts auch nicht gesperrt. Aber was ist dann mit meiner Laufschrift (siehe erstes Posting)? Btw: Da hängt über asynchronen Betriebsmodus ein 32khz Quartz extern dran ... ich hab so das Gefühl, irgendetwas würde damit nicht stimmen, weil das eigentlich eins der wenigen Features ist, die ich noch nicht verwendet habe und somit auch noch keine Erfahrung damit habe. Aber trotzdem weiß ich nicht, wo mein Problem dann ist :-( verzweifel
Problem gefunden, aber verstehen kann ich es nicht - ist wohl ein weiterer Punkt für dieses unverschämte ATMEGA169 Errate ... Wenn USART Receive-Interrupt aktiviert ist - und bei mir war die Behandlungsroutine leer, was nur in einem
1 | SIGNAL(SIG_USART_RECV) |
2 | {
|
3 | }
|
1 | SIGNAL(SIG_USART_RECV) |
2 | { |
3 | b48: 1f 92 push r1 |
4 | b4a: 0f 92 push r0 |
5 | b4c: 0f b6 in r0, 0x3f ; 63 |
6 | b4e: 0f 92 push r0 |
7 | b50: 11 24 eor r1, r1 |
8 | b52: 0f 90 pop r0 |
9 | b54: 0f be out 0x3f, r0 ; 63 |
10 | b56: 0f 90 pop r0 |
11 | b58: 1f 90 pop r1 |
12 | b5a: 18 95 reti |
resultiert und keine Auswirkungen haben dürfte, dann bleibt nach dem Interrupt das LCD einfach stehen. Aber wieso und warum und weshalb und überhaupt - keine Ahnung ...
Ahja - und was ja sogar noch seltsamer ist ... Mit dem aktivierten Interrupt dauerte eine _delay_ms(10) schleife 10 mal so lange, ohne aktivierten Interrupt dauert sie genau so lang wie sie dauern soll ... Ich glaub mein MEGA169 hat einen Schuss ...
"und keine Auswirkungen haben dürfte" der Code selbst nicht, aber das ist nicht alles. Wenn man den RX-Interrupt aktiviert, sollte man auch die UART-Hardware entsprechend "bedienen". Zumindest Data- und Status-Register in der ISR auslesen mal versucht? Habe den Butterfly fuer einige Einzelanfertigungen genutzt, auch mit UART-Interruptbetrieb - bisher keine Problemberichte von den Nutzern. (Man kann seinen richtigen Namen in diesem Forum sogar ganz "lazy" ohne Login angeben)
> Aber wieso und warum und weshalb und überhaupt - keine Ahnung ...
Lass mich raten:
Du schickst ein Zeichen per USART zum Butterfly.
Daraufhin tritt der Receive-Interrupt auf.
Dein entsprechender Handler kümmert sich aber nicht
um das empfangene Zeichen: Es wird nicht abgeholt.
Tja. Und jetzt nimmt das Verhängnis seinen Lauf:
Dadurch dass du UDR nie ausliest, wird auch die Interrupt
Anforderung nicht gelöscht. Sobald der Prozessor aus dem
Receive Interrupt raus ist, geht er auch schon wieder in
den Interrupt hinein, weil ja das Interrupt Flag nie gelöscht
wurde.
Dein Mega168 will dir quasi mit allem Nachdruck sagen, dass da ein
Zeichen in der UART auf Bearbeitung wartet. Das macht er so
nachdrücklich, dass er sich quasi nur noch mit dieser Interrupt
Routine beschäftigt.
Mach einfach mal:
SIGNAL(SIG_USART_RECV)
{
char c = UDR;
}
und dein Mega168 sollte dich wieder mitspielen lassen.
Na eben dann ohne lazy^^ >>> Dadurch dass du UDR nie ausliest, wird auch die Interrupt Anforderung nicht gelöscht. <<< Ihr habt echt recht - das ist das Problem! Das UDR wird bei mir zwar nicht im ISR gelesen, sondern außerhalb. Vorher hatte ich auch immer in der ISR das UDR ausgelesen und in einen Ringpuffer gespeichert. Das Ganze ist aber - wie so oft - für Fehlersuchzwecke ausgeklammert worden und schwupps hat man neue Probleme. Das Fehlerbild passt auch zu meiner Situation, weil eben in meiner Endlosschleife das UDR eben nicht abgefragt worden ist. Und wenn der AVR jetzt wirklich ständig durch die ISR iteriert, dann würde das genau die Probleme verursachen die ich beschrieben habe ... Vielen Dank für die Erkenntnis! Da werde ich in Zukunft aufpassen, dass mir so ein Blödsinn nicht noch einmal passiert :-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.