Muss man beim avr-gcc immer noch mittels Progmem auf konstante Tabellen zugreifen oder geht auch:?
1 | const uint8_t test[]={1,2,3}; |
2 | |
3 | x=test[0]; |
|
Forum: Compiler & IDEs avr-gcc progmem immer noch?![]() Muss man beim avr-gcc immer noch mittels Progmem auf konstante Tabellen zugreifen oder geht auch:?
fast. mit den neuesten gcc kannst du auch die Attributierung __flash benutzen AVR-GCC-Tutorial Im Abschnitt über die Flash Zugriffe (14.2) :
Bearbeitet durch User
Ein einfaches "const" allein kann auf einer Harvard-Maschine dafür übrigens nicht genügen. OK, zumindest nicht, solange man keine generic pointers hat, aber die wiederum verursachen Overhead sowohl hinsichtlich Speicherverbrauch als auch Laufzeit, daher ist das auf einem Controller wenig wünschenswert. Ok, vielen Dank für eure Antworten. Ich dachte mal gehört zu haben, dass es mittlerweile ohne "PROGMEM" geht. Für die Portierbarkeit von Code auf einen ARM ist das manchmal ein wenig lästig. Nö. Inhalt meiner pgmspace.h:
Funktioniert auf AVR, ARM und unter Windows mit dem MSVC. Viele Grüße W.T. Walter Tarpan schrieb: > #define pgm_read_byte(a) (*a) Besser: #define pgm_read_byte(a) (*(a)) Das könnte sonst bei pgm_read_byte (adr + offset) in die Hose gehen. markus schrieb: > Ich dachte mal gehört zu haben, dass es mittlerweile ohne "PROGMEM" > geht. Es geht ohne die pgm_read_...-Funktionen, wenn man die (neue) Deklarationsmethode mit __flash benutzt. Anders als die frühere Variante mit __attribute__((section(".progmem"))) kann der Compiler den qualifier __flash intern am Datentyp mitführen und weiß daher, dass er die entsprechenden Daten mittels LPM lesen muss statt mit LDS. Aber es geht nicht ohne __flash. Frank M. schrieb: > Besser: > > #define pgm_read_byte(a) (*(a)) > > Das könnte sonst bei pgm_read_byte (adr + offset) in die Hose gehen. Stimmt. Ich sollte all meinen Quelltext stückweise in Foren posten :-) Jörg Wunsch schrieb: > Ein einfaches "const" allein kann auf einer Harvard-Maschine dafür > übrigens nicht genügen. OK, zumindest nicht, solange man keine generic > pointers hat, aber die wiederum verursachen Overhead sowohl hinsichtlich > Speicherverbrauch als auch Laufzeit, daher ist das auf einem Controller > wenig wünschenswert. DIe Aussage ist ja wohl der Groesste Unsinn. KEIL C51 kann das schon seit 30 Jahren. Und das sehr Effizient hal9000 schrieb: > DIe Aussage ist ja wohl der Groesste Unsinn. Soso. > KEIL C51 kann das schon > seit 30 Jahren. Und das sehr Effizient Klar, mit generic pointers. Man muss sich im Zeiger noch ein Bit mit merken, welches aussagt, ob der Zeiger nun in RAM oder Flash zeigt. Dann muss jede damit befasste Routine zur Laufzeit entscheiden, ob sie nun aus dem Flash oder RAM liest. Beim AVR würde das bedeuten, dass man nicht mehr mit 16 Bit für einen RAM-Zeiger auskommt, denn der RAM selbst braucht schon 16 Bit für die Adressierung. Damit braucht man dann ein ganzes Byte pro Zeiger mehr. @Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite >Klar, mit generic pointers. Man muss sich im Zeiger noch ein Bit >mit merken, welches aussagt, ob der Zeiger nun in RAM oder Flash >zeigt. Dann muss jede damit befasste Routine zur Laufzeit >entscheiden, ob sie nun aus dem Flash oder RAM liest. Schon mal nicht schlecht, so muss man sich nicht selber drum kümmern. >Beim AVR würde das bedeuten, dass man nicht mehr mit 16 Bit für einen >RAM-Zeiger auskommt, denn der RAM selbst braucht schon 16 Bit für die >Adressierung. Damit braucht man dann ein ganzes Byte pro Zeiger mehr. Dieses Opfer könnte man bringen, schließlich werden nicht tausende von Pointern in typischen AVR-Programmen verwendet. Falk Brunner schrieb: > Dieses Opfer könnte man bringen, Müsste man es nur noch dem GCC beibiegen ... > schließlich werden nicht tausende von > Pointern in typischen AVR-Programmen verwendet. Naja, hinreichend viele, wobei natürlich genügend davon wieder wegoptimiert werden. Andererseits: der Typ eines Zeigers ändert sich im Allgemeinen zur Laufzeit nicht mehr. Der Programmierer weiß also bereits vorher, ob das Ding ins Flash oder in den RAM zeigt. Dann kann man es doch aber auch gleich passend deklarieren und sich den Overhead sparen, oder? @ Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite >Müsste man es nur noch dem GCC beibiegen ... Jaja, der berühmte Spruch, "Wir müssten mal . . " ;-) >aber auch gleich passend deklarieren und sich den Overhead sparen, >oder? Naja, es geht ja darum, dass man beim AVR RAM und Flash mit getrennten Zeigern und Zugriffen explizit handhaben muss. Das würde entfallen, so wie beim PC oder ähnlichen Systemen (ARM, MPS430, etc.) Ausserdem könnte man dann endlich mal die Speicheraddressierung jenseits von 64kB Flash sauber machen, ohne das "Hackermakro". AVR-GCC-Tutorial -> Variablenzugriff >64kB Oder man steigt gleich auf STM32 um ;-) (Hallo mmvisual) Falk Brunner schrieb: > ohne das "Hackermakro". Brauchst du für __flash nicht (denke ich jedenfalls, müsste es verifizieren). > Oder man steigt gleich auf STM32 um ;-) Oder eben einen beliebigen anderen ARM. Karl Heinz schrieb: > mit den neuesten gcc kannst du auch die Attributierung __flash benutzen > > AVR-GCC-Tutorial > Im Abschnitt über die Flash Zugriffe (14.2) Ich versuche mich gerade mit PROGMEM, bin nun allerdings über __flash gestolpert und würde hier direkt umschwenken wollen. Konkret in Verbindung mit einem Menü (für HD44780). Hat da jemand gute Tutorials, Beispielcode oder ähnliches? Bisher habe ich da nicht schönes zur Erklärung gefunden. Das AVR-GCC-Tutorial hier gibt auch nicht so viel her: > Ein Zugriff auf Konstanten im Programmspeicher ist mittels avr-gcc erst > ab Version 4.7 "transparent" möglich. Um Daten aus dem Flash zu lesen, > muss die AVR-Instruktion LPM (Load from Program Memory) erzeugt werden, > bei Controllern mit mehr als 64kiB Flash auch ELMP. Danach geht es um PROGMEM. Da das noch alles Neuland für mich ist, bin ich etwas verloren :-) Gruß Max edit: Wer nach unten scrollt ist klar im Vorteil! Unter "Flash mit __flash und Embedded-C" stehen schonmal interessante Infos. Mal sehen, ob es so besser klappt :). Bin natürlich weiterhin an entsprechenden Infos etc. interessiert. :
Bearbeitet durch User
Gibt es mit diesem neuen Qualifier eigentlich eine Möglichkeit einen String direkt (ohne eine Variable erstellen zu müssen) im Flash abzulegen, also ein Äquivalent zum PSTR() Makro? Edit: Auch ich hätte wohl erstmal genau gucken sollen. Die Antwort findet sich im Wiki und lautet: FSTR(), wobei es trotzdem noch einmal Unterschiede zu PSTR() gibt. So ganz einschätzen kann ich dieses Feature aber noch nicht. Wenn ich das richtig sehe, dann gibt es jetzt drei Möglichkeiten, um eine Funktion zu implementieren, welche Daten aus dem RAM und Flash entgegennehmen kann: - Wie bisher, d.h. jeweils zwei Versionen mit einer "_P" Version, wenn man Daten aus dem Flash lesen möchte, wobei man den Parameter direkt mit dem __flash Qualifier versehen kann und sich dadurch das pgm_read* Gedöns erspart. - Eine Funktion mit einem zusätzlichen Parameter, welcher Auskunft darüber gibt, ob es sich um Daten aus dem Flash handelt. Abhängig davon kann man die Argumente entsprechend Casten. - Verwenden des __memx Addressbereichs. Dadurch werden Zeiger ein Byte länger (24 Byte) und es kann zur Laufzeit festgestellt werden auf welchen Bereich man sich bezieht. Nachteil: Overhead Hat das jemand schon einmal im größeren Maßstab umgesetzt? Würde das alles gerne mal in einem größeren Projekt sehen und wie man die dabei auftretenden Probleme gelöst bekommt. Ich empfand die Lösung über das PROGMEM Attribut zwar nie als wirklich schön (vor allem bei mehrfacher Indirektion muss man sehr viel "Herumtricksen"), aber irgendwie hat man sich über die Jahre dann doch daran gewöhnt ;). Btw: Würde ein solcher Qualifier nicht auf das EEPROM Sinn machen? Mit freundlichen Grüßen, Karol Babioch :
Bearbeitet durch User
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.
|
|