Forum: Mikrocontroller und Digitale Elektronik STM32F7 und SDRAM


von A. F. (elagil)


Lesenswert?

Hallo!

Ich habe Probleme bei der Nutzung von SDRAM mit dem STM32F7.

Es handelt sich um ein selbst entworfenes Board mit 256Mbit SDRAM von 
ISSI:

IS42S16160J
http://www.issi.com/WW/pdf/42-45S83200J-16160J.pdf

Das ist SDRAM mit 13 bit Adressen und 16 bit Daten.

Die Initialisierungsvorschriften für den SDRAM habe ich mit dem CubeMX 
Programm erzeugt. Die Initialisierung verläuft ohne Fehlermeldungen 
(returns).

Ich kann Daten auf den Speicher schreiben und lesen, allerdings nur bis 
zu einer bestimmten Adresse:
1
  uint32_t adr = 0xC0000000;
2
  volatile uint32_t a[32];
3
4
  for(uint32_t k=0; k<16; k++) {
5
    *(uint32_t *)(adr + 4 * k) = k;
6
    a[k] = *(uint32_t *)(adr + 4 * k);
7
  }

Für k bis 16 funktioniert schreiben und lesen ohne Probleme. Dann stehen 
in a[k] am Ende die Werte von 0 bis 15. Wenn ich k größer werden lasse 
als 16, friert der debugger ein (Blackmagic Probe GDB Server).

Woran kann das liegen? Ich tippe auf ein Hardwareproblem, weiß aber 
nicht wo ich suchen soll.

Vielen Dank im Voraus

von A. B. (Gast)


Lesenswert?

Lässt sich das RAM ohne BusError komplett auslesen (unabhängig ob der 
Inhalt wirklich ausgelesen wird, oder einfach Schrott zurückkommt)?

Das RAM ist doch mehr oder minder passiv, selbst wenn es komplett falsch 
angesteuert würde, könnte es doch schlimmstenfalls Unsinn zurückliefern, 
wenn man von einer Kollision infolge falscher Ansteuerung von WE mal 
absieht? Es hat doch keinerlei Ausgang, über den ein Fehler signalisiert 
oder ein Buszyklus verzögert werden kann.

Das "Einfrieren" muss dann doch auf Controller-Seite seinen alleinigen 
Ursprung haben. Da hilft wohl nur, per Hand alle FMC-Register zu 
kontrollieren.

Dass von der Initialisierungsroutine kein Fehler zurückkommt, heisst 
nichts, es können da unmöglich alle mit der tatsächlichen Hardware nicht 
möglichen Parameterkonfigurationen abgefangen werden.

Vielleicht auch mal ST-Link oder J-Link ausprobieren, vielleicht ist's 
ja auch der Debug-Adapter? Oder GDB?

Stack oder Heap landen nicht zufällig im SDRAM? Das wär' ja fatal.

Wenn das alles nicht hilft, bleibt wohl nur LA oder Scope und erst 
einmal nur Lese- oder nur Schreibzugriffe, am besten in Assembler in 
'ner Endlos-Scheife, am besten durch den gesamten Adressraum der SDRAMs. 
Ob das, was man reinschreibt, auch an richtiger Stelle wieder 
herauskommt, käme dann VIEL später.

von drm (Gast)


Lesenswert?

>Die Initialisierungsvorschriften für den SDRAM habe
>ich mit dem CubeMX Programm erzeugt.

Dann hast du den SDRAM Controller in der CPU konfiguriert.
Wie sieht es mit dem SDRAM Controller im SDRAM aus ?
Die Einstellungen müssen zu den Einstellungen in CubeMX passen.

Vielleicht schreibst du nur in den Cache der CPU, und so bald er das 
SDRAM
ansprechen will gibt es einen HardFault, weil das SDRAM gar nicht läuft, 
sondern nur der SDRAM Controller in der CPU.

von A. F. (elagil)


Angehängte Dateien:

Lesenswert?

Danke für die Hinweise!

Zuerst einmal: Ich teste jetzt mit dem ST-Link V2 und Eclipse (System 
Workbench).

A. B. schrieb:
> Lässt sich das RAM ohne BusError komplett auslesen (unabhängig ob der
> Inhalt wirklich ausgelesen wird, oder einfach Schrott zurückkommt)?

Nein, ich kann scheinbar gar nicht mehr lesen. Wenn ich einen 
Lesezugriff durchführe (diesmal mit HAL_SDRAM_Read_32b(...)), dann 
endete diese Zeile:
1
*pDstBuffer = *(__IO uint32_t *)pSdramAddress;

