Forum: Mikrocontroller und Digitale Elektronik Grundlegende Frage SRAM


von Luke (Gast)


Lesenswert?

Hallo,

Grundlegende Frage zum SRAM von einem AT90CAN32.

Brauche einige Speicherregister die ich im Programm oft ein- und 
auslese.
Ich definiere die Register wie folgt im SRAM:
*******************************************************************
.include <can32def.inc>

.def temp  = r21


.dseg
Beispiel_register1: .Byte 1      ;Register definieren
Beispiel_register2: .Byte 1

.cseg
.org 0x0000
  rjmp  init
  .
  .
  .
  .
********************************************************************
Und beschreiben bzw. auslesen mache ich wie folgt:

lds   temp,Beispiel_register1
  .
  .
  .
sts   Beispiel_register1,temp



Ist das bis dahin alles richtig so ?

Kann es passieren das der Prozessor auf Grund von falsch gesetzten Fuse 
bits oder falscher Registerdefinition (falls die oben falsch sein 
sollte) mir sporadisch Unsinn in von mir definierte SRAM Register 
schreibt bzw. ich unsinn auslese? (oder Problem mit STACK Pointer?)

Habe nämlich einen Fehler im Programm der ganz sporadisch auftretet. 
Manchmal nach 2 Stunden z.B.. und wollte sicher gehn dass ich da keinen 
Fehler beim auslesen oder schreiben vom SRAM mache.

Für Hilfe bin ich dankbar!

LG

von spess53 (Gast)


Lesenswert?

Hi

>Ist das bis dahin alles richtig so ?

Ja.

>Kann es passieren das der Prozessor auf Grund von falsch gesetzten Fuse
>bits

Die Fuse-Bits haben nichts mit dem RAM zu tun.

>oder falscher Registerdefinition (falls die oben falsch sein
>sollte)

Das ist richtig so.

>(oder Problem mit STACK Pointer?)

Der AT90CAN32 hat 2k Ram. Den musst du erst mal mit dem Stack voll 
bekommen. Prinzipiell ist das natürlich möglich: Rekursive Aufrufe, ein 
einsames 'PUSH' das regelmäßig ohne das zugehörige 'POP' aufgerufen 
wird, ... .

MfG Spess

von Michael (Gast)


Lesenswert?

Amok laufende Pointer könnte man noch ergänzen. Wer weiß, was "..." 
alles bedeutet.

von spess53 (Gast)


Lesenswert?

Hi

>Amok laufende Pointer könnte man noch ergänzen. Wer weiß, was "..."
>alles bedeutet.

Es geht um Assembler.

MfG Spess

von Luke (Gast)


Lesenswert?

Ok danke für die Bestätigung Spess!

Fehlersuche geht weiter :S

von c-hater (Gast)


Lesenswert?

spess53 schrieb:

>>Amok laufende Pointer könnte man noch ergänzen. Wer weiß, was "..."
>>alles bedeutet.
>
> Es geht um Assembler.

Als wenn es in Asm keine Pointer gäbe...

Natürlich kann in purem Asm ganz genau dieselbe Scheiße passieren, wie 
in in Macro-Assemblern wie etwa C und auch in allen echten Hochsprachen, 
solange sie nur Pointer und Pointer-Arithmetik prinzipiell ermöglichen.

Viele dieser potentiellen Probleme sind allerdings in Asm deutlich 
einfacher zu erkennen, weil einem nicht der Syntax-Vorhang die Sicht auf 
das Geschehen auf dem Spielfeld versperrt.

von Mikki M. (mmerten)


Lesenswert?

.dseg
.org SRAM_START                  ;1. SRAM Adresse nach I/O
Beispiel_register1: .Byte 1      ;Register definieren
Beispiel_register2: .Byte

evtl. Zeile 2 Vergessen ? Sonst wird auf R0, R1 zugegriffen

von spess53 (Gast)


Lesenswert?

Hi

>Als wenn es in Asm keine Pointer gäbe...

Ist mir seit Anfang der 80er bereits bekannt.

>Viele dieser potentiellen Probleme sind allerdings in Asm deutlich
>einfacher zu erkennen,...

Genau deshalb meine Bemerkung. Und die Frage des TO lässt mich stark 
vermuten das Pointer hier nicht im Spiel sind. Deswegen muss man das 
nicht unnötig verkomplizieren.

MfG Spess

von Luke (Gast)


Lesenswert?

Mikki Merten schrieb:
> .dseg
> .org SRAM_START                  ;1. SRAM Adresse nach I/O
> Beispiel_register1: .Byte 1      ;Register definieren
> Beispiel_register2: .Byte
>
> evtl. Zeile 2 Vergessen ? Sonst wird auf R0, R1 zugegriffen

Ist das so? Hab die zeile nicht drinnen.
SRAM_START ist wie definiert? Im includefile,?

von spess53 (Gast)


Lesenswert?

Hi

>> evtl. Zeile 2 Vergessen ? Sonst wird auf R0, R1 zugegriffen

