Ich verzweifle bei einer relativ einfachen asm - Routine.
Hintergrund: Ein kleines Programm für eine Funkfernsteuerung mit RFM12.
Es werden immer 7 Bytes übertragen, wobei das erste als Startbyte "S"
angesehen wird. Die restlichen 6 Bytes sind einstellbar. Diese Bytefolge
wird zweimal gesendet und bei richtigem Empfang soll ein Befehl
ausgeführt werden. So weit die Theorie.
Grundsätzlich macht das Programm auch das, was es machen soll,
allerdings nur dann, wenn ich in der Vergleichschleife eine UART Ausgabe
anspringe. Lasse ich die weg, spielt das Programm verrückt. Dabei ist es
auch egal an welcher Stelle dieser Vergleichschleife ich den Sprung
einbaue.
1
;Empfänger abfragen
2
receive:
3
ldiw Y, Eingang ;Y -Pointer auf 1. Byte
4
ldi datacnt, 10 ;Anzahl Datenbytes +4
5
rcall rf12_rxdata_rec ;10 empfangene Bytes werden im SRAM abgelegt
6
;prüfen, ob Startbyte = S
7
S_test:
8
ldiw Y, Eingang ;Y - Pointer wieder auf Anfang setzen
9
S_test_loop:
10
ld temp, Y+ ;Y - Byte laden und auf nächstes Byte stellen
11
nop
12
cpi temp, 'S'
13
breq Vergleich ;wenn S, dann die übrigen 6 Byte vergleichen
14
inc cnt
15
cpi cnt, 3 ;S muß in den ersten 3 Bytes enthalten sein
16
breq main
17
rjmp S_test_loop
18
19
;weitere 6 Bytes überprüfen
20
Vergleich:
21
clr cnt
22
ldi ZL, LOW(Befehl_2*2) ;Z - Pointer auf Befehlsmuster
23
ldi ZH, HIGH(Befehl_2*2)
24
Ver_loop:
25
inc cnt
26
ldi temp, '0'
27
add temp, cnt
28
rcall uart_transmit ;!!!!hier liegt das Problem!!!
29
cpi cnt, 7 ;6 Bytes müssen verglichen werden
30
breq Ver_loop_exit
31
lpm ;Z - Byte laden und Register erhöhen
32
adiw ZL, 1
33
ld temp, Y+ ;Y - Byte laden und auf nächstes Byte stellen
Also PIC und MPASM ist es wahrscheinlich nicht. Ich muss passen.
Kann sonst jemand aus dem bloßen Aussehen des Quellcodes erraten, um
welchen Mikrocontroller es geht?
PIC kundiger schrieb im Beitrag #4251165:
> Also PIC und MPASM ist es wahrscheinlich nicht. Ich muss passen.> Kann sonst jemand aus dem bloßen Aussehen des Quellcodes erraten, um> welchen Mikrocontroller es geht?
Sorry, aber durch das lange Suchen und Testen bin ich schon etwas
betriebsblind. Es ist ein ATMega48.
> spielt das Programm verrückt
Wie äußerst sich das?
> rcall uart_transmit ;!!!!hier liegt das Problem!!!
Die Routine wird nicht mitgeliefert, dafür sieben Ausrufezeichen.
Und das von jemandem, der seit über sechs Jahren dabei ist.
Bruno M. schrieb:> Lasse ich die weg, spielt das Programm verrückt.
Wie äussert sich das?
Was erwartest du und was passiert stattdessen?
Hast du mal statt der UART Geschichte einfach nur etwa gleich viel Zeit
verplempert?
S. Landolt schrieb:> Die Routine wird nicht mitgeliefert, dafür sieben Ausrufezeichen.
Die Routine ist Standard und selbst auch nicht das Problem, sondern ein
fehlender Sprung dahin (wie beschrieben).
Lothar M. schrieb:> Wie äussert sich das?> Was erwartest du und was passiert stattdessen?
Die empfangenen Zeichen werden nicht als richtig erkannt, obwohl sie es
sind und daher Sprung in die Fehlerroutine.
Lothar M. schrieb:> Hast du mal statt der UART Geschichte einfach nur etwa gleich viel Zeit> verplempert?
Ja daran habe ich auch schon gedacht, und auch versucht. Allerdings habe
ich die Taktzahl noch nicht genau nachgehalten. Das will ich aber mal
machen.
Bruno M. schrieb:> uart_transmit: ;temp wird ausgegeben> cli> lds r10, UCSR0A> sbrs r10, UDRE0> rjmp UART_Transmit> sts UDR0, temp> exit_usart_transmit:> ret
Es ist ungewöhnlich, in einer Unterroutine das I-Flag zu löschen (cli),
aber nicht wieder zu restaurieren.
Nase schrieb:> Es ist ungewöhnlich, in einer Unterroutine das I-Flag zu löschen (cli),> aber nicht wieder zu restaurieren.
Danke für den Hinweis. Das gehört da nicht hin, da ich keinen interrupt
verwende.
Bruno M. schrieb:> S_test:> ldiw Y, Eingang ;Y - Pointer wieder auf Anfang setzen> S_test_loop:> ld temp, Y+ ;Y - Byte laden und auf nächstes Byte stellen> nop> cpi temp, 'S'> breq Vergleich ;wenn S, dann die übrigen 6 Byte vergleichen> inc cnt> cpi cnt, 3 ;S muß in den ersten 3 Bytes enthalten sein> breq main> rjmp S_test_loop
Wird "cnt" auch mal initialisiert?
Bruno M. schrieb:> Die Routine ist Standard
Bestimmt nicht. Die ist so verbuggt, wenn das Standard wäre...
Erstmal sperrt sie die Interrupts (gibt sie aber niemals wieder frei).
Einen tiefgreifenderen Eingriff in das System kann man sich schon fast
nicht mehr vorstellen...
Des Weiteren ist sie blockierend, also de facto ein Delay mit der Größe
einer Bytedauer. Jedenfalls ab dem dritten zu sendenden Byte...
Wenn "rf12_rxdata_rec" genauso Scheiße prgrammiert ist, braucht man sich
über nichts mehr zu wundern. Aber auch das hast du uns ja
vorenthalten...
c-hater schrieb:> Des Weiteren ist sie blockierend, also de facto ein Delay mit der Größe> einer Bytedauer. Jedenfalls ab dem dritten zu sendenden Byte...
Und das ist verboten?
Nase schrieb:> Und das ist verboten?
Natürlich nicht. Man muß eben bloß dafür sorgen, dass andere
Programmfunktionen dadurch nicht gestört werden.
Und das fällt auf Dauer am leichtesten, indem man sich auf blockierenden
Code erst garnicht einläßt.
Entweder man macht's interruptgesteuert oder man pollt. Aber man
blockiert niemals, wenn es sich irgendwie vermeiden läßt. Und bei einer
USART-Ausgabe läßt es sich nun wirklich völlig problemlos vermeiden.
Nase schrieb:>> Des Weiteren ist sie blockierend, also de facto ein Delay mit der Größe>> einer Bytedauer. Jedenfalls ab dem dritten zu sendenden Byte...> Und das ist verboten?
In Verbindung mit Interrupts ist es das.
Also das Programm "spielt verrückt" wenn nicht eine Routine aufgerufen
wird (egal wo), die die Interrupts sperrt... vielleicht sollte man da
mal gucken...
Carl D. schrieb:>> Poste den ganzen Quellcode>> als Attachment!
Das mache ich natürlich gerne, ich dachte ich könnte Euch das ersparen.
Den Sprung in den 2. Vergleich habe ich zum Testen entfernt.
An der Zeit liegt es übrigens nicht! An cli auch nicht, das habe ich
entfernt.
Und so sehen die UART-Ausgaben aus:
Mit einem Sprung in die UART-Routine sowohl in der S-test Schleife als
auch in der Vergleichschleife:
SYYBYYB7SYYBYYBAuftrag 1 ausfuehren!!!<\n><\r>
und so, wenn ich den UART-Sprung aus der Vergleichschleife nehme.
@?SVergleichs-Fehler!!<\n><\r>?/SVergleichs-Fehler!!<\n><\r>
Ich bin nicht fit in AVR-Assembler... aber: Du verwendest überall nur
eine Hilfsvariable "temp", obwohl Du weitere temp1, temp2 definiert
hast.
Überschreibst Du Dir da nicht etwas?
Es bestätigt sich!!
Wenn ich auch aus S_test nur die Warteschleifen einbaue, sieht es bei
mehrfachem Versuch so aus.
Auftrag 1 ausfuehren!!!<\n><\r>Auftrag 1 ausfuehren!!!<\n><\r>Auftrag 1
ausfuehren!!!<\n><\r>Auftrag 1 ausfuehren!!!<\n><\r>Auftrag 1
ausfuehren!!!<\n><\r>
Jetzt würde mich nur noch die Ursache interessieren. Da ich den
Vergleich mit Daten aus dem SRAM durchführe, kann es ja mit der
Funkübertragung nichts zu tun haben.
S. Landolt schrieb:>> S??SAuftrag 1 ausfuehren!!!<\n><\r>> Woher kommen eigentlich die Fragezeichen? Liegt das an der unüblichen> Baudrate?
Diese Frage kann ich leider nicht beantworten.
Schau mal was sich im SREG tut mit und ohne UART/Delay.
Ich wette fast drauf, dass du False-Poitives beim Vergleich bekommst,
weil irgend was im SREG rummurkst.
SeDa schrieb:> Schau mal was sich im SREG tut mit und ohne UART/Delay.> Ich wette fast drauf, dass du False-Poitives beim Vergleich bekommst,> weil irgend was im SREG rummurkst.
Wie soll ich das machen? Der Debugger meckert ja nicht.
Bruno M. schrieb:> Wie soll ich das machen? Der Debugger meckert ja nicht.
Warum sollte er?
Sei dir sicher: das Programm macht im uC genau das, was du
hingeschrieben hast.
Ich würde raten sagen, da funkt irgendein Interrupt dazwischen. Was
anderes kann diese Routine ja nicht unterbrechen und an den Flags
herumschrauben. Wie viele Interrupts hast du?
Lothar M. schrieb:> Wie viele Interrupts hast du?
keinen!
Aus Interesse habe ich in der Zwischenzeit testweise das Programm so
abgeändert, daß nicht der RFM12 das SRAM füllt, sondern das Programm
selbst. Dann verhält es sich so wie erwartet, d.h. der Vergleich
funktioniert auch ohne wait-Schleife.
Es muß also doch ein timing - Problem mit dem RFM12 sein. Was das ist,
kann ich mir allerdings nicht erklären.
Nochmal, Du verwendest dieselbe Hilfsvariable "temp" (r16) in
verschiedenen Modulen an verschiedenen Stellen, bist Du sicher dass sich
da nichts überschreibt?
Tcf K. schrieb:> Nochmal, Du verwendest dieselbe Hilfsvariable "temp" (r16) in> verschiedenen Modulen an verschiedenen Stellen, bist Du sicher dass sich> da nichts überschreibt?
ja, sonst hätte ich schon beim debuggen das Problem!