im "Infinite_Loop" des startup-files. pSdramAddress zeigt hier auf 
0xc0000000.
1
Default_Handler:
2
Infinite_Loop:
3
  b  Infinite_Loop
4
  .size  Default_Handler, .-Default_Handler

Was bedeutet das?

A. B. schrieb:
> Das "Einfrieren" muss dann doch auf Controller-Seite seinen alleinigen
> Ursprung haben. Da hilft wohl nur, per Hand alle FMC-Register zu
> kontrollieren.

Ja, sieht so aus. Die Konfigurationsregister vom FMC sind zumindest so, 
wie ich es gerne hätte. Anbei ein paar Screenshots.

A. B. schrieb:
> Stack oder Heap landen nicht zufällig im SDRAM? Das wär' ja fatal.

Ich denke, die liegen im RAM. Hier alle Definitionen aus dem 
Linker-file, die mit stack/heap zu tun haben.
1
/* Highest address of the user mode stack */
2
_estack = 0x20050000;    /* end of RAM */
3
/* Generate a link error if heap and stack don't fit into RAM */
4
_Min_Heap_Size = 0x200;      /* required amount of heap  */
5
_Min_Stack_Size = 0x400; /* required amount of stack */
6
...
7
MEMORY
8
{
9
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 320K
10
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 1024K
11
}
12
...
13
/* User_heap_stack section, used to check that there is enough RAM left */
14
  ._user_heap_stack :
15
  {
16
    . = ALIGN(8);
17
    PROVIDE ( end = . );
18
    PROVIDE ( _end = . );
19
    . = . + _Min_Heap_Size;
20
    . = . + _Min_Stack_Size;
21
    . = ALIGN(8);
22
  } >RAM

drm schrieb:
> Dann hast du den SDRAM Controller in der CPU konfiguriert.
> Wie sieht es mit dem SDRAM Controller im SDRAM aus ?

Wie ist das gemeint?

Es gibt einen Aufruf
1
HAL_SDRAM_Init(&hsdram1, &SdramTiming)

im Quelltext, der den FMC mit den gewünschten Timings initialisiert.
1
/**
2
  * @brief  Performs the SDRAM device initialization sequence.
3
  * @param  hsdram: pointer to a SDRAM_HandleTypeDef structure that contains
4
  *                the configuration information for SDRAM module.
5
  * @param  Timing: Pointer to SDRAM control timing structure 
6
  * @retval HAL status
7
  */
8
HAL_StatusTypeDef HAL_SDRAM_Init(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_TimingTypeDef *Timing)
9
{   
10
  /* Check the SDRAM handle parameter */
11
  if(hsdram == NULL)
12
  {
13
    return HAL_ERROR;
14
  }
15
  
16
  if(hsdram->State == HAL_SDRAM_STATE_RESET)
17
  {  
18
    /* Allocate lock resource and initialize it */
19
    hsdram->Lock = HAL_UNLOCKED;
20
    /* Initialize the low level hardware (MSP) */
21
    HAL_SDRAM_MspInit(hsdram);
22
  }
23
  
24
  /* Initialize the SDRAM controller state */
25
  hsdram->State = HAL_SDRAM_STATE_BUSY;
26
  
27
  /* Initialize SDRAM control Interface */
28
  FMC_SDRAM_Init(hsdram->Instance, &(hsdram->Init));
29
  
30
  /* Initialize SDRAM timing Interface */
31
  FMC_SDRAM_Timing_Init(hsdram->Instance, Timing, hsdram->Init.SDBank); 
32
  
33
  /* Update the SDRAM controller state */
34
  hsdram->State = HAL_SDRAM_STATE_READY;
35
  
36
  return HAL_OK;
37
}

von tzhgfhgrhzfghz6453454353453534534533453453 (Gast)


Lesenswert?

nutzt du den I und D Cache?
bitte den mal weglassen am anfang

oder mach ein __DMB(); nach der Anweisung rein

der cache ist gut, versaut aber bei solchen sachen das timing ...

von A. B. (Gast)


Lesenswert?

Adrian F. schrieb:
>
1
> *pDstBuffer = *(__IO uint32_t *)pSdramAddress;
2
>
>
> im "Infinite_Loop" des startup-files. pSdramAddress zeigt hier auf
> 0xc0000000.
>
>
1
> Default_Handler:
2
> Infinite_Loop:
3
>   b  Infinite_Loop
4
>   .size  Default_Handler, .-Default_Handler
5
>
>

