05-SDRAM-Library (STM32F429)

Mit dieser Library kann das externe SD-RAM auf dem STM32F429 Discovery-Board benutzt werden.

Das RAM hat eine Speichergröße von 64Mbit (8MByte) und hängt am FMC-Bus der CPU. Ich habe mehrere Funktionen geschrieben um Daten auf das RAM zu lesen und zu schreiben.

Benutzte Pins :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PB5  = SDCKE1 (CKE)      PF0  = A0
PB6  = SDNE1  (/CS)      PF1  = A1
PC0  = SDNWE  (/WE)      PF2  = A2
PD0  = D2                PF3  = A3
PD1  = D3                PF4  = A4
PD8  = D13               PF5  = A5
PD9  = D14               PF11 = SDNRAS (/RAS)
PD10 = D15               PF12 = A6
PD14 = D0                PF13 = A7
PD15 = D1                PF14 = A8
PE0  = NBL0   (LDQM)     PF15 = A9
PE1  = NBL1   (UDQM)     PG0  = A10
PE7  = D4                PG1  = A11
PE8  = D5                PG4  = BA0    (BANK A0)
PE9  = D6                PG5  = BA1    (BANK A1)
PE10 = D7                PG8  = SDCLK  (CLK)
PE11 = D8                PG15 = SDNCAS (/CAS)
PE12 = D9
PE13 = D10
PE14 = D11
PE15 = D12

Funktionen :

1
2
3
4
5
6
7
8
9
ErrorStatus UB_SDRAM_Init(void);                                                             // zum init vom RAM
void UB_SDRAM_Write8b(uint32_t adr, uint8_t wert);                                           // zum schreiben von einem 8bit Wert
uint8_t UB_SDRAM_Read8b(uint32_t adr);                                                       // zum lesen von einem 8bit Wert
void UB_SDRAM_Write16b(uint32_t adr, uint16_t wert);                                         // zum schreiben von einem 16bit Wert
uint16_t UB_SDRAM_Read16b(uint32_t adr);                                                     // zum lesen von einem 16bit Wert
void UB_SDRAM_Write32b(uint32_t adr, uint32_t wert);                                         // zum schreiben von einem 32bit Wert
uint32_t UB_SDRAM_Read32b(uint32_t adr);                                                     // zum lesen von einem 32bit Wert
void UB_SDRAM_WriteBuffer32b(uint32_t* ptrBuffer, uint32_t startAdr, uint32_t lenBuffer);    // zum schreiben von einem Block von 32bit Werten
void UB_SDRAM_ReadBuffer32b(uint32_t* ptrBuffer, uint32_t startAdr, uint32_t lenBuffer);     // zum lesen von einem Block von 32bit Werten

Beispiel :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//--------------------------------------------------------------
// File     : main.c
// Datum    : 24.10.2013
// Version  : 1.0
// Autor    : UB
// EMail    : mc-4u(@)t-online.de
// Web      : www.mikrocontroller-4u.de
// CPU      : STM32F429
// IDE      : CooCox CoIDE 1.7.4
// GCC      : 4.7 2012q4
// Module   : CMSIS_BOOT, M4_CMSIS_CORE
// Funktion : Demo der SDRAM-Library
// Hinweis  : Diese zwei Files muessen auf 8MHz stehen
//              "cmsis_boot/stm32f4xx.h"
//              "cmsis_boot/system_stm32f4xx.c"
// In Configuration diese Define hinzufügen :
// "STM32F429_439xx" , "__ASSEMBLY__" , "USE_STDPERIPH_DRIVER"
//--------------------------------------------------------------
 
#include "main.h"
#include "stm32_ub_sdram.h"
#include "stm32_ub_led.h"
 
void Delay(__IO uint32_t nCount)
{
  while(nCount--)
  {
  }
}
 
