Hallo Ich möchte eine Zahlentabelle die als Binärdatei vorliegt direkt in den Flash eines ATtiny2313 übertragen und dort nutzen. Ich könnte natürlich die Zahlen in eine ASCII Datei konvertieren, Beistriche und Klammern setzten und als header einbinden und dann mit kompilieren. Das ist aber unelegant und ich möchte das nach Möglichkeit vermeiden. Es handelt sich um 16 Bit unsigned integer Zahlen, die Gesamtlänge ist fest vorgegeben. Im RAM und im EEPROM ist wahrscheinlich zu wenig Platz, deshalb müssen die Daten in den Flash. Gibt es eine Möglichkeit die Zahlen einfach hinten an das kompilierte Programm an zu hängen? Zugreifen kann ich dann ja wahrscheinlich mit den Methoden wie hier beschrieben: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29 Der Compiler braucht ja nichts von den Daten zu wissen. Vielen Dank schon mal, mfg Fritz
avrdude kann das doch:
1 | -U <memtype>:r|w|v:<filename>[:format] |
2 | Memory operation specification. |
3 | Multiple -U options are allowed, each request |
4 | is performed in the order specified. |
achso , eben erst gelesen, dass du sie ja ANHÄNGEN willst. Dann müsstest du halt deine Daten an das gelinkte Programm anhängen und dann flashen. Was insofern doof ist, weil du dann nachdenken musst, wo diese Daten dann zur Laufzeit zu finden sind. Ich würde es eher in ein C-Feld verpacken; das Thema wurde hier glaube ich schon mehrfach debattiert? Ich habe mir dafür mal ein Progrämmchen gebaut, das eine beliebige Datei liest und die Initialisierung eines C-Feldes draus macht, das ich dann wiederum per #include in meinen Quelltext einfüge. Aber da scheint jeder seine eigene Variante zu mögen.
Man könnte ein Assembler-Symbol draus machen, dort mit der entsprechenden GCC-Assemblerinstruktion (welche mir jetzt natürlich nicht einfällt, irgendwas von wegen binary-include) den Datenmüll einbinden. Dann alles zusammen durch den Linker und fertig.
Cool, so viele Antworten auf einmal! Danke erstmal. Wie schon gesagt, die Sache mit dem C Feld ist für mich nur eine Notlösung. Am besten gefällt mir die Methode von Martin Thomas mit avr-objcopy. Allerdings ist mir das alles noch eine Spur zu hoch, ich habe ehrlich gesagt keine Ahnung von makefiles, ich muss mich da erst einlesen. Wenn ich das richtig verstanden habe, dann macht mir dieser Befehl aus einem binary file ein object file und setzt zusätzlich Marken, die ich in meinem Programm verwenden kann um auf die Daten zu zu greifen. Soweit, so gut, jetzt muss ich nur noch irgendwie das o-file ans eigentliche Programm anhängen und zum höchsten aller files, dem hex file, "verwurschten", richtig? mfg Fritz
Hallo So ich hab jetzt endlich Zeit gehabt mir das makefile Fragment zu Gemüte zu führen.
1 | $(OBJDIR)/%.o : %.bin |
2 | @echo Converting $< |
3 | @$(OBJCOPY) -I binary -O elf32-avr \ |
4 | --rename-section .data=.progmem.data,contents,alloc,load,readonly,data \ |
5 | --redefine-sym _binary_$*_bin_start=$* \ |
6 | --redefine-sym _binary_$*_bin_end=$*_end \ |
7 | --redefine-sym _binary_$*_bin_size=$*_size_sym \ |
8 | $(<) $(@) |
9 | @echo "extern const char" $(*)"[] PROGMEM;" > $(*).h |
10 | @echo "extern const char" $(*)_end"[] PROGMEM;" >> $(*).h |
11 | @echo "extern const char" $(*)_size_sym"[];" >> $(*).h |
12 | @echo "#define $(*)_size ((int)$(*)_size_sym)" >> $(*).h |
Aber so einige Sachen sind mir noch unklar: 1. Was bedeutet das $(OBJDIR) vor %.o? Ist da ein eigener Ordner für .o files vorgesehen oder wie? 2. Wenn ich diese Regel in mein makefile einfüge kommt das doch in Konflikt mit der Regel die es dort für .o files schon gibt, nähmlich zu kompilieren, oder? Wie kann ich dieses Fragment jetzt in mein makefile integrieren? 3. Die 4 Zeilen am Schluss definieren offenbar ein headerfile. Was ist das für ein headerfile und was muss ich damit machen? In dem wird offenbar ein array deklariert, dass meine Daten enthält, sowie dessen Ende und Länge. Aber warum steht auch hinter Ende und Länge ein [], das sind doch keine arrays? 4. Was ist $(*) und $* und was ist der Unterschied? Vielen Dank schon mal. mfg Fritz
Also ehrlich: C ist eine Notlösung, aber wie man das mit objcopy macht verstehst Du nicht und ein Makefile kannst Du nicht lesen? Dann ist die "Notlösung" wohl eher das Du die Daten als Binärdaten vorliegen hast. Es ist aus meiner Sicht eher eine "Notlösung" die Daten an Compiler und Linker vorbei ranzuklatschen. Aber gut, wat dem eenen sin Uhl....
Hallo, Hrm schrieb: > Also ehrlich: C ist eine Notlösung, aber wie man das mit objcopy macht > verstehst Du nicht und ein Makefile kannst Du nicht lesen? > > Dann ist die "Notlösung" wohl eher das Du die Daten als Binärdaten > vorliegen hast. Es ist aus meiner Sicht eher eine "Notlösung" die Daten > an Compiler und Linker vorbei ranzuklatschen. > > Aber gut, wat dem eenen sin Uhl.... :-)) ich habe schon eine Wave-Datei per php-Script auf meinem Webserver in eine asm-include-Datei konvertiert weil gerade nichts anderes zur Hand war. PS: war eine Notlösung, hat ca. 20min gedauert, keine 5 Tage ;-) und liegt immernoch dort parat... Gruß aus Berlin Michael
Fritz schrieb: > 1. Was bedeutet das $(OBJDIR) vor %.o? Ist da ein eigener Ordner für .o > files vorgesehen oder wie? Ja. Wenn es bei dir anders ist, muss du das entsprechend ändern. > 2. Wenn ich diese Regel in mein makefile einfüge kommt das doch in > Konflikt mit der Regel die es dort für .o files schon gibt, nähmlich zu > kompilieren, oder? Nein, denn es ist eine ".bin nach .o"-Regel. Ich nehme mal nicht an, dass deine zu kompilierenden Files auch die Endung .bin haben, oder? > 3. Die 4 Zeilen am Schluss definieren offenbar ein headerfile. Was ist > das für ein headerfile und was muss ich damit machen? "Müssen" musst du gar nichts damit. Es ist nur ein Beispiel, wie du dann die Symbole verwenden kannst. > In dem wird > offenbar ein array deklariert, dass meine Daten enthält, sowie dessen > Ende und Länge. Aber warum steht auch hinter Ende und Länge ein [], das > sind doch keine arrays? Objcopy definiert nur Symbole, also quasi nur Adressen. Welchen Typ die Daten an dieser Adresse haben obliegt der Interpretation des Anwenders.
1 | extern const char BEISPIEL_size_sym[]; |
Bedeutet hier einfach nur: Unbestimmte Anzahl Bytes an der Adresse BEISPIEL_size_sym. Das darauffolgende #define interpretiert dann diese "Bytes unbestimmter Anzahl" als int. Man könnte auch gleich schreiben:
1 | extern const int BEISPIEL_size_sym; |
Da deine Daten 16 Bit unsigned Zahlen sind, kannst du für die Daten auch schreiben:
1 | extern const uint16_t BEISPIEL[] PROGMEM; |
Aber Vorsicht: das size-Symbol bleibt natürlich die Größe in Bytes.
BTW: Haben diese Zahlen denn auch die richtige Endianness?
> 4. Was ist $(*) und $* und was ist der Unterschied?
Das ist die Namensbasis, für die die Regel gerade angewendet wird. Wenn
gerade BEISPIEL.bin in BEISPIEL.o überführt wird, ist es "BEISPIEL". Die
Klammern dienen dazu, den $-Part von nachfolgenden Buchstaben eindeutig
zu trennen.
Vielen Dank @ Stefan Ernst!! Für die ausführliche Beantwortung aller meine Fragen, das hat mir sehr geholfen :) zwecks Endianness: ich habe mich mittlerweile dazu entschlossen 8 Bit Zahlen zu verwenden, damit ist das hinfällig. Vielen Dank nochmal, falls mir noch was einfällt meld ich mich wieder. mfg Fritz
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.