Forum: Mikrocontroller und Digitale Elektronik Speicherbelegung wenn Daten als const oder variabel


von StinkyWinky (Gast)


Lesenswert?

Hallo Forum

In einem Projekt (RealView Compiler, LM3S1968) wird ein grosser Struct, 
bestehend aus 3008 Float (à 4-Bytes) benützt, macht also 12038 Bytes. 
Diese Struktur enthält vordefinierte Kurvendaten, die konstant sind und 
bleiben.

Gegenwärtig wird der Struct wie folgt deklariert:
1
TData Data = {
2
    {0.004133f, 0.000003f, 0.000000f},
3
    {0.004546f, 0.000023f, 0.005283f},
4
    ...}

So wie ich das verstehe, liegt der Struct im RAM. Ferner wird irgend wo 
Initialisierungscode liegen, welcher nach einem Reset die Werte ins RAM 
schreibt.
Nun dachte ich, es wäre effizienter, wenn ich den Struct als const 
deklariere:
1
const TData Data = {
2
    {0.004133f, 0.000003f, 0.000000f},
3
    {0.004546f, 0.000023f, 0.005283f},
4
    ...}

Dann wäre 1. sichergestellt, dass niemand mehr darauf schreiben kann, 2. 
müsste der Initialisierungscode entfallen und folglich weniger Flash 
belegt werden.

Meine Erwartung (2.) wird aber nicht erfüllt, und ich verstehe nicht 
warum:

           variabel           const
Code         146904          146880
ROdata        41800           53832
RWdata        13944            1912
ZIdata        35984           35984
Code used    200724          201100

Der Unterschied bei ROdata beträgt 12038, ebenso bei RWdata, wie 
erwartet, da der Struct vom einen in den anderen Bereich wandert. Der 
Code bleibt aber praktisch gleich gross. Insgesamt belegt die "const" 
Variante mehr Platz im Flash!

von Roland H. (batchman)


Lesenswert?

Der Code für die Initialisierung von "Flash -> RAM" im Startup ist 
"immer" vorhanden, da spielt es keine Rolle, wie viel kopiert wird. Da 
fällt nichts weg.

An Deiner Rechnung verstehe ich nicht, weshalb bei (2) ganz unten eine 
größere Zahl steht, obwohl die Einzelwerte in Summe kleiner sind 
(verglichen mit (1)). Was bedeutet "Code used"?

Ist der einzige Unterschied zwischen den beiden Varianten nur das 
"const"?

Spielt hier u. U. ein "alignment" eine Rolle, welches sich ungünstig für 
Variante (2) auswirkt, da dort in diesem Fall der Verschnitt größer ist?

von StinkyWinky (Gast)


Lesenswert?

> da spielt es keine Rolle, wie viel kopiert wird. Da fällt nichts weg.

Doch muss aber, weil im einen Fall 13944 Bytes und im anderen Fall nur 
1912 Bytes kopiert werden müssen. Die Initialwerte müssen ja auch 
"irgendwo" stehen, da sie ja praktisch alle unterschiedlich sind.

Der Unterschied im Code ist einzig die Zeile mit dem "const".

von qaytzu (Gast)


Lesenswert?

Die Initialwerte sind bei beiden Varianten im Code vorhanden. Und für 
den Init Code selbst ändert sich maximal eine Iterations Variable, 
welche die Größe der zu kopierenden Daten repräsentiert.

von Karl H. (kbuchegg)


Lesenswert?

StinkyWinky schrieb:
>> da spielt es keine Rolle, wie viel kopiert wird. Da fällt nichts weg.
>
> Doch muss aber, weil im einen Fall 13944 Bytes und im anderen Fall nur
> 1912 Bytes kopiert werden müssen.

Das ist doch völlig egal.
Das ist doch nur ein Zahlenwert bei

   for( i = 0; i < 13944; i++ )
     *Ziel++ = *Quelle++;

Ein Compiler wird sich allerdings nach Möglichkeit ALLE zu 
initialisierenden Variablen zusammenfassen, so dass in Wirklichkeit 
nicht 13944 steht, sondern eine höhere Zahl. Eben die Summe aller 
Variablen die initialisiert werden müssen. Und ob dann in dieser 
Schleife bis 25000 oder nur bis 14000 gezählt wird, ändert am Code ja 
nichts.

> Die Initialwerte müssen ja auch
> "irgendwo" stehen, da sie ja praktisch alle unterschiedlich sind.

Natürlich. Aber den Anteil hast du ja trotzdem. Denn: irgendwo müssen 
die Daten ja erst mal sein. Der einzige Unterschied: im einen Fall 
werden sie dann zusätzlich noch ins RAM umkopiert was im anderen Fall 
unterbleibt.

von (prx) A. K. (prx)


Lesenswert?

Wenn "const" Daten direkt im Flash angesprochen werden, was bei ARM 
problemlos möglich ist (im Unterschied zu AVR), dann entfällt die 
Notwendigkeit, diese Daten aus dem ROM ins RAM umzukopieren. Somit 
sollten sie in der RAM-Version zweimal und in der ROM-Version einmal im 
Adressraum auftauchen. Im Image hingegen sollten sie in beiden Fällen 
nur einmal auftauchen, da der Inhalt der RAM-Section dort keinen Sinn 
ergibt.

Anders sieht es aus, wenn der Compiler auch "const" Daten ins RAM legt, 
beispielsweise weil der Zugriff darauf üblicherweise schneller ist als 
auf das ROM. Dann ändert sich substantiell überhaupt nichts.

von StinkyWinky (Gast)


Lesenswert?

Der Groschen ist gefallen:

Anstelle der Initialwerte für die Kopiererei in das RAM, steht halt der 
Struct fixfertig initialisiert im ROM (Flash). Beides braucht gleich 
viel Paltz.

Danke sehr!

von ag34tgeq (Gast)


Lesenswert?

Und Du sparst jede Menge RAM.

von Pako (Gast)


Lesenswert?

Nur so am Rande:
Es gibt Architekturen (z.B. TC1796), wo ein Datenzugriff (nicht 
Programmcodezugriff!) ins Flashs deutlich langsamer ist als ins RAM 
(weil ein anderer Weg über interne Busse genommen wird). Hier macht es 
durchaus Sinn, bestimmte konstante Daten ins RAM zulegen, um CPU-Zeit zu 
sparen.

von 53g4368j (Gast)


Lesenswert?

Das ist richtig. Es gibt mehrere Gründe, es so oder so zu tun. Meistens 
wird es aber am viel knapperen RAM als am größeren Flash liegen.

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.