Forum: Mikrocontroller und Digitale Elektronik LCD Timings - SVGA - LPC2478


von Omega G. (omega) Benutzerseite


Lesenswert?

Hallo,

ich bin am testen meines LPC Boards. Da ich am Display Port einen LVDS 
Transmitter habe, habe ich ein 800x600 Display von Unipac angeschlossen.

Prinzipiell habe ich ein Bild, allerdings sieht es aus als würden die 
Back und Front porch Angaben nicht stimmen. (Zittern und zu lange 
Zeilen)

Es handelt sich um ein UB084S01: 
http://www.gblcd.com/datacenter/unipac/UB084S01.pdf

Meine Initialisierung sieht so aus:
1
PCONP |= (1<<20);  //Enable LCD controller
2
LCD_CTRL = 0x2A;  //TFT 24 Bit
3
LCD_CFG = 1;    //Set divider CCLK/2 = 40 MHz 
4
LCD_POL =  (0x01 << 26)|(799 << 16)|(0x00 << 14)|(0x01 << 13)|(0x01 << 12)|(0x01 << 11);  
5
//Bypass pixel clock divider | 800 clocks per line | invert: panel clock, h clock, v clock
6
LCD_TIMH =  (87 << 24)|(39 << 16)|(127 << 8 )|(49 << 2);  
7
//Back porch = 88 clk | Front porch = 40 clk | Pulse with = 128 clk | Size = (49 + 1)*16 = 800 px
8
LCD_TIMV = (22 << 24)|(0 << 16)|(3 << 10)|(599);      
9
//Back porch = 22 px | Front porch = 1 px | Pulse with = 3 px | Size = 600 px
10
LCD_UPBASE = LCD_VRAM_BASE_ADDR & 0xfffffff8;
11
LCD_LPBASE = LCD_VRAM_BASE_ADDR & 0xfffffff8;
12
LCD_CTRL |= 1|(1<<11);    //Enable LCD

Habe ich die porch clocks etc. korrekt umgerechnet und eingesetzt? Oder 
muss ich meinen Fehler wo anders suchen?

Der LPC2478 läuft auf 80 MHz, das macht keine Probleme, auch mit dem 
SDRAM.

von Kai F. (k-ozz)


Lesenswert?

Stimmt der Zeilenanfang, d.h. ist der Pixel ganz links in einer Zeile da 
wo er sein soll, oder ist er auch schon nach rechts verschoben?

von Benedikt K. (benedikt)


Lesenswert?

Da das Display das DataEnable Signal auswertet, sind die Front und 
Backporchzeiten nicht allzu kritisch.
Wenn ich das Datenblatt des LPC2478 richtig verstehe, ist der CPL Wert 
im LCD_POL Register die gesamten Takte pro Zeile, also 1056 und nicht 
800.

von Omega G. (omega) Benutzerseite


Lesenswert?

Der Zeilenanfang stimmt. Das Ändern des CPL Wertes auf 1056 führt dazu, 
dass gar nichts mehr angezeigt wird. Wäre 1056 nicht eh zu groß für 
dieses Register?! (11 Bit in 9 Bit Register?)

von Benedikt K. (benedikt)


Lesenswert?

Omega G. schrieb:
> Wäre 1056 nicht eh zu groß für
> dieses Register?! (11 Bit in 9 Bit Register?)

Das Register hat 10 bit, aber das ist immer noch zu klein. Der LPC ist 
also etwas beschränkt was die Displaygröße angeht. Stell mal 1023 ein.
Die Summe aus Frontporch + Backporch + Syncimpuls + Pixel auf dem 
Display muss gleich dem CPL Wert sein. Vermutlich musst du daher die 
Front + Backporch Werte reduzieren, damit die Zeile eben maximal 1024 
Pixel lang wird.

von Kai F. (k-ozz)


Lesenswert?

Dieses Zittern und die zu langen Zeilen deuten darauf hin, dass du ein 
übersprechen von Datenleitungen auf die Clock-Leitung hast. Deine 
Aussage, dass der Zeilenanfang stimmt, bestätigt diese Theorie.
Du hast in dener Clock-Leitung einen Widerstand (R20). Löte einmal einen 
18pF oder 22pF Kondensator hinter dem Widerstand gegen Masse, sozusagen 
ein Tiefpass.

von Omega G. (omega) Benutzerseite


Angehängte Dateien:

Lesenswert?

Stimmt 10 Bit!

1023 verändert an der anzeige was, aber natürlich bringt es nicht den 
gewünschten Effekt.

Im Anhang das Bild. Es sollen alle 10 Zeilen eine Zeile weiß sein.

Sieht aus, also ob das nichts wird mit diesem LCD, obwohl der Controller 
theoretisch bis 1024x768 unterstützen sollte.

von Benedikt K. (benedikt)


Lesenswert?

Omega G. schrieb:
> 1023 verändert an der anzeige was, aber natürlich bringt es nicht den
> gewünschten Effekt.

Reduzier mal den Frontporch auf 32, den Backporch auf 80 und die 
Syncbreite auf 112. Das sollte exakt 1024 Pixel pro Zeile ergeben.

von Kai F. (k-ozz)


Lesenswert?

Die Angabe von 799 für CPL stimmt aber!

von Omega G. (omega) Benutzerseite


Lesenswert?

Erste Zeile stimmt so, die zweite hat etwas rechts von der Mitte aus 
eine Unterbrechung. Wenn ich das richtig sehe, stimmt jede zweite Linie.

von Benedikt K. (benedikt)


Lesenswert?

Kai F. schrieb:
> Die Angabe von 799 für CPL stimmt aber!

Sicher? Dann ist das Datenblatt aber falsch:

CPL Clocks per line.
This field specifies the number of actual LCDDCLK clocks to the
LCD panel on each line.

-> gesamte Anzahl an Takten pro Zeile

PPL Pixels-per-line.
The PPL bit field specifies the number of pixels in each line or
row of the screen.

-> aktiver Bildbereich

von Kai F. (k-ozz)


Lesenswert?

Betreibe hier ein 480x272-Display mit dem LPC2478 und da ist 479 
richtig.

von Omega G. (omega) Benutzerseite


Lesenswert?

Mit CPL = 799 zeigt das Display gar nichts an, mit den Angaben von 
Benedikt. Wenn ich CPL auf 1023 setze schon.

von Kai F. (k-ozz)


Lesenswert?

Mach mal bitte ein Bild vom Display mit den Settings, die du in deinem 
ersten Post hattest.

von Omega G. (omega) Benutzerseite


Angehängte Dateien:

Lesenswert?

So sah's aus.

von Benedikt K. (benedikt)


Lesenswert?

Falls du ein Oszilloskop oder einen Frequenzzähler hast, schau dir mal 
das Signal an DataEnable an oder messe zumindest die Frequenz von HSync.
Daran kann man leicht erkennen, ob der CPL Wert korrekt ist.
Bei 1056 Takten pro Zeile sollte die Frequenz 40MHz/1056=37,88Hz 
betragen, bei 800 dagegen 50kHz.
Ebenso sollte bei den richtigen Einstellungen DataEnable ein 
Tastverhältnis von 800/1056=75,75% haben.

von Omega G. (omega) Benutzerseite


Lesenswert?

Ich kann gleich mal mit einem Oszilloskop ran. Mir kam noch eine andere 
Idee. Wenn ich die CLK Frequenz reduziere, kann ich auch den CPL Wert 
reduzieren?!
Ich bin etwas runter mit dem Takt auf 38 MHz, und habe den CPL Wert auf 
952. Das führt dazu, dass die Unterbrechungen am weiter am Anfang der 
Zeile sind.

von Kai F. (k-ozz)


Lesenswert?

Das Bild steht so aber still?
Was hast du in den Framebuffer geschrieben?

von Omega G. (omega) Benutzerseite


Lesenswert?

DataEnable:
Frequenz: 37,8 kHz
Duty Cyle: 75,7%

HSync:
Frequenz: 37,8 Khz
Duty Cycle: 87,8%

von Benedikt K. (benedikt)


Lesenswert?

Omega G. schrieb:
> Wenn ich die CLK Frequenz reduziere, kann ich auch den CPL Wert
> reduzieren?!

Nein. Der Pixeltakt hat nichts mit den Pixeln pro Zeile zu tun. Die 
Eingangsstufe des Displays ist erstmal rein digital und leitet über 
durch DataEnable und HSync synchronisierte Zähler aus dem Pixeltakt alle 
weiteren internen Signale an. Das Display möchte im Idealfall 1056 Takte 
pro Zeile. Dies kann man durch Verlängern oder Verkürzen der Porch Werte 
etwas verändern. Um wie viel, dazu schweigt das Datenblatt leider und 
aus Erfahrung kann ich sagen, dass sich hier jedes Display anders 
verhält.

> DataEnable:
> Frequenz: 37,8 kHz
> Duty Cyle: 75,7%

Bei welchem CPL Wert?
Der scheint also zu passen.

von Omega G. (omega) Benutzerseite


Lesenswert?

Mit den Werten im ersten Post. Also CPL = 799.

Bei keinem der Werte Stand das Bild still. Es zittern die stellen wo die 
Stellen wo Linien doppelt sind bzw. unterbrochen sind.

von Benedikt K. (benedikt)


Lesenswert?