>Ist das so? Hab die zeile nicht drinnen.
>SRAM_START ist wie definiert? Im includefile,?

Selbstverständlich im Include File:

.equ  SRAM_START  = 0x0100
.equ  SRAM_SIZE  = 2048
.equ  RAMEND  = 0x08ff

Das .org SRAM_START kannst du dir auch sparen. Der Assembler ordnet die 
Variablen automatisch nach .dseg ab RAM_START an.

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

Nachtrag: Das stammt ja nicht von dir, sondern von Mikki.

@ Mikki Merten (mmerten)

Nach .dseg ist kein .org SRAM_START notwendig. genau so wenig wie ein 
.org $0000 nach dem .cseg am Programmstart. Das macht der Assembler 
selbst.

MfG Spess

von Thomas (kosmos)


Lesenswert?

Benutzt du Interupts?

von Mikki M. (mmerten)


Lesenswert?

Stimmt seit Vers. 2.xx wertet der Assembler SRAM_START selber aus. Das 
war den 1.xx Versionen noch nicht der Fall. Dann bleibt wohl eher das 
häufig
vergessene sichern und restaurieren des SREG in Interrupt-Routinen ;)

von spess53 (Gast)


Lesenswert?

Hi

>Stimmt seit Vers. 2.xx wertet der Assembler SRAM_START selber aus. Das
>war den 1.xx Versionen noch nicht der Fall.

Im 4er Studio sind beide Assembler enthalten. Bei beiden ist das .org 
nicht notwendig.

MfG Spess

von Mikki M. (mmerten)


Lesenswert?

also ich hab hier noch 4er .lst files bei denen das nicht der Fall ist. 
Da wurde immer 0 angenommen. War damals ein echter Stolperstein die 
Unterschiede 0x60 (Classic AVR) oder 0x100 bzw. 0x200 bei den neueren 
MEGA im Griff zu halten.
Wobei mit .dseg per Default bei SRAM_START zu beginnen, auch nicht 
unbedingt
korrekt ist, zumindest aber dokumentiert das dies ab Vers. 1.75 der Fall 
ist.

von Luke (Gast)


Lesenswert?

Thomas O. schrieb:
> Benutzt du Interupts?

Ja benutze ich !
Denkst du da an eine mögliche fehlerquelle? Arbeitsregister sichere ich 
mit push und pop.  Hatte da nämlich schon mal einen Fehler.

von Matthias (Gast)


Lesenswert?

>oder Problem mit STACK Pointer?)

Initialisierst Du den irgendwo?
Der sollte gleich am Anfang des Programms auf RAMEND gesetzt werden.

von Thomas (kosmos)


Lesenswert?

ich mache das auch so wie du neben der Register die man am schnellsten 
ansprechen kann lege ich bestimmte Sachen im SRAM ab um Sie jederzeit 
wieder dort abholen zu können, wenn ich die Register anderweitig 
verwenden will.

ich setzte meinen Programmstart auch immer auf 0x00 habe mir aber schon 
gedacht das das der Assembler selber macht.
1
.DSEG            ;Reserve jeweils 1 Byte im SRAM
2
Ergebniss1l:    .byte 1
3
Ergebniss1h:    .byte 1
4
Ergebniss2l:    .byte 1
5
Ergebniss2h:    .byte 1
6
Aufloesung1l:    .byte 1
7
Aufloesung1h:    .byte 1
8
9
.CSEG
10
.ORG  0x00
11
rjmp reset
12
13
reset:
14
ldi temp, high(RAMEND)    ;Stackpointer initialisieren
15
out SPH,  temp
16
ldi temp, low (RAMEND)
17
out SPL,  temp
18
19
ldi temp,  low(3600)    ;Auflösung = 0,1°
20
ldi temp2, high(3600)
21
sts Aufloesung1l, temp
22
sts Aufloesung1h, temp2

von Luke (Gast)


Lesenswert?

Ja stackpointer initialisiere ich.

von Thomas (kosmos)


Lesenswert?

Hast du es mal durchsimuliert, gerade die Interuptsaufrufe und beobachte 
dabei das dseg.

von Luke (Gast)


Angehängte Dateien:

Lesenswert?

Thomas O. schrieb:
> Hast du es mal durchsimuliert, gerade die Interuptsaufrufe und beobachte
> dabei das dseg.

Wo kann ich das dseg beobachten?

Habe jetzt den Fehler auf eine Divisionsroutine eingegrenzt.. wenn ich 
diese durch die gleiche Divisionsroutine nur mit anderen Register 
ersetze (also statt call Division_32_32 ... call Division_32_32_X) und 
nur bei der fehlerhaften Stelle aufrufe dann funktionierts.

Wenn ich dann aber überall wieder die gleiche (also mehrmals im 
Programm) Divisionsroutine aufrufe funktionierts nicht mehr.

Jetzt frag ich mich natürlich wo der Fehler ist. Ganz verstehen tu ichs 
nicht.
Kann es an der Divisionsroutine selber der Fehler sein weil sie zu oft 
aufgerufen wird?

