mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik U-Boot erkennt DDR3-RAM nicht korrekt


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Habe hier ein eigenes Board mit einer Allwinner A13 CPU.
Habe für dieses Board nun ein u-boot compiliert und aufgespielt.
Ebenso habe ich den test auch mit einem u-boot bzw. Image von armbian 
durchgeführt.

Auf dem Board befindet sich ein 128Mx16 Memory.

Leider zeigt u-boot beim Starten folgendes an:
U-Boot SPL 2020.RC
DRAM: 0 MiB
### ERROR ### Please RESET the board ###

Nun kommt natürlich ein HW-Fehler sehr wahrscheinlich in Frage. Dazu 
hätte ich ein paar Fragen an die Experten unter euch.

1) Ich habe die Datenbits untereinander getauscht.
Was heist dies?: D0 = D0 | D1-D7 untereinander vertauscht
D8 = D8 | D9-D15 untereinander vertauscht.

Dies sollte m.M.n kein Problem darstellen. An anderere Stelle habe ich 
gelesen, dass das LSB teilweise zur Kalibration herangezogen wird. Daher 
D= = D0 und D8=D8.

2) Wie versucht u-boot die Speichergrösse zu bestimmen? Ich sehe an der 
diff. ClockLeitung zum DDR3 nach dem Start von u-boot keine Aktivität 
ausser dem wechsel von low (vermutlich unkonfigutiert) zu high. Dieser 
Pegel bleibt dann auch bestehen. Es findet kein Tatken o.Ä. statt. Ist 
dies plausibel?

- Die Beschaltung habe ich mehrfach geprüft. Sollte korrekt sein.
- Habe bereits viele BGA-96 aufgelötet. Bisher immer erfolgreich. Habe 
den Chip auch bereits zweimal gewechselt. Dabei immer das selbe 
Ergebnis. Daher denke ich mal nicht an einen Lötstellenfehler bzw. 
Kurzschluss.

Bin über Vorschläge dankbar.

Grüsse
Krähe

von Μαtthias W. (matthias) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Hi

Also meinen U-Booten geb ich die Speichergröße immer per

#define PHYS_SDRAM_SIZE      SZ_256M

mit. Automatisch kann das U-Boot meines Wissens nur wenn Speichermodule 
samt SPD-EEPROM verwendet werden.

Matthias

von habeichvergessen (Gast)


Bewertung
0 lesenswert
nicht lesenswert
https://linux-sunxi.org/Mainline_U-Boot

Am Ende der Seite gibt es Hinweise zur SDRAM-Konfiguration in u-boot.

von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
Danke für eure Antworten.

Μαtthias W. schrieb:
> Hi
>
> Also meinen U-Booten geb ich die Speichergröße immer per
>
> #define PHYS_SDRAM_SIZE      SZ_256M

Sehr interessant.
Das könnte sehr gut die Quelle des Übels sein.
Werde ich heute testen.

habeichvergessen schrieb:
> https://linux-sunxi.org/Mainline_U-Boot
>
> Am Ende der Seite gibt es Hinweise zur SDRAM-Konfiguration in u-boot.

Vielen Dank. Hab ich bereits gesehen. Mein U-Boot ist entsprechend 
deisem hier:
+S:CONFIG_DRAM_CLK=360
+S:CONFIG_DRAM_ZQ=123
+S:CONFIG_DRAM_EMR1=4
+S:CONFIG_DRAM_TIMINGS_DDR3_800E_1066G_1333J=y

Konfiguriert.

von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
Μαtthias W. schrieb:
> Also meinen U-Booten geb ich die Speichergröße immer per
>
> #define PHYS_SDRAM_SIZE      SZ_256M

Du scheinst ein i.MX board zu verwenden, richtig?

Denn nach dem durchsuchen des u-boot git repos scheint dieses Define 
hauptsächlich in Zusammenhang mit i.MX Prozessoren verwendung zu 
finden...

Für Allwinner scheint es keine solche Einstellung zu geben... Bzw. 
verwendet z.B. Olimex keine solche Definition bei deren Allwinner 
Boards.