Ok, dann hab ich dich in die falsche Richtung gelotst, da die 
Beschreibung im Datenblatt falsch ist...

Liegt das HSync Signal in dem Bereich von DataEnable der Low ist?

von Omega G. (omega) Benutzerseite


Lesenswert?

Wenn DE low ist, geht auch HSync auf low.

Gelb = Data Enabled
Grün = Hsync

von Omega G. (omega) Benutzerseite


Angehängte Dateien:

Lesenswert?

Anhang vergessen.

von Benedikt K. (benedikt)


Lesenswert?

Das grundsätzliche Timing sieht gut aus. Daran dürfte es also nicht 
liegen, das kann man jetzt ausschließen.
Du setzt das IPC Bit, um den Pixeltakt zu invertieren. Passt das?
Das Display übernimmt die Daten mit der fallenden Flanke, du gibst die 
Daten ebenfalls mit der fallenden Flanke aus.
Üblicherweise wählt man die steigende Flanke um den damit verbundenen 
Timingproblemen aus dem Weg zu gehen.
Allerdings hängt das auch davon ab, welchen LVDS Encoder du verwendet 
hast. Wenn der auch die Daten an der fallenden Flanke einliest, ist das 
Bit falsch gesetzt.

von Omega G. (omega) Benutzerseite


Lesenswert?

Es macht keinen Unterschied ob ich das IPC Bit setze oder nicht.

Den SDRAM habe ich geprüft, funktioniert.
SN75LVDS84A habe ich als LVDS Transmitter.

von Benedikt K. (benedikt)


Lesenswert?

Der SN75LVDS84A übernimmt die Daten auch mit der fallenden Flanke, das 
IPC Bit sollte also nicht gesetzt sein. Es führt aber "nur" dazu, dass 
das Bild oder einzelne Pixel ab und zu um einen Pixel hin und her 
tanzen.

Lass mal ein Bild ausgeben, dessen linkes viertel rot, dann 1/4 blau, 
dann grün und dann weiß ist und mach davon mal ein Foto.

von Kai F. (k-ozz)


Lesenswert?

Was hast du denn bisher in den Framebuffer geschrieben, d.h. wie sollte 
das Bild eigentlich aussehen? Jede zehnte Zeile weiß, der Rest schwarz? 
Mach mal ein Muster mit vertikalen Linien.

von Kai F. (k-ozz)


Lesenswert?

Da war wohl einer schneller ... ;-)

von Omega G. (omega) Benutzerseite


Lesenswert?

Testweise schreibe ich so in den Framebuffer:
1
for (x = 0; x < 800; x++){
2
    for(y = 0; y < 600; y++){
3
      for (c = 0; c < 3; c++){
4
        if((x%10==0))
5
          *(unsigned char*)((unsigned int)&SDRAM_BASE_ADDR+z) = 0xff;
6
        z+=1;
7
      }
8
    }
9
  }
Das müsste doch alle 10 Zeile eine Linie ergeben, oder denke ich falsch?
1
for (x = 0; x < 800; x++){
2
    for(y = 0; y < 600; y++){
3
      for (c = 0; c < 3; c++){
4
        if((x%10==0)|(y%10==0))
5
          *(unsigned char*)((unsigned int)&SDRAM_BASE_ADDR+z) = 0xff;
6
        z+=1;
7
      }
8
    }
9
  }
Müsste dann eine Karomuster geben?

Stimmt das so, bevor ich mit falschem Ansatz weitermache?

von Benedikt K. (benedikt)


Lesenswert?

Omega G. schrieb:
> Testweise schreibe ich so in den Framebuffer:
>
1
> if((x%10==0))
2
>
> Das müsste doch alle 10 Zeile eine Linie ergeben, oder denke ich falsch?

Nein, jede 10. Spalte wen du x abfragst. Aber kann es sein, dass du die 
x und y Schleifen vertauscht hast? Im Speicher folgt eine Zeile nach der 
anderen und nicht eine Spalte nach der anderen.


>
1
>         if((x%10==0)|(y%10==0))
2
>
> Müsste dann eine Karomuster geben?

Du wolltest vermutlich anstelle von dem | ein || schreiben (auch wenn es 
hier auf das gleich hinausläuft)?

von Kai F. (k-ozz)


Lesenswert?

Wieso schreibst du nicht gleich 32 Bit?
1
for (y=0;y<600;y++)
2
{
3
  for (x=0;x<800;x++)
4
  {
5
    if (((x%10)==0) || ((y%10)==0))
6
      *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ffffff;
7
    z++;
8
  }
9
}

von Omega G. (omega) Benutzerseite


Angehängte Dateien:

Lesenswert?

1
for (x = 0; x < 800; x++){
2
    for(y = 0; y < 600; y++){
3
      for (c = 0; c < 3; c++){
4
        if((x%10==0)||(y%10==0))
5
          *(unsigned char*)((unsigned int)&SDRAM_BASE_ADDR+z) = 0xff;
6
        z+=1;
7
      }
8
    }
9
  }
