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
volatileuint16_tData[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?
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.
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.
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.
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!
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.
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.
>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.
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
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];
}
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
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.