von Μαtthias W. (matthias) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Holger K. schrieb:
> Μαtthias W. schrieb:
>> Also meinen U-Booten geb ich die Speichergröße immer per
>>
>> #define PHYS_SDRAM_SIZE      SZ_256M
>
> Du scheinst ein i.MX board zu verwenden, richtig?
>
> Denn nach dem durchsuchen des u-boot git repos scheint dieses Define
> hauptsächlich in Zusammenhang mit i.MX Prozessoren verwendung zu
> finden...
>
> Für Allwinner scheint es keine solche Einstellung zu geben... Bzw.
> verwendet z.B. Olimex keine solche Definition bei deren Allwinner
> Boards.

Ja, ist ein iMX. War aber früher™ auch bei anderen ARM Systemen so. Bin 
aber ehrlich gesagt nicht auf dem Stand von 2016 vor der Verwendung von 
device tree und kconfig im U-Boot.

Matthias

von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für deine Antwort.

Es scheint wirklich unauffindbar, wie in U-Boot die Speichergrösse 
angegeben wird.

Hier eine Beispielkonfiguration für ein Olimex A13 Board:

https://github.com/linux-sunxi/u-boot-sunxi/blob/0189be69ff8986f234c4183d241ff0fface50bd0/configs/A13-OLinuXinoM_defconfig

Da sieht man beispielsweise nichts vom RAM ausser:
CONFIG_DRAM_CLK=408
CONFIG_DRAM_EMR1=0
CONFIG_NR_DRAM_BANKS=1

Auch unter board/olimex/ lässt sich nichts zu einem Allwinner finden, 
wohl aber etwas für ein i.MX Board.

https://github.com/linux-sunxi/u-boot-sunxi/tree/d2faf46f3e5a7b42c69c226f5f5b54c6a5fea60d/board/olimex

Für das i.MX Board wurde die bereits erwähne Konfiguration vorgenommen:

https://github.com/linux-sunxi/u-boot-sunxi/blob/0b80e1c63d5ff9585c79afff1092cf761cea46cc/include/configs/mx23_olinuxino.h

Doch für das A13 Board findet sich nichts.

von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass u-boot das memory im Device-Tree erwartet?
 12         memory {

13                 linux,usable-memory = <0x80000000 0x1ff00000>,

14                                 <0xa0000000 0x1ff00000>;

15         };

Wobei mir dies unwahrscheinlich erscheint, da u-boot nichts mitteilt, 
dasss es bereits den fdt geladen hätte...

von Dergute W. (derguteweka)


Bewertung
0 lesenswert
nicht lesenswert
Moin,

Koennt' es sein, dass bei den Allwinners noch vor dem eigentlichen uboot 
ein SPL vorgeschaltet wird, der so Zeugs, wie SDRAM-Controller init 
macht?
<hibbelhibbel>Ach was freu' ich mich schon auf den naechsten 
Ramschkarton vom Pollin mit dem A20 Board drinnen</hibbelhibbel>

Gruss
WK

von Holger K. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Dergute W. schrieb:
> Koennt' es sein, dass bei den Allwinners noch vor dem eigentlichen uboot
> ein SPL vorgeschaltet wird, der so Zeugs, wie SDRAM-Controller init
> macht?

Nun, u-boot wird tatsächlich mit einem SPL erzeugt. Daher würd ich mal 
sagen, ja.

Aber die frage ist, wo definiert ich nun die Memorygrösse?
Im SPL ja vemutlich. Aber bisher hab ich keinerlei Boardspezifische 
Files in den u-boot Sourcen ausfindig machen können.

von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
Ich pushe mal den Thread :)

von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
So ich bin etwas weiter gekommen.

In der Datei: board/sunxi/board.c

Gibt es folgenden code auf Zeile 669
  printf("DRAM:");
  gd->ram_size = sunxi_dram_init();
  printf(" %d MiB\n", (int)(gd->ram_size >> 20));
  if (!gd->ram_size)
    hang();

Dieser ist das Quell des Übels...
Die Funktion sunxi_dram_init sieht so aus:

[dram_sun5i_auto.c]
unsigned long sunxi_dram_init(void)
{
  return dramc_init(&dram_para);
}