Divisionsroutine ist am Anhang. Vielleicht findet wer einen Fehler?

LG

von Luke (Gast)


Lesenswert?

Fehler kann durch Interrupts ja eigentlich nur verursacht werden wenn 
ich die Register nicht sichern würde mit push und pop?

von Karl H. (kbuchegg)


Lesenswert?

Poste halt mal den komnpletten Code.

Leute wie c-Hater, deren Blick dann durch nichts getrübt ist, werden dir 
dann sicher helfen den Fehler zu finden.

(Sorry, aber da musste jetzt mal sein)

von Thomas (kosmos)


Lesenswert?

oder wenn ein Interrupt nicht wieder korrekt beendet wird wird einfach 
der nächste Befehl ausgeführt der nach der Interruptroutine steht. Wenn 
das dann ein paar hundert mal passiert ist der SRAM bei den kleinen AVRs 
dann voll.

Hab hier leider kein AVR-Studio auf dem Lappi, bei der Version 4 konnte 
ich ein Fenster öffnen wo ich dann Data auswählen konnte, dann sah ich 
genau wo was ins SRAM geschrieben oder gelesen wurde, schaute wie ein 
kleines Fenster ala HEX Editor aus.

Starte mal das Programm im AVR-Studio, dann kannst du schritt für 
Schritt das Programm abarbeiten oder mit Breakpoints Sachen 
überspringen, die Eingangspins kannst du per Mausklick umschalten um 
z.B. das Programm drauf reagieren zu lassen und sieht immer sehr schon 
wohin das Programm abzweigt...

von Luke (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

Bin jetzt mit der Fehlersuche weiter. Der Fehler dürfte im Interrupt 
liegen. Ich verstehe leider nicht warum.

Im Anhang sende ich die Programmteile mit der timer1_interruptroutine 
der timer1 initialisierung, der Berechnung2 wo der Fehler schlussendlich 
auftritt nach der Division, und der Divisionsroutine selbst.

Entdeckt wer beim Interrupt einen Fehler?
Ich komm nicht mehr weiter und häng grad.

Divisionsroutine habe ich nicht selber geschrieben..
Die anderen Sachen( ich weiß sie könnten schöner programmiert 
sein...mein Fehler).

Danke!

LG


PS: Das Fenster wo ich das SRAM überwachen kann hab ich im AVR Studio 4 
leider nicht gefunden.

von spess53 (Gast)


Lesenswert?

Hi

Mal ehrlich, du rufst die Divisionsroutine, in der keines der 
verwendeten Register gesichert wird, im Mainloop und im Timerinterrupt 
auf. Schon mal überlegt, was passiert, wenn der Timerinterrupt mitten in 
der Division des Mainloops zuschlägt?


>PS: Das Fenster wo ich das SRAM überwachen kann hab ich im AVR Studio 4
>leider nicht gefunden.

View->Memory. Dort 'Data' auswählen.

MfG Spess

von Luke (Gast)


Lesenswert?

Ja ganz Blöd.

Sorry. Hab jez erst bemerkt was ich da für einen Blödsinn verzapft hab.

von c-hater (Gast)


Lesenswert?

Luke schrieb:

> Bin jetzt mit der Fehlersuche weiter. Der Fehler dürfte im Interrupt
> liegen. Ich verstehe leider nicht warum.

> Entdeckt wer beim Interrupt einen Fehler?

Der Interupthandler enthält (wahrscheinlich) einen Fehler, der sofort 
auffällt. Du benutzt twitest zum Retten der Flags ohne twitest zuvor 
erstmal selber zu retten. Damit ist im Minumum erstmal der Inhalt von 
twitest verloren.

Ob das wirklich ein Fehler ist, hängt davon ab, ob twitest auch noch 
irgendwo anders im Code verwendet wird. Der symbolische Name weist 
darauf hin, daß das wohl der Fall ist, im geposteten Teil des Codes ist 
er aber nirgendwo weiter zu finden.

von Luke (Gast)


Lesenswert?

twitest wird sonst nirgends verwendet. Das passt also.

Wie gesagt Fehler gefunden. Ganz dumm.
Sorry

von Thomas (kosmos)


Lesenswert?

1
ldi    temp1,0b00000000    ;normal operation (overflow)
2
sts    TCCR1A,temp1

speicherst du die Einstellungen zusätzlich im RAM oder funktioniert hier 
statt out auch sts?

von spess53 (Gast)


Lesenswert?

Hi

>speicherst du die Einstellungen zusätzlich im RAM oder ...

TCCR1A liegt im erweiterter IO-Bereich und ist nur mit sts ansprechbar.

>...funktioniert hier statt out auch sts?

STS funktioniert immer. Z.B. lädt ein 'sts 0,r16' das Register r0 mit 
dem Inhalt von r16. Allerdings sind die Adressen der Register, die mit 
in/out erreichbar sind, im inc-File an in/out angepasst. Also 0x20 
kleiner als für sts/lds.

MfG Spess

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.