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
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.
>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.
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
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 ...
>> 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)?
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.
>> 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.
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.