STM32 und externer RAM

OP #1645199
Lesenswert?
• ▲
▼
Hallo,

ich versuche bei dem besagten uC mit externen SRAM diesen zu beschreiben 
und auszulesen. Die Konfiguration ist soweit in Ordnung.
Aus dem Datenblatt habe ich entnommen, dass die erste Adresse die 
0x60000000 ist.

Bei dieser Adresse soll ein Header geschrieben werden, der 32 Byte lang 
ist. Dem folgenden die eigentliche Werte, die ich mittels des Headers 
später auslesen möchte.

Leider funktionieren meine Funktionen nicht so, wie ich mir das 
vorstelle. Deshalb meine Frage an euch, hat jemand auch schon mal sowas 
gemacht und könnte mir weiterhelfen?
Momentan habe ich eine Funktion, die den Header in den SRAM bei eine 
angegebenen Adresse schreiben soll und eine andere die diesen auslesen 
soll. Dabei bediene ich mir eines Makros, dass 32Byte in den interen 
Registern des Cortex beschreibt und das ist scheinbar der Knackpunkt...
1
 #define copyData32(pSrc, pDest) asm volatile(                      \
2
                      "ldmia   r0!,{r2-r6,r8-r10}\n"        \
3
                      "stmia   r1,{r2-r6,r8-r10}\n"        \
4
                      : /* no outputs  */            \
5
                      : "r" (pSrc), "r" (pDest)          \
6
                      : "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10");

Die Funktion zum Aufruf sieht folgendermaßen aus
1
AddrHead_Write = AddrHead[MessNr];
2
copyInBufferH((u32*)&HeaderR, (u32*)AddrHead_Write);
3

4
.
5
.
6
.
7

8
void copyInBufferH(register u32* pSrc, register u32* pAddr)
9
{
10
  copyData32(pSrc, pAddr);
11
}

Die Konfiguration des RAMS
1
 /*-- FSMC Configuration ------------------------------------------------------*/
2
  p.FSMC_AddressSetupTime = 1;    //no effect
3
  p.FSMC_AddressHoldTime = 1;    //no effect
4
  p.FSMC_DataSetupTime = 1;      //no effect
5
  p.FSMC_BusTurnAroundDuration = 1;  //no effect
6
  p.FSMC_CLKDivision = 1;      //HCLK / 2
7
  p.FSMC_DataLatency = 0;      //must be 0
8
  p.FSMC_AccessMode = FSMC_AccessMode_C;
9

10
  //FSMC asynchronen Mode für PSRAM Init setzen
11
  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;  //2;
12
  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Enable;
13
  FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM;
14
  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
15
  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
16
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
17
  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
18
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
19
  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
20
  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
21
  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
22
  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
23
  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
24
  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
25

26
  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); 
27

28
  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2;
29
  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); 
30

31
  /* Enable FSMC Bank2_PSRAM Bank */
32
  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);  //entfällt später  
33

34
  /* Enable FSMC Bank2_PSRAM Bank */
35
  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM2, ENABLE);
Nach dem zweiten Ausführen der Fkt. "copyInBufferH" bleibt der
Prozessor an dem Marko hängen. In der AddrHead[MessNr] steht immer
die Anfangsadresse des zu beschreibenden RAMs...

Stephan
#1645204
Lesenswert?
• ▲
▼
Musst den Befehlen schon die Register mitgeben, die der Compiler für die 
Adressen auserkoren hat:
1
#define copyData32(pSrc, pDest) asm volatile(                      \
2
                      "ldmia   %0,{r2-r6,r8-r10}\n"        \
3
                      "stmia   %1,{r2-r6,r8-r10}\n"        \
4
                      : /* no outputs  */            \
5
                      : "r" (pSrc), "r" (pDest)          \
6
                      : "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10");

Das "!" bei LDMIA könnte den Compiler bei Inlining durcheinanderbringen.
Persönliche Seite #1645331
Lesenswert?
• ▲
▼
A. K. schrieb:
> Wenn immer nur die 32 Bytes kopiert werden und keine grösseren Blöcke,
> dann würde ich nicht drauf wetten, dass deine Version viel effizienter
> ist als eine, die weniger Register braucht.

Nur die Codegröße unterscheidet sich möglicherweise. Aber warum nicht 
einfach memcpy() verwenden?

> Denn die Zwischenregister müssen gesichert werden, was auch Zeit braucht.

Ja, der Teil fehlte mir auch irgendwie :-)

--
Marcus
#1645668
Lesenswert?
• ▲
▼
Marcus Harnisch schrieb:

> Ja, der Teil fehlte mir auch irgendwie :-)

Nicht unbedingt, denn da die Register korrekt als "verwendet" 
gekennzeichnet wurden kümmert sich der Compiler selbst darum.

Allerdings werden so aus den 2 LDM/STMs insgesamt 4, sofern das als 
eigenständige Funktion implementiert ist. Andernfalls steht diese Aktion 
einer effektiven Registeroptimierung im Weg.
Persönliche Seite #1646198
Lesenswert?
• ▲
▼
A. K. schrieb:
> Nicht unbedingt, denn da die Register korrekt als "verwendet"
> gekennzeichnet wurden kümmert sich der Compiler selbst darum.

Irgendwann werde ich mal versuchen, diese kryptische Syntax des GCC 
Inline Assemblers zu verstehen. Wenn ich mir die memcpy() 
Implementierung bei CodeSourcery anschaue, dann sollte man wirklich 
darüber nachdenken...

Und ich dachte schon, der RealView Compiler hätte das durchaus besser 
machen können. Erst bei einem doppelten memcpy() mit jeweils vier Worten 
wird das von diesem Compiler richtig effizient umgesetzt.
1
void copyData32(u32 *pSrc, u32 *pDest)
2
{
3
    memcpy(pDest, pSrc, 16);
4
    memcpy(pDest + 4, pSrc + 4, 16);
5
}

Aber wenn Zeit nicht das eigentliche Problem ist, dann ist memcpy() in 
jedem Fall sinnvoller als Inline Assembler.

--
Marcus

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.