Arbeite mich gerade mit dem VL Discovery Board ein auf die STM32 und komme von den AVRs. Bei denen musste man ja PROGMEM benutzen um konstante Arrays, Strings usw. im Flash zu plazieren, und dann mit read_pgm_byte() usw. sich den Wert wieder zu holen. Wie läuft das nun bei den ARMs ? Kann darüber nichts finden und bin natürlich dran interessiert, den RAM zu sparen, da ich den für bessere Sachen brauchen kann. Reicht es, mit const u8 myArray[SIZE] = {werte,werte,werte}; die Sächelchen als Konstanten zu definieren ? Leider zeigt die Atollic IDE den Verbrauch an RAM und Flash nicht an.
bei den ARMs wurde das soweit ich weiß korrigiert .. der M3 is glaube immernoch harvard (?) aber genau das wurde glaube angepasst sobald also ein
1 | const .... |
steht sollte es auch im flash landen
Es ist vom Linkerskript abhängig. Wenn dort z.B. Folgendes eingetragen ist (Auszug), landen sie in der Section .text und folglich im Flash: .text : { *(.rodata) *(.rodata*) } >FLASH
Für den Code gibt es eigene Einträge, ich hatte nur den relevanten Ausschnitt für die Konstanten gepostet. Am besten schaust du dir mal die Linkerskripte genauer an, die der Firmware Library beiliegen (unter CMSIS).
Matthias Sch. schrieb: > komme von den AVRs. Bei denen musste man ja PROGMEM benutzen Alle anderen mir bekannten Archtiekturen (MSP430, PIC32 bzw. MIPS, ARMs) benötigen das nicht. Ein const genügt (wenn das "linker script" so ist, wie es Oliver beschrieben hat). Und das ist auch gut so :-) PROGMEM und GCC machen einem das Leben nicht einfach: Schreibarbeit, manche Funktionen müssen doppelt ausgelegt werden usw. Es gibt m. W. andere Compiler, die das PROGMEM implizit machen. Der GCC tut sich damit schwer bzw. das ist nicht seine Ausrichtung. Es gibt - neben der Vereinfachung - beim GCC noch einen Vorteil. Im Gegensatz zu PROGMEM Strings kann der GCC die "normalen" const Strings optimieren. D. h. gleiche Strings sind nur 1x im Flash, und Teilstrings ebenso: "Hallo, Welt" und "Welt" belegt nur den Platz, den "Hallo, Welt" benötigt. Hängt vom Optimierungslevel ab. Das führt bei mir regelmäßig dazu, dass das gleiche Programm locker in einen ARM mit 32K passt, während es im AVR zum Überlauf kommt.
fdssd schrieb: > bei den ARMs wurde das soweit ich weiß korrigiert .. > der M3 is glaube immernoch harvard (?) Wenn man an dieser Stelle mit Havard und Von Neumann argumentiert, dann sollte man sich entscheiden, ob damit Busse oder Adressräume gemeint sind. Anno Harvard Mark 1 was das noch gleichbedeutend, aber heutzutage ist es das längst nicht mehr. Denn alle ARMs (und x86, wenn man vom I/O-Adressraum absieht) haben einen einzigen einheitlichen Adressraum, unabhängig davon mit wievielen internen und externen Bussen der Core implementiert ist. PROGMEM hängt damit zusammen, dass AVRs 3 völlig getrennte Adressräume haben (Flash, EEPROM, RAM) und GCC nicht wie manche 8051er Compiler adressraumübergreifende softwarekontrollierte und damit langsame Pointer implementiert. Also muss man die Adressräume explizit angeben und erwischt da nicht die stärkste Seite von GCC. Hat man nur einen einzigen Adressraum, dann löst sich das Problem in Luft auf und Konstanten können problemlos im Flash landen, ohne dass man irdendwie besonders damit umgehen müsste. Es ist also völlig irrelevant, ob der ARM Core nur einen Bus hat (ARM7) oder gleich drei (ARM9). Ob er also im auf die Busse bezogenen Sinn Harvard ist oder Von Neumann.
Wenn man in einer Funktion eine const Variable habt, so erzeugt der GCC einen Code für die Initialisierung der const Variable. Wenn hingegen die const Variable außerhalb der Funktion deklariert, dann landet die ohne Umwege im Flash.
Markus Müller schrieb: > Wenn man in einer Funktion eine const Variable habt, so erzeugt der GCC > einen Code für die Initialisierung der const Variable. Ausser man verziert diese Variable mit "static".
Vielen Dank nochmal für die ausführlichen Infos. Ich habe bisher eben nur mit 8051, TMS320C25 , AVRs und 8048 gearbeitet, alles MC/DSP mit getrennten Adressräumen, wobei ich die TMS,51er und 48er nur in Assembler bearbeitet habe. C bisher nur auf Linux, Windows und AVRs. Bei Linux und Windows nimmt man ja dann eh 'const' , die haben aber kein Flash, hehe. Schön, das es so einfach ist, was ja auch bedeutet, das Zugriffe auf solche Konstanten oder eben Variablen im RAM gar keine Kunstgriffe brauchen.
Matthias Sch. schrieb: > Linux und Windows nimmt man ja dann eh 'const' , die haben aber kein > Flash, hehe. Aber sie haben ggf. RAM-Bereiche, die von der Anwendung nicht beschrieben werden können. Was ungefähr aufs Gleiche rausläuft.
Roland H. schrieb: > Im > Gegensatz zu PROGMEM Strings kann der GCC die "normalen" const Strings > optimieren. D. h. gleiche Strings sind nur 1x im Flash, und Teilstrings > ebenso: "Hallo, Welt" und "Welt" belegt nur den Platz, den "Hallo, Welt" > benötigt. Hängt vom Optimierungslevel ab. wie soll das denn gehen? In C sind muss doch ein 0 byte am ende stehen, sonst kommt keine stringfunktion damit klar.
Beim Beispiel "Hallo, Welt\0" und "Welt\0" geht das ja auch, was nicht geht, ist ein separates "Hallo\0".
Rufus Τ. Firefly schrieb: > Beim Beispiel "Hallo, Welt\0" und "Welt\0" geht das ja auch, was nicht > geht, ist ein separates "Hallo\0". ok, hatte irgendwie gelesen das "Hallo" einzeln steht. Anders rum macht es schon mehr sinn.
A. K. schrieb: > Markus Müller schrieb: > >> Wenn man in einer Funktion eine const Variable habt, so erzeugt der GCC >> einen Code für die Initialisierung der const Variable. > > Ausser man verziert diese Variable mit "static". Nee, ging auch nicht nicht. Ich hatte ein Array mit 10KB, der Compiller machte daraus 50KB mehr Flash-Verbrauch.
Markus Müller schrieb: > Wenn man in einer Funktion eine const Variable habt, so erzeugt der GCC > einen Code für die Initialisierung der const Variable. Das kapier ich ja nun gar nicht. Also entweder hast du sowas hier :
1 | void printword(const u16 data) |
2 | {
|
3 | printbyte(data >> 8); |
4 | printbyte((u8)data); |
5 | }
|
Was der Funktion ja nur sagt, das sie an der Variable 'data' nichts verändern soll, oder sowas:
1 | int hex2int(char * hexcode) |
2 | {
|
3 | const char hextable[18] = "0123456789ABCDEF"; |
4 | unsigned char i,b; |
5 | int c; |
6 | char *k; |
7 | b = strlen(hexcode); |
8 | c = 0; |
9 | for (i = 0; i < b; i++){ |
10 | k = strchr(hextable,hexcode[i]); |
11 | if (!k) return 0; |
12 | // wild pointer arithmetics . Note that this might only work in GCC
|
13 | c += (pow16(b-i-1) * (k - hextable)); |
14 | }
|
15 | return c; |
16 | }
|
Wo ich halt nur möchte, das 'hextable' im Flash landet. ( Was es übrigens tut, ich hab mir die Atollic Linkerskripts angeschaut). In beiden Fällen sollte der Compiler nix initialisieren dürfen/müssen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.