Forum: Mikrocontroller und Digitale Elektronik STM32F4 Daten passen nichts ins RAM


von Ingo (Gast)


Lesenswert?

Hallo,

ich habe einen STM32F405 Controller in dessen RAM ich ein großes 
Datenpaket ablegen möchte.

Ohne dieses Datenpaket habe ich:
      text   data   bss    dec  hex
      6654   1292   2620  10566  2946


dann kommt folgender Code hintzu:
1
#define BUFFERSIZE 65536
2
volatile uint16_t Data[BUFFERSIZE];
somit sollten zu den 2620 Bytes nochmal 131072 Bytes dazu kommen.
Macht 133692. Dann habe ich noch den Stack mit
1
#define STACK_SIZE       0x00000200      /*!< The Stack size suggest using even number    */

Macht also 512Byte Stack, 2620 Bytes normale Daten und die 131072 Bytes. 
Sollte doch alles in die 192kB RAM reinpassen, oder?

Ich bekomme allerdings die Warnung:
section `.bss' will not fit in region `ram'
region ram  overflowed with stack
region `ram' overflowed by 3912 bytes

Warum bzw. wie kann ich das Problem beheben? Wer blockiert hier den 
Restlichen RAM?

von Dr. Sommer (Gast)


Lesenswert?

Ingo schrieb:
> #define STACK_SIZE       0x00000200      /*!< The Stack size suggest
> using even number    */
Die Stack-Size muss im Linker-Script angegeben werden, damit die 
Berechnung da funktioniert. Außerdem sind die 192kB kein homogener Block 
sondern teilen sich auf 128kB SRAM und 64kB CCM auf (siehe 
Datasheet+Reference Manual), die will der Linker vermutlich nicht in 
einem reservieren.

von René K. (cyprius)


Lesenswert?

AFAIR ist das RAM vom STM32F4 segmentiert. Da kann aber vermutlich 
jemand anders noch mehr zu schreiben ;)

Ich empfehle aber vorsorglich schonmal einen Blick ins Datenblatt.

von Ingo (Gast)


Lesenswert?

Somit passt der Datenblock weder in den einen noch in den anderen 
Speicherblock, richtig?

Wie kann man das umgehen? Jemand eine Idee?

von Ingo (Gast)


Lesenswert?

Bzw. gibt es eine möglichkeit dem Linker zu sagen, er möge bitte beide 
Speicherblöcke als einen benutzen?

von Dr. Sommer (Gast)


Lesenswert?

Wenn dein "Data" Array nur von der Cpu, nicht von DMA oder so 
zugegriffen wird, pack das doch ins CCM, passt da ja genau rein... 
Ansonsten musst du andere Teile ins CCM packen und "Data" ins den 
normalen SRAM.

von Ingo (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Wenn dein "Data" Array nur von der Cpu, nicht von DMA oder so
> zugegriffen wird, pack das doch ins CCM, passt da ja genau rein...
> Ansonsten musst du andere Teile ins CCM packen und "Data" ins den
> normalen SRAM.

Das Data Array soll mit Werten von ADC über DMA vollgepackt werden, 
somit mit der DMA auch darauf zugreifen können => somit muss das dann 
wohl ins SRAM. Die Restlichen sachen werden nur von der CPU genutzt, 
also könnte das ins CCM.

Wie teile ich dem Linker mit, welche Daten wo landen sollen? Bin mit dem 
Linker nicht vertraut :(


Danke schonmal!

von Dr. Sommer (Gast)


Lesenswert?

Ingo schrieb:
> Wie teile ich dem Linker mit, welche Daten wo landen sollen? Bin mit dem
> Linker nicht vertraut :(
Irgendwas mit __attribute__((section("blablub"))) im Code an der 
jeweiligen Variablen, wobei blablub der Section im Linker-Script 
entspricht... Musste schauen wie die CCM-Section in deinem Linkerscript 
heißt.

von Ingo (Gast)


Lesenswert?

Wo finde ich das? In der CoIDE werden ja die beiden Speicherbereiche 
eingestellt, aber wo finde ich die Sections bzw das Linkerscript?

von Dr. Sommer (Gast)


Lesenswert?

Keine Ahnung. Schau mal was bei der Linker-Kommandozeile beim Parameter 
-T steht.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Man könnte auch den CCM RAM als Standard RAM deklarieren, dann landet 
automatisch alles darin und mit __attribute__((section("blablub"))) 
werden dann nur noch die Variablen deklariert die in das SRAM kommen.
Sogar der Stack kann im CCM RAM liegen, allerdings muss man erst den CCM 
RAM aktivieren (Clock), ansonsten kann man darin nichts rein 
schreiben/lesen.

Wie man das bei CoIDE einstellt weiß ich nicht. Ich nutze Eclipse, 
direkt mit GCC und Linker-Script und kann mir das von Hand 
zusammenschreiben wie ich mag - dafür ist alles Handarbeit.

: Bearbeitet durch User
von Ingo (Gast)


Lesenswert?

Ja danke, ich werde morgen mal rumprobieren! Bin weiterhin für Tips oder 
Hilfe dankbar!

von holger (Gast)


Lesenswert?

>Bin weiterhin für Tips oder
>Hilfe dankbar!

Mach das Array einfach kleiner.

von Ingo (Gast)


Lesenswert?

Warum, das Ding hat so viel RAM, dass will ich nutzen!

von holger (Gast)


Lesenswert?

>Warum, das Ding hat so viel RAM, dass will ich nutzen!

Und dafür dann irgendwelche Verrenkungen machen?
8kB oder 16kB weniger für das Array wird dir schon nicht weh tun.

von Ingo (Gast)


Lesenswert?

Ich brauche aber so viel Daten wie möglich

von holger (Gast)


Lesenswert?

>Ich brauche aber so viel Daten wie möglich

Blödsinn.

von Ingo (Gast)


Lesenswert?

Außerdem welchen Sinn macht es von 192kB nur 128kB zu nutzen? Außerdem 
will ich ja dabei auch was lernen!

von Ingo (Gast)


Lesenswert?

holger schrieb:
> Ich brauche aber so viel Daten wie möglich
>
> Blödsinn.
Du musst es ja wissen...

von User (Gast)


Lesenswert?

> Ich brauche aber so viel Daten wie möglich

Und die müssen für immer und ewig im RAM stehen?

von Ingo (Gast)


Lesenswert?

Nein, es wird das Array mit Daten gefüllt, analysiert und auf bestimmte 
Charactarisrika untersucht. Danach werden die Daten verworfen und nur 
ein paar Sachen davon gespeichert. Danach beginnt das Spiel von vorn. Es 
ist daher nötig, so viele zusammenhängende Daten wie möglich auszuwerten

von Lothar (Gast)


Lesenswert?

Ingo schrieb:
> Bzw. gibt es eine möglichkeit dem Linker zu sagen, er möge bitte beide
> Speicherblöcke als einen benutzen?

Das kann man dem Linker schon sagen, es nützt aber nichts, weil das 
Array dann über zwei physikalische Blöcke verteilt ist, und der Zugriff 
im Programm beim "Sprung" zum Speicherfehler führt.

Da der STM32F405 keine MMU hat, die daraus einen logischen Block machen 
könnte, gibt es nur eine Möglichkeit: eine struct aus zwei Arrays die in 
den beiden Blocks deklariert werden und Zugriff über Zeiger:

struct array
{
  __DATA(RAM1) char data_buffer[128*1024];
  __DATA(RAM2) char data_buffer[64*1024];
}

von 6A66 (Gast)


Lesenswert?

Ingo schrieb:
> Nein, es wird das Array mit Daten gefüllt, analysiert und auf bestimmte
> Charactarisrika untersucht. Danach werden die Daten verworfen und nur
> ein paar Sachen davon gespeichert. Danach beginnt das Spiel von vorn. Es
> ist daher nötig, so viele zusammenhängende Daten wie möglich auszuwerten

Das ist IMHO nur dann der Fall wenn das gesuchte Charakteristikum auch 
so groß ist dass es über den ganzen Speicher verteilt ist. Alternativ 
könnte man: die Samplefrequenz verdoppeln (also Abtastrate halbieren) 
und den Speicher halbieren oder den Algorithmus anderweitig anpassen. 
Wenn das nicht geht wäre zu überlegen ob die Wahl des Prozessors mit dem 
grenzwertigen RAM als geeignet zu bezeichnen ist.

rgds

von Ingo (Gast)


Lesenswert?

Also ich habe mir jetzt folgendes überlegt:

Ich verkleinere meinen Datenpuffer auf 100kB (50000 Werte). Dann habe 
ich noch reichlich Reserven für Stack und sonstige kleinen Sachen.

Zusätzlich packe ich "normale" Variablen, die nicht über DMA sondern nur 
vom Prozessor angesprochen werden in den CCM.

Dazu habe ich im Linkerscript folgende Codezeilen hinzu gefügt:
.ccm :
{
 . = ALIGN(4);
 _sccm = .;
 *(.ccm)
 . = ALIGN(4);
 _eccm = .;
}>ram1

Dann werden die Variablen über _attribute_ ((section (".ccm")))
dort abgelegt.

Das sollte soweit funktionieren hoffe ich. Ich habe zwar keinen blassen 
Schimmer was diese Codezeilen genau machen, es scheint aber zu 
funktionieren, denn die Variablen landen nun nicht mehr unter .bss 
sonder werden zu .data gepackt.

unter CooCox muss man dann noch sagen "bitte eigenes Linkerscript 
verwenden" nämlich das mit den geänderten Codezeilen.

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.