Dann die dramc_init
[dram_sun4i.c:692]
unsigned long dramc_init(struct dram_para *para)
{
  unsigned long dram_size, actual_density;

  /* If the dram configuration is not provided, use a default */
  if (!para)
    return 0;

  /* if everything is known, then autodetection is not necessary */
  if (para->io_width && para->bus_width && para->density)
    return dramc_init_helper(para);

  /* try to autodetect the DRAM bus width and density */
  para->io_width  = 16;
  para->bus_width = 32;
#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN5I)
  /* only A0-A14 address lines on A10/A13, limiting max density to 4096 */
  para->density = 4096;
#else
  /* all A0-A15 address lines on A20, which allow density 8192 */
  para->density = 8192;
#endif

  dram_size = dramc_init_helper(para);
  if (!dram_size) {
    /* if 32-bit bus width failed, try 16-bit bus width instead */
    para->bus_width = 16;
    dram_size = dramc_init_helper(para);
    if (!dram_size) {
      /* if 16-bit bus width also failed, then bail out */
      return dram_size;
    }
  }

  /* check if we need to adjust the density */
  actual_density = (dram_size >> 17) * para->io_width / para->bus_width;

  if (actual_density != para->density) {
    /* update the density and re-initialize DRAM again */
    para->density = actual_density;
    dram_size = dramc_init_helper(para);
  }

  return dram_size;
}

Und schlussendlich noch die wichtige dramc_init_helper funktion

[dram_sun4i.c:561]
static unsigned long dramc_init_helper(struct dram_para *para)
{
  struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
  u32 reg_val;
  u32 density;
  int ret_val;

  /*
   * only single rank DDR3 is supported by this code even though the
   * hardware can theoretically support DDR2 and up to two ranks
   */
  if (para->type != DRAM_MEMORY_TYPE_DDR3 || para->rank_num != 1)
    return 0;

  /* setup DRAM relative clock */
  mctl_setup_dram_clock(para->clock, para->mbus_clock);

  /* Disable any pad power save control */
  mctl_disable_power_save();

  mctl_set_drive();

  /* dram clock off */
  dramc_clock_output_en(0);

#ifdef CONFIG_MACH_SUN4I
  /* select dram controller 1 */
  writel(DRAM_CSEL_MAGIC, &dram->csel);
#endif

  mctl_itm_disable();
  mctl_enable_dll0(para->tpr3);

  /* configure external DRAM */
  reg_val = DRAM_DCR_TYPE_DDR3;
  reg_val |= DRAM_DCR_IO_WIDTH(para->io_width >> 3);

  if (para->density == 256)
    density = DRAM_DCR_CHIP_DENSITY_256M;
  else if (para->density == 512)
    density = DRAM_DCR_CHIP_DENSITY_512M;
  else if (para->density == 1024)
    density = DRAM_DCR_CHIP_DENSITY_1024M;
  else if (para->density == 2048)
    density = DRAM_DCR_CHIP_DENSITY_2048M;
  else if (para->density == 4096)
    density = DRAM_DCR_CHIP_DENSITY_4096M;
  else if (para->density == 8192)
    density = DRAM_DCR_CHIP_DENSITY_8192M;
  else
    density = DRAM_DCR_CHIP_DENSITY_256M;

  reg_val |= DRAM_DCR_CHIP_DENSITY(density);
  reg_val |= DRAM_DCR_BUS_WIDTH((para->bus_width >> 3) - 1);
  reg_val |= DRAM_DCR_RANK_SEL(para->rank_num - 1);
  reg_val |= DRAM_DCR_CMD_RANK_ALL;
  reg_val |= DRAM_DCR_MODE(DRAM_DCR_MODE_INTERLEAVE);
  writel(reg_val, &dram->dcr);

  dramc_clock_output_en(1);

  mctl_set_impedance(para->zq, para->odt_en);

  mctl_set_cke_delay();

  mctl_ddr3_reset();

  udelay(1);

  await_bits_clear(&dram->ccr, DRAM_CCR_INIT);

  mctl_enable_dllx(para->tpr3);

  /* set refresh period */
  dramc_set_autorefresh_cycle(para->clock, density);

  /* set timing parameters */
  writel(para->tpr0, &dram->tpr0);
  writel(para->tpr1, &dram->tpr1);
  writel(para->tpr2, &dram->tpr2);

  reg_val = DRAM_MR_BURST_LENGTH(0x0);
#if (defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I))
  reg_val |= DRAM_MR_POWER_DOWN;
#endif
  reg_val |= DRAM_MR_CAS_LAT(para->cas - 4);
  reg_val |= DRAM_MR_WRITE_RECOVERY(ddr3_write_recovery(para->clock));
  writel(reg_val, &dram->mr);

  writel(para->emr1, &dram->emr);
  writel(para->emr2, &dram->emr2);
  writel(para->emr3, &dram->emr3);

  /* disable drift compensation and set passive DQS window mode */
  clrsetbits_le32(&dram->ccr, DRAM_CCR_DQS_DRIFT_COMP, DRAM_CCR_DQS_GATE);

#ifdef CONFIG_MACH_SUN7I
  /* Command rate timing mode 2T & 1T */
  if (para->tpr4 & 0x1)
    setbits_le32(&dram->ccr, DRAM_CCR_COMMAND_RATE_1T);
#endif
  /* initialize external DRAM */
  mctl_ddr3_initialize();

  /* scan read pipe value */
  mctl_itm_enable();

  /* Hardware DQS gate training */
  ret_val = dramc_scan_readpipe();

  if (ret_val < 0)
    return 0;

  /* allow to override the DQS training results with a custom delay */
  if (para->dqs_gating_delay)
    mctl_set_dqs_gating_delay(0, para->dqs_gating_delay);

  /* set the DQS gating window type */
  if (para->active_windowing)
    clrbits_le32(&dram->ccr, DRAM_CCR_DQS_GATE);
  else
    setbits_le32(&dram->ccr, DRAM_CCR_DQS_GATE);

  mctl_itm_reset();

  /* configure all host port */
  mctl_configure_hostport();

  return get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE);
}