int main(void)
{
  uint32_t adr;
  uint8_t sollwert, istwert;
  ErrorStatus ramcheck;
 
  SystemInit(); // Quarz Einstellungen aktivieren
 
  // init der LEDs
  UB_Led_Init();
 
  // init vom externen SDRAM (und test ob es vorhanden ist)
  ramcheck=UB_SDRAM_Init();
  if(ramcheck==SUCCESS) {
    // zum test RAM komplett füllen
    sollwert=0xA1B2;
    for(adr=0;adr<SDRAM_MAX_ADR;adr+=2) {
      UB_SDRAM_Write16b(adr,sollwert);
      sollwert++;
    }
 
    // Ram wieder auslesen und prüfen
    sollwert=0xA1B2;
    for(adr=0;adr<SDRAM_MAX_ADR;adr+=2) {
      istwert=UB_SDRAM_Read16b(adr);
      if(istwert!=sollwert) {
        // RAM-Inhalt fehlerhaft
        ramcheck=ERROR;
      }
      sollwert++;
    }
  }
 
  while(1)
  {
    if(ramcheck==SUCCESS) {
      // wenn kein Fehler -> gruene LED leuchtet
      UB_Led_On(LED_GREEN);
    }
    else {
      // wenn Fehler -> rote LED blinkt
      UB_Led_Toggle(LED_RED);
      Delay(5000000);
    }
  }
}

Hier die Library zum Download :

sdram_f429_v100

Hier der komplette CooCox-Projektordner zum Download :

Demo_F429_05


