Forum: Mikrocontroller und Digitale Elektronik Problem mit Speicherverwaltung? (8051)


von Dida N. (quader)


Angehängte Dateien:

Lesenswert?

Ich bin im Moment an einem Schulprojekt. Ziel ist es ein einfaches 
Oszilloskop zu erstellen. Die Anwendung schlussendlich ist eigentlich 
nicht wichtig, es geht nur ums Prinzip. Nun habe ich aber ein komischs 
Problem.

Ich benutze einen 80C537-N als Controller, die Ausgabe erfolgt über ein 
T6963C-Display.
Das Speichermodell ist small, einige Variabeln sind als data andere als 
idata und ein grosses Array ist als xdata definiert. Um Variabeln auch 
im Interrupt zu gebrauchen habe ich globale Variabeln verwendet. Habe 
ich dies üerhaupt richtig gelöst?

IN MAIN.C:
1
char xdata ScopeMem[220];  // Speicherung der ADC-Daten in externem Speicher
2
char MemFlag = 0;      // Flag für Timer0-Überlauf
3
unsigned char MemPos = 0;    // Position in ScopeMem

IN INTERRUPT.C:
1
extern char xdata ScopeMem[220];  // Speicherung der ADC-Daten in externem Speicher
2
extern char MemFlag;    // Flag für Timer0-Überlauf
3
extern unsigned char MemPos;  // Position in ScopeMem

Im main() sollte eigentlich gar nicht viel gemacht werden, dieses wurde 
um den Fehler zu suchen stark vereinfacht.

Das Problem ist, dass auf dem Display in Abhängigkeit des Interrupts 
eine andere Ausgabe erfolgt. Eigentlich sollte das Display nur 
intialisiert werden und auf ihm ein Raster gezeichnet werden. Ist im 
Interrupt aber folgende Zeile aktiv, so wird noch eine weitere Funktion 
ausgeführt.

Besagte Zeile, welche auskommentiert wird oder nicht (befindet sich in 
interrupt.c):
1
ScopeMem[MemPos] = ADDAT;  // AD-Wert zwischenspeichern

Funktion, die fälschlicherweise aufgerufen wird, wenn obere Zeile 
ausgefürt wird (befindet sich in T6963C.c):
1
void T6963cPutADCline(int idata delay, int idata zoom)

Ich glaube, dass diese Funktion nur einmal am Anfang aufgerufen wird.
Nun, ich sehe nicht ganz wo das Problem liegt, allerdings kenne ich mich 
mit Memorybereichen etc. auch nicht sonderlich gut aus. Im Anhang habe 
ich noch das MemoryMap des Projektes angehängt.
Dieses sieht zwar je nach Code-Optimierungslevel (welches im Moment auf 
Level 0 'constant folding' eingestellt ist) ein bisschen anders aus, der 
Fehler wirkt sich aber gleich aus.

Es wird wohl irgendwas in der Speicherzuordnung (Stack, Adressierung der 
Funktionen, o.ä.) nicht stimmen.
Wäre sehr dankbar wenn mir jemand helfen könnte. Bin am verzweifeln!

[Anhängend in einer Datei:]
- main.c
- interrupt.c

von Dida N. (quader)


Angehängte Dateien:

Lesenswert?

Hier noch das MemoryMap. Die Datei kann mit jedem Texteditor geöffnet 
werden.

[Anhängend in einer Datei:]
- MemoryMap

von Matthias (Gast)


Lesenswert?

1
char xdata ScopeMem[220];
2
....
3
4
if(MemPos>219) MemPos = 0;

Hier ein mögliches Problem:

ScopeMem[220];
reserviert 220 Werte, aber von 0...219

if(MemPos>219) MemPos = 0;
MemPos wird bei Dir aber 220, das darf es nicht, also auf >218 testen 
sonst überschreibst Du irgendwas im Speicher.

von Dida N. (quader)


Lesenswert?

Matthias wrote:
> MemPos wird bei Dir aber 220, das darf es nicht, also auf >218 testen
> sonst überschreibst Du irgendwas im Speicher.

Es wird zwar 220, in dem Fall wird es aber gleich darauf wieder 
gelöscht. Es kommt nie zum Aufruf ScopeMem[220]. Die Reihefolge ist ja: 
inkrementieren, prüfen, schreiben.
1
ScopeMem[MemPos] = ADDAT;  // AD-Wert zwischenspeichern
2
MemFlag = 1;        // neuer Wert gespeichert
3
MemFlag++;          // neuer Wert gespeichert
4
MemPos++;          // Position f�r n�chstes mal inkrementieren
5
6
if(MemPos>219)        // Falls Array voll ist, wieder bei erster Position beginnen
7
   MemPos = 0;

Ich habe aber noch etwas herausgefunden: Bestimme ich die Position in 
ScopeMem nicht mit einer Variabeln, sondern mit einer Konstante (sei es 
0, 50, 219, oder was auch immer) so tritt der Fehler nicht auf.
Wenn ich es aber doch mit einer Variable mache, dann funktioniert es 
nur, wenn ich diese nicht inkrementiere. Ich kann die Variable aber mit 
anderen Werten laden (0...219).

Beispiele die funktionieren:

