Datum: 03.05.2008 16:43
Hallo,
bin gerade dabei ein bestehendes µC-Programm eines ATMEL-Controllers, in
C-Code, umzuschreiben um es auf einem anderen µC laufen zu lassen. Dabei
bin ich auf folgendes Makro gestoßen, welches mir Verständnisprobleme
bereitet:
#define FlashConst(s) (__extension__({static unsigned char __c[]
PROGMEM =
(s); &__c[0];}))
Ist jemand in der Lage mir diesen Qellcode zu erläutern?
Danke im voraus...
Datum: 03.05.2008 17:21
Naja, als erstes solltest du eine beispielhafte Makroersetzung durchführen. Nehmen wir mal an, du hast irgendwo:
cp = FlashConst("Hello, world!");
|
dann ergibt sich daraus:
cp = (__extension__({static unsigned char __c[] __attribute__((__progmem__)) = ("Hello, world!"); &__c[0];}))
|
Dabei hast du folgende Teile:
__extension__ |
markiert den nachfolgenden Konstrukt als eine Erweiterung (des GCC) zum C-Standard. Damit wird es bei -std=c89 oder -std=c99 nicht angewarnt, weil dem Compiler explizit mitgeteilt wird, dass sich der Entwickler darüber im Klaren ist, dass der Konstrukt nicht dem Standard entspricht.
static unsigned char __c[] |
eine normale statische Variable, die lokal zum soeben angelegten Block ist.
__attribute__((__progmem__)) |
eine Sonderanweisung an den GCC, die damit deklarierte Variable statt im SRAM des AVR im Flash-ROM unterzubringen. Danach folgt eine gewöhnliche Initialisierung dieser Variable mit der übergebenen Zeichenkettenkonstanten.
&__c[0]; |
Es wird die Adresse des ersten Elements der statischen Variablen gebildet und als Ausdruck verwendet. Da dieser Ausdruck der letzte innerhalb des umschließenden Blocks ist, gibt der Block dessen Wert (ähnliche der “return”-Anweisung einer Funktion) zurück, d. h. er darf auf der rechten Seite einer Zuweisung benutzt werden. Die Möglichkeit, dass ein Block einen Wert zurückgeben kann, ist die eigentliche Spracherweiterung des GCC, für die einleitend das __extension__-Schlüsselwort notwendig geworden ist. Ob andere Compiler über ähnliche Mechanismen verfügen wie GCC hier, lässt sich nicht ohne weiteres sagen. Ohne C-Spracherweiterungen ist die entsprechende Funktionalität nicht implementierbar (zumindest nicht auf diese Weise), daher wurde dieser vergleichsweise umständliche Konstrukt gewählt.
Datum: 03.05.2008 19:49
Ich könnte also demnach auch eine Funktion definieren, mit einem "unsigned char"-Array und einem Zeiger in dem die Adresse des ersten Elementes dieses Arrays gespeichert wird als Parameter?
Datum: 03.05.2008 22:25
Die Frage verstehe ich so nicht... Erstens, nicht "unsigned char", sondern "char". Es handelt sich um Zeichenkettenkonstanten, und die sind per definitionem immer vom Typ char[], nicht signed char[], auch nicht unsigned char[]. Zweitens schrieb ich doch: mir ist keine Möglichkeit bekannt, die gleiche Funktionalität auf irgendeine Weise mit Mitteln zu erreichen, die komplett vom C-Standard abgedeckt sind.
Datum: 04.05.2008 12:31
Tut mir leid, ich bin absoluter Anfänger im Thema µC und im Programmieren mit C. Mir würde es ausreichen wenn ich eine Funktion hätte die als Argument eine Zeichenkette erwartet und die Adresse des ersten Elements dieser Kette als Rückgabewert dient.- Ich hoffe das ist jetzt einigermaßen verständlich. Aber im Original-Quelltext steht
unsigned char |
.
Datum: 04.05.2008 12:40
> Mir würde es ausreichen wenn ich eine Funktion hätte die als Argument > eine Zeichenkette erwartet und die Adresse des ersten Elements dieser > Kette als Rückgabewert dient. Dazu brauchst du keine Funktion. Wenn du das Array verwendest, wird automatisch die Adresse des ersten Elements dafür eingesetzt. > Aber im Original-Quelltext steht > unsigned char Funktionieren wird's vermutlich trotzdem, aber richtig ist eben eigentlich nicht.
Datum: 04.05.2008 19:37
Rolf Magnus wrote: > Dazu brauchst du keine Funktion. Wenn du das Array verwendest, wird > automatisch die Adresse des ersten Elements dafür eingesetzt. Allerdings hat der Makro im Original halt was anderes getan: er hat den String im Flash-ROM platziert und dann dessen Adresse ermittelt. Wenn dein Zielprozessor sowas nicht braucht, dann kannst du den Makro wahrscheinlich durch einen Nullmakro ersetzen:
#if defined __AVR__ # define FlashConst(s) // hier das, was du schon kennst #elif defined __FOOBAR__ // Test für Zielprozessor FOOBAR # define FlashConst(s) (s) #else # error "Unknown target CPU" #endif |
Antwort schreiben
Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
- Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
- Aussagekräftigen Betreff wählen
- Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
- Groß- und Kleinschreibung verwenden
- Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
- JPEG-Dateien (.jpg) nur für Fotos verwenden, Schaltpläne, Screenshots usw. als PNG oder GIF anhängen
Formatierung (mehr Informationen...)
- [c]C-Code[/c]
- [avrasm]AVR-Assembler-Code[/avrasm]
- [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
- [math]Formel in LaTeX-Syntax[/math]
- [[Titel]] - Link zu Artikel


