Hallo,
Anfängerfrage:
Kann mir jemand sagen, wie man ein Datenpaket im hinteren Teil des
Progammspeichers eines AVRs (vorliegend M32) unterbringen kann, ohne
jedes Mal mit einem Hex-Editor hantieren zu müssen?
Bis jetzt habe ich es so gemacht: Programm geschrieben (ca. 4Kb), in
hex-Datei umgewandelt, mit einem Hex-Editor geöffnet, in den hinteren
Bereich der hex-Datei die Daten eingefügt (ca. 24Kb), das ganze wieder
abgespeichert und dann gebrannt. Das ist mir aber auf Dauer zu
umständlich.
Gibt es die Möglichkeit, die Daten dem C-Programm direkt anzuhängen,
damit man nicht nach jeder kleinen Programmvänderung die ganze
Hex-Editor-Operation komplett durchführen muss?
Ich benutze übrigens AVR-Studio.
Μαtthias W. schrieb:> Hi>> In ein C-Array umwandeln (z.B. mit einem Hexeditor wie> http://mh-nexus.de/en/hxd/) und dann einfach mitcompilieren.>> Matthias
Meinst du damit sowas, wie Wayne geschrieben hat (Array aus Strings im
Flash-Speicher) oder ist deine Methode einfacher?
Gibt es keine lib, die die Daten aus einer beliebigen Datei beim
Compilieren direkt 1:1 in den Programmspeicher schreiben kann?
Bertrand_H schrieb:> Gibt es keine lib, die die Daten aus einer beliebigen Datei beim> Compilieren direkt 1:1 in den Programmspeicher schreiben kann?
Alles was du brauchst, ist in deinem C-File so etwas
1
....
2
3
uint8_tMyData[]PROGMEM={
4
5
// und hier dann deine Daten, zb in Hex-Form
6
0x10,0x20,0x30,.....
7
};
8
9
....
und du hast sie in einer Form, dass sie vom C-Compiler mitkompiliert
werden
Wie kriegst du sie dort hin?
Du brauchst irgend ein Tool welches dir aus deinem Datenfile, diese Form
erzeugt.
Für einzelne, spezielle Datenformate (Bilder, Sound) gibt es sicherlich
Programme, die so etwas machen. Für den allgemeinen Fall ... kenne ich
keines, ausser wie Matthias schon andeutete einen Hex-Editor, der so ein
Format erzeugen kann.
Aber: Es ist doch keine Hexerei, sich selber so ein Progrmm zu
schreiben, welches ein beliebiges Datenfile hernimmt und es in ASCII-Hex
Form wieder ausdumpt. Ist doch nur eine Fingerübung, und ist schneller
geschrieben, als du in Google suchen kannst
PS:
Man kann das ja im C-File auch so machen
1
....
2
3
uint8_tMyData[]PROGMEM={
4
#include"MyData.h"
5
};
6
7
....
und das angesprochene Werkzeug, erzeugt dann den Hex-Dump der Daten in
eine Datei MyData.h
1
0x10, 0x20, 0x30, ...
welche dann beim Compilieren vom Compiler eingebunden wird.
Also: ran an die Buletten, einen Daten-Dumper geschrieben.
Man braucht nicht für jeden Mückenfurz "eine fertige Lib". Manchmal
macht man sich eben seine Hilfs-Werkzeuge am PC selber. Dafür ist man ja
schliesslich Softwareentwickler und nicht Powerpoint-Zusammenklicker.
Mir kommt grade noch eine andere Idee:
theoretisch müsste es doch möglich sein, die Daten ein Mal im hinteren
Teil des Programmspeichers unterzubringen und bei Änderungen des
Programms immer nur den vorderen Teil des Flash Speichers neu zu
beschreiben...
Bertrand_H schrieb:> Mir kommt grade noch eine andere Idee:> theoretisch müsste es doch möglich sein, die Daten ein Mal im hinteren> Teil des Programmspeichers unterzubringen und bei Änderungen des> Programms immer nur den vorderen Teil des Flash Speichers neu zu> beschreiben...
Machs richtig und hör auf dir Gedanken über solche Krücken zu machen. In
der Zeit in der du hier rumlametierst, hättest du schon längst den 8
Zeiler am PC für ein entsprechendes Hilfs-Werkzeug selber geschrieben.
Oder du benutzt avr_objcopy wie in diesem Forumsbeitrag gezeigt:
Beitrag "Re: Binärdatei in C-Quelltext umwandeln" Das hätte den
Vorteil, das die eingefügten Daten ohne umständliche Verenkungen aus dem
C-Programm angesprochen werden können und es somit egal ist, auf welcher
Adresse die Daten im Programmspeicher liegen. Das Einbinden kann man ins
Makefile einbauen.
Μαtthias W. schrieb:> Nicht für jeden <zitat>Mückenfurz</zitat> muss man ein eigenes Programm> schreiben :-)
Ja, wenn man natürlich in seinem Werkzeugkasten was passendes vorrätig
hat, kann die Mücke pfurzen soviel sie will :-)
(Mich hat nur geärgert, dass nach einer knappen Stunde das 'Problem'
immer noch nicht gelöst ist und anstatt die 10 Minuten für ein
Hilfswerkzeug zu investieren, lieber über selektives Flashen nachgedacht
wird)
Vorgehensweise bringt nichts, wenn die Progammiersoftware Chip Erase vor
Flash-Programmierung auslöst, üblich bei ISP. In einem Bootloader kann
man jedoch einen Schreibschutz implementieren, der den Bereich nur
einmalig schreibt, wenn vorher leer.
Hi
SF schrieb:> Oder du benutzt avr_objcopy wie in diesem Forumsbeitrag gezeigt:> Beitrag "Re: Binärdatei in C-Quelltext umwandeln" Das hätte den
objcopy ist natürlich auch noch eine Möglichkeit. Leider ist die
Beschreibung dort für einen AVR nicht ganz vollständig da die Daten bei
der beschriebenen Methode im .data landen was dazu führt das sie RAM
belegen was ja nicht Sinn und Zweck der Aktion ist. Der korrekte Aufruf
wäre:
Hallo,
Danke für die vielen Antworten! Das Projekt läuft nebenher und hat keine
akute Eile, soll nur in den nächsten Tagen irgendwann fertig werden (bin
im Moment noch mit was anderem beschäftigt).
Datenformat umschreiben wäre nicht das Problem.
das sieht ja schon mal ganz interessant aus:
>uint8_t MyData[] PROGMEM = {>> // und hier dann deine Daten, zb in Hex-Form> 0x10, 0x20, 0x30, .....>};
was für eine lib brauche ich da und wie wird die startadresse der daten
im flash-speicher festgelegt?
@matthias:
>Ich hab mal einen Artikel im Wiki angefangen.>http://www.mikrocontroller.net/articles/Bin%C3%A4r...>>Muss jetzt aber mal kurz weg. Ich stell ihn dann heute Mittag fertig.
Tolle Idee! Das wäre super!
Μαtthias W. schrieb:> Artikel> http://www.mikrocontroller.net/articles/Bin%C3%A4r...> ist jetzt mal soweit fertiggestellt.
Hi Mαtthias, Danke!
Ok, ich werd das morgen mit dem "Einfügen als C-Array" probieren...
Mir ist allerdings noch nicht ganz klar, wie ich konkret die mit dem
Hex-Editor erzeugte C-Array-Datei ins Programm einbinde.
>Beim avr-gcc ist noch darauf zu achten das die Daten, falls gewünscht, im >Programmspeicher und nicht im SRAM landen.
Und wie macht man das?
Bertrand_H schrieb:> Mir ist allerdings noch nicht ganz klar, wie ich konkret die mit dem> Hex-Editor erzeugte C-Array-Datei ins Programm einbinde.
Mach die Datei auf. Das ist einfach nur eine Textdatei.
Was steht drinnen?
WEnn du sie von Hand erzeugen würdest, wie würdest du die dann
einbinden?
>>Beim avr-gcc ist noch darauf zu achten das die Daten, falls gewünscht, im>>Programmspeicher und nicht im SRAM landen.> Und wie macht man das?
Ich glaube, das ist jetzt zum 3.ten mal in diesem Post, dass ich dir den
Link zum AVR-GCC-Tutorial, Abschnitt "Flash-Speicher" poste. Liest du
den jetzt bitte endlich einmal durch?
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29
Und wenns geht vom Anfang des Kapitels bis zu seinem Ende. Inklusive der
Subkapitel. Wenn du dann an Textpassagen kommst, die ziemlich
offensichtlich nichts mehr mit Flash zu tun haben, kannst du aufhören.
Und nicht einfach nur drüberscrollen. Lesen!
So, das Erzeugen der .c-Datei hat schon mal geklappt, ist ja wirklich
simpel mit HxD.
>WEnn du sie von Hand erzeugen würdest, wie würdest du die dann>einbinden?
Ich würde den erzeugten Text per Makieren rüberkopieren, ans
Programmende packen und dann die Startadresse eintragen. Werde das
morgen mal testen.
Die Daten landen auch im Speicher, aber nicht als uint8_t, sondern als
uint16_t (=2bytes, hb = 0x00).
Kein Wunder, dass diese Warnung auftritt:
>>warning: initialization makes pointer from integer without a cast
Die Frage ist, wie mache ich dem Programm klar, dass die Array-Daten als
uint8_t abgelegt werden sollen?
Bertrand_H schrieb:> PGM_P array[36] PROGMEM =
Warum PGM_P?
> Die Daten landen auch im Speicher, aber nicht als uint8_t, sondern als> uint16_t (=2bytes, hb = 0x00).
Ja logisch. Genau das hast du ja geschrieben.
Du hast kein Array von Bytes angelegt. Du hast ein Array von Pointern
angelegt.
> Kein Wunder, dass diese Warnung auftritt:>>>warning: initialization makes pointer from integer without a cast
Richtig.
Das ist kein Wunder.
Aber aus einem ganz anderen Grund.
> Die Frage ist, wie mache ich dem Programm klar, dass die Array-Daten als> uint8_t abgelegt werden sollen?
Sag mal.
Warum streubst du dich so dermassen, endlich einmal einen Blick ins
Tutorial zu werfen? Klick auf den Link.
Gleich im ersten Abschnitt, in der Übersicht über das Kapitel, wird ein
Array aus Bytes (uint8_t) ins Flash gelegt
1
constuint8_tpgmFooByteArray1[]PROGMEM={18,3,70};
Und? Ist das jetzt so schwer, das auf deine Daten anzuwenden?
Bertrand_H schrieb:> Ich würde den erzeugten Text per Makieren rüberkopieren, ans> Programmende packen
Wozu?
Mittels #include kann man wunderbar andere Dateien zum compilieren
einbinden
> und dann die Startadresse eintragen.
Wozu?
Überlass das doch dem Compiler/Linker die Daten irgendwo in den Speicher
zu packen! Ist doch völlig egal, wo die Daten tatsächlich hinkommen,
Hauptsache dein Programm kann sie wiederfinden und alles hat zusammen
Platz im Flash.
Datei: daten.txt
Bertrand_H schrieb:> PGM_P array[36] PROGMEM => [...]> Die Daten landen auch im Speicher, aber nicht als uint8_t, sondern als> uint16_t (=2bytes, hb = 0x00).> [...]> Die Frage ist, wie mache ich dem Programm klar, dass die Array-Daten als> uint8_t abgelegt werden sollen?
Schau mal, was Du selbst in
Beitrag "Re: Datenpaket in Programmspeicher - C"
zitiert hast. Welches Zauberwort steht da vor MyData[]?
Und wozu willst Du die "Startadresse" wissen/bestimmen? Du greifst doch
einfach über pgm_read_byte(&array[i]) drauf zu!
Gruß,
Frank
P.S.
Boah, diese Ignoranz ist unglaublich. Wie es geht, steht doch im
entsprechenden Tutorial-Kapitel, welches Karl-Heinz schon mehrfach hier
erwähnt hat. Karl-Heinz hat wahrscheinlich schon ein Stück aus seinem
Tisch ausgebissen vor Verzweiflung...
Frank M. schrieb:> erwähnt hat. Karl-Heinz hat wahrscheinlich schon ein Stück aus seinem> Tisch ausgebissen vor Verzweiflung...
Davon kannst du ausgehen.
Ich dachte ursprünglich, dass man ihm lediglich die Idee eines #includes
nahe bringen muss und der Rest steht ohnehin mehr oder weniger 1:1 im
Tutorial. Aber so dermassen das Tutorial ignorieren, ts, ts.
Das ganze ist eine Sache auf 10 Minuten, selbst wenn man noch nie mit
Daten im Flash gearbeitet hat. Und jetzt gehts schon in die Verlängerung
des 5.ten Tags.
Edit: Was heißt ignorieren.
Die ganze Vorgehensweise ist in diesem Thread schon am ersten Tag mehr
oder weniger komplett aufgezeigt worden. Selbst ein Blinder hätte das
Greifen können.
Ich bekenne mich in allen genannten Punkten für schuldig!
Aber bitte trotzdem keine Stücke aus Tischen beißen!!!
Ok, es gibt Fortschritte:
const uint8_t pgmFooByteArray1[] PROGMEM = { "Datenkram" }
bringt immerhin schon mal knapp 32kb von meinem 60kb großen Datenpaket
in den Speicher:
>>Build started 31.8.2010 at 10:27:46>>avr-gcc -mmcu=atmega128 -Wl,-Map=speichi.map speichi.o -o speichi.elf>>avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature>>speichi.elf speichi.hex>>avr-objdump -h -S speichi.elf > speichi.lss>>>>AVR Memory Usage>>---------------->>Device: atmega128>>>>Program: 32516 bytes (24.8% Full)>>(.text + .data + .bootloader)>>>>Data: 0 bytes (0.0% Full)>>(.data + .bss + .noinit)>>>>>>Build succeeded with 0 Warnings...
(noch ohne es wie von Karl Heinz vorgeschlagen mit #include "daten.txt"
zu machen, die Idee ist aber super und das wird auf jeden Fall hinterher
so gemacht!)
Wenn ich allerdings mehr Daten ins Array packe, z.B. 40kb, dann
erscheint folgende Fehlermeldung:
Build started 31.8.2010 at 10:51:13
>>avr-gcc -mmcu=atmega128 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char>>-funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT speichi.o>>-MF dep/speichi.o.d -c ../speichi.c>>../speichi.c:3240: error: size of array is too large>>../speichi.c:3240: error: expected ',' or ';' at end of input>>make: *** [speichi.o] Error 1>>Build failed with 2 errors and 0 warnings...
Ich tippe darauf, dass der K(n)ack bei (32kb + 1b) liegt. Im Tutorial
finde ich im Zusammenhang "Programmspeicher" nichts dazu (ja,
reingeguckt).
Nebenbei fällt auf, dass der von mir benutzte Controller ein M644 ist,
habe ich bei der Projektanlegung korrekt eingestellt und auch noch mal
überprüft.
Nach dem Built wird aber "avr-gcc -mmcu=atmega128" angezeigt (s.o.).
Weiß jemand, warum?
Bertrand_H schrieb:> Ich tippe darauf, dass der K(n)ack bei (32kb + 1b) liegt. Im Tutorial> finde ich im Zusammenhang "Programmspeicher" nichts dazu (ja,> reingeguckt).
Das kann schon sein.
Wenn du deinen Mega mit Daten vollpumpst, wirst du auch in eventuell in
dieses Problem laufen
Beitrag "pgm_read_byte(); --> Nur für Lower 64k Flash (mega128)???"> Nebenbei fällt auf, dass der von mir benutzte Controller ein M644 ist,> habe ich bei der Projektanlegung korrekt eingestellt und auch noch mal> überprüft.> Nach dem Built wird aber "avr-gcc -mmcu=atmega128" angezeigt (s.o.).> Weiß jemand, warum?
Keine Ahnung.
Habs gerade bei mir ausprobiert:
Neues Projekt angelegt, C ausgewählt, Mega644 ausgewählt, compiliert.
Der Compiler wird vom AVR-Studio mit
avr-gcc.exe -mmcu=atmega644 -Wall -gdwarf-2 -Os -std=gnu99
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP
-MT dffa.o -MF dep/dffa.o.d -c ../dffa.c
aufgerufen. Also alles korrekt.
Hallo, Danke für die Antwort! Ich habe grade parallel dazu folgende
Zeilen verfaßt:
...so, das Problem mit dem "falschen" Prozessor ist jetzt behoben (unter
"Configurations Optiones" noch mal von Hand eingestellt), der M644 wird
nun nach dem Compilieren korrekt angezeigt.
Ein Blick auf "Memory Settings" unter "Configurations Optiones" zeigt,
dass dort der M664 mit einem Flash Size von 0x8000 angegeben ist
(32.768bytes).
Also kein Wunder, dass das 60kb große Daten-Array nicht passt.
Im Datenblatt findet sich oben die Beschreibung 8-Bit AVR
microcontroller with 64k bytes flash und weiter unten unter AVR Memories
"...the flash is organized as 32/64 x 16 ...", was bei mir den Verdacht
aufwirft, dass der Flash Speicher in zwei Bereiche zu 32kb unterteilt
ist.
Karl heinz Buchegger schrieb:>> Nebenbei fällt auf, dass der von mir benutzte Controller ein M644 ist,>> habe ich bei der Projektanlegung korrekt eingestellt und auch noch mal>> überprüft.>> Nach dem Built wird aber "avr-gcc -mmcu=atmega128" angezeigt (s.o.).>> Weiß jemand, warum?>> Keine Ahnung.> Habs gerade bei mir ausprobiert:> Neues Projekt angelegt, C ausgewählt, Mega644 ausgewählt, compiliert.
Hatte vielleicht mit der zu(?) großen Datenmenge zu tun, dass
automatisch ein größerer Controllertyp eingestellt wurde!?!
>Wenn du deinen Mega mit Daten vollpumpst, wirst du auch in eventuell in>dieses Problem laufen>>Beitrag "pgm_read_byte(); --> Nur für Lower 64k Flash (mega128)???"
Bei einem Speicher >64kb macht die Aufteilung natürlich Sinn, um die
Speicheradressen handlich zu halten.
Aber beim 644 mit seinen grade mal 64kb wird das auch so gemacht? Gibt
es da irgendwo im Tutorial einen Hinweis zu, den ich überlesen habe?
Bertrand_H schrieb:>> Keine Ahnung.>> Habs gerade bei mir ausprobiert:>> Neues Projekt angelegt, C ausgewählt, Mega644 ausgewählt, compiliert.>> Hatte vielleicht mit der zu(?) großen Datenmenge zu tun, dass> automatisch ein größerer Controllertyp eingestellt wurde!?!
Nein.
Mit Sicherheit nicht.
>> Aber beim 644 mit seinen grade mal 64kb wird das auch so gemacht? Gibt> es da irgendwo im Tutorial einen Hinweis zu, den ich überlesen habe?
Nein.
Es wird vorausgesetzt, dass jemand der mit derartigen Boliden
programmiert, weiß was er tut :-)
Karl heinz Buchegger schrieb:> Nein.> Es wird vorausgesetzt, dass jemand der mit derartigen Boliden> programmiert, weiß was er tut :-)
Na da hab ich mir ja was aufgeladen ;)
Wie würdest du denn (grob umrissen) die 60kb in den Boliden packen?
Bertrand_H schrieb:> Karl heinz Buchegger schrieb:>> Nein.>> Es wird vorausgesetzt, dass jemand der mit derartigen Boliden>> programmiert, weiß was er tut :-)>> Na da hab ich mir ja was aufgeladen ;)>> Wie würdest du denn (grob umrissen) die 60kb in den Boliden packen?
auf 2 oder 3 mal und hoffen das der Compiler schon weiß wie das geht :-)
Karl heinz Buchegger schrieb:> auf 2 oder 3 mal und hoffen das der Compiler schon weiß wie das geht :-)
Na das ist doch eine Aussage ;-)
Ich bin dann mal testen (Internetrechner != Programmierrechner) ...
Ich hoffe, man kann die Einsen und Zweien so an die Variablen anhängen,
wie im Programm gezeigt, z.B. hier:
value1 = pgm_read_byte( &pgmDaten1[i]
^da
Wie viele Prozessortakte braucht der Controller eigentlich für diesen
Befehl "value1 = pgm_read_byte( &pgmDaten1[i] );"?
Bertrand_H schrieb:> Wenn ich allerdings mehr Daten ins Array packe, z.B. 40kb, dann> erscheint folgende Fehlermeldung:>> Ich tippe darauf, dass der K(n)ack bei (32kb + 1b) liegt. Im Tutorial> finde ich im Zusammenhang "Programmspeicher" nichts dazu (ja,> reingeguckt).
Sollte daran liegen das der maximal Arrayindex in C INT_MAX - 1 ist. Das
ist beim AVR dann 32767.
Matthias