www.mikrocontroller.net

Forum: Compiler & IDEs Leseprobleme von char[] in einer struct im Flash


Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

obwohl ich sämtliche Suchen und Dokumentationen benutzt/durchsucht
habe, kann ich keine Lösung für mein spezielles Problem finden. Deshalb
möchte ich Euch bitten mir zu helfen.
Ziel ist, ein Array von struct's im Flash abzulegen und dann über den
Index auf die Daten zuzugreifen. Anschließend sollen die Werte auf dem
LCD (16x2) ausgegeben werden. Folgendes (verkürztes) Beispiel
funktioniert:


database.c:
-----------

#include <avr/pgmspace.h>

struct database_object
{
    char name[6];
    int  i1;
    int  i2;
};

unsigned char MAX_OBJECT_INDEX=109;

struct database_object PROGMEM objects[110]=
{
    {"text1\0",    1234,  12345},
    {"text2\0",   12345,    123},
    ....
    {"textn\0",   12345,    123}
}


Zugriffsmethode:
----------------

char    object_name[16];

...
strcpy_P(object_name, objects[act_object].name);

// Ausgabe von object_name auf LCD


Ausgabe:
--------

text1
text2
...
textn



Das Problem liegt jetzt im Zugriff auf die Strings. mit den int-Werten
habe ich kein Problem. Erhöhe ich die Anzahl der char's in der
struct-Definition auf 7 bekomme ich irgendwelchen Mist ausgegeben. Ziel
ist, diese Länge auf maximal 16 zu erhöhen. Das dabei Speicherplatz
verschwendet wird, würde ich erstmal in Kauf nehmen. Erhöhe ich die
Länge weiter, wird der Mist noch größer.

hier noch ein Beispiel:
-----------------------

struct database_object
{
    char name[7];
    int  i1;
    int  i2;
};


und die zugehörige Ausgabe:
---------------------------

text1
&#8616;text2
&#8593;&#8595;text3
...


Erhöhe ich die Länge weiter, zerlegt sich die Anzeige meist schon von
Anfang an.

Könnte mir bitte jemand sagen, wo mein Fehler liegt!

Als Controller verwende ich einen Atmega16. Die Definition der Werte
würde ich, wegen der Übersicht, strukturell so gern beibehalten.


Danke
   Frank

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist schon x-mal durchgekaut worden.  Du hast zwar die eher kleine
Tabelle im ROM, die Strings selbst sind aber im RAM.  Wahrscheinlich
willst du es eher umgekehrt oder beides im ROM.

Autor: OldBug (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin mir nicht sicher, ob das so stimmt, aber kann es sein, daß

 "text1\0"

nicht in 6 chars reinpasst!? "Gänsefüße" veranlassen den Compiler,
eine Nullterminierung durchzuführen, d.h. Du müsstest bei Deinem
erzeugten Binary zwei Nullen hinter den Strings haben.

Ich weis nicht, ob das Dein Problem löst. Das ganze ohne "Progmem
geraffel" auf dem x86-gcc (mit ein paar kleinen Änderungen) läuft
jedenfalls einwandfrei, siehe Anhang.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hups, zu lahm ;-)

...und auch noch daneben gelegen...

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die schnellen Antworten.

@OldBug: Daß das Ganze im RAM läuft wußte ich schon. Selbst auf dem
Atmega (natürlich mit weniger Daten). Daß ich die '\0' weglassen
kann hatte ich mir schon gedacht, war mir aber nicht sicher.

@Jörg: Meckern kann ich selber: "Ist schon x-mal durchgekaut
worden.". Deshalb erklär's mir bitte! Leider sorgt hier keiner dafür,
daß man die Hintergründe auch versteht (Das, was ich zumindest gefunden
habe). Ich nehme jetzt mal an, daß die "Pointer"/"Referenzen" auf
die einzelnen Objekte des Array's im FLASH liegen, aber die Daten
weiterhin im RAM. Nur verstehe ich nicht, warum mir
"pgm_read_word(&objects[index].i1);" dann die Werte korrekt liefert
und ich auch die Strings, solange sie kleiner als 6 sind, korrekt
zurück bekomme. Würden die Daten im RAM liegen, dann müßte ich generell
nur Schrott bekommen. Außerdem würde ich mit meiner Menge an Daten das
RAM generell überladen und mir würde die komplette Anwendung um die
Ohren fliegen.
Also ist meine Vermutung, daß schon jedes (struct-)Objekt mit seinen
Daten im FLASH abgelegt wird, nur beim Zugriff auf die Strings
irgendwas schief geht. Mach mir doch bitte mal nen Vorschlag, wie ich
dieses spezielle Problem lösen könnte und erklär mir meinen Fehler. Auf
jeden Fall muß die Überichtlichkeit (Wartbarkeit) der Daten
gewährleistet bleiben.


Danke
   Frank

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, ich habe keine Zeit, das zum (x+1). Mal durchzukauen.

Am besten schaust du dir mal die GCC-Version der Butterfly-Applikation
an.  Die macht sowas in laufenden Metern.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann frage ich mich, was Du hier machst!!! Den dicken Löffel raushängen,
dazu gehört nicht viel! So ziemlich alle Beiträge, die ich von Dir hier
gefunden habe drehen sich nur darum, daß Du keine Lust hast alles X-Mal
zu wiederholen. Nur fachlich hast Du keine wirklichen Antworten. Zum
Rumsülzen scheinst Du ja mehr als ausreichend Zeit zu haben! Ich frage
mich wirklich, was so lange dauert mal kurz nen Stück Code zu
korrigieren, bzw. ein paar ordentliche Antworten zu geben. Wenn Du
soviel Ahnung hättest, wie du tust, wäre das in 2min erledigt. Für mich
stellt es sich eher so dar, als ob Du versuchst den Eindruck zu
erwecken, daß Du der absolute Oberguru wärst, aber in Wirklichkeit
keinen blassen Schimmer hast.

Sorry, aber das mußte jetzt raus. Sowas regt mich auf!


Könnte mir mal bitte einer sagen, was ne Butterfly-Applikation ist und
wo ich die finde?

Ich geh mich jetzt erstmal abkühlen...

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hoho!

Mach mal halblang!
Die avr-libc-FAQ beschreibt das Problem ganz gut.
Ausserdem befindet sich EINIGES an Sourcen in mindestens zwei der Foren
hier.

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Könnte mir mal bitte einer sagen, was ne Butterfly-Applikation ist

Eine Art Minimal-Demo von Atmel für den AVR.  Guck mal bei denen auf
dem Webserver nach.

> und wo ich die finde?

Für den IAR-Compiler bei Atmel selbst.

Für den GCC tippst du bitte "avr butterfly gcc" in Google ein und
folgst dem ersten Link.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo OldBug,

In der avr-libc-faq habe ich dazu nichts gefunden. (Wahrscheinlich zu
blind) Im Tutorial steht zu dem Thema nur: "TODO: Beispiele fuer
structs und pointer aus flash auf struct im flash (menues,
state-machines etc.)"

In den Sourcen finde ich nur die Geschichte, daß z.B. in meiner struct
jedes char-array außerhalb extra deklariert wird. Komischerweise die
int's aber nicht. gerade das wollte ich mir aber ersparen, dadurch die
Übersichtlichkeit flöten geht. Außerdem kann ich mir nicht erklären,
warum ein String extra mit PROGMEM gekennzeichnet werden muß und ein
int nicht.

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> In der avr-libc-faq habe ich dazu nichts gefunden.

Schau nochmal nach, ungefähr in der Mitte (nein, die genaue Nummer sag
ich jetzt nicht).

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Am besten schaust du dir mal die GCC-Version der
Butterfly-Applikation
an.  Die macht sowas in laufenden Metern."

...genau das macht sie eben nicht. Das was sie macht, sind Arrays von
primitiven Datentypen in den FLASH zu schreiben. Ich habe aber nicht
eine struct gefunden, die die in den FLASH schreiben, geschweige denn
ein Array von struct.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Chris: Gut, das kannte ich. Nur ist das für mich die schlechteste
Lösung und die Hintergründe sind (zumindest für den
Assamblerunkundigen) nicht erläutert. Wenn ich die Strings erst
außerhalb der Arraydeklaration anlegen muß, dann brauche ich auch keine
Struct mehr. Dann kann ich mir gleich ein windiges #define-Kunstrukt
schaffen und darüber auf meine Daten zugreifen.
Außerdem wird auch dort nur ein Array von Array's erzeugt aber kein
Array von struct's

Autor: mthomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
An http://www.nongnu.org/avr-libc/user-manual/FAQ.htm...
geht noch kein Weg vorbei. Hintergund ist m.W. die noch unvollkommene
Anpassung des gcc an die AVR-Architektur, die es nicht ermoeglicht z.B.
Character-Arrays als Elemente von Structs im Progmem zu initialisieren.
Im gcc-Port der Butterfly-Application wird sehr wohl ein Array von
Structs im Progmem abgelegt und auch das "Umschiffen" des Problems
mit den Character-Arrays als Elemente von Structs und deren
Initialisierung fuer Objekte des Arrays im Progmem demonstriert. Das
Struct enthaelt zur Verwaltung von Zeichenketten Pointer, diese werden
mit der Adresse der "progmem-Zeichenkette" initialisiert, die
ausserhalb definiert ist. Vgl. gcc-Port Quellcodedateien menu.h (struct
MENU_STATE, Array of MENU_STATE menu_state[]) fuer Initialisierung und
main.c (pgm_read...) fuer Zugriff. Das ist zwar etwas umstaendlich,
weniger bei der Initialisierung als beim Zugriff, aber m.W. mit
avr-gcc/avr-libc nicht anders zu machen. Warum dadurch die Verwendung
von structs in diesem Anwendungsfall ueberfluessig sein sollte und wie
dies mit "windigen" #defines zu machen sein soll, wuerde mich
allerdings interessieren.

Martin

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo mthomas!

vielen, vielen Dank für Deine ausführliche Beschreibung. Diese Stelle
hatte ich dann doch übersehen. Damit sollte es generell machbar sein.
Das große Problem ist, daß ich mit relativ großen Datenmengen (mind.
150 Objekte) operieren will. Wenn jetzt jeder Objektname erst außerhalb
der Strukturinitialisierung deklariert werden muß ist die Wartbarkeit
für'n Bobs, da Objektname und Objektdaten im direkten Zusammenhang
stehen. Außerdem sind das Einpflegen neuer Daten und anderer
Operationen darauf von Hand extrem mühsam. Zwar nimmt einem ein guter
Texteditor mit einer sehr guten "Ersetzen"-Funktion viel Arbeit ab
aber die Fehlerquote wird an dieser Stelle extrem steigen.
Mein Problem ist an dieser Stelle wahrscheinlich, daß ich die
prozedurale Programmierung lange hinter mir gelassen habe und von den
Möglichkeiten der Objektorientierung mittlerweile zu sehr verwöhnt
bin.

Frank

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das große Problem ist, daß ich mit relativ großen Datenmengen (mind.
> 150 Objekte) operieren will. Wenn jetzt jeder Objektname erst
> außerhalb der Strukturinitialisierung deklariert werden muß ist die
> Wartbarkeit für'n Bobs, da Objektname und Objektdaten im direkten
> Zusammenhang stehen. Außerdem sind das Einpflegen neuer Daten und
> anderer Operationen darauf von Hand extrem mühsam.

Wie Martin schon schrieb, GCC hatte vor dem AVR nie ernsthaft was mit
Harvard-Architekturen am Hut.  Im Grunde genommen hat C selbst nie
ernsthaft etwas mit Harvard am Hut gehabt... (Erstaunlich übrigens, da
es selbst von der PDP-11 eine Art Harvard-Modifikation gab, die die
Jungs damals sehnsüchtig erwartet haben, weil sie den Adressraum von
64 KB auf 2 * 64 KB erweitert hat.)  Es gibt einen Vorschlag zur
Erweiterung des C-Standards um die Möglichkeit, mehrere Speicherräume
angeben zu können, und hoffentlich wird sich dann auch jemand
finden, der den für den GCC umsetzt (was natürlich massive Eingriffe
in den Compiler verursacht).  Wenn das mal passiert ist, wird das
hoffentlich alles ein Stück einfacher.

Kannst du deine Strukturen und Datenelemente denn nicht eventuell mit
einem Script anlegen?  Auch Makros könnten eine Hilfe sein, weil man
die Makro-Parameter ja sowohl in einen Namen als auch einen String
expandieren kann, also sowas:

#define FOO(x) const char data_##x[] = #x
FOO(hi);
FOO(lo);

expandiert zu:

const char data_hi[] = "hi";
const char data_lo[] = "lo";

Das nur als Idee -- ich würde das vermutlich eher über einen Script
(Shell, Perl, Python) tun, insbesondere dann, wenn das auch
gelegentlichen Änderungen unterworfen ist.

Autor: mthomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörgs Vorschlag, die Verwaltung mit einem "externem Praeprozessor"
(Skript od. C-Programm) zu machen (Textdatei mit "Metainformationen"
als Eingabe - Ausgabe: avr-gcc/avr-libc Code), scheint mit fuer die
beschriebene Anwendung auch die beste Loesung. Dies duerfte die
Wartung/Erweiterung deutlich erleichtern. Sicher wuerde ein solches
Skript/Programm auch viele Interessenten finden.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm, na mal sehen. Jetzt muß ich das Ganze erstmal zum Laufen bringen
(wenn ich mal wieder Zeit finde) und dann kann ich mir immer noch nen
kleines PC-Progrämmchen zur Verwaltung schreiben. Wär nicht das erste
Mal. Ist warscheinlich die beste Lösung, da ich es auch mit
unterschiedlichen Datenquellen zu tun haben werde.

Danke für die Vorschläge.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.