Ergibt das Bild im Anhang.
1
for (x = 0; x < 800; x++){
2
    for(y = 0; y < 600; y++){
3
      //for (c = 0; c < 3; c++){
4
        if((x%10==0)||(y%10==0))
5
          *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ffffff;
6
        z+=1;
7
      //}
Ergibt nur ein Bild in der oberen Hälfte?!

von Kai F. (k-ozz)


Lesenswert?

Du mußt in der äußeren Schleife y inkrementieren und in der inneren x!

von Kai F. (k-ozz)


Lesenswert?

Sorry:
1
z+=4;

von Omega G. (omega) Benutzerseite


Angehängte Dateien:

Lesenswert?

Sieht so aus.

Genau wie wenn ich x und y vertausche.

von Omega G. (omega) Benutzerseite


Angehängte Dateien:

Lesenswert?

z+=4 sieht so aus.

von Benedikt K. (benedikt)


Lesenswert?

Poste mal den Code der dieses Bild erzeugt hat.

von Omega G. (omega) Benutzerseite


Lesenswert?

1
  for (y=0;y<600;y++)
2
{
3
  for (x=0;x<800;x++)
4
  {
5
    if (((x%10)==0) || ((y%10)==0))
6
      *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ffffff;
7
    z+=4;
8
  }
9
}

erzeugt dieses Bild. Das Muster im Hintergrund sollten auch Linien 
sein...

von Kai F. (k-ozz)


Lesenswert?

Also wie sieht der Code jetzt komplett aus?

von Benedikt K. (benedikt)


Lesenswert?

Probier mal das aus:
1
  for (y=0;y<600;y++)
2
{
3
  for (x=0;x<800;x++)
4
  {
5
    if (x<200)
6
      *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ff0000;
7
    else if (x<400)
8
      *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x0000ff00;
9
    else if (x<600)
10
      *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x000000ff;
11
    else
12
      *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ffffff;
13
    z+=4;
14
  }
15
}

von Omega G. (omega) Benutzerseite


Angehängte Dateien:

Lesenswert?

Der Code von Benedikt erzeugt dieses Bild.

von Benedikt K. (benedikt)


Lesenswert?

Sehr seltsam.
Ich sehe weder rot noch grün, nur blau.
Ersetze mal die letze Zeile in der weiß ausgegeben wird durch rot. Wenn 
dann die Streifen rot/blau sind, dann stammen immerhin alle Daten aus 
dem Speicher und nicht sonst wo her.

von Kai F. (k-ozz)


Lesenswert?

1
unsigned int TestFunc(void)
2
{
3
unsigned int x;
4
unsigned int y;
5
unsigned int z;
6
z=0;
7
for (y=0;y<600;y++)
8
{
9
  for (x=0;x<800;x++)
10
  {
11
    if (x<200)
12
      if (*(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) != 0x00ff0000)
13
      {
14
        return z;
15
      }
16
    else if (x<400)
17
      if (*(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) != 0x0000ff00)
18
      {
19
        return z;
20
      }
21
    else if (x<600)
22
      if (*(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) != 0x000000ff)
23
      {
24
        return z;
25
      }
26
    else
27
      if (*(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) != 0x00ffffff)
28
      {
29
        return z;
30
      }
31
    z+=4;
32
  }
33
}
34
return 0xffffffff;
35
}

Ruf mal diese Testfunktion nach dem beschreiben des Framebuffers auf und 
werte den Rückgabewert aus.

von Omega G. (omega) Benutzerseite


Lesenswert?

Da bekomme ich 0 zurück. Sieht aus als ob doch was mit dem RAM nicht 
stimmt. Zumindest im 32 Bit Betrieb.

von Omega G. (omega) Benutzerseite


Lesenswert?

Meine Testroutine:
1
for (i = 0; i < 0x100000; i+=sizeof(unsigned int))
2
  {
3
    *(unsigned int*)((unsigned int)&SDRAM_BASE_ADDR+i) = i;
4
  }
5
6
  for (i = 0; i < 0x100000; i+=sizeof(unsigned int))
7
  {
8
  temp = *(unsigned int*)((unsigned int)&SDRAM_BASE_ADDR+i);
9
    if (temp != i)
10
    {
11
    sendint8_uart0(i);
12
    send_uart0(' ');
13
    sendint8_uart0(temp);
14
    send_uart0(10);
15
    send_uart0(13);
16
    }
17
  }
18
  return(1);

gibt 1 zurück und sendet nichts über UART.

Ich bin momentan ratlos.

von Kai F. (k-ozz)


Lesenswert?

Zeig mal bitte deine SDRAM Initialisierung.

von Omega G. (omega) Benutzerseite


Lesenswert?

1
PCONP|=(1<<11);
2
  //  EnableRAMPower();
3
  PINSEL5 = 0x55010115;
4
  PINMODE5 = 0xAAaaaaaA;
5
  PINSEL6 = 0x55555555;
6
  PINMODE6 = 0xAAAAAAAA;
7
  PINSEL7 = 0x55555555;
8
  PINMODE7 = 0xAAAAAAAA;
9
  PINSEL8 = 0x05555555;
10
  PINMODE8 = 0x0AAAAAAA;
11
  PINSEL9 = (1 << 18);
12
  PINMODE9 = 0x80000;
13
 
14
  
15
16
  EMC_CTRL=1; // enable EMC
17
  EMC_DYN_RD_CFG=1;//Configures the dynamic memory read strategy(Command delayed strategy)
18
  EMC_DYN_RASCAS0|=0x303;
19
  EMC_DYN_RP= 4;//RP
20
  EMC_DYN_RAS = 8;//RAS
21
  EMC_DYN_SREX = 5;// SREX, XSR not found
22
  EMC_DYN_APR = 2; //APR not found
23
  EMC_DYN_DAL = 5; //DAL, APW not found
24
  EMC_DYN_WR = 3; //WR, DPL, RWL, RDL
25
  EMC_DYN_RC = 11;//
26
  EMC_DYN_RFC = 11; //rfc rc
27
  EMC_DYN_XSR = 5;//txsr not found
28
  EMC_DYN_RRD = 3;//RRD
29
  EMC_DYN_MRD = 8;//RAS
30
  EMC_DYN_CFG0 = (1<<14)|(3<<9)|(1<<8)|(1<<12);//8,9,14
31
  
32
  for(i = 0; i < 100; i++);
33
  EMC_DYN_CTRL = 0x0183; // NOP
34
  for(i = 0; i < 100; i++);
35
  EMC_DYN_CTRL=0x101; 
36
  EMC_DYN_RFSH = 1;
37
  for(i = 0; i < 100; i++);
38
  EMC_DYN_RFSH = 19;
39
40
  EMC_DYN_CTRL=0x81; 
41
  i = (*(volatile int*)(0xA0000000 | (0x32<<12)));
42
  EMC_DYN_CTRL = 0;
43
44
  EMC_DYN_CFG0|=0x80000;

Ich habe einen K4S643232E-TC70 drinnen. Ich hoffe nächste Woche bekomme 
ich 128 Mbit RAMs.

von Kai F. (k-ozz)


Lesenswert?

Ich bin noch nicht durch, aber das ist mir schon mal aufgefallen:

Du schreibst:
1
EMC_DYN_CFG0 = (1<<14)|(3<<9)|(1<<8)|(1<<12);//8,9,14
Wenn man diesen Wert im User Manual anschaut, dann müsstest du einen 
"256 MB (8Mx32), 4 banks, row length = 13, column length = 8" 
angeschlossen haben.

Du hast aber lt. deiner Bauteilbezeichnung einen "64 MB (2Mx32), 4 
banks, row length = 11, column length = 8" -> 0x5300
Also müsste deine Zeile lauten:
1
EMC_DYN_CFG0 = (1<<14)|(1<<12)|(1<<9)|(2<<7);
Du kannst die (1<<12) auch weglassen, dann wird das Ding als High 
Performance angesprochen.

von Omega G. (omega) Benutzerseite


Lesenswert?

Das funktioniert nur, wenn ich Bit 12 setze. Genau wie meine Funktion.

Noch Ideen, ansonsten warte ich auf das vorgesehene RAM.

von Kai F. (k-ozz)


Lesenswert?

Wenn du Bit 12 nicht setzt, dann kommt garnichts?
Hast du mal die Zeile so, wie ich sie oben geschrieben habe ausprobiert?
Verändert sich das Bild, oder das Ergebnis des Speichertest dadurch?

von Omega G. (omega) Benutzerseite


Lesenswert?

Wenn ich Bit 12 nicht setze, dann habe ich nur Speicherfehler mit deiner 
Zeile.

von Kai F. (k-ozz)


Lesenswert?

Und wenn du es setzt?

von Omega G. (omega) Benutzerseite


Lesenswert?

Dann habe ich laut meiner Testroutine keine Speicherfehler. Aber die 
Funktion zum Balken aufs Display schreiben und lesen, bringt immer noch 
0 zurück, also Fehler an Adresse 0.

von Kai F. (k-ozz)


Lesenswert?

Noch ein Versuch:
Laß die Zeile
1
EMC_DYN_CFG0 = (1<<14)|(1<<12)|(1<<9)|(2<<7);

und ändere weiter unten die Zeile so ab:
1
i = (*(volatile int*)(0xA0000000 | (0x32<<10)));
(aus 12 mach 10)

von Tobias P. (hubertus)


Lesenswert?

Hi,
wenn ich mich auch mal einmischen darf:
Ich glaube, deine SDRAM-Initialisierung ist nicht ganz korrekt.
Ich muss nachher schnell meinen eigenen Code raussuchen, dann kann ich 
dir den mal hier rein stellen.
Sicher - die Timings wirst du anpassen müssen (stimmen wirklich alle?), 
aber ich glaube meine Initialisierung sieht auch sonst noch ein bisschen 
anders aus....

Andere Frage:
hast du zum Vereinfachen des Layouts Adressleitungen oder Datenleitungen 
getauscht, verdraht, oder sonst wie anders angeschlossen?
DQMx-Signale richtig herum? DQM0 => D0..7, DQM1 => D8..15 usw.
Wie sieht der Clock aus - am Pin vom LPC sowie am Pins vom SDRAM? -> 
mach doch mal schnell ein Bild.
Wenn es dir was bringt, mache ich nachher auch schnell ein paar Bilder 
von meinen Signalen, dann kannst du vergleichen, ob bei dir irgendwas 
anders aussieht.

Ach ja: sind CLK und CKE mindestens gleich lang oder länger als die 
Adressleitungen? Ich meine mal gelesen zu haben, dass das evtl. noch 
eine Rolle spielen /könnte.

Und, noch etwas OT:
Hast du das MCI oder Ethernet schon ausprobieren können? ;-)

von Omega G. (omega) Benutzerseite


Lesenswert?

Unverändert:
Mit Bit 12: RAM test ok, Bild fehlerhaft
Ohne Bit 12: RAM test fehlerhaft, Bild fehlerhaft

von Tobias P. (hubertus)


Lesenswert?

Ach ja, was mir auffält:
weiter oben hast du gesagt, du hättest keine Speicherfehler mehr, wenn 
du Bit 12 setzt.
Das würde dann ja bedeuten, dass dein SDRAM korrekt funktioniert. 
Dummerwise macht dann aber deine "Balken-aufs-Display-zeichen-Funktion" 
einen Fehler - welche Funktion ist das nochmal?

Stack richtig initialisiert? (gross genug, an einer gültigen 
Speicheradresse).

Ich finde, wenn dein Ram-Test fehlerfrei durch läuft, dann kann der 
Fehler auch nicht beim SDRAM liegen - das lässt sich ja dann 
offensichtlich beschreiben und lesen....

von Omega G. (omega) Benutzerseite


Lesenswert?

CLK und CKE sind länger als die Adressleitungen. DQM0 vom LPC geht an 
DQMOUT0 vom Controller etc.

Kann es sein, dass es daran liegt, das mein Layout für 128 Mbit augelegt 
ist, aber 64 Mbit drinnen sind? (BA0 und BA1 vom RAM an A12 und A13 
geplant, allerdings ist A11 bei mir ja unbelegt...)

Würde es vielleicht was bringen die Serienwiderstände von 22 auf 33 Ohm 
zu vergrößern? (Mein Prototyp hat scheinbar 33 Ohm gehabt, hier sind 22 
Ohm drinnen)

Ich mache gleich Aufnahmen von den CKE und CLK Signalen.

Ethernet und MCI habe ich noch nicht getestet.

von Omega G. (omega) Benutzerseite


Lesenswert?

1
 for (y=0;y<600;y++)
2
{
3
  for (x=0;x<800;x++)
4
  {
5
    if (x<200)
6
      *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ff0000;
7
    else if (x<400)
8
      *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x0000ff00;
9
    else if (x<600)
10
      *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x000000ff;
11
    else
12
      *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ffffff;
13
    z+=4;
14
  }
15
}
erzeugt Balken
1
unsigned int TestFunc(void)
2
{
3
unsigned int x;
4
unsigned int y;
5
unsigned int z;
6
z=0;
7
for (y=0;y<600;y++)
8
{
9
  for (x=0;x<800;x++)
10
  {
11
    if (x<200)
12
      if (*(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) != 0x00ff0000)
13
      {
14
        return z;
15
      }
16
    else if (x<400)
17
      if (*(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) != 0x0000ff00)
18
      {
19
        return z;
20
      }
21
    else if (x<600)
22
      if (*(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) != 0x000000ff)
23
      {
24
        return z;
25
      }
26
    else
27
      if (*(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) != 0x00ffffff)
28
      {
29
        return z;
30
      }
31
    z+=4;
32
  }
33
}
34
return 0xffffffff;
35
}
Prüft diese Balken

von Tobias P. (hubertus)


Angehängte Dateien:

Lesenswert?

> Kann es sein, dass es daran liegt, das mein Layout für 128 Mbit augelegt
> ist, aber 64 Mbit drinnen sind? (BA0 und BA1 vom RAM an A12 und A13
> geplant, allerdings ist A11 bei mir ja unbelegt...)


Uuuh, das könnte der Grund sein - BAx sollten an A13 und A14 liegen, so 
viel ich weiss....
Schau dir vielleich mal angehängtes PDF an; ab Seite 32 wirds für dich 
interessant ;-)

