Forum: Mikrocontroller und Digitale Elektronik 2x 16-Bit counter im SRAM funktioniert nicht (AVR, ASM)


von Maik (Gast)


Lesenswert?

Hallo zusammen,

habe folgendes Problem, ich möchte in der ISR für den timer0 overflow 
zwei sich im SRAM befindende 16-Bit counter inkrementieren. Das 
funktioniert auch soweit sofern ich nur einen counter benutze. Lasse ich 
jedoch beide counter laufen, funktioniert das ganze nicht mehr, 
wahrscheinlich überschreiben sich die beiden gegenseitig oder so.

Hier mal der relevante Code:
1
.dseg
2
counter1:   .BYTE 2
3
counter2:   .BYTE 2
4
5
.cseg
6
timer_overflow:            ; ISR timer overflow
7
 push XL
8
 push XH
9
 push temp
10
 push r0
11
 in r0, SREG
12
13
counter1:
14
 lds  XL, LOW(counter1)    ; 16Bit counter inkrementieren
15
 lds  XH, HIGH(counter1)
16
 subi XL, LOW(-1)          ; geht natürlich auch mit:" adiw  XL, 1"
17
 sbci XH, HIGH(-1)
18
 sts  LOW(counter1), XL
19
 sts  HIGH(counter1), XH
20
21
 ldi  temp, HIGH (1000)    ; mit Zielwert vergleichen
22
 cpi  XL, LOW(1000)
23
 cpc  XH, temp
24
 brne counter2
25
26
 clr temp                  ; counter resetten
27
 sts HIGH(counter1), temp
28
 sts LOW(counter1), temp
29
30
counter2:
31
 lds  XL, LOW(counter2)    ; 16Bit counter inkrementieren
32
 lds  XH, HIGH(counter2)
33
 subi XL, LOW(-1)          ; geht natürlich auch mit:" adiw  XL, 1"
34
 sbci XH, HIGH(-1)
35
 sts  LOW(counter2), XL
36
 sts  HIGH(counter2), XH
37
38
 ldi  temp, HIGH (60000)   ; mit Zielwert vergleichen
39
 cpi  XL, LOW(60000)
40
 cpc  XH, temp
41
 brne ende
42
43
 clr temp                  ; counter resetten
44
 sts HIGH(counter2), temp
45
 sts LOW(counter2), temp
46
47
 sbis PINB, 0              ; schalte eine LED ein oder aus
48
 sbi  PORTB, 0
49
 sbic PINB, 0
50
 cbi  PORTB, 0
51
52
ende:
53
 ldi  temp, 10             ; timer vorladen
54
 out  TCNT0, temp
55
56
 in SREG, r0
57
 pop  r0
58
 pop  temp
59
 pop  XH
60
 pop  XL
61
reti

Hat vielleicht jemand eine Idee woran das liegt und vor allem wie sich 
das vermeiden lässt? Für Hilfe wäre ich sehr dankbar!!!

von Klaus (Gast)


Lesenswert?

Hast Du mal nachgerechnet ob der Code abgearbeitet werden kann,
bevor das nächst mal Int. aufgerufen wird?

von Klaus (Gast)


Lesenswert?

edit:

Hast Du mal nachgerechnet ob der Code abgearbeitet werden kann,
bevor das nächst mal der Int. vom Timer auftritt?

von Mark .. (mork)


Lesenswert?

Kann zwar keinen Fehler bezüglich des Hochzählens erkennen, aber am Ende 
der ISR sollte out SREG, r0 stehen und nicht in SREG, r0

MfG Mark

von Klaus (Gast)


Lesenswert?

nö Mark ist schon richtig so!

von Maik (Gast)


Lesenswert?

"Kann zwar keinen Fehler bezüglich des Hochzählens erkennen, aber am 
Ende
der ISR sollte out SREG, r0 stehen und nicht in SREG, r0"

Das habe ich ausprobiert, aber funtkioniert leider trotzdem nicht.

"Hast Du mal nachgerechnet ob der Code abgearbeitet werden kann,
bevor das nächst mal der Int. vom Timer auftritt?"

