Forum: Mikrocontroller und Digitale Elektronik [Butterfly] LCD-Laufschrift bleibt stehen


von 2lazy2login (Gast)


Lesenswert?

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

von 2lazy2login (Gast)


Lesenswert?

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

von Karl heinz B. (kbucheg)


Lesenswert?

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.

von 2lazy2login (Gast)


Lesenswert?

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

von 2lazy2login (Gast)


Lesenswert?

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

von 2lazy2login (Gast)


Lesenswert?

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

von Martin Thomas (Gast)


Lesenswert?

"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)

von Karl H. (kbuchegg)


Lesenswert?

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

von Pototschnig (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.