get_ram_size ist übrigens in common/memsize.c:26 definiert


Offenbar wird hier sehrwohl der DDR-Clock aktiviert:
  /* setup DRAM relative clock */
  mctl_setup_dram_clock(para->clock, para->mbus_clock);

Das ich diesen nicht messen kann, irritiert mich ein wenig.

von Dergute W. (derguteweka)


Bewertung
0 lesenswert
nicht lesenswert
Holger K. schrieb:
> Das ich diesen nicht messen kann, irritiert mich ein wenig.

Mit was misst du denn "den"? So ein paar 100MHz bei ein paar zig 
Millivolt - das wird ja mit'm Phasenpruefer, Duspol oder der Zunge etwas 
schwierig ;-)

Gruss
WK

von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
Dergute W. schrieb:
> Holger K. schrieb:
>> Das ich diesen nicht messen kann, irritiert mich ein wenig.
>
> Mit was misst du denn "den"? So ein paar 100MHz bei ein paar zig
> Millivolt - das wird ja mit'm Phasenpruefer, Duspol oder der Zunge etwas
> schwierig ;-)
>
> Gruss
> WK

Danke für deine Antwort.

Aktuell messe ich dies mit einem Oszilloskop mit 200MHz Analogbandbreite 
sowie einem kapazitätsarmen Tastkopf.

von oszi40 (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Holger K. schrieb:
> Aktuell messe ich

Aktuell messe ich gar nicht und sehe was der SPD liefert. Das könnte man 
aber abschalten oder manipulieren. Manchmal lügt er auch. 
https://de.wikibooks.org/wiki/Computerhardware:_RAM:_Details:_SPD-ROM

von X2 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
oszi40 schrieb:
> Aktuell messe ich gar nicht und sehe was der SPD liefert. Das könnte man
> aber abschalten oder manipulieren. Manchmal lügt er auch.
> https://de.wikibooks.org/wiki/Computerhardware:_RAM:_Details:_SPD-ROM

Schonmal was von Memory Down gehört? Da gibt es normalerweise kein 
SPD-EEPROM, da es keinen Sinn macht...

von Holger K. (holgerkraehe)


Bewertung
0 lesenswert
nicht lesenswert
Tatsächlich habe ich bei meinem Embedded-Board kein SPD-EEPROM.

von Dergute W. (derguteweka)


Bewertung
0 lesenswert
nicht lesenswert
Moin,

Hm, tja. Dann bin ich mit meinem Latein erstmal am Ende und beneide dich 
nicht um die Fehlersuche.

Gruss
Wolfram

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.