ARM Cortex M3: SRAM mit Muster füllen

OP #4112507
Lesenswert?
• ▲
▼
Hallo zusammen,
für den AVR in 
http://rn-wissen.de/wiki/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc#Dynamischer_RAM-Verbrauch 
beschrieben, wie man den SRAM mit einem Muster fluten kann, um die 
Speicherbelegung testen zu können. Das hat sich in der Vergangenheit als 
sehr praktisch erwiesen.

Gibt es für den ARM-GCC für den ARM Cortex M3 (arm-none-eabi-gcc) eine 
Möglichkeit, auch das SRAM mit Mustern zu füllen?

Viele Grüße
W.T.
OP #4112530
Lesenswert?
• ▲
▼
Torsten Robitzki schrieb:
> Vielleicht verstehe ich das Problem / Aufgabe nicht,

Den Speicher mit Mustern zu füllen und anschließend den Inhalt auf einem 
Display auszugeben ist eine einfache Möglichkeit, die Sicherheitsmarge 
zwischen Stack und Heap darzustellen und kann per Fotoapparat sogar 
dabei helfen, einen Memory-Dump herzustellen, ohne daß der Nutzer 
Hardware hat.

Im Bild im Anhang ist das für einen AVR zu sehen: Der RAM wurde im 
.init3 mit 0xAA gefüllt, so daß der Platz zwischen Stack und Heap direkt 
ins Auge  fällt.

Torsten Robitzki schrieb:
> aber was spricht
> dagegen im Start-Up code in einer Schleife über das gesamte Ram zu gehen
> und das mit einem Muster zu füllen?

Nichts - wenn man weiß wo und wie. Wer weiß das?

Viele Grüße
W.T.
Angehängte Dateien:
(Firma: Torrox.de) #4112601
Lesenswert?
• ▲
▼
Ich habe das Projekt mit den cmsis file von ST aufgesetzt. Da gibt es 
ein liker file, in dem ist die Länge des Ram-Bereichs und die 
Start-Adresse des Ram-Bereichs definiert:
1
/* Specify the memory areas */
2
MEMORY
3
{
4
    FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 512K
5
    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 80K
6
}