22 Antworten auf 05-SDRAM-Library (STM32F429)

  1. Holger sagt:

    Sorry, wenn es eine Anfänger-Frage ist. Habe seit letztem Wochenende auch das stm32f429 Discovery hier… Wie adressiet der Controller die 8 MB SDRAM mit den oben erwähnten benutzten Pins? Mit den insgesamt. 12 Axx Pins alleine geht das doch nicht vollständig, oder?

    • admin_ub sagt:

      Wenn du rausgefunden hast, das A0-A11 nicht für 8MByte reichen bist du doch kein Anfänger mehr :-) … Das RAM ist als 2D-Matrix aufgebaut. Eine “RAM-Zelle” wird mit Reihe und Spalte Adressiert (Row mit A0 bis A11, Col mit A0 bis A7) . Zum unterscheiden ob Row oder Col gibt es die RAS und CAS Leitungen. Damit sind 1048576 Zellen Adressierbar. Jetzt gibt es noch die 2 Bank Leitungen (BA0,BA1) und der Umstand das eine Zelle 16bit breit ist. Damit wären wir auch bei der Bezeichnung des RAMs : 1M x 4 x 16 = 8MByte

  2. Flo sagt:

    Erstmal vielen Dank für die ganzen Sourcen, das macht alles sehr viel einfacher!

    Bei der SDRAM-Library habe ich per “__attribute__ ((section(“.sdram”)))” und entsprechendem Linkerfile-Eintrag

    sdram (rwx) : ORIGIN = 0xD0100000, LENGTH = 7M /* first MB is used as LCD frame buffer */

    .sdram (NOLOAD) :
    {
    . = ALIGN(4);
    *(.sdram .sdram.*)
    } > sdram

    versucht, einen größeren Puffer ins SDRAM auszulagern. Laut Map-File liegt er auch dort, sobald ich aber etwas mehr als ein paar Byte da rein schreibe (ohne die Library-Funktionen zu verwenden, bis auf UB_SDRAM_Init() natürlich) hängt sich der Mikrocontroller auf.

    In deinen Write/ReadBuffer Funktionen wartest du auf das Busy-Flag. Kann man den FMC nicht auch so einstellen, dass man das SDRAM transparent nutzen kann?

    • admin_ub sagt:

      alle Grafik routinen von mir nutzen das SDRAM mit direktem zugriff
      z.B.

      1
      2
      3
      4
      5
      
      uint32_t LCD_CurrentFrameBuffer=((uint32_t)0xD0000000);
       
        for (index = 0x00; index < LCD_FRAME_OFFSET; index+=2) {
          *(volatile uint16_t*)(LCD_CurrentFrameBuffer + index) = color;
        }

      du machst da wohl etwas falsch

      • Flo sagt:

        Stimmt, ich hatte die Initialisierung vergessen… mein Fehler ;)

  3. Lurch sagt:

    typo in Demo: uint8_t sollwert, istwert; sollte wohl uint16_t sein
    Danke für die tolle Arbeit. Schöne Libs!

    • admin_ub sagt:

      so ein shi… du hast recht (danke), komisch das der Compiler nicht meckert. Wenn ich dazukomme änder ich es ab.

  4. Falko sagt:

    Hallo und vielen Dank für den tollen Code.
    Ich habe dein Beispielprojekt mit emwin am laufen. Leider habe ich ein mysteriöses Problem, wenn ich in einer Funktion die überhaupt nichts mit dem Display zu tun hat, eine Variable entferne, ist das Display plötzlich dunkel. Kann es etwas mit dem externen Ram zu tun haben? Ich habe den RAM etwas anders angeschlossen, anstelle Bank 2 verwende ich Bank 1 (Chip ist an SDNE0 und SDCKE0) angeschlossen. Ich habe die stellen die stellen im code wo bank2 steht in bank1 geändert. Die Start Adresse im SDRAM Header habe auf #define SDRAM_START_ADR ((uint32_t)0xC0000000) geändert. Ist das richtig? Muss ich noch irgendwas anderes beachten?
    LG Falko

    • admin_ub sagt:

      wenn du das Linker-Script von mir benutzt, muss dort die Adresse auch geändert werden.

      • Falko sagt:

        Danke! Habe ich jetzt geändert. Der Fehler ist leider immer noch da :-( . Wo finde ich eigentlich die Startadresse in den Datenblättern? Mir ist aufgefallen das das Display eigentlich noch geht, nur die PWM der Hintergrundbeleuchtung ausgeht (Auf meinen Board sitzt ein Step-Up Stromregler, der per PWM gedimmt wird) und dadurch nichts mehr zu sehen ist. Grade ist mir noch aufgefallen, das der Fehler nicht mehr auftaucht, wenn ich die Compiler Optimierung (-Os) EINschalte. Sehr sehr merkwürdig… ich brauch jetzt ne große Tasse Kaffee…

  5. Christian sagt:

    Hallo,

    ohne es ausprobiert zu haben: Es gibt in der CMSIS Boot Lib ein .h. File wo drinsteht, dass man eine Zeile auskommentieren soll, wenn das SDRAM verwendet werden soll. Muss man das?

    Ich versuche eigentlich soweit es geht die Funktionen der Std_Peripherals zu nutzen oder direkt auf die Hardware zuzugreifen, damit ich nicht so viele Libs habe, die meine Applikation ausbremsen.

    PS: Falls Du mal Lust hast wäre eine “RTC Kalibration” mal ganz nett, wie sowas geht. Meine RTC läuft 3s pro Tag falsch, die würde ich gern raustrimmen aber so einfach ist das wohl nicht.

    Gruss,
    Christian

    • Joerg B. sagt:

      Ich versuche eigentlich soweit es geht die Funktionen der Std_Peripherals zu nutzen oder direkt auf die Hardware zuzugreifen, damit ich nicht so viele Libs habe, die meine Applikation ausbremsen.

      Das widerspricht sich aber Christian, gerade durch die Std_Peripherals Libs machst du keine direkten Register Zugriffe und bremst damit letztendlich dein Programm aus. Bei 168 MHz wirst du da aber sicher kaum mal Probleme bekommen :D

      • admin_ub sagt:

        das sehe ich genauso. Ich verstehe das gemeckere “die STD-LIB ist zuviel Overhead” sowieso nicht. In welcher Anwendung spielt es eine Rolle ob die Initialisierung vom DAC/DMA/SPI/UART usw. 10us oder 10ms dauert ? OK da liegt der Faktor 1000 dazwischen aber wen stört es denn ?Die Zeiten von Befehlszyklen sparen und Speicherplatz sparen sind m.M. nach mit einer MCU die das DOS-Spiel “DOOM” flüssig laufen lassen kann vorbei. Aber wer alle Register selbst setzen will, soll damit glücklich werden ;-)

  6. Christian sagt:

    Hi,

    ihr habt sicher recht. Ich bin total Z80 und PIC geschädigt, wo man absolut effizient sein muss, jeden Takt rausoptimieren bei rund 750.000 Befehlen/sec . Bei einer CPU wie der M4 mit 2MB Flash (also unendlich viel) werde ich mich wohl dran gewöhnen müssen, dass die Frage nicht mehr lautet “Welches register muss ich wie setzen, damit das passiert was ich will?” sondern “Welche Library Funktionen muss ich wie aufrufen? Der LPC2368 war noch gut per Register beherrschbar, in die man dieBits reingeklopft hat. Beim M4 sehe ich da kaum mehr Land, allein schon mit dieser Matrix Geschichte und den vielen Bussen.

    Wie gesagt baucht es für das SDRAM aber keine Libs, das ist einfach als Section definierbar im Linkerfile und dann kann man es mit “variable _attribute (.section sdram)” oder ähnlich auch benutzen wie jede normale Var auch.

    Gruss,
    Christian

  7. Frank sagt:

    Hallo,

    ich versuche gerade den Einstieg in die STM32 Controller zu vollziehen. Mit deinen Beispielen wird einem das doch sehr erleichtert. Klasse Arbeit. Das muss doch auch mal erwähnt werden.

    Nun zu meinem Problem:
    Wenn ich mir im Memorybrowser den Speicher ab 0xD0000000 anzeigen lasse, so werden mir hier nur lauter Nullen angezeigt. Dein Speichertest läuft aber anstandslos durch. Auch kann ich hier keinen neuen Wert hineinschreiben.
    Mach ich hier irgendetwas falsch ? muss noch irgendetwas anders konfiguriert werden damit ich im Debugger auch den Speicherbereich auslesen kann oder ist das ein Problem der CoIDE (1.7.8)

    Gruss
    Frank

    • admin_ub sagt:

      bin mir nicht sicher ob man per debugger externen Speicher anzeigen lassen kann…hab ich noch nie ausprobiert.

      • Frank sagt:

        Also dazu kann ich nur sagen, dass es beim Keil-MDK über den Debugger problemlos funktioniert. Da kann ich das Externe RAM im Debugger auslesen. Dann muss das also am Debugger der Coocox-IDE liegen.

        Gruss
        Frank

        • Sakul Relda sagt:

          Hallo Frank,

          kannst du mir das Keil Projekt mal zuschicken?
          Wäre wirklich super :)

  8. Sakul Relda sagt:

    Hallo an alle,

    ist es möglich dieses Testprojekt auch in Keil uVision 5 zum laufen zu bringen und welche Änderungen brauche ich dafür?

    Danke für die Hilfe :)

    • Sakul Relda sagt:

      Also mein Problem ist, dass wenn ich das Projekt in Keil versuche zum laufen zu bekommen, bekomme ich Unmengen an Fehlern und ein Problem im Scatterfile – Section wird nicht richtig angesprochen.

  9. Sakul Relda sagt:

    Hallo ihr,

    der externe SDRAM für das STM32F429 Disco funktioniert jetzt. Die Frage für mich ist, wie viel langsamer ist der externe SDRAM?

    • admin_ub sagt:

      schreib einfach eine test funktion zum messen der Geschwindigkeit.


Wie hat Dir dieser Artikel gefallen?

1 Stern2 Sterne3 Sterne4 Sterne5 Sterne (Noch keine Bewertungen)
Loading...

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert