Problem mit asm Routine

OP #4251096
Lesenswert?

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
34
  cp    r0, temp          ;Y mit Z vergleichen
35
  breq  Ver_loop          ;wenn gleich, nächstes Byte
36
  rjmp  Fehler
37
  ;rjmp  Vergleich_2            
38
Ver_loop_exit:
39
  clr    cnt
40
  inc    OKcnt_1            ;Zähler für erfolgreichen Vergleich
41
  rjmp  Clear            ;Daten im SRAM löschen
42
rjmp    main

Kann sich darauf jemand einen Reim machen?
OP #4251185
Lesenswert?

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.
Gast #4251189
Lesenswert?

> 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.
Gast #4251212
Lesenswert?

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?
Gast #4251218
Lesenswert?

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...
Gast #4251234
Lesenswert?

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.
OP #4251273
Lesenswert?

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>
Angehängte Dateien:
OP #4251320
Lesenswert?

Bruno M. schrieb:
> An der Zeit liegt es übrigens nicht!

Ich muß mich korrigieren! Es scheint doch ein timing Problem zu sein.
1
Vergleich:
2
  clr    cnt
3
  ldi    ZL, LOW(Befehl_2*2)      ;Z - Pointer auf Befehlsmuster
4
  ldi    ZH, HIGH(Befehl_2*2)
5
Ver_loop:
6
  inc    cnt
7
  cpi    cnt, 7            ;6 Bytes müssen verglichen werden
8
  breq  Ver_loop_exit
9
  rcall  wait
10
  rcall  wait
11
  lpm                  ;Z - Byte laden und Register erhöhen
12
  adiw  ZL, 1              
13
  ld    temp, Y+          ;Y - Byte laden und auf nächstes Byte stellen
14
  ;rcall  uart_transmit
15
  cp    r0, temp          ;Y mit Z vergleichen
16
  breq  Ver_loop          ;wenn gleich, nächstes Byte
17
  rjmp  Fehler
18
  ;rjmp  Vergleich_2            
19
Ver_loop_exit:
20
  clr    cnt
21
  inc    OKcnt_1            ;Zähler für erfolgreichen Vergleich
22
  rjmp  Clear            ;Daten im SRAM löschen
23
rjmp    main

So funktioniert es nämlich auch!

S??SAuftrag 1 ausfuehren!!!<\n><\r>
OP #4251326
Lesenswert?

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.
Moderator (Firma: Titel) Persönliche Seite #4251709
Lesenswert?

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?
OP #4251717
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren