Forum: Compiler & IDEs größere Daten-Dateien im C-Projekt


von Christoph M. (mchris)


Lesenswert?

Mittlerweile haben die Mikrocontroller ja Speichergrößen im 
Megabyte-Bereich. Wie bindet man am besten größere Datenmengen wie z.B. 
Bilder oder Sounds in ein C-Projekt ein?
Die Methode Byte-Array scheint mir auf Grund der Dateigröße nicht 
geeignet.

: Bearbeitet durch User
von Dergute W. (derguteweka)


Lesenswert?


von Michael B. (laberkopp)


Lesenswert?

Windows wählt den Weg der Ressourcen, eine dazugelinkte RES Datei und 
Zugriffsfunktionen z.B. für BITMAPs.

Diese Struktur gibt es für den uC nicht, könnte man aber 
hinprogrammieren.

Aber wozu, wenn sowieso alles statisch geladen ist, dann tut es auch 
eine statische Variable.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Christoph M. schrieb:
> Wie bindet man am besten größere Datenmengen wie z.B.
> Bilder oder Sounds in ein C-Projekt ein?

An C23: #embed

https://en.cppreference.com/w/c/preprocessor/embed

von Christoph M. (mchris)


Lesenswert?

Dergute W. (derguteweka)
>https://www.burtonini.com/blog/2007/07/13/embedding-binary-blobs-with-gcc/
Johann L. (gjlayde)
>An C23: #embed
>https://en.cppreference.com/w/c/preprocessor/embed

Das sind schon mal sehr interessante Links. Ich will Sound-Dateien bei 
Controllern wie ESP32 oder PiPico einbinden.
Bei beiden verwende ich ein Arduino-Framework.
Beim PiPico
https://github.com/earlephilhower/arduino-pico
Dort wird es spannend ob die verwendete gcc-Version schon "C23: #embed" 
kann und die Dateipfade hinhauen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Es gibt auch den Artikel "Binäre Daten zum Programm hinzufügen" im 
Wiki.

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Christoph M. schrieb:
> Die Methode Byte-Array scheint mir auf Grund der Dateigröße nicht
> geeignet.

Solange du das Array mit einem Script generierst und dein Build-System 
die generierte Datei aktuell hält ist's eigentlich egal.

Dergute W. schrieb:
> https://www.burtonini.com/blog/2007/07/13/embedding-binary-blobs-with-gcc/

Ist schon ein bisschen peinlich dass der Dude es nicht schafft auf der 
Kommandozeile ein \0 an den Text anzuhängen um aus ihm einen gültigen C 
String zu machen
1
printf '\0' >> foo.txt

Man sollte auch noch sagen dass sein Vorschlag eventuell 
"_binary_foo_txt_size" zu nehmen meines Wissens nicht mehr in allen 
Umgebungen funktioniert. Das hat was damit zu tun dass das Symbol, 
obwohl es als absolut definiert ist, unter manchen Bedingungen trotzdem 
relocated wird.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Hannes J. schrieb:
> Christoph M. schrieb:
>> Die Methode Byte-Array scheint mir auf Grund der Dateigröße nicht
>> geeignet.
>
> Solange du das Array mit einem Script generierst und dein Build-System
> die generierte Datei aktuell hält ist's eigentlich egal.

Ein Problem davon ist dass solche C-Dateien mit riesigen Arrays ziemlich 
lange zum Kompilieren brauchen, außer man definiert es als 
String-Literal statt als Array, da muss man aber höllisch mit 
Escape-Sequencen aufpassen (GIMP macht(e) es z.B. falsch beim 
XPM-Export). Die Source-Datei ist dann gern um ein Vielfaches größer als 
die Binärdatei. Der Weg über "ld" oder "objcopy" ist da eleganter und 
viel schneller, weil die Binärdaten einfach nur kopiert und mit einem 
ELF-Header versehen werden.

Hannes J. schrieb:
> Das hat was damit zu tun dass das Symbol,
> obwohl es als absolut definiert ist, unter manchen Bedingungen trotzdem
> relocated wird.

Man könnte "size" auch im Linkerscript des finalen Link-Vorgangs als 
Differenz von Ende-Anfang definieren, dann wird da nix mehr relokiert.

: Bearbeitet durch User
von Daniel A. (daniel-a)


Angehängte Dateien:

Lesenswert?

Ich würde auch einfach mit "xxd -i" .c Dateien daraus erstelen, und noch 
passende .h Dataien.
Einfach in ein makefile target reinpacken, und das geht alles ganz 
automatisch (siehe Anhang).

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Ein meines Erachtens sehr eleganter Weg, der vor allem ohne irgendwelche 
Dateikonvertierungen und komische Quelltextkonstrukte auskommt, ist eine 
Definition im entsprechenden Linkerskript. Das ist meines Erachtens auch 
deswegen die semantisch korrekte Stelle, da dort ja auch für die 
kompilierten Anteile und Bibliotheken bestimmt wird, wie sie im Speicher 
anzuordnen sind. Gerade bei großen einzubindenden Binärdateien will man 
ja meist ohnehin explizit definieren, wo der Kram landen soll.
1
/* Direkt am Dateianfang, vor den anderen Definitionen: */
2
TARGET(binary)
3
INPUT("path/to/audio_example.bin")
4
OUTPUT_FORMAT(default)
5
6
...
7
...
8
...
9
/* Eigener Abschnitt mit Zuweisung in den Abschnitt FLASH: */
10
  .audio_example (READONLY) :
11
  {
12
    . = ALIGN(4);
13
    audio_example_start = .;
14
    "path/to/audio_example.bin"
15
    p_audio_example_end = .;
16
    . = ALIGN(4);
17
  } >FLASH

Der Zugriff aus dem C-Code o.ä. erfolgt dann über die Symbole 
audio_example_start und audio_example_end; natürlich muss man hierfür 
entsprechende Deklarationen anlegen.
1
extern uint8_t   audio_example_start[];
2
extern uint8_t * p_audio_example_end;

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Andreas S. schrieb:
> ist eine Definition im entsprechenden Linkerskript

Klasse, schreib das mal in den Wiki-Artikel 😉

von Joachim B. (jar)


Angehängte Dateien:

Lesenswert?

Christoph M. schrieb:
> Die Methode Byte-Array scheint mir auf Grund der Dateigröße nicht
> geeignet.

wieso nicht?

du schreibst ja selber:

Christoph M. schrieb:
> Speichergrößen im
> Megabyte-Bereich.

da sind doch die paar Bytes kein Problem

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.