von Kai F. (k-ozz)


Lesenswert?

Ich meine auf BA0 muß A13 und auf BA1 muß A14, auch für den 128Mbit 
SDRAM.

von Tobias P. (hubertus)


Lesenswert?

> Ich meine auf BA0 muß A13 und auf BA1 muß A14, auch für den 128Mbit
> SDRAM.

Sach ich doch ;-)

von Kai F. (k-ozz)


Lesenswert?

Ja klar, ich war aber (wieder einmal) zu langsam!

von Tobias P. (hubertus)


Lesenswert?

:-)

Ich glaube, es geht aus dem Datenblatt des 2478 auch nicht wirklich klar 
hervor, dass A13 und A14 mit BA0 und BA1 verbunden werden müssen. Dass 
ich das bei meinem ersten Testboard so gemacht hatte, hat sich auch eher 
durch Zufall ergeben, weil mein RAM genau 13 Adressleitungen (A0 bis 
A12) braucht - dann kommen A13 und 14 automatisch auf BAx.
Aber wie gesagt - auch wenn das RAM nur 10 Adressen oder so braucht - 
trotzdem muss man A13 und 14 mit BA verbinden (oder Kai? Das steht 
jedenfalls irgendwo in oben angehängtem Dokument).

von Omega G. (omega) Benutzerseite


Lesenswert?

Okay, das ist schlecht. Schade, das es keiner gesehen hat im Schaltplan 
von mir.

Gibt es dafür irgendeine Möglichkeit das Problem softwaremäßig zu lösen?

Oder muss ich Drähte ziehen?

von Tobias P. (hubertus)


Lesenswert?

Hi Omega,
tja ich habe mir deinen Schaltplan leider gar nicht angeschaut, sonst 
hätte ich es gesehen :-( Ich war mehr am Layout interessiert....

Aber gut, deine Leiterplatte lässt sich trotzdem noch retten - mittels 
dünnen Wrapdraht und einem Skalpell.
Softwaremässig wirst du die Bankselects nicht verbieben können, die sind 
m.W. hart verdrahtet (im LPC2478 innen drin).
Aber die fehlerhaften beiden Leiterbahnen sind ja schnell abgetrennt und 
mittels einer kleinen Drahtbrücke an den richtigen Pins angeschlossen...
Mir ist bei meinem ersten Testboard was ähnliches passiert - Ich hatte 
an den DQMx-Pins einen Layoutfehler; DQM0 und 1 waren vertauscht. 
Wrapdraht hilft da wunder; jetzt läuft das Board (auch mit 72 MHz).

von Omega G. (omega) Benutzerseite


Lesenswert?

Darf BA0 und 1 vertauscht werden?

Dann müsste ich nur eine Leitung legen^^

von Kai F. (k-ozz)


Lesenswert?

Genau. Die meisten Beispielschaltungen verwenden SDRAMs, die A0-A12, BA0 
und BA1 verwenden.
Das User Manual zum LPC2478 schweigt sich zur Belegung leider aus.

Richtig ist aber mit ziemlicher Sicherheit, dass BA0 immer an A13 und 
BA1 an A14 kommt. Die oberen Adressleitungen (A12, A11) werden bei 
fehlenden Bedarf freigelassen.
Tobias hat also vollkommen recht.

von Tobias P. (hubertus)


Lesenswert?

Also ich bin nicht DER SDRAM-Experte, aber wenn man sich diese 
Datenblätter so anguckt: das sieht so aus, als wären in einem Chip 
eigentlich 4 identische SDRAMs drinnen (eben die 4 Banks), die von BA0 
und BA1 ausgewählt werden. Von daher würde ich sagen: könnte gehen! 
Allerdings bin ich mir nicht 100%ig sicher; evtl. könnte es ja Ärger mit 
dem Refresh geben? Da weiss Kai sicher noch besser Bescheid.

Übrigens, @Kai:
Was ist los mit unserem Projekt? ;-)

von Kai F. (k-ozz)


Lesenswert?

Ich wüsste jetzt nicht, was dagegen sprechen würde. -> Ausprobieren!

von Kai F. (k-ozz)


Lesenswert?

@Tobias: Das alte Problem: Zu viel zu tun und zu wenig Zeit, aber ich 
melde mich in den nächsten Tagen wieder!

von Omega G. (omega) Benutzerseite


Lesenswert?

So. A14 geht auf BA0 und A13 auf BA1.

von Tobias P. (hubertus)


Lesenswert?

Und, funktioniert's?

von Omega G. (omega) Benutzerseite


Lesenswert?

Unverändert?! Aber ich habe noch eine Idee, Stichwort PINSEL.

von Tobias P. (hubertus)


Lesenswert?

Okay, wart mal. Ich suche jetzt meinen Notebook hervor; dort drauf habe 
ich einen funktionierenden Code, den ich nachher hier hochladen werde.
Moment...

von Omega G. (omega) Benutzerseite


Lesenswert?

So, sieht schon besser aus. Bit 12 ist nun Wurscht.

von Kai F. (k-ozz)


Lesenswert?

Wie gesagt, die relevanten Stellen in der Initialisierung des SDRAM sind 
diese beiden Zeilen:
1
EMC_DYN_CFG0 = (1<<14)|(1<<12)|(1<<9)|(2<<7);
2
...
3
i = (*(volatile int*)(0xA0000000 | (0x32<<10)));

Die Initialisierung des Displays haben wir ja schon durch. ;-)

von Tobias P. (hubertus)


Lesenswert?

Also, mein SDRAM-Code sieht wie folgt aus:
1
/*===========================================================================*/
2
void fLowLevelInit(void)
3
/*-----------------------------------------------------------------------------
4
  Function:
5
  performs a low-level hardware initialization function; called directly
6
  after reset.
7
  in:  none
8
  out: none
9
=============================================================================*/
10
{
11
#ifdef DEBUG
12
  MEMMAP = 2; /* map interrupt vectors to internal RAM (debug in RAM) */
13
#else
14
  MEMMAP = 1; /* no remapping of interrupt vectors */
15
#endif
16
17
  /* initialize the pll */
18
#if CLOCKSOURCE == CLK_MAIN /* check if the main osc is the clk source */
19
  SCS |= OSCRANGE; /* first select an oscillator range */
20
  SCS |= OSCEN; /* then enable the main oscillator */
21
  while(!(SCS & OSCSTAT)); /* wait until the main osc is ready */
22
#endif
23
  PLLCON &= ~PLLC; /* disconnect the pll */
24
  PLLFEED = 0xAA;
25
  PLLFEED = 0x55;
26
  PLLCON &= ~PLLE; /* disable the pll */
27
  PLLFEED = 0xAA;
28
  PLLFEED = 0x55;
29
  CCLKCFG = 0; /* disable cpu clock divider to speed up pll configuration */
30
  CLKSRCSEL = CLOCKSOURCE; /* select the desired clock source */
31
32
  /* set the N and M values */
33
  PLLCFG = (((NSEL - 1) & 0xFF) << 16) | ((MSEL - 1) & 0xFFFF);
34
  PLLFEED = 0xAA;
35
  PLLFEED = 0x55;
36
  PLLCON |= PLLE; /* enable the pll */
37
  PLLFEED = 0xAA;
38
  PLLFEED = 0x55;
39
  CCLKCFG = CCLK_DIV; /* select cpu clock divider */
40
  while(!(PLLSTAT & PLOCK)); /* wait for the pll to lock */
41
  PLLCON |= PLLC; /* connect the pll */
42
  PLLFEED = 0xAA;
43
  PLLFEED = 0x55;
44
45
  VICIntEnClr = 0xFFFFFFFF; /* initialize the vic by clearing any interrupts */
46
  VICAddress = 0; /* reset vic address register */
47
  VICIntSelect = 0; /* switch all interrupts to irq mode */
48
49
  MAMTIM = 3; /* initialize the memory accelerator module */
50
  MAMCR = 2;
51
52
#ifdef HI_SPEED_GPIO
53
  SCS |= BIT_00; /* select all gpios as fio instead of legacy */
54
#else
55
  SCS &= ~BIT_00; /* select legacy io ports */
56
#endif
57
58
  tDWord dwDelay;
59
  PCONP |= BIT_11; /* enable power for the emc */
60
  PINSEL5 = 0x55010115; /* enable emc pins */
61
  PINMODE5 = 0xAA02022A;
62
  PINSEL6 = 0x55555555;
63
  PINMODE6 = 0xAAAAAAAA;
64
  PINSEL7 = 0x55555555;
65
  PINMODE7 = 0xAAAAAAAA;
66
  PINSEL8 = 0x15555555;
67
  PINMODE8 = 0x2AAAAAAA;
68
  PINSEL9 = (1 << 18);
69
  PINMODE9 = 0x80000;
70
  EMCControl = 1; /* setup the emc and the timings for sdram */
71
  EMCDynamicReadConfig = 1; /* select command delayed read strategy */
72
  EMCDynamicRasCas0 = 0x203; /* cas latency 2, ras latency 3 */
73
  EMCDynamictRP = 3; /* setup all the other timings for the sdram */
74
  EMCDynamictRAS = 5; /* see the sdram calculation sheet */
75
  EMCDynamictSREX = 2;
76
  EMCDynamictAPR = 2;
77
  EMCDynamictDAL = 5;
78
  EMCDynamictWR = 3;
79
  EMCDynamictRC = 6;
80
  EMCDynamictRFC = 6;
81
  EMCDynamictXSR = 2;
82
  EMCDynamictRRD = 3;
83
  EMCDynamictMRD = 3;
84
  EMCDynamicConfig0 = (BIT_14 | BIT_10 | BIT_09 | BIT_07);
85
  for(dwDelay = 0; dwDelay < 100; dwDelay++);
86
  EMCDynamicControl = 0x181; /* issue nop command */
87
  for(dwDelay = 0; dwDelay < 100; dwDelay++);
88
  EMCDynamicControl = 0x101; /* issue precharge all command */
89
  EMCDynamicRefresh = 1; /* start the refresh timer */
90
  for(dwDelay = 0; dwDelay < 100; dwDelay++);
91
  EMCDynamicRefresh = 19; /* set up the refresh timer */
92
  EMCDynamicControl = 0x081; /* issue sdram mode command */
93
  dwDelay = (*(tpDWord)(0xA0000000 | (0x22 << 13))); /* burst length 4, 2 cas */
94
  EMCDynamicControl = BIT_01; /* clkout runs continuously */
95
  EMCDynamicConfig0 |= 0x80000; /* enable the buffer */
96
} /* end fLowLevelInit */