Das sollte eigentlich passen, der overflow tritt nur jede  milli Sekunde 
auf.

Aber generell sollte das mit der Adressierung aber hinhauen, oder? Wie 
gesagt sofern ich nur einen inkrementiere funktioniert alles, 
inkrementiere ich beide geht es halt nicht...
Habt ihr vielleicht noch eine Idee für einen workaround, möchte ungern 
zwei arbeitsregister verschwenden nur für einen Zähler?

von Peter D. (peda)


Lesenswert?

Wo ist denn Dein Datensegment plaziert?
Schreib mal nach

.dseg

.org SRAM_START


Peter

von Klaus (Gast)


Lesenswert?

Hi Maik,

wenn Du nichts über den Vorteiler schreibst wirds schwierig.

Frage: was läuft sonst noch auf dem µC, ist das alles?

von Peter D. (peda)


Lesenswert?

Maik wrote:
> "Kann zwar keinen Fehler bezüglich des Hochzählens erkennen, aber am
> Ende
> der ISR sollte out SREG, r0 stehen und nicht in SREG, r0"
>
> Das habe ich ausprobiert, aber funtkioniert leider trotzdem nicht.

Was hast Du denn fürn komischen Assembler?
Das "in SREG, r0" erzeugt mit dem AVR-Assembler 2 die Fehlermeldung:

t13.asm(66): error: Invalid register


Peter

von Klaus (Gast)


Lesenswert?

Hallo Peter Dannegger,

"in SREG, r0"

geht bei mir poblemlos durch, ohne Fehler oder Warnungen.
Ist zwar ungewöhnlich SREG in R0 zusichern (würde es auf dem
Stack tun) aber es sollte gehen.

AVR-Studio 4.13

Klaus

von Maik (Gast)


Lesenswert?

Zur Info, das ganze läuft auf einem ATmega16 bei 16 MHz...

"wenn Du nichts über den Vorteiler schreibst wirds schwierig."

Ich dachte, dass wäre nicht relevant, der Vorteiler wird im Präprozessor 
vom Compiler berechnet, was aber definitiv funktioniert, benutze den 
Code dafür auch schon länger und es gab nie Probleme.
Zum testen habe ich aber die Anweisung um die LED ein/aus zu schalten 
hinter den ersten counter gehängt der diese dann nach 1000 Zählvorgängen 
(als 1000x1ms=1Sekunde) ausführt.

Der Code ist eine Datei die ich im Hauptprogramm includiere

"Wo ist denn Dein Datensegment plaziert?"
Wird das nicht automatisch vom compiler organisiert, der beim SRAM 
anfang beginnt und nacheinander dort die Bereiche für die definierten 
Variablen reserviert???
In anderen includierten Dateien benutze ich auch auf diese Weise 
Variablen die alle funktionieren.
In diesem Codeabschnitt benutze ich allerdings das einzige Mal 
reservierte Bereiche mit mehr als 8-Bit, kann es vielleicht daran 
liegen?
Hatte das vorher auch schonmal alles über .DB und .DW organisiert, hat 
aber auch nicht geklappt.

"Was hast Du denn fürn komischen Assembler?"

Ich benutze AVRStudio 4 mit dem entsprechenden Assembler.
Das mit dem "in" ist mir beim abschreiben des Codeschnippsels für diesen 
Beitrag passiert, im Code selber benutze ich "out".

"Ist zwar ungewöhnlich SREG in R0 zusichern"
Ach das klappte bisher einwandfrei... ist ja eines der "limitierten" 
Register, die man leicht entbehren kann.

von Falk B. (falk)


Lesenswert?

@ Klaus (Gast)

>"in SREG, r0"

>geht bei mir poblemlos durch, ohne Fehler oder Warnungen.

???
Kann gar nicht, weil vollkommen falsch. IN lädt I/O Register in CPU 
Register, und das erste Argument muss ein CPU Register sein.

>Ist zwar ungewöhnlich SREG in R0 zusichern

Das würde man mit
1
in r0, sreg

erreichen.

MFG
Falk

von Maik (Gast)


Lesenswert?

Also das mit "in" und "out" funktioniert definitiv, sollte nicht das 
Problem sein. Wie gesagt im ersten Beitrag war es wirklich ein 
Abschreibefehler!!!