das Linkerscript beschreibt da einige RAM-Bereich (welche, die mit 
Werten aus dem Rom initialisiert werden und welche, die mit 0 gefüllt 
werden müssen. Danach könntest Du ein Symbol definieren, dass dann auch 
von C aus zugreifbar wäre:
1
  /* User_heap_stack section, used to check that there is enough RAM left */
2
  ._user_heap_stack :
3
  {
4
    . = ALIGN(4);
5
    _head_start = .;
6
    PROVIDE ( end = . );
7
    PROVIDE ( _end = . );
8
    . = . + _Min_Heap_Size;
9
    . = . + _Min_Stack_Size;
10
    . = ALIGN(4);
11
  } >RAM
Die Funktion, die bei mir den Ram-Bereich initialisiert, wäre in 
Assembler und hat den Namen Reset_Handler. Jetzt könnte man die Funktion 
in Assembler schreiben, oder (was vielleicht einfacher ist), einen 
zusätzlichen Initialisierungsschritt in Form eines zusätzlichen 
Funktionsaufrufs einfügen:
1
/* Call memory intitialization function.*/
2
    bl  WalterInit
3
/* Call the clock system intitialization function.*/
4
    bl  SystemInit

Dann könnte man in WalterInit() den Bereich von _heap_start bis Ende-Ram 
füllen.

mfg Torsten
OP #4112662
Lesenswert?
• ▲
▼
Der Default_Reset_Handler() in startup_stm32f10x_md.c stellt den 
Reset-Handler und ist leicht überschreibbar, da definiert ist:
1
#pragma weak Reset_Handler = Default_Reset_Handler

Hier sind u.A. ein paar Zeilen Assembler, die mir den Bereich  zwischen 
_sbss und _ebss mit Nullen füllen. Also mal das Ganze für mich angepaßt:
1
void Reset_Handler(void)
2
{
3
  /* Initialize data and bss */
4
  unsigned long *pulSrc, *pulDest;
5

6
  // Segment mit 0xAAAAAAAA fuellen.
7
  __asm("  ldr     r0, =_ebss\n"
8
        "  ldr     r1, = #33574912\n" // 0x20000000 + 20*1024
9
        "  mov     r2, #2147483647\n" // 0xAAAAAAAA
10
        "  .thumb_func\n"
11
        "data_loop:\n"
12
        "    cmp     r0, r1\n"
13
        "    it      lt\n"
14
        "    strlt   r2, [r0], #4\n"
15
        "    blt     data_loop");
16

17
  /* Copy the data segment initializers from flash to SRAM */
18
  pulSrc = &_sidata;
19

20
  for(pulDest = &_sdata; pulDest < &_edata; )
21
  {
22
    *(pulDest++) = *(pulSrc++);
23
  }
24

25
  /* Zero fill the bss segment.  This is done with inline assembly since this
26
     will clear the value of pulDest if it is not kept in a register. */
27
  __asm("  ldr     r0, =_sbss\n"
28
        "  ldr     r1, =_ebss\n"
29
        "  mov     r2, #0\n"
30
        "  .thumb_func\n"
31
        "zero_loop:\n"
32
        "    cmp     r0, r1\n"
33
        "    it      lt\n"
34
        "    strlt   r2, [r0], #4\n"
35
        "    blt     zero_loop");
36

37

38

39
  /* Setup the microcontroller system. */
40
  SystemInit();
41

42
  /* Call the application's entry point.*/
43
  main();
44
}

Beim Dump des SRAMs sehe ich allerdings keine AAAAAAAA im SRAM-also 
vermutlich das falsche Segment?
#4112678
Lesenswert?
• ▲
▼
nix Versteher schrieb:
> Warum glauben die Hobbybastler, dass sie in asm besser codieren als ein
> C Compiler?

Weil es einem der C-Compiler möglicherweise übel nimmt, wenn man den 
gesamten RAM Speicher überschreibt! Stichwort: Variablen auf dem 
Stack.

Bin auch kein Fan von (längerem) Assemblercode, aber es gibt nun mal 
Situationen, da macht es schlicht und ergreifend Sinn!
Gast #4113397
Lesenswert?
• ▲
▼
Walter Tarpan schrieb:

> Kennt jemand eine gute Übersicht über das Speicher-Layout der STM32?
Was genau meinst Du damit?
Die Memory Map (wo die einzelnen Peripherieeinheiten liegen, steht ja im 
RM) wirst Du wohl nicht meinen und wie das int. SRAM sich in 
Vektortabelle, DATA, BSS, Heap und Stack aufteilt, sollte aus dem 
Linkerscript/Mapfile hervor gehen.

Zu Ramtest:
http://www.ganssle.com/articles/ramtest.htm
http://www.ganssle.com/testingram.htm

Wobei diese m.E. eher bei ext. RAM wg. Verdrahtungsfehlern, Lötbrücken 
und nicht angelöteten IC-Beinchen Sinn machen. Bei int. SRAM kann/sollte 
dies ja nicht vorkommen.
(Firma: Torrox.de) #4113418
Lesenswert?
• ▲
▼
Walter Tarpan schrieb:
> Beim Dump des SRAMs sehe ich allerdings keine AAAAAAAA im SRAM-also
> vermutlich das falsche Segment?

Das bss ist in meinem Linker-Script auch das letzte Segment. Du füllst 
ab Ende-BSS bis Ende-BSS + 20k. Das klingt relativ willkürlich, ist für 
einen ersten Test aber ggf. ok. Wenn das bss das letzte Segment ist, 
dann möchtest Du eigentlich von ebbs bis Ende-Ram (Anfang-Ram + Größe 
Ram) mit Deinem Füllmuster füllen.

Alternativ könntest Du natürlich als allerersten Schritt den gesamten 
Ram-Bereich mit Deinem Muster füllen. Dann wird ein Teil wieder 
überschrieben, aber ggf. stört Dich das nicht.

Vielleicht initialisiert Dir Deine Runtimelibrary aber auch zumindest 
den Bereich, in dem der Heap liegt. Vielleicht gibst Du im Dump auch den 
flahscen Bereich aus?

Und den Stack bekommst Du natürlich mit Assembler zuverlässig 
initialisiert, weil Du dort keine auf dem Stack liegenden Laufvariablen 
verwenden möchtest.

mfg Torsten

Edit: Und meine Idee mit der zusätzlichen Funktion funktioniert 
natürlich auch nicht, da die Funktion beim initialisieren des Stacks 
natürlich auch die auf dem Stack liegende Rücksprungadresse zuschießen 
würde.
Gast #4113763
Lesenswert?
• ▲
▼
Warum können solch engagierte Programmierer sich bloß nicht einen 
simplen RAM-Test selber schreiben?

Ich zitiere hier mal nen steinalten RAM-Test, den ich in meinen Annalen 
gefunden habe:


/* ein billiger RAM Test: Bereich ist eigentlich A0000000 .. AFFFFFFF
   aber ab A1000000 friert der uC ein - anstelle Data Abort.
 */
void ExtRamTest(void)
{ dword* PDW;
  dword* PDW0;
  dword* PDEND;

  PDEND = (dword*) CgBWSP;

  PDW0 = PDW = (dword*) ExtRamBegin;
  *PDW0 = 0x4711AFFE;
  ++PDW;

  while ((PDW < PDEND) && (*PDW0 == 0x4711AFFE))
  { *PDW = 0xFFFEFFFE;
    ++PDW;
  }

  *PDW0 = 0xFFFEFFFE;
  while (PDW0 < PDW)
  { if (*PDW0 == 0xFFFEFFFE) *PDW0 = *PDW0 + 0x10002;
    ++PDW0;
  }

  PDW0 = (dword*)ExtRamBegin;
  while ((PDW0 < PDW) && (*PDW0==0)) ++PDW0;
  ExtRamSize = (dword)PDW0 - (dword)ExtRamBegin;
}


/*  ende */

So, wer will, der mache sich was draus.

W.S.

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.