mikrocontroller.net

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


Autor: Maik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
.dseg
counter1:   .BYTE 2
counter2:   .BYTE 2

.cseg
timer_overflow:            ; ISR timer overflow
 push XL
 push XH
 push temp
 push r0
 in r0, SREG

counter1:
 lds  XL, LOW(counter1)    ; 16Bit counter inkrementieren
 lds  XH, HIGH(counter1)
 subi XL, LOW(-1)          ; geht natürlich auch mit:" adiw  XL, 1"
 sbci XH, HIGH(-1)
 sts  LOW(counter1), XL
 sts  HIGH(counter1), XH

 ldi  temp, HIGH (1000)    ; mit Zielwert vergleichen
 cpi  XL, LOW(1000)
 cpc  XH, temp
 brne counter2

 clr temp                  ; counter resetten
 sts HIGH(counter1), temp
 sts LOW(counter1), temp

counter2:
 lds  XL, LOW(counter2)    ; 16Bit counter inkrementieren
 lds  XH, HIGH(counter2)
 subi XL, LOW(-1)          ; geht natürlich auch mit:" adiw  XL, 1"
 sbci XH, HIGH(-1)
 sts  LOW(counter2), XL
 sts  HIGH(counter2), XH

 ldi  temp, HIGH (60000)   ; mit Zielwert vergleichen
 cpi  XL, LOW(60000)
 cpc  XH, temp
 brne ende

 clr temp                  ; counter resetten
 sts HIGH(counter2), temp
 sts LOW(counter2), temp

 sbis PINB, 0              ; schalte eine LED ein oder aus
 sbi  PORTB, 0
 sbic PINB, 0
 cbi  PORTB, 0

ende:
 ldi  temp, 10             ; timer vorladen
 out  TCNT0, temp

 in SREG, r0
 pop  r0
 pop  temp
 pop  XH
 pop  XL
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!!!

Autor: Klaus (Gast)
Datum:

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

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
edit:

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

Autor: Mark .. (mork)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nö Mark ist schon richtig so!

Autor: Maik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo ist denn Dein Datensegment plaziert?
Schreib mal nach

.dseg

.org SRAM_START


Peter

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Maik,

wenn Du nichts über den Vorteiler schreibst wirds schwierig.

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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Maik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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
in r0, sreg

erreichen.

MFG
Falk

Autor: Maik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus (Gast)
Datum:

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

Gute Nacht Falk

Klaus

Autor: Maik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Maik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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???

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maik wrote:

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

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

Autor: Maik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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"?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lds  XL, counter1
lds  XH, counter1 + 1
subi XL, LOW(-1)
sbci XH, HIGH(-1)
sts  counter1, XL
sts  counter1 + 1, XH


Peter

Autor: Maik (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.