hallo
ich habe folgendes Problem mit meinem LPC2478 +SDRam, wenn ich ein Wort
in den Speicher schreibe, habe ich dieses jedes aml an 4 worten,
anstelle von nur 1 wort, kann mir jemand einen tip geben, was ich beim
initialisieren falsch mache?
SD-Ram: http://www.issi.com/pdf/42S32800B.pdf
Code
1
voidinit_ram(void)//routine zum initialisieren des SD-Ram Controllers
Schau mal ganz unten im Beitrag:
LCD Timings - SVGA - LPC2478
Dort hat Kai F. folgendes zu diesem Thema geschrieben:
Das Mode-Register wird ja über die Adressleitung geschrieben, d.h. diese
Zeile ist ja ein (spezieller) Lesezugriff auf eine bestimmte Adresse.
Jetzt ist es aber so, dass die Adressierung bei einem SDRAM nicht in
einem Schritt passiert, sondern in drei (Row, Column und dann in der
Seite). Schau mal in das Dokument, das du oben verlinkt hast.
Das knifflige an den SDRAMS und deren Initialisierung ist dann halt den
Shift-Wert (in den Fall 13) richtig zu bestimmen, dass die Bits auch an
der richtigen Stelle im Mode-Register landen.
Burst-Length steht in Bit[2:0], CAS-Latency in Bit[6:4].
Mit der 13 werden nun diese Bits so verschoben, dass sie in der
Row-Adresse stehen. Wenn ich mich richtig erinnere: Column-Breite +
Bus-Breite (1 für 16 Bit; 2 für 32 Bit) + 2 (für Bänke) -> 9+2+2 = 13.
Ich denke, dass da nichts mehr hinzuzufügen ist.
Nimms nicht persönlich aber dein Code ist ja sowas von hässlich, ständig
irgendwelche Pointer und der ganze Müll.
Hab dir meine eigene SDRAM Schreib- und Leseroutinen angehängt.
Bei SDRAM_LENGTH muss du zunächst die Größe deines SDRAMs in Byte
angeben.
Nach der SDRAM Initialisierung löschst du diesen mit SDRAM_erase und
dann schreib einfach ein paar chars und lies diese aus und prüfe auf
Korrektheit.
Wenn weiterhin Probleme hast dann melde dich
Gruß Alex
OK. Fangen wir aber bei der Hardware an. Ein oft gemachter Fehler ist
die Geschichte mit der A13 und A14 Leitung.
A13 und A14 muss immer an BA0 und BA1.
Kannst du dein Schaltplan posten, das würde die Sache um einiges
erleichtern.
Hoppla ich sehe grad, dass du ja gar keine pull-ups pull-downs an den
SDRAM Pins deaktiviert/aktiviert hast.
Bei mir, bei nem 128 Mbit SDRAM sieht das Ganze so aus:
//-----------------
PCONP|=(1 << 11); // EnableRAMPower();
PINSEL5 |= 0x55010115;
PINMODE5 |= 0xAAaaaaaA;
PINSEL6 |= 0x55555555;
PINMODE6 |= 0xAAAAAAAA;
PINSEL7 |= 0x55555555;
PINMODE7 |= 0xAAAAAAAA;
PINSEL8 |= 0x15555555;
PINMODE8 |= 0x1AAAAAAA;
PINSEL9 |= (1 << 18);
PINMODE9 |= 0x80000;
//---------------
Beim LPC2478 sind die Pins im Default (after reset) auf pull up gesetzt.
Es ist bei mir etwas länger her, dass ich mich dem dem SDRAm
beschäfftigt habe.
Das wird ja immer interessanter!
laut deinem memory dump werden alle 32 Adressen die Schreibdaten einmal
um 8 und daraufhin um 2 Zähler verringert, irgendwie kann ich das
überhaupt nicht hachvollziehen. Ich vermute ganz stark, dass die
Testroutine Fehler enthält.
Leider ist der Kode so hässlich, dass man den überhaupt nicht lesen mag.
Versuch mal Folgendes:
//------------------------------
int main(void){
PLL_init();
SDRAM_init();
SDRAM_erase();
for(unsigned int a = 0; a < 50000; a++)
{
SDRAM_write_byte(a,250); // schreibe die ersten 50k bytes
}
for(unsigned int b = 0; b < 50000; b++)
{
unsigned char buf = 0;
buf = SDRAM_read_byte(b); // lese die ersten 50K bytes
if( buf != 250)
{
RED_LED_ON; // prüfe auf Korrektheit z.B. mit einer LED
while(1);
}
}
}//main
//-------------------------------
Hast du eigentlich schon funktionierenden UART? Wenn nicht dann hätte
ich hier was für den UART0.
von mir:
> laut deinem memory dump werden alle 32 Adressen die Schreibdaten einmal> um 8 und daraufhin um 2 Zähler verringert
sorry, hab Quatsch geredet, es sind einmal 24 und daraufhin 30 Zähler,
die ständig nach je 32 Adressen abgezogen werden.
es fängt ja schon hiermit an:
> volatile WORD *short_wr_ptr;> volatile WORD *long_wr_ptr;
warum soll denn der Bezeichnung nach ein short_wr_ptr und long_wr_ptr
von gleicher länge( WORD) sein?
Ein long_wr_ptr müsste dem Namenssinn nach ein long = DWORD sein.
also so: volatile DWORD *long_wr_ptr;
> soweit gehts, nur das ganze ram testen?
Sehr schön, wenn die ersten 50000 bytes schon mal richtig sind, dann ist
es der Rest auch. Damit testest du das ganze SDRAM, wird aber vllt. ne
Minute brauchen:
//-----------------------------------
int main(void){
PLL_init();
SDRAM_init();
SDRAM_erase();
for(unsigned long a = 0; a < 32000000; a++)
{
SDRAM_write_byte(a,250);
}
for(unsigned long b = 0; b < 32000000; b++)
{
unsigned char buf = 0;
buf = SDRAM_read_byte(b);
if( buf != 250)
{
RED_LED_ON; // prüfe auf Korrektheit z.B. mit einer LED
while(1);
}
}
}//main
//-----------------------------------
Meinetwegen:
Folgende Routine schreibt jeweils 4 bytes (=long) auf einmal
und zwar jedes mal die eigene SDRAM-Daten-Adresse und prüft diese
anschließend auf korrektheit:
//-----------------------------------
int main(void){
PLL_init();
SDRAM_init();
SDRAM_erase();
for(unsigned long a = 0; a < 8000000; a++)
{
SDRAM_write_long(a,a);
}
for(unsigned long b = 0; b < 8000000; b++)
{
unsigned long buf = 0;
buf = SDRAM_read_long(b);
if( buf != b)
{
RED_LED_ON; // prüfe auf Korrektheit z.B. mit einer LED
while(1);
}
}
}//main
//-----------------------------------
> Für mich sieht es so aus, als ob er den bereich 2mal beschreibt und zwar> genau nach der hälfte
Genau, ist ja auch richtig so!
Wenn die Speicheradresse beim Schreiben zu Ende ist, dann wird die
Adresse automatisch auf den Ursprung zurück gesetzt und man überschreibt
somit den alten Inhalt, kurz gesagt: wenn man ununterbrochen auf das RAM
schreibt, dann schreibt man immer im Kreis.
Das siehst du auch an deinem letzten geposteten memory dump. Das letzte
Programmstück von mir schreibt an jede 32-Bit Adresse seine eigene
Adresse.
nach 16 Mbyte (= 0x00400000 * 4) schreibt er wieder von vorne und
beginnt an der Adresse 0x00400001, die aber gar nicht da ist, weil du ja
dein SDRAM auf 16 Mbyte eingestellt hast. Weil die Testroutine von mir
dies aber ignoriert, der SDRAM Controller aber nicht, schreibst du
munter weiter als ob nix wäre.
Das Timing, die Hardware und alle anderen Einstellungen scheinen also
korrekt zu funktionieren, nur muss man noch die Größe richtig
einstellen, hab jetzt leider nicht viel Zeit fürs Datenblatt, aber ich
komme noch dazu..
Mach mal bitte in deiner void init_ram(void) am Schluss
aus dem: EMCDynamicControl = 0x00000000;
hier das: EMCDynamicControl = 1; // = all clock enabled continuously
so habe deine vorschläge getestet, bis jetzt hat leider noch nichts zum
erfolg geführt... mit dem buffer macht keinen unterschied, und wenn ich
die burst länge respektive die adresse verändere, an der ich den SDRam
konfiguriere wird es höchstens schlechter anstelle von besser... wäre es
evtl möglich, dass etwas mit den bankselect leitungen nicht richtig
funktioniert, dass der ram immer auf den banks 0 und 1 angesprochen
wird? sprich ba1 immer 0 ist und dadurch der speciher auf den unteren
beiden banks immer überschrieben wird?
ist aber so angeschlossen, siehe schema, evtl möglich wäre eine
schlechte lötstelle oder eine unterbrechung in der leiterbahn, werde ich
überprüfen sobald ich wieder zuhause bin, das würde erklären, wieso er
beide mal die gleichen 2 banks beschreibt, wenn die leitung A14 nicht
richtig verbunden wäre...
Nein, in deinem Schaltplan sind die Leitungen verdreht:
A14 >> BS0
A13 >> BS1
bei mir sieht es so aus:
A14 >> BS1
A13 >> BS0
Theoretisch müsste es egal sein ob BS0 auf A13 oder A14 kommt, bei mir
funktioniert das aber so und sogar sehr stabil, nutze das SDRAM als
Frame_Buffer für ein 7" TFT-LCD mit 800x480 px. Pixelfehler wären sofort
sichtbar gewesen.
Wie du schon sagtest, piepse mal die Leitungen durch. Wenn alles in
Ordnung ist, dann kannst ja mal ein Oszi an die BS0/BS1 Leitungen hängen
oder irgnedwas hochohmiges wie eine LowCurrent LED mit hohem
Vorwiderstand, um zu schauen, ob der LPC die Leitungen beim Ramtest
überhaupt wackelt. Wenn dies nicht der Fall sein sollte, dann schau
nochmal die ganzen PINSELxx Einstellungen an.
Irgendwie komme ich hier grad etwas durcheinander.
Laut Datenblatt akzeptiert der LPC nur ein
8Mx32 SDRAM mit row length = 13, column length = 8.
das ist auch das, was du eingestellt hast.
Dein SDRAM ist aber laut seinem Datenblatt ein
8Mx32 SDRAM mit row length = 12, column length = 9.
Das würde theoretisch heißen, dass der LPC auf das 9. column bit gar
nicht zugreifen kann, wodurch dir nur die Hälfte (256 anstatt 512) der
column Adressen zur Verfügung steht, was somit auch insgesamt nur die
Hälfte des Gesamtspeichers bedeuten würde.
... Ist aber nur eine Vermutung.
> also ich seh in meinem schaltplan> A13 = BA0> A14 = BA1
Stimmt!
Sorry, bin grad selbst durcheinander gekommen.
bei mir sind sie verdreht:
A13 = BA1
A14 = BA0
so jetzt ist es richtig.
Ich kenne da leider keinen Trick und ich glaube da gibt es auch keinen,
der LPC unterstützt zwar column length >= 9 aber nicht bei 32bit SDRAMs.
Wenn du ins Datenblatt (user manual) vom LPC auf Seite 90 schaust, bei
allen 32bit SDRAMS ist die column length = 8.
Da ist meiner Meinung nach nichts mehr zu machen.
Zumal, wenn ich fragen darf, wozu brauchst du denn soviel RAM, mit dem
aktuellen hast du doch schon 16Mbyte sicher.