Hallo, ich habe mehrere uint8_t-Arrays im PROGMEM, die eine Art Bytecode für eine Ablaufsteuerung enthalten. Nun möchte innerhalb eines solchen Arrays den Pointer auf ein anderes Array ablegen. Wegen des uint8_t muss ich den noch in High- und Low-Byte zerlegen: #include <inttypes.h> #include <avr/pgmspace.h> uint8_t PROGMEM prog_thread1[] = { 1, 2, 3 }; uint8_t PROGMEM prog_main[] = { 42, // ... beliebig viele weitere Bytes (uint8_t)(((uint16_t)prog_thread1) & 0xff), (uint8_t)(((uint16_t)prog_thread1) >> 8), }; avr-gcc -c -mmcu=atmega16 foo.c foo.c:7: error: initializer element is not constant foo.c:7: error: (near initialization for 'prog_main[0]') foo.c:8: error: initializer element is not constant foo.c:8: error: (near initialization for 'prog_main[1]') Was ist denn an dem prog_thread1 Pointer nicht konstant? Hat jemand eine Idee für einen Workaround mit dem avr-gcc (Version 4.2.2) oder weiß wie man das richtig macht?
Ich glaube ich komme langsam dahinter was hier passiert. Vielleicht kann mir jemand meine Vermutung bestätigen: Für den Compiler ist die Adresse von prog_thread1 zwar konstant, aber nur innerhalb des Object-Files bekannt. Die Adresse schreibt er in die Symboltabelle. Die wirkliche Adresse setzt aber am Ende der Linker ein und der muss sie u.a. aus dem Eintrag der Symboltabelle berechnen. Die logischen Verknüpfungen zur Trennung in Hi und Lo Byte (& und >>) müssen auf die vom Linker berechnete Adresse angewendet werden. Der Compiler kann das noch nicht machen. Der Linker ist für sowas (verständlicherweise) nicht ausgelegt. Wenn ich das Array, in das ich die Adresse einfügen will, zu einem uint16_t mache, entfallen die & und >> Operationen und es funktioniert (danke Jörg): uint8_t prog_thread1[] = { 1, 2, 3 }; uint16_t prog_main[] = { 42, (uint16_t)prog_thread1 }; Das möchte ich allerdings vermeiden, da ich so meinen Kommandosatz auf 16 Bit umstellen muss und wegen einer Reihe von 3 Byte Befehlen reichlich Verschnitt hätte. Hat jemand eine Idee, wie man das mit 8 Bit Arrays hinbekommen kann? Mirko
Notfalls halt nicht als Initialisierung, sondern gleich nach Programmstart mit einer normalen Zuweisung?
Die Arrays sind im Flash. Das PROGMEM hatte ich im ersten Beitrag noch drin, im zweiten dann aber vergessen.
Vielleicht wäre es auch ein Weg, in prog_main nicht Adressen sondern Indizes zu speichern?
Ja, die Idee hatte ich auch schon. So in der Art: #include <inttypes.h> #include <avr/pgmspace.h> uint8_t prog_thread1[] = { 1, 2, 3 }; prog_uint8_t *thread_addresses[] = { prog_thread1 /* , weitere Adressen */ }; uint8_t prog_main[] = { 42, 0 /* Index ins thread_addresses[] Array */ }; Mein Programm muss dann über thread_addresses[i] die Adresse holen. Es ist zwar nicht so schön, das thread_addresses-Array noch extra pflegen zu müssen, erscheint mir aber noch praktikabel. Ich glaube so werde ich es machen. Danke, wieder was gelernt :-) Mirko
Mirko Kaffka schrieb: > Die logischen Verknüpfungen zur Trennung in Hi und Lo Byte (& und >>) > müssen auf die vom Linker berechnete Adresse angewendet werden. Der > Compiler kann das noch nicht machen. Der Linker ist für sowas > (verständlicherweise) nicht ausgelegt. Ja, ich denke auch, dass das das Problem ist. Der Linker von RSX-11 (dort "taskbuilder" genannt) auf der PDP-11 konnte sowas. ;-) Die haben im Objektcode einen RPN-Faden mit Berechnungen ablegen können, die auf das Symbol anzuwenden sind bei der Relokation. Ich hatte dafür mal einen Disassembler geschrieben und hatte die Ehre, aus dem RPN-Faden eine algebraische Darstellung zu erfinden. :) Der Unix-Linker kann das nicht. Alles, was der machen soll, muss als "relocation record type" zwischen Assembler und Linker vereinbart worden sein. In diesem Falle hier bedürfte es offenbar sogar noch einer Vereinbarung zwischen Compiler und Assembler, wie man sowas auf Assembler-Niveau ausdrücken soll.
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.