Mit einer Konstante:
1
ScopeMem[0] = ADDAT;  // AD-Wert zwischenspeichern (0...219)
2
MemFlag = 1;        // neuer Wert gespeichert
3
MemFlag++;          // neuer Wert gespeichert
4
MemPos++;          // Position für nächstes mal inkrementieren
5
6
  if(MemPos>219)        // Falls Array voll ist, wieder bei erster Position beginnen
7
    MemPos = 0;

Mit Variabel aber ohne Inkrementierung:
1
ScopeMem[MemPos] = ADDAT;  // AD-Wert zwischenspeichern
2
MemFlag = 1;        // neuer Wert gespeichert
3
MemFlag++;          // neuer Wert gespeichert
4
MemPos = 0;          // Position für nächstes mal inkrementieren (0...219)
5
6
if(MemPos>219)        // Falls Array voll ist, wieder bei erster Position beginnen
7
    MemPos = 0;

Bin echt überfordert mit der Sache...

von Dida N. (quader)


Lesenswert?

Also, noch eine Erkenntniss...

Hab das ganze mal ausserhalb des Interrupts realisiert, der Fehler blieb 
gleich.

Die Übergabe von MemPos an ScopeMem[] scheint wirklich das Problem zu 
sein.
Ist MemPos als data definiert funktioniert es nicht. Bei idata oder 
xdata jedoch schon:

funktioniert nicht:
1
unsigned char MemPos = 0;        // Position in ScopeMem
2
oder
3
unsigned char data MemPos = 0;        // Position in ScopeMem
funktioniert:
1
unsigned char idata MemPos = 0;        // Position in ScopeMem
2
oder
3
unsigned char xdata MemPos = 0;        // Position in ScopeMem

Könnt ihr euch vorstellen, woran das liegt? Kann man mit einer 
'data'-Variable kein kein Feld eines 'xdata'-Arrays bestimmen?
Kanns ja nicht sein. Und die Variable nun als idata oder xdata zu 
definieren will ich eigentlich nicht, da diese rel. oft gebraucht wird.

von Peter D. (peda)


Lesenswert?

Es gibt mehrere Unbekannte:

Wo wird das Programm abgelegt?
Wird es vielleciht im RAM abgelget, der glechzeitig als Codespeicehr 
dient?
Dann überschreibst Du Dir die ersten 220Byte Deines Programms.


Wo ist das Displayprogramm, wie ist das Display angeschlossen (memory 
mapped)?

Vielleicht schreibst Du ja statt in den SRAM, ins Display.

Schau Dir mal die Board-Doku an, wie welche Speicherbereiche 
angeschlossen sind.


Peter

von Helmi (Gast)


Lesenswert?

Setze mal in main

MemPos = 0;

Es kann sein das der Startup Code die Variable nicht auf 0 setzt und 
dann da etwas undefniertes drinsteht

Gruss Helmi

von Matthias (Gast)


Lesenswert?

Was steht im .LNP-File (Linker-Einstellungen)?

von Dida N. (quader)


Angehängte Dateien:

Lesenswert?

@Helmi
Hab ich probiert, allerdings leider ohne Erfolg.

@Peter Dannegger
Keil sollte das eigentlich intern selbst regeln. Ich muss gestehen, dass 
ich in diesem Bereich leider nicht gereade viel Erfahrung habe.
Aber der 8051 sollte ja eigentlich verschiedene Speicherbereiche haben, 
für code, data, xdata, etc.
Solange ich nicht selbst etwas mit dem Memory-Typ 'code' überschreibe 
sollte eigentlich nichts passieren. Ganz sicher bin ich mir aber nicht.

Das Display ist Parallel an Port4 und Port5 angehängt. Dass ich direkt 
in das RAM des Displays schreibe habe ich auch schon gedacht, aber das 
kann ich mir nicht wirklich vorstellen.
memory mapped habe ich zwar schon gehört, habe damit aber noch nie was 
gemacht. Und so ausversehen das Display so anzusteuern ist wohl nicht 
möglich, oder schon?
Habe meine Funktion denen von Simon Küppers angepasst, und in diesem 
Thread steht, dass es nicht memory mapped ist.
Beitrag ""Bessere" T6963c Library"

Doku hab ich vom uC schon gelesen, aber nichts spezielles gefunden :|

@Matthias
Auszug aus ScopeMeter.lnp:
1
"main.obj",
2
"T6963C.obj",
3
"timer.obj",
4
"interrupt.obj" 
5
TO "ScopeMeter" 
6
RAMSIZE(256)

Im Anhang nochmals die neueste Memory Map.

von Matthias (Gast)


Lesenswert?

Da in Deiner .lnp die Angabe zum XDATA-Bereich fehlt, wird der Linker 
XDATA bei Adresse 0x0000 beginnen. Liegt Dein XDATA wirklich ab Adresse 
0000H?

Auch gibt es keine Angabe zu der XDATA Größe.

In der .lnp sollte noch dies stehen:
XDATA(0X0000-0X3FFF)
nur als Bsp., hier Xdata ab 0000H und 16kB Lang

Diese Einstellung musst Du bei Keil (Device-Optionen) machen und wird 
dann automatisch in die .lnp übernommen.

von Dida N. (quader)


Lesenswert?

@Matthias
Es klappt nun tatsächlich, danke!
Ich hatte wohl wirklich Tomaten vor den Augen, dass ich dies im Memory 
Map nicht realisiert hatte.

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.