Forum: Mikrocontroller und Digitale Elektronik STM32: neuer SDRAM-IC läuft nicht


von lars (Gast)


Angehängte Dateien:

Lesenswert?

Auf einem selbst entwickeltes Board mit einem STM32F746 verwende ich 
einen SDRAM IC (4 Bänke, 16-Daten-Bits, 256Mb). Bisher habe ich einen 
MT48LC16M16A2 von Micron verwendet, nun möchte ich stattdessen einen 
NDS36PT5-20ET von Insignis benutzen.
(Datenblatt: http://insignis-tech.com/download/145)

Der Micron IC funktioniert (auf dem gleichen Board) problemlos, aber ich 
bekomme den Insignis IC einfach nicht zum Laufen. In meinem kleinen 
Testprogramm
1
uint32_t i;
2
for (i = 0; i < 16384; i += 2) {
3
  *(__IO uint16_t *) (SDRAM_BASE + i) = i & 0xffff;  //SDRAM_BASE=0xC000k
4
}
5
     
6
for (i = 0; i < 16384; i += 2) {
7
  uint16_t data = *(__IO uint16_t *) (SDRAM_BASE + i);
8
  if (data != (i & 0xffff)) {
9
    while (1);  // breakpoint here
10
  }
11
}

liefert der erste Lesezugriff 0x3ffe anstatt 0 zurück.

Der STM32F746 läuft mit 200 MHz, der FMC und das SDRAM daher mit 100 
MHz. Ein FMC-Zylkus dauert also 10 ns. Das SDRAM IC ist für 200 MHz 
ausgelegt. Ich habe dann die Zeitabgaben für 200 MHz aus dem Datenblatt 
(Bild 1) jeweils durch 10 ns geteilt und aufgerundet, um die Anzahl der 
FMC-Zyklen für CubeMX zu erhalten (Bild 2). Write recovery time müsste 1 
sein, wird aber von CubeMX auf 2 gesetzt.

Als CAS Latency habe ich 3 gewählt. Die Refresh-Rate ist (64 / 8192 * 
100) * 1000 - 20 (die *1000 ergeben sich durch den Einheitenfehler, den 
die Formel macht).

Das SDRAM wird mit diesem Code initialisiert, was dem Datenblatt (Bild 
3) entspricht.
1
static void SDRAM_Init()
2
{
3
  FMC_SDRAM_CommandTypeDef Command;
4
     
5
  __IO uint32_t tmpmrd =0;
6
  /* Step 3:  Configure a clock configuration enable command */
7
  Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
8
  Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
9
  Command.AutoRefreshNumber = 1;
10
  Command.ModeRegisterDefinition = 0;
11
  HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
12
     
13
  /* Step 4: Insert 100 us minimum delay */
14
  /* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
15
  HAL_Delay(1);
16
     
17
  /* Step 5: Configure a PALL (precharge all) command */
18
  Command.CommandMode = FMC_SDRAM_CMD_PALL;
19
  Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
20
  Command.AutoRefreshNumber = 1;
21
  Command.ModeRegisterDefinition = 0;
22
  HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
23
     
24
  /* Step 6 : Configure a Auto-Refresh command */
25
  Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
26
  Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
27
  Command.AutoRefreshNumber = 2;  // Insignis SDRAM
28
  Command.ModeRegisterDefinition = 0;
29
  HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
30
     
31
  /* Step 7: Program the external memory mode register */
32
  tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1          |  // 0
33
                     SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |  // 0
34
                     SDRAM_MODEREG_CAS_LATENCY_3           |  // 0x30
35
                     SDRAM_MODEREG_OPERATING_MODE_STANDARD |  // 0
36
                     SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;    // 0x200
37
     
38
  Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
39
  Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
40
  Command.AutoRefreshNumber = 1;
41
  Command.ModeRegisterDefinition = tmpmrd;
42
  HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
43
     
44
  /* Step 8: Set the refresh rate counter: (64 ms / 8192 x Freq) - 20 */
45
  hsdram1.Instance->SDRTR |= ((uint32_t)761);  // 2HCLK, Insignis SDRAM
46
}

Wie gesagt, auf dem gleichen Board läuft ein SDRAM von Micron ohne 
Probleme, so dass ich Fehler im Layout eigentlich ausschließen möchte. 
Außerdem habe ich zwei Boards gelötet, was Lötfehler vermeiden sollte.

Aber welchen Fehler habe ich bei der Konfiguration gemacht? Wie könnte 
ich das Problem weiter einkreisen?

von lars (Gast)


Lesenswert?

Da ich nicht so recht weiß, wie man mit Timings für ein 200 MHz-IC 
umgeht, das nur mit 100 MHz betrieben wird, habe ich mal testweise alle 
Timings x2 gerechnet.

In CubeMX musste ich allerdings den Wert für Write recovery time von 2 
auf 5 Zyklen erhöhen, da sonst die internen logischen Bedingungen nicht 
mehr gelten.

Leider funktioniert es auch damit nicht; das Lesen an Adresse 0xc0000000 
liefert immer noch 0x3ffe statt 0 zurück.

Ich würde ja einen anderen Hersteller versuchen, aber ich sehe keinen 
wirklichen Unterschied in den Datenblättern.

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.