in und out sind wie folgt definiert:

in  Rd, SFR ==> lade Rd mit SFR Register

out SFR, Rd ==> lade SFR mit Rd


Habe das, was Peter Danegger geschrieben hat mit .org SRAM_START 
ausprobiert, dabei bekomme ich immer einen Fehler beim compilieren:
error: Overlap in .dseg: addr=0x60 conflicts with 0x60:0x73

und das für alle darauf folgenden Speicherreservierungen.

von Klaus (Gast)


Lesenswert?

@ Falk

 hast Du gelesen?

 push r0
 in r0, SREG  ; am Anfang der ISR

>Kann gar nicht, weil vollkommen falsch. IN lädt I/O Register in CPU
>Register, und das erste Argument muss ein CPU Register sein.

ja klar SREG ist eine Ram-Zelle

@ Maik

>Der Code ist eine Datei die ich im Hauptprogramm includiere

 was macht der µC da in der Zwischenzeit?

Klaus

von Falk B. (falk)


Lesenswert?

@ Maik (Gast)

>Also das mit "in" und "out" funktioniert definitiv, sollte nicht das
>Problem sein. Wie gesagt im ersten Beitrag war es wirklich ein
>Abschreibefehler!!!

Abschreibfehler? Wer Quelltexte ABSCHREIBT sollte sich ne Packung 
Ohrfeigen abholen. So ein Blödsinn zu machen ist fast strafbar.

Quelltexte werden sinnvollerweise direkt als Anhang gepostet. Dann gibt 
auch keine Abschreibfehler. Ich glaub ich steh im Wald.

MFG
Falk

von Klaus (Gast)


Lesenswert?

push r0
 in r0, SREG
 .
 .
 .
 in SREG, r0
 pop  r0

 push r0
 in r0, SREG
 .
 .
 .
 out SREG, r0
 pop  r0

 ist doch das gleiche. Der Inhalt von SREG steht während der Punkte
 in R0. Es ist Wurst, ob ich mir den Wert von SReg über "in" aus R0
 zurück hohle, oder ihn über "out" bewußt dahin zurück schreibe.

 Klaus

von Falk B. (falk)


Lesenswert?

@  Klaus (Gast)

>push r0
> in r0, SREG
 .
 .
 .
> in SREG, r0

GEHT NICHT!
Siehe mein Posting

Beitrag "Re: 2x 16-Bit counter im SRAM funktioniert nicht (AVR, ASM)"

Dort muss stehen

out SREG, r0

Der Abschreibfehler, schauder!

> in R0. Es ist Wurst, ob ich mir den Wert von SReg über "in" aus R0
> zurück hohle, oder ihn über "out" bewußt dahin zurück schreibe.

Nöö, du kannst mit IN keinen Wert IN SREG schreiben, nur AUS SREG lesen.

MFG
Falk

von Klaus (Gast)


Lesenswert?

>Nöö, du kannst mit IN keinen Wert IN SREG schreiben, nur AUS SREG lesen.

Gute Nacht Falk

Klaus

von Maik (Gast)


Lesenswert?

"Abschreibfehler? Wer Quelltexte ABSCHREIBT sollte sich ne Packung
Ohrfeigen abholen. So ein Blödsinn zu machen ist fast strafbar."

Danke für die klaren Worte, sowas mag ich :-)

Ich kann dir diesen Blödsinn aber erklären, ich habe den Code 
ursprünglich mit Kopieren/Einfügen in den Beitrag eingefügt, allerdings 
kann der Beitragseditor anscheinend nicht so gut mit Tabulatoren umgehen 
und es gab Darstellungsfehler in der Vorschau, vielleicht auch da 
AVRStudio stadardmäßig eine Tabulatorbreite von 4Zeichen und nicht wie 
üblich 8 Zeichen verwendet (damit hatte ich schon öfters Ärger, habs 
aber bewußt nicht umgestellt).
Also habe ich die eingefügten Zeilen per Hand bearbeitet und den zweiten 
counter habe ich dann aus dem bereits editierten Stück kopiert und 
geändert, ebenso bin ich auch mit dem zurückschreiben der Register 
verfahren und habe diese aus dem Anfang des editierten Beitrags 
kopiert... dabei habe ich dann zwar die Reihenfolge der Operanden 
verändert allerdings nicht das "in" in "out" geändert. (Erklärt das 
diesen, zugegebenen, Schwachsinn?)