Ist wohl einer der Exception-Vektoren, der nicht (sinnvoll) belegt ist 
und deshalb auf diese Endlos-Schleife zeigt. Da wäre wichtig zu wissen, 
welche Exception das war (HardFault, Interrupt, ...). Der erste Zugriff 
aufs RAM triggert also gleich irgendwas?!

Was steht im RCC_AHB3ENR (Clock für FMC) und im RCC_AHB3RSTR (Reset für 
FMC)? Die sollten zwar bei der Initialisierung automatisch ein- bzw. 
ausgeschaltet werden, aber ...

Außerdem: Tut sich überhaupt irgendwas am RAM (CLK, CKE, DQML, DQMH)?

von A. F. (elagil)


Lesenswert?

tzhgfhgrhzfghz6453454353453534534533453453 schrieb:
> nutzt du den I und D Cache?
> bitte den mal weglassen am anfang
>
> oder mach ein __DMB(); nach der Anweisung rein
>
> der cache ist gut, versaut aber bei solchen sachen das timing ...

I und D Cache benutze ich nicht.

Neuigkeiten:
Ich habe den RAM zum Laufen gebracht. Lesen und schreiben von zufälligen 
32 bit Werten geht. Im Moment habe ich aber nur getestet, 4096 Werte an 
den Speicheradressen (Offsets) 0x800 und 0x10000 zu lesen/schreiben.

Allerdings benutze ich dafür im Moment nicht den Code, den CubeMX 
generiert, sondern das Beispiel von ST für das Discovery 746 board. 
Wichtig war die Anpassung der Timings, bis keine Fehler mehr aufgetreten 
sind. Die Werte im Datenblatt haben teilweise abweichende Namen von 
denen, die der STM32 erwartet.

Falls jemand den gleichen RAM benutzt, diese Timings funktionieren bei 
CL=2 und 100 MHz.
1
  SDRAM_Timing.LoadToActiveDelay    = 3;
2
  SDRAM_Timing.ExitSelfRefreshDelay = 7;
3
  SDRAM_Timing.SelfRefreshTime      = 4;
4
  SDRAM_Timing.RowCycleDelay        = 8;
5
  SDRAM_Timing.WriteRecoveryTime    = 2;
6
  SDRAM_Timing.RPDelay              = 2;
7
  SDRAM_Timing.RCDDelay             = 2;

Jetzt versuche ich noch, das mit der CubeMX Vorlage lauffähig zu 
bekommen.

A. B. schrieb:
> Was steht im RCC_AHB3ENR (Clock für FMC) und im RCC_AHB3RSTR (Reset für
> FMC)? Die sollten zwar bei der Initialisierung automatisch ein- bzw.
> ausgeschaltet werden, aber ...
>
> Außerdem: Tut sich überhaupt irgendwas am RAM (CLK, CKE, DQML, DQMH)?

Das prüfe ich gleich.

: Bearbeitet durch User
von dasrotemopped (Gast)


Angehängte Dateien:

Lesenswert?

>> Wie sieht es mit dem SDRAM Controller im SDRAM aus ?
>Wie ist das gemeint?
>Es gibt einen Aufruf
>HAL_SDRAM_Init(&hsdram1, &SdramTiming)
das ist die Initialisierung des SDRAM COntrollers im STM32F7

In den Board Support Packages wird beides gemacht, uC und SDRAM 
Initialisierung. CubeMX macht nur die Initialisierung des STM32.
Ich habe mal den zusätzlichen Code aus dem BSP in eine eigene Funktion 
extrahiert, so das die CubeMX HAL_SDRAM_Init() und meine Funktionen 
zusammen wieder die Funktion des BSP haben. Hier das Beispiel zu dem 
STM32F746G-Disco. Im Code sind hoffentlich genug Kommentare als 
Erläuterung. Da du aber anderes SDRAM als auf dem Disco Board benutzt, 
musst du wahrscheinlich ein paar Werte ändern.

Gruß,
dasrotemopped.

von A. F. (elagil)


Lesenswert?

Vielen Dank für die Mühe! Das funktioniert ausgezeichnet.

dasrotemopped schrieb:
> In den Board Support Packages wird beides gemacht, uC und SDRAM
> Initialisierung.

Jetzt habe ich es begriffen.

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.