Die Timings musst du halt noch anpassen, aber wenigstens kannst du 
vielleicht mal schauen, in welcher Reihenfolge ich was wo initialisiert 
habe, und was nicht.
die Pinsel und Pinmode sind jedenfalls für 32 Bit externes SDRAM 
konfiguriert, passen so also zu deinem Design.

von Kai F. (k-ozz)


Lesenswert?

Vorsicht! Tobias verwendet einen anderen SDRAM!
Die Zeilen
1
EMCDynamicConfig0 = (BIT_14 | BIT_10 | BIT_09 | BIT_07);
2
...
3
dwDelay = (*(tpDWord)(0xA0000000 | (0x22 << 13))); /* burst length 4, 2 cas */
treffen für dich nicht zu!

von Tobias P. (hubertus)


Lesenswert?

Klar, sorry das hatte ich natürlich vergessen zu erwähnen!

Aber vielleicht bringt der Code ja trotzdem was, ich selber bin 
jedenfalls immer froh wenn ich eine Vorlage habe...

von Omega G. (omega) Benutzerseite


Lesenswert?

1
void init_ram_high(void){
2
  int i;
3
4
  PCONP|=(1<<11);
5
  //  EnableRAMPower();
6
  PINSEL5 = 0x55010115;
7
  PINMODE5 = 0xAAaaaaaA;
8
  PINSEL6 = 0x55555555;
9
  PINMODE6 = 0xAAAAAAAA;
10
  PINSEL7 = 0x55555555;
11
  PINMODE7 = 0xAAAAAAAA;
12
  PINSEL8 = 0x15555555;
13
  PINMODE8 = 0x1AAAAAAA;
14
  PINSEL9 = (1 << 18);
15
  PINMODE9 = 0x80000;
16
 
17
  
18
19
  EMC_CTRL=1; // enable EMC
20
  EMC_DYN_RD_CFG=1;//Configures the dynamic memory read strategy(Command delayed strategy)
21
  EMC_DYN_RASCAS0|=0x303;
22
  EMC_DYN_RP= 4;//RP
23
  EMC_DYN_RAS = 8;//RAS
24
  EMC_DYN_SREX = 5;// SREX, XSR not found
25
  EMC_DYN_APR = 2; //APR not found
26
  EMC_DYN_DAL = 5; //DAL, APW not found
27
  EMC_DYN_WR = 3; //WR, DPL, RWL, RDL
28
  EMC_DYN_RC = 11;//
29
  EMC_DYN_RFC = 11; //rfc rc
30
  EMC_DYN_XSR = 5;//txsr not found
31
  EMC_DYN_RRD = 3;//RRD
32
  EMC_DYN_MRD = 8;//RAS
33
  EMC_DYN_CFG0 = (1<<14)|(1<<9)|(2<<7);//8,9,14
34
  
35
  for(i = 0; i < 100; i++);
36
  EMC_DYN_CTRL = 0x0181; // NOP
37
  for(i = 0; i < 100; i++);
38
  EMC_DYN_CTRL=0x101; 
39
  EMC_DYN_RFSH = 1;
40
  for(i = 0; i < 100; i++);
41
  EMC_DYN_RFSH = 19;
42
43
  EMC_DYN_CTRL=0x81; 
44
  i = (*(volatile int*)(0xA0000000 | (0x32<<12)));
45
  EMC_DYN_CTRL = 1;
46
47
  EMC_DYN_CFG0|=0x80000;  
48
}

Sieht jemand noch Fehler? So läuft mein RAM test durch, allerdings die 
Balkensache sieht immernoch unverändert aus.

von Tobias P. (hubertus)


Lesenswert?

Wenn der RAM-Test so durch läuft, dann wird das RAM ja wohl jetzt 
funktionieren. Dann kann es nur noch an der Initialisierung des LCDs 
liegen...

von Omega G. (omega) Benutzerseite


Lesenswert?

Sollte man denken...

von Tobias P. (hubertus)


Lesenswert?