Aber weiter mit meinem Problem, dass Hauptprogramm empfängt per 
Interrupt auch noch RC5 codes, wertet sie aus und sendet sie über die 
UART.
In diesen Routinen, die auch im Hauptprogramm includiert werden, benutze 
ich ebenfalls den SRAM und diese stören sich nicht gegenseitig, deshalb 
gehe mich mal davon aus, dass der Speicher generell schon richtig vom 
compiler organisiert wird (die Routinen funktionieren auch einwandfrei, 
sogar mit in, out und R0 in den ISRs).

Ich nehme an, dass es eher was mit den erstmalig verwendeten 2 Byte 
reservierungen zu tun hat, bin aber nach wie vor ratlos, was ich noch 
verändern könnte.

Wie sieht das aus, es ist doch so, dass, solange eine interrupt 
gehändelt werden die anderen gesperrt werden, bis das handling 
abgeschlossen ist?

von Klaus (Gast)


Lesenswert?

ist komisches Zeug warum mein µC das mit 16MHz das nicht schafft!

>Der Code ist eine Datei die ich im Hauptprogramm includiere

Kommentiere doch bitte mal die restlichen ISRs aus!

Du wirst sehen das (nahzu 100%) Dein Code-Snip rennt!
Du hast zu 100% Warhscheinlichkeit ein Zeit-Problem,
auf dem µC!

Klaus

von Maik (Gast)


Lesenswert?

Was schafft denn dein µC mit 16MHz nicht, 16 MHz ist doch wirklich schon 
"atemberaubend"? :-)

Also, hab das gemacht, was du mir geraten hast und wirklich ALLES 
weggelassen, das Programm macht jetzt nichts mehr, ausser in einer 
Endlosschleife im Hauptprogramm zu laufen und bei einem Timerinterrupt 
den geposteten Code (abgesehen von dem zweimal "in")auszuführen.

Wie bereits vorher vermutet kann es am restlichen Programm nicht liegen 
(es ist ja nunmehr nicht vorhanden).

Danke erstmal für die zahlreichen vorangegangenen Posts!

Habt ihr sonst noch Ideen... schaut euch doch bitte nochmal mein 
Codeschnippsel an irgendwo muss sich der Hund doch in den Schwanz 
beißen???

von Peter D. (peda)


Lesenswert?

Maik wrote:

>
1
>  lds  XL, LOW(counter1)    ; 16Bit counter inkrementieren
2
>  lds  XH, HIGH(counter1)
3
>

Das ist völliger Unsinn.

Die Macros LOW und HIGH haben nur zum Laden eines Pointers Sinn, d.h. 
bei Verwendung des Befehls "LDI".

"LDS" benötigt immer die ganze 16Bit-Adresse, d.h. Deine Zugriffe gehen 
in den Wald.


Peter

von Maik (Gast)


Lesenswert?

Danke Peter Dannegger, das hätte ich wahrscheinlich erstmal weiter 
übersehen...

Und wie mache ich das dann jetzt am besten, lade ich die Adresse des 
Speicherbereichs in den Pointer und lese/schreibe die Werte dann aus, 
oder lade ich mittels "lds  XL, counter1" den kompletten 16-Bit Inhalt 
und speichere ihn mit "sts XL, counter1"?

von Peter D. (peda)


Lesenswert?

1
lds  XL, counter1
2
lds  XH, counter1 + 1
3
subi XL, LOW(-1)
4
sbci XH, HIGH(-1)
5
sts  counter1, XL
6
sts  counter1 + 1, XH


Peter

von Maik (Gast)


Lesenswert?

EUREKA er hats... Genau das wars!

Du bist einfach der Beste, vielen vielen DANK!!!

Da wäre ich so schnell nicht drauf gekommen, wieder was dazu gelernt :-)

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.