Forum: Mikrocontroller und Digitale Elektronik externer SRAM


von Steinhaus (Gast)


Lesenswert?

Hallo zusammen,

ich möchte an meinem ATmega 128 einen esternen SRAM Baustein(64kByte)
ansteuern.

Die 8 Adress/Datenleitungen sind an PortA, die Adressleitungen an
PortC, WE_N an Pin PG0, RD_N an PG1 und ALE an Pin PG2.

Wie müsste eine C-Funktion aussehen, um Daten in den Speicher
reinzuschreiben bzw. Daten aus dem Speicher auszulesen.

Ich wäre für eure Hilfe sehr dankbar!

Peter

von Christof Krüger (Gast)


Lesenswert?

Du musst den Externen Speicher erstmal aktivieren, das machst du ganz
genau so wie in ASM (siehe Datenblatt welche Register dafür
verantwortlich sind). Schaue dir auch das Memory Mapping an, dann
weisst du auch, welcher Speicher wo eingeblendet ist.

Ein ganz klares RTFM! ;)

von OldBug (Gast)


Lesenswert?

Oder auch: Suchen lernen mit dem suchen-Link:

http://www.mikrocontroller.net/forum/forum.php?action=search&forum=1

von Steinhaus (Gast)


Lesenswert?

Hallo,

Danke für Eure schnelle Antwort.
Ich habe bereist den externen Speicher wie folgt aktiviert.

void xmem_interface_init(void)
{
MCUCR|=0x80;     // External SRAM/XMEM Interface enable
XMCRB&=0xF8;    // full 60 kB space
XMCRA|=0x02;   //wait 2 cycles during read/write strobe
}
Meine Frage: Wie kann ich jetzt beispielsweise die Speicherzelle mit
der Adresse 0x10 mit Daten beschreiben. Muss ich die Steuerleitungen
wie RD(read strobe), WE(write strobe), ALE handeln oder macht es die
XMEM interface. Wie müsste die C-Funktion dazu aussehen.

Ich wäre für eure Antwort sehr dankbar.

Peter

von KoF (Gast)


Lesenswert?

hmm...
als erstes cs (cable select) selectieren (wird warscheinlich lowactiv
sein).
dann die write leitung selectieren (höchst warscheinlich auch
lowactiv).
dann die adresse anlegen und zum schluss die daten.

von OldBug (Gast)


Lesenswert?

Nix da!
Macht alles das XMEM-Interface!

Mit "Speicherzelle mit der Adresse 0x10" meinst Du wahrscheinlich die
Speicherstelle im externen SRAM.
Leider musst Du da zur Zeit noch mit ein bißchen Pointer-Salat drauf
Zugreifen!
Kleines Beispiel:

uint8_t *pExtSRAM = (uint8_t *) 0x1110; /* extmem start: 0x1100 */

[..]
    pExtSRAM[0] = 0x55;
[..]

Der Wert 0x1110 ergibt sich natürlich aus dem Adressoffset, der durch
das interne SRAM des AVRs entsteht (OFFSET + ADR = EXTADR: 0x1100 +
0x10 = 0x1110).

von OldBug (Gast)


Lesenswert?

Achso, noch was vergessen: CS steht hier nicht für 'Cable Select'
sondern für 'Chip Select'!

von OldBug (Gast)


Lesenswert?

Einen hab ich noch =)

'//wait 2 cycles during read/write strobe'

Bist Du eigentlich sicher, daß Du so lange warten willst?

von Steinhaus (Gast)


Lesenswert?

Könnte ich nicht einfach meine Funktion auch so gestallten..?

void XMEM_Write(unsigned char adr,unsigned char daten)
{
/* # define OFFSET 0x8600
unsigned int *ptr=(unsigned int *)(OFFSET+adr);
*p=daten;
}

oder liege ich total falsch???

von OldBug (Gast)


Lesenswert?

Wenn Dein externes SRAM erst ab Adresse 0x8600 anfängt, geht das im
Prinzip schon, nur solltest Du die Sache ein wenig anders angehen:

void
XMEM_write_byte(uint8_t * adr, uint8_t data)
{
    *adr = data;
}

void
XMEM_write_int(int * adr, int data)
{
    *adr = data;
}

Den offset dann bei Aufruf hinzufügen:

[..]
    XMEM_write_byte(OFFSET + 0x10, 128);
    XMEM_write_int(OFFSET + 0x11, 32767);
[..]

etc, pp.

von Steinhaus (Gast)


Lesenswert?

Danke für deine große Hilfe.

Ihr seid wirklich super!!!

von Alex (Gast)


Lesenswert?

hi
kann mir mal jemand sagen was ich hier falsch mache
Ich schreibe den Wert ins externe SRAM,lese ihn dann erneut aus und
gebe ihn über die serielle Schnittstelle zurück.
Aber der Wert der bei der seriellen Schnittstelle am PC ankommt stimmt
überhaupt nicht überein mit dem ins RAM geschriebenen.
In diesem Fall kommt der Wert 4111 zurück.


#define OFFSET 0x10FF
//---------------------------------------------

void XMEM_wr(int *address,int data);
int XMEM_rd(int* address);
//---------------------------------------------
...
//---------------------------------------------
void XMEM_wr(int* address, int data)
{
*address=data;
}

int XMEM_rd(int* address)
{
int wert;
wert= *address;
return wert;
}
//---------------------------------------------
 void main (void) {
while(1) {
        XMEM_wr(OFFSET+0x10, 27);
  printf("\t%d",XMEM_rd(OFFSET+0x10));
 }
}


mfg alex

von Alex (Gast)


Lesenswert?

weiß den keiner einen rat

von Ingo (Gast)


Lesenswert?

OFFSET muss die erste externe Adresse sein, bei Dir wahrscheinlich
0x1100 (steht aber im Datenblatt).

Um Fehler mit der seriellen SSt auszuschliessen würde ich 0xaa und 0xff
in das externe mem schreiben und auf einem Port die gelesenen werte
ausgeben. Dann kannst Du mit LEDs oder schlimmstenfalls einem
Multimeter in Ruhe messen, ob alles stimmt.

von Wolfram (Gast)


Lesenswert?

Wo und wie initialisierst du deinen externen Speicher?
Wo liegt dein Stack?

von Alex (Gast)


Lesenswert?

Die Initialisierung erfolgt dort wo ich die ... geschrieben habe.
Sie erfolgt gleich zu Beginn des Programmes und wird normalerweise
natürlich in der main vor der while(1) aufgerufen.

Ich habs jetzt eingefügt wie mein SRAM konfiguriert ist.
Ich hab meinen RAM mit nur 1 Sector definiert und 2 die wait states als
2r/w für diesen Sektor.

//SRAM Initialisierung
MCUCR=0x80;
XMCRA=0x02;


@Wolfram: "Wo liegt dein Stack?" ...versteh die Frage leider nicht
ganz, aber hab mal meine Speicher/Stack-größen angeführt
Data Stack Size: 1024bytes
Internal SRAM size:  4096bytes

@Ingo: Stimmt, mein Fehler. Hab die Adresse des Endes des internen
Speichers als OFFSET angegeben. Natürlich gehört der Beginn des
externen Speichers als OFFSET mit 0x1100 angegeben.

von Wolfram (Gast)


Lesenswert?

Auch wenn das funktionieren wird, was du gerade machst.
Es liegt nur daran weil der Compiler denkt du würdest ohne externes RAM
arbeiten. d.h. Stack und Daten liegen unterhalb der 4KB.
Solltest du das XMEM_read/rw aufgeben wollen und in der Art
unsigned char array[5000];
array[5]=6;
arbeiten wollen, so solltest du dir den entsprechenden Abschnitt in der
avrlibc Doku durchlesen. Es ist sowieso besser das Mapping des
Speichers
abgeschlossen zu haben BEVOR man in main eintritt. DER COMPILER WEISS
NÄMLICH NICHTS DAVON!
Solltest du nicht gerade im ATMEGA103 Modus arbeiten dann möchte ich
dich darauf hinweisen, dass im ATMEGA128 die ersten 4352 Byte des
Datamemory intern sind. Das hast du ja auch schon mitbekommen.
Ein Zugriff auf OFFSET 0x10ff geht also voll in den Stack!
Bei Rücksprüngen kann sowas einen sehr interessanten Programmablauf
bewirken.

von Alex (Gast)


Lesenswert?

Danke erstmal.
Ich werde mal den betreffenden Teil der avrlibc studieren.

Aber wenn ich es so schreibe: unsigned char array[5000];
array[5]=6;
kann es ja passieren das der Compiler die Datei ins interne RAM legt.
ICh muss ihm ja sagen dass er die VAriable array[] ins externe
schreiben soll. Das jedoch machst du nicht. Wenn ich die Variable so
initializiere dann legt er sie automatisch in den internen RAM.

Und nein ich bin nicht im Atmega103-kompatibiltätsmodus

von Alex (Gast)


Lesenswert?

hi
hab erst jetzt wieder den Weg zum Programmieren gefunden.
Hab den Abschnitt zum externen RAM gelesen aber leider kein Wort
verstanden.

Naja, das Problem besteht weiterhin. Ich kann die Werte ins RAM
schreiben (mit debugger kontrolliert) und sie bleiben dort auch. Nur
beim Auslesen haperts. Über USART kommt immer noch 4111 und ich hab mal
0xAA ins RAM geschrieben und dann auf Port D ausgegeben aber dort liegt
dann 0x0F an.

Muss ich irgendein RegisterBit setzen damit /RD auch funktioniert? Weil
eigentlich sollte das XMEM das ja automatisch machen.

Init wie oben in älterem Post von mir bereits beschrieben

mfg Alex

von lawmower (Gast)


Lesenswert?

int XMEM_rd(int* address)
{
int wert;
wert= address;    <-- den Wert nicht die Adresse zurückgeben
return wert;
}

von lawmower (Gast)


Lesenswert?

ups Fehler.

Ports als output schalten
DDRA=0xFF
DDRC=0xFF
DDRG=0x1F

so läufts zumindest bei mir

von Wolfram (Gast)


Lesenswert?

>Hab den Abschnitt zum externen RAM gelesen aber leider kein Wort
>verstanden
Das ist schlecht, ist nämlich sehr wichtig das man weiss was man tut.

Ich versuchs mal zu erklären
Du willst einen externen RAM benutzen, für dein C Programm sollte das
ganze vollkommen transparent sein, du hast halt mehr SRAM. Also nicht
4K sondern 64 K.
Probleme:
1.Der C-Compiler muss dies mitgeteilt bekommen. Er benutzt einen Stack
der liegt am Ende des Speichers, solange du ihm nicht sagst dass dein
Ende des Speichers nicht mehr bei 4K liegt sondern bei 64K wird er
seinen Stack weiterhin bei 4K abwärts anfangen.
2. Bevor du in main kommst hat dein Programm schon einiges gemacht
Stack anlegen, Variablen mit 0 füllen ,Strings laden etc.
d.h. du must vorher das Speicherinterface initialisiert haben und zwar
OHNE den Stack zu benutzen(Funktionsaufrufe und lokale Variablen sind
zu diesem Zeitpunkt absolut tabu!). Dazu gibt es die init Sektionen
hier gibts du eine Funktion an die das Speicherinterface einschaltet.
Sobald du dies getan hast, kannst du ohne weiteres im Programm
schreiben
unsigned char Variable[6000];

Da du einen Debugger hast (JTAG?) ,kannst du den ja sehr einfach testen
ob dein externer RAM funktioniert. Assembler-Projekt in AVR-Studio laden
(ohne gehts leider nicht) in IO-Register wechseln
und Speicherinterface aktivieren. Dann in Speicherfenster wechseln und
kontrollieren ob der Speicher funktioniert.

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.