Etwa nicht? :-)
Ich meine - wenn das SDRAM sich beschreiben und lesen lässt, dann sollte 
der LCD-Controller das ja auch tun können.
Leider habe ich mich noch nicht mit dem LCD-Controller der 2478 befasst, 
aber wenn du deinen Code mal postest, kann dir vielleicht Kai helfen. 
Vom LCD habe ich leider nur wenig Ahnung :-(

von Benedikt K. (benedikt)


Lesenswert?

Sieht das Bild auf dem TFT immer noch exakt so aus wie vorher, jetzt da 
der SDRAM geht?

von Omega G. (omega) Benutzerseite


Lesenswert?

Ja -.-

von Tobias P. (hubertus)


Lesenswert?

Hast du vielleicht ein anderes Display, das du mal testen könntest? Wenn 
das RAM funktioniert und der LCD-Controller richtig initialisiert ist, 
kanns nur noch am Display liegen. Oder gar am LVDS-Chip? Bist du dir 
sicher, dass dieser LVDS75... oder wie der auch schon wieder hiess, 
kompatibel ist zum LPC2478 LCD Controller?

von Benedikt K. (benedikt)


Lesenswert?

Wie sieht das Bild aus, wenn du z.B. komplett alles rot machst?
Ist dann alles einheitlich gefärbt?
Da der Controller vermutlich nur während des aktiven Bildbereiches Daten 
ausgibt, müssten die Datenleitungen für rot dann ein ähnliches Signal 
beinhalten wie DataEnable.

Tobias Plüss schrieb:
> Oder gar am LVDS-Chip? Bist du dir
> sicher, dass dieser LVDS75... oder wie der auch schon wieder hiess,
> kompatibel ist zum LPC2478 LCD Controller?

Der LVDS Encoder ist nichts anderes wie ein parallel -> Seriell Wandler, 
und der Dekoder macht das ganze umgekehrt. Das einzige was inkompatibel 
sein kann, ist die Flanke, aber deren Auswirkungen sind gering.

von Omega G. (omega) Benutzerseite


Lesenswert?

0x00ff0000 = Alles Blau
0x0000ff00 = Alles Grün
0x000000ff = Alles Rot

Also als Leuchtfläche Funktioniert es. Ich hoffe der LVDS Transmitter 
läuft mit dem Controller.

von Tobias P. (hubertus)


Lesenswert?

Na, also - als Leuchtfläche geht schon mal. Rein aus Neugier: Kannst du 
mit

0xffff00,
0xff00ff,
0x00ffff

alles Cyan, Magenta und Gelb färben? (wird sicher gehen; wie gesagt 
reine Neugier).

Dann: sind die Flächen "schön", oder sehen sie auch so zerhackstückelt 
aus wie die Bilder oben? Was passiert, wenn du abwechslungsweise z.B. 
0x0000ff und 0xff0000 in das RAM schreibst? dann müsste das Bild ja eine 
Art Schachbrettmuster geben, wo jeder Pixel abwechslungsweise rot und 
dann wieder blau ist.

von Benedikt K. (benedikt)


Lesenswert?

Gut, die Farben passen schonmal.
Daraus kann man schließen, dass LVDS mäßig alles passt, ansonsten würde 
nämlich garnichts funktionieren, da die Farbdaten sowie Timingsignale 
gemultiplexed übertragen werden.

Jetzt versuch mal herauszufinden was passiert wenn du z.B. nur den 
halben Speicher beschreibst usw.

von Omega G. (omega) Benutzerseite


Lesenswert?

So, das zittern ist weg!
1
void TFT_init(){
2
//Set up 24 bit mode etc.
3
4
PINSEL0 |= 0x00055500;
5
PINSEL3 |= 0x05555500;
6
PINSEL4 |= 0x050FFFFF;
7
PINSEL9 |= 0x0A000000;
8
PINSEL11 |= 0x0000000F;
9
10
PCONP |= (1<<20);  //Enable LCD controller
11
LCD_CTRL = 0x2A;  //TFT 24 Bit
12
LCD_CFG = 1;    //Set divider CCLK/2 = 40 MHz 
13
LCD_POL =  (0x01 << 26)|(799 << 16)|(0x00 << 14)|(0x00 << 13)|(0x01 << 12)|(0x01 << 11);  
14
//Bypass pixel clock divider | 800 clocks per line | invert: panel clock, h clock, v clock
15
LCD_TIMH =  (87 << 24)|(39 << 16)|(127 << 8 )|(49 << 2);  
16
//Back porch = 88 clk | Front porch = 40 clk | Pulse with = 128 clk | Size = (49 + 1)*16 = 800 px
17
LCD_TIMV = (22 << 24)|(1 << 16)|(3 << 10)|(599);      
18
//Back porch = 22 px | Front porch = 1 px | Pulse with = 3 px | Size = 600 px
19
LCD_UPBASE = LCD_VRAM_BASE_ADDR & 0xfffffff8;
20
LCD_LPBASE = LCD_VRAM_BASE_ADDR & 0xfffffff8;
21
LCD_CTRL |= 1|(1<<11);    //Enable LCD
22
23
}

Wenn ich in
1
 for (y=0;y<600;y++)
2
 {
3
   for (x=0;x<800;x++)
4
   {
5
     if ((x<200)==0)
6
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x0000ff00;
7
     else if (x<400)
8
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ff0000;
9
     else if (x<600)
10
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x000000ff;
11
     else
12
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ffffff;
13
     z+=4;
14
   }
15
 }

y nur bis 100 laufen lasse ich nur ein Teil des TFTs gefüllt, der Rest 
schwarz.
1
for (y=0;y<600;y++)
2
 {
3
   for (x=0;x<800;x++)
4
   {
5
     if (((x==y)))
6
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ffffff;
7
     z+=4;
8
   }
9
 }

Sollte doch einen schräge Linie anzeigen. Es zeigt mir verteilte weiße 
Punkte an, aber Standbild!

Sieht aus, als ob ich den Framebuffer entweder in x oder y 
vergrößern/verkleinern müsste.

von Benedikt K. (benedikt)


Lesenswert?

Ist das Farbmuster mit den 4 Farbbereichen ok? Also siehst du alle 4 
Farben so wie es sein sollte? Falls ja, passt die Bildbreite, sonst 
wären die Zeilen versetzt.

von Omega G. (omega) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ich habe den Balkencode so abgeändert:
1
for (y=0;y<600;y++)
2
 {
3
   for (x=0;x<800;x++)
4
   {
5
     if (x<200)
6
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x0000ff00;
7
     else if ((x<400)&&(x>200))
8
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ff0000;
9
     else if ((x<600)&&(x>400))
10
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x000000ff;
11
     else
12
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ffffff;
13
     z+=4;
14
   }
15
 }

Bild 94 zeigt das Bild in Betrieb, Bild 93, wenn man das Display nicht 
mehr ansteuert.
Es sind alle Farben vorhanden.

von Benedikt K. (benedikt)


Lesenswert?

Anstelle der 200 Pixel breiten Farbbalken erscheinen also diese nur 
wenige Pixel breiten, verzerrten Streifen?

Bist du sicher, dass das SDRAM Timing passt? Eventuell funktioniert z.B. 
der Burst Read nicht, der eventuell für den LCD Controller verwendet 
wird?

von Omega G. (omega) Benutzerseite


Lesenswert?

Exakt.

von Tobias P. (hubertus)


Lesenswert?

Meiner Meinung nach sieht das so aus, als ob da irgendwie Zeilen und 
Spalten irgendwie vertauscht wären - wenn du den ganzen SDRAM ja mit 
0xff0000 füllst ist ja alles schön blau, bei 0x0000ff ist alles rot - 
soweit okay. Aber das sagt nichts darüber aus, wie die einzelnen 32 Bit 
Wörter im Memory zu den Pixeln korrelieren. Vielleicht ist da ja 
irgendwas vertauscht?

von Omega G. (omega) Benutzerseite


Lesenswert?

Mit der TestFunc weiter oben kann ich nachweisen, das die Daten im RAM 
stimmen. Es muss also entweder an der Init des Controllers liegen, dem 
Aufbau des Framebuffers oder der Palette des Controllers, der ich 
momentan nicht ein Byte würdige.

Vielleicht kann mir jemand sagen, wie wichtig die Palette ist? Ich werde 
an der Stelle aus dem Datenblatt echt nicht schlau.

von Benedikt K. (benedikt)


Lesenswert?

Die Palette ist üblicherweise für den 24bit Modus uninteressant, da man 
hier schon alle Farben darstellen kann. Siehe dazu Abschnitt 8. TFT 
panels: Nur bei 8bpp und kleiner wird die Palette verwendet.

Wie sieht das Bild aus, wenn du im obigen Code anstelle von den 4 
vertikalen Balken 4 horizontale anzeigst?

von Omega G. (omega) Benutzerseite


Angehängte Dateien:

Lesenswert?

1
 for (y=0;y<600;y++)
2
 {
3
   for (x=0;x<400;x++)
4
   {
5
     if (y<150)
6
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x0000ff00;
7
     else if ((y<300)&&(y>150))
8
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ff0000;
9
     else if ((y<450)&&(y>300))
10
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x000000ff;
11
     else if (y>450)
12
       *(unsigned int *)((unsigned int )&SDRAM_BASE_ADDR+z) = 0x00ffffff;
13
     z+=4;
14
   }
15
 }

Ich habe etwas experimentiert: Mit dem obigen Code erhalte ich dieses 
Bild.

von Tobias P. (hubertus)


Lesenswert?

Dass die Daten im RAM stimmen, bezweifelt ja niemand. Was ich eigentlich 
meinte mit meinem vorherigen Post war eher folgendes:
Logischerweise Gehört das erste 32 Bit Wort im LCD-Puffer zum Pixel Nr. 
0, also links oben. Zu welchem Pixel gehört dann das nächste Wort? Wenn 
diese Zuordnung Speicherinhalt -> Pixel nicht stimmt, kommt Murks auf 
dem Display raus.
Deshalb meinte ich auch: Füll mal deinen Speicher abwechslungsweise mit 
0 und 0xffffff (als Beispiel). Was kommt dann raus? Oder füll den ganzen 
Speicher mit 0, und nur das aller erste Wort mit 0xffffff.
So würde ich jedenfalls versuchen, das zu debuggen - immer nur Schritt 
für Schritt. Wenn du gleich auf einen Schlag das mit den 4 farbigen 
Bereichen machen willst, birgt das doch zu viele Fehlerquellen. Irgend 
ein Fehler im Code, Alignment nicht richtig im SDRAM, was weiss ich.
Ach ja, was mir grade einfällt, was du noch versuchen könntest:
Füll den Speicher derart, dass das erste Wort 0 ist, und jedes weitere 
dann um eins inkrementiert wird. Dann müsste irgend ein 
"Regenbogenmuster" auf dem Display erscheinen (meine ich).

von Benedikt K. (benedikt)


Lesenswert?

Das sieht für mich so aus, als wenn er mit schnellen Wechseln der 
Bilddaten Probleme hätte. Für lange Zeit die gleichen Daten sind dagegen 
absolut problemlos.
Bau mal einen Code ein, der einfach sinnlos in einen anderen 
Speicherbereich 0en schreibt und lass diesen Code ununterbrochen laufen, 
so dass die Daten auf dem Datenbus vom SDRAM mit 0en unterbrochen 
werden.
Ich hatte man ein ähnliches Phänomen was sich am Ende als Timingproblem 
beim SDRAM rausstellte.

von Omega G. (omega) Benutzerseite


Lesenswert?

Selbst auf 24 MHz CPU und RAM Takt sieht es unverändert aus. Auch wenn 
ich zwischendurch immer auf irgendwas zugreife.

Möglicherweise stimmen meine RAM Timings nicht ganz, oder dieser RAM ist 
einfach defekt. (Auf Grund von Ungeduldigikeit von einer Grafikkarte 
ausgelötet, von der ich nicht weiß ob die noch funktionierte!)

Was mich aber wundert: warum läuft der Speichertest durch ohne Fehler?!

von Benedikt K. (benedikt)


Lesenswert?

Um sicherzugehen, dass der RAM Test wirklich funktioniert (auch wenn es 
sehr unwahrscheinlich ist dass er es nicht tut): Veränder doch mal 
irgendein Byte nach dem Beschreiben. Dann müsste der RAM Test den Fehler 
anzeigen.

Irgendwo müssen die Daten durcheinander kommen.
Da die horizontalen Balken passen, kann man das Display sowie dessen 
Ansteuerung als Fehler ausschließen. Auch scheinen zumindest ab und zu 
die Daten zu passen.

Kannst du mal prüfen ob eventuell ein FIFO Underflow eintritt? Bei 80MHz 
SDRAM Takt und 40MHz Displaytakt dürfte das eigentlich nicht vorkommen, 
aber man weiß ja nie...

von Omega G. (omega) Benutzerseite


Lesenswert?

Also RAM Test, ich habe einfach mal ein Byte nach dem beschreiben 
verändert. Wurde korrekt gemeldet.

Ja, die Daten müssen irgendwo durcheinander kommen, und ich bin etwas 
ratlos wo das passiert.

Display timings:
Dann dürfte sich ja nichts verändern wenn man nicht im Framebuffer 
rumpfuscht. Ich habe ja ein Standbild. Also kann man den LVDS 
Hochfrequenzteil auch ausschließen.

SDRAM: RAM Test funktioniert, da werden die Daten auch schnell 
hintereinander beschrieben, und das erfolgreich.

Wie prüfe ich auf einen FIFO underflow?

von Kai F. (k-ozz)


Lesenswert?

Mach mal einen Test:
1. Alles schwarz füllen, nur einen einzigen Punkt weiß.
2. Einen zweiten Punkt links neben dem ersten abwechselnd (vielleich 1 
Hz) in weiß und schwarz zeichnen, den Rest so lassen.

Frage: Verändert sich die Position des ersten Punktes auf dem 
Bildschirm?

von Benedikt K. (benedikt)


Lesenswert?

Omega G. schrieb:
> Also RAM Test, ich habe einfach mal ein Byte nach dem beschreiben
> verändert. Wurde korrekt gemeldet.

Also kann man den auch ausschließen.
Der Fehler muss also irgendwo im Bereich des internen LCD Controllers 
liegen.

> Display timings:
> Dann dürfte sich ja nichts verändern wenn man nicht im Framebuffer
> rumpfuscht. Ich habe ja ein Standbild. Also kann man den LVDS
> Hochfrequenzteil auch ausschließen.

Ja.
Was du mal probieren könntest: Den Pixeltakt halbieren, den Rest lassen 
(also den CPU und SDRAM Takt).
Ist dann zwar außerhalb der Specs, aber es sollte dennoch gehen.

> Wie prüfe ich auf einen FIFO underflow?

Laut Datenblatt wird dann im LCD_INTRAW Register ein Bit gesetzt.

von Omega G. (omega) Benutzerseite


Angehängte Dateien:

Lesenswert?

Funktioniert!

Woran lag's:
Benedikt hatte (wie so oft in Sachen Displays) die zündende Idee: 
Display Clock zu hoch. Scheinbar kam das SDRAM einfach nicht hinterher.

von Benedikt K. (benedikt)


Lesenswert?

Wunderbar!
Das wundert mich aber dennoch, denn eigentlich läuft der SDRAM doppelt 
so schnell wie die Daten benötigt werden. Allerdings hatte ich mit einem 
LCD Controller schon ähnliche Erfahrungen gemacht, daher auch die Frage 
nach der zusätzlichen Schleife die Daten ins SDRAM schreibt um das 
zusätzlich zu belasten.
Die SDRAM Controller scheinen also nicht perfekt zu sein.
Als Ausweg könntest du entweder das SDRAM Timing verbessern indem du ein 
schnelleres SDRAM verwendest (und somit z.B. eine geringere CAS Latency 
einstellen kannst, ob das allerdings ausreicht ist zu bezweifeln), oder 
aber indem du nur 16bit Farbtiefe verwendest.

von Kai F. (k-ozz)


Lesenswert?

Genau! Habe grad mal den LCD-BusLoadCalculator durchlaufen lassen: Bei 
60Hz sind's 153% Buslast auf dem Speicher!

von Omega G. (omega) Benutzerseite


Lesenswert?

Eigentlich ist eh ein anderes RAM vorgesehen, dann optimiere ich das ein 
wenig, mal sehen was machbar ist! Vielen Dank für die Hilfe!!!

von Benedikt K. (benedikt)


Lesenswert?

Offtopic:
Hat jemand ein Erklärung dafür, warum gerade mal 85MByte/s Datenrate zur 
Verfügung stehen, obwohl das SDRAM eigentlich 80MHz*32bit=320MByte/s 
könnte?
Klar, es gibt einen Overhead bei der Ansteuerung, aber die erklärt 
keinen Unterschied von fast Faktor 4.

Und vor allem: Warum sich bei einem 16bit SDRAM die Datenrate gerade mal 
auf 67,4Mbyte/s reduziert und nicht halbiert. Das sind gerade mal 26% 
Unterschied in der Datenrate.

von Tobias P. (hubertus)


Lesenswert?

Yeah, cool dass es jetzt funktioniert!
Geht denn nun auch wirklich alles zuverlässig?

von Omega G. (omega) Benutzerseite


Lesenswert?

Es scheint soweit zuverlässig zu sein. Ich habe ein Weile eine Plasma 
Animation laufen lassen. Ruckt zwar ziemlich, aber macht viele 
Speicheroperationen.

von Benedikt K. (benedikt)


Lesenswert?

Läuft das TFT immer noch mit 20MHz?
Für den richtigen Betrieb würde ich auch 16bpp runtergehen, denn 20MHz 
ist weit außerhalb der Specs. Ob das langfristig negative Auswirkungen 
auf das TFT hat, kann man daher nicht sagen.

Ich denke ich habe die Ursache für den langsamen SDRAM gefunden:
Der LPC liest dem BusLoadCalculator nach immer 16Bytes auf einmal. Dazu 
benötigt er bei einem 32bit SDRAM 15 Takte! Der SDRAM Controller ist 
also dumm, da er nichtmal eine bereits geöffnete Bank berücksichtigt 
wenn ich das richtig sehe. Das hätte man deutlich besser machen können. 
Das würde die Zeit pro Burst auf 11 Takte reduzieren wenn die Bank 
gleich ist, was rund 25% mehr Datenrate bedeuten würde.

von Kai F. (k-ozz)


Lesenswert?

Es hätte auch schon viel gebracht, wenn er mit 32bit SDRAMs 8er Bursts 
unterstützen und somit gleich 32 Bytes lesen würde.

von Benedikt K. (benedikt)


Lesenswert?

Ein 8er Burst wurde 19 Takte dauern, dafür aber die Datenrate 
verdoppeln, macht 134,7MByte/s statt 85,3MByte/s. Rund 58% 
Geschwindigkeitssteigerung.
Das noch kombiniert mit dem intelligenteren Controller (da es ein LCD 
Controller ist, kann man wohl davon ausgehen dass viele Daten 
sequentiell gelesen werden so dass dies Sinn macht, und so aufwendig ist 
das auch nicht) wären das 32Bytes in 15 Takten, also 170,7MByte/s, eine 
Steigerung um satte 100%.
Anscheinend haben die das Problem erkannt, denn der LPC32x0 liest immer 
64Bytes auf einmal, was immerhin 80% der theoretisch maximalen Datenrate 
erlaubt (ok, der spielt auch in einer anderen Liga, das ist klar). Der 
LPC2478 kommt gerade mal auf schlappe 21,3%.

von Kai F. (k-ozz)


Lesenswert?

Der LCD-Controller im LPC2478 und in den LPC32x0 ist ja der gleiche und 
stammt ursprünglich von Sharps LH7-Controllern, die NXP aufgekauft hat.
Das Problem ist halt der Speichercontroller, der in den LPC32x0 halt ein 
anderer und besserer ist.

Wenn es beim LPC2478 etwas knapp wird mit der Bandbreite kann man den 
AHB von Round-Robin auf eine Priorisierung einzelner Peripheriemodule 
umstellen. So kann man, auch wenn die Last des Speichercontrollers gegen 
100% geht, das Display trotzdem noch flüssig laufen lassen. Näheres im 
Usermanual: AHBCFG1 und AHBCFG2.

von Tobias P. (hubertus)


Lesenswert?

@Kai,

du schnell eine Frage wegen der SDRAMs!
Ich hatta ja seinerzeit, bei der Inbetriebnahme meines Testboards, etwas 
Ärger mit denen, du hast mir dann freundlicherweise einen kleinen 
Initialisierungscode gebastelt, den ich bis heute so benutze (weil er 
absolut einwandfrei funktioniert ;-).
Mittlerweile verstehe ich den mehr oder weniger, nur eines ist mir heute 
aufgefallen, und zwar die Zeile:

dwDelay = (*(tpDWord)(0xA0000000 | (0x22 << 13))); /* burst length 4, 2 
cas */


Was bewirkt diese? rein vom Kommentar her würde ich mal drauf tippen, 
dass sie das Mode Register initialisiert. Aber das kann nicht sein, da 
das Mode Register nur 14 Bits umfasst, und wenn die Konstante 0x22 um 13 
nach links geschoben wird, wäre diese ja grösser als das Mode 
Register... Ausserdem sind die Bits zum Einstellen der Burstlänge und 
der CAS-Latency die Bits 0..2 und 3..4 (oder irgendwie so). Warum muss 
da noch um 13 geschoben werden?
Ich benutze übrigens immernoch meine ominösen IS42S16160B.

von Kai F. (k-ozz)


Lesenswert?

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.

von Tobias P. (hubertus)


Lesenswert?

Hi Kai,
danke! Das erklärt so einiges.
Noch eine Frage:
Es gibt die beiden Register EMCDynamictXSR und EMCDynamictSREX. Diese 
beiden Zeiten findet man in den wenigsten SDRAM-Datenblättern; ausserdem 
lautet im User's Manual die Beschreibung zu beiden Registern "Dynamic 
Memory Self-Refresh exit time", sie bewirken also (rein von der 
Beschreibung her) dasselbe. Ist das ein Fehler im Manual, oder sind 
diese Register wirklich redundant? Wenn ja - was ergibt das für einen 
Sinn?
Und - was tun, wenn man tXSR bzw. tSREX nicht findet in dem Datenblatt 
des gewünschten SDRAM?
Und - wie kritisch ist das Timing? Ich habe mir ein Excel-Sheet gebaut, 
bei welchem man die Timings des SDRAM-Chips direkt aus dem Datenblatt 
eingeben kann, sowie die CPU-Frequenz, und die Werte aller Register 
werden dann selbsträndig berechnet.
So komme ich auf leicht andere Werte, als die, die du mir damals 
angegeben hast (teilweise bekomme ich mehr, teilweise weniger). Die 
ganze Sache scheint mir eine nicht ganz so exakte Wissenschaft zu sein; 
kannst du dazu auch was sagen?
Ich könnte mir ausserdem gut vorstellen, dass bei falsch oder ungünstig 
eingestellten Timings das SDRAM zwar funktioniert, aber eben nicht 
zuverlässig bzw. dass die Burst-Zugriffe oder ähnliches nicht korrekt 
funktioniert. Wie kann man dies einigermassen zuverlässig testen?
Ich habe jetzt, da ich die Timings von meinem SDRAM zu optimieren 
versucht habe, einen Memory Test implementiert, der jedes einzelne Bit 
des SDRAMs testet. Der Test läuft jetzt schon 15 Minuten ohne Fehler in 
einer Endlosschleife durch, aber Burstzugriffe oder dergleichen werden 
so natürlich nicht wirklich getestet....

Falls übrigens bei jemandem Interesse bestehen sollte, kann ich mein 
Excel-Sheet hier hochladen. Es berechnet die Werte für den Refresh 
Timer, sowie die anderen Timing-Register; das einzige was man machen 
muss ist, die Daten aus dem SDRAM-DB ins Excelsheet zu übertragen und 
CPU-Frequenz angeben. Der nächste Schritt ist dann die automatische 
Generierung eines Initialisierungscodes.... ;-)

von Omega G. (omega) Benutzerseite


Lesenswert?

Darf ich das Excel Sheet haben? Ich habe meine Werte von Hand 
ausgerechnet. Bzw. teils von anderen Implementationen übernommen weil 
Angaben fehlten.

Übrigens läuft das Display momentan mit 16 MHz. Mehr geht noch nicht. 
(Ich habe seit gestern Abend keine Zeit mehr gehabt was zu machen.) Ich 
würde gerne versuchen den RAM schneller laufen zu lassen (Also an den 
Timings drehen) und dann versuchen auf 20 MHz zu gehen.

von Tobias P. (hubertus)


Angehängte Dateien:

Lesenswert?

Na klar kannst du es haben - siehe Anhang :-)
Ich habe jetzt meine Timings gemäss dem Sheet berechnet, und das SDRAM 
scheint zuverlässig zu laufen. Von daher denke ich sollten die 
Berechnungen stimmen.
Eine weiteres Sheet für den Static Memory Controller werde ich auch noch 
machen (der Static Memory Controller lässt sich wunderbar missbrauchen, 
um am externen Bus irgendwelche Memory Mapped IOs anzuschliessen; ich 
habe mal einen Haufen Flipflops ['HC273] angeschlossen, das ergibt 
wunderbare 8 Bit Ports....).
Bei Interesse lade ich das dann auch noch hoch.

Allerdings hat auch das Excel Sheet einen Mangel:
Wenn gewisse Angaben im Datenblatt fehlen (z.B. tSREX), dann können 
diese damit natürlich auch nicht berechnet werden :-( da habe ich auch 
teils ausprobieren müssen oder einfach geraten.

Übrigens: wer Freude an solchen Excel Sheets hat....
ich hab einige hier, allerdings nicht nur zu LPC24xx Controllern, 
sondern auch zur Schaltnetzteilberechnung.

von Tobias P. (hubertus)


Lesenswert?

Hi Leute,
mal noch eine Frage wegen des SDRAM-Interface.
Ich habe festgestellt, dass der CLKOUT recht verschliffene Flanken hat, 
wenn er mehrere SDRAMs treiben soll.
Auf meinem Testboard sieht er schon fast sinusförmig aus! Natürlich, es 
funktioniert, ist aber hässlich. Ich habe jetzt aus ein paar alten 
Mainboards Clock-Treiber ausgelötet - sogenannte "Zero Delay Clock 
Buffers". Es handelt sich dabei um TI CDCVF2505PWR - ein Clock-Input, 4 
Clock Outputs.
Diesen möchte ich jetzt einsetzen als Clock Buffer; er schafft diese 
Frequenz natürlich locker (geht bis 200 MHz).
In den Kennlinien kann man jedoch erkennen, dass der Duty Cycle nicht 
50% ist - etwas weniger; daher frage ich mich: kann man den dennoch als 
Clock Buffer benutzen für den LPC2468? Denn ich möchte noch einen 
kleinen FPGA mit dem Clock versorgen und noch weitere ICs, deshalb denke 
ich ist ein Clock Buffer schon nötig.
Was meint ihr dazu?

@Omega:
noch eine kleine Frage; kann man deinen Source Code zum Ethernet mal 
kriegen? Im Thread Beitrag "Re: NXP verschenkt ARM-Chips" 
schreibst du ja, dass das bei dir bereits läuft.

von Benedikt K. (benedikt)


Lesenswert?

Tobias Plüss schrieb:
> In den Kennlinien kann man jedoch erkennen, dass der Duty Cycle nicht
> 50% ist - etwas weniger; daher frage ich mich: kann man den dennoch als
> Clock Buffer benutzen für den LPC2468?

Solange die steigende Flanke an der selben Stelle bleibt geht das (und 
genau das macht das IC). Ob 48 oder 50% Duty macht keinen wirklichen 
Unterschied.

von Tobias P. (hubertus)


Lesenswert?

Hi Benedikt,
cool danke!
Ja ich glaube, die steigende Flanke sollte wirklich an der selben Stelle 
bleiben. Der Skeq ist im ps-Bereich... Sonst wäre ja die Bezeichnung 
"Zero Delay Buffer" nicht korrekt ;-)

von Omega G. (omega) Benutzerseite


Lesenswert?

Mein Ethernet Treiber macht momentan noch nicht viel, da mir unter der 
Woche auf Grund von Studium die Zeit doch etwas knapp ist. Aber trotzdem 
hier meinen Anfang
1
int MAC_init(){
2
  int tout,i;
3
  PCONP |= (1<<30);
4
  PINSEL2 |= 0x50150105;
5
  PINSEL3 |= 0x5;
6
  
7
  //Reset MAC
8
  MAC_MAC1 = 0x00000100 | 0x000002009 | 0x00000400 | 0x00000800 | 0x00004000 | 0x00008000;
9
  MAC_COMMAND = (1<<3) | (1<<4) | (1<<5);
10
  
11
  
12
  for (tout = 0; tout<10000; tout++);
13
  MAC_MAC1 = 0x00000002;
14
  MAC_MAC2 = 0x00000010 | 0x00000020;
15
  MAC_MAXF = 1522;
16
  MAC_CLRT = 0x0000370F;
17
  MAC_IPGR = 0x00000012;
18
  
19
  /* Enable Reduced MII interface. */
20
  MAC_COMMAND = 0x00000200 | 0x00000040;
21
  
22
  write_PHY (0, 0x8000); //send reset command
23
  while(read_PHY(0) & 0x8000); //wait until reset is complete
24
  
25
  MAC_MCFG = (0x06 << 2) | 0x00008000;  
26
  for ( i = 0; i < 0x40; i++ );
27
  MAC_MCFG &= (~0x00008000);  /* Clear the reset */
28
  MAC_MCMD = 0;
29
30
  write_PHY (0, 0x1100); //Setup auto-negotiation, full duplex
31
  
32
  //tout = 0;
33
  //while(!(read_PHY(1) & 4) & (tout < 500000))  //check and wait until ethernet is up
34
  //  tout++;
35
  //  
36
  MAC_SA0 = (MYMAC_1 << 8) | MYMAC_2;
37
  MAC_SA1 = (MYMAC_3 << 8) | MYMAC_4;
38
  MAC_SA2 = (MYMAC_5 << 8) | MYMAC_6;
39
  
40
  MAC_RXDESCRIPTOR = 0x7FE00000;
41
  
42
  return read_PHY(1);  
43
}
Ich werde sämtliche Treiber die ich schreibe auch auf meine Homepage 
stellen. Dort protokolliere ich auch gefundene Fehler und zeige wie sie 
umgeht. Die 50 MHz Clock von der PHY sehen übrigens sehr schön aus. 
Soweit ich das mit einem 200 MHz Oszilloskop beurteilen kann.

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.