Hallo,
in einem aktuellen Arduino Projekt würde ich gerne ein Objekt in den
Flash legen (Klasse im Anhang).
const Word Wort1(12,22,22) PROGMEM;
main()
{
Word Wort1Ram;
memcpy_P(&Wort1Ram, &Wort1, sizeof(Word));
}
In der Wort1Ram stehen nach dem Kopieren lauter falsche Werte. Nutze ich
anstatt einer Klasse eine Struktur passen die Werte. Unterstützt PROGMEM
die Ablage von Objekten nicht? Oder stimmt mit dem Code irgendetwas
nicht?
Gruß Andreas
Naja, eine Struktur, die nur Daten haelt, ist halt was anderes als eine
Klasse die Daten und Funktionen beinhaltet. Logischerweise sieht der
Speicher mit der Struktur anders aus, als mit der Klasse.
Wenn du wirklich das Objekt speichern willst, dann musst du dich mit
serialisierung beschaeftigen.
https://de.wikipedia.org/wiki/Serialisierung
Kaj G. schrieb:> Naja, eine Struktur, die nur Daten haelt, ist halt was anderes als eine> Klasse die Daten und Funktionen beinhaltet.
Das stimmt zwar, ist hier aber überhaupt nicht das Problem. Das Problem
ist vielmehr, dass die Instanz einer Klasse ein Referenztyp ist, die
Instanz einer Struktur aber ein Wertetyp. Diese beiden Grundtypen werden
vom Compiler völlig unterschiedlich gehandhabt.
Das ist ein leicht zu begreifender Unterschied für
Assembler-Programmierer, denen die Indirektion als Werkzeug im Blute
liegt, aber schwer zu begreifen für Leute, die nur mit Hochsprachen
umgehen, denn diese bemühen sich ja gerade, Indirektionen vor dem
Anwender zu verbergen. Klappt halt nur nicht immer...
c-hater schrieb:> Das Problem> ist vielmehr, dass die Instanz einer Klasse ein Referenztyp ist
Das ist in Java so, aber nicht in C++. Das Problem ist, dass der
Compiler im Konstrukturaufruf nicht weiß, dass das eine PROGMEM-Instanz
ist. Es ist also mehr ein Problem der AVR-Architektur. Auf ARM würde das
Beispiel so problemlos funktionieren, und memcpy_P wäre da auch nicht
nötig.
Mit einem "constexpr"-Konstruktur und -Instanz würde es vielleicht gehen
(ausprobieren).
c-hater schrieb:> aber schwer zu begreifen für Leute, die nur mit Hochsprachen> umgehen
Die meisten Hochsprachen sind halt nicht für getrennte Adressräume
konzipiert. C(++) auf solchen Controllern ist daher problematisch.
Kaj G. schrieb:> Wenn du wirklich das Objekt speichern willst, dann musst du dich mit> serialisierung beschaeftigen.
Dazu gibt's hier auch einen Artikel: Serialisierung. Ist aber so
wahrscheinlich eher nicht nötig.
Mir scheint es auch erst mal so als würde der Konstruktor Probleme
machen. Wenn ich eine Struktur verwende, liegt die Tabelle sauber
initialisiert im Flash. Genau wie ich es eigentlich erwarte. Mit der
Variante als Objekt und der Compiler Option -Wall erhalte ich folgende
Fehlermeldung: uninitialized variable 'WordsTable' put into program
memory area [-Wuninitialized]. Passt zu dem was ich im Flash sehe,
nämlich nur Nullen.
Struktur:
Map Datei:
.progmem.data._ZN12DisplayWords10WordsTableE
0x00000068 0x6 DisplayWords.o
0x00000068 _ZN12DisplayWords10WordsTableE
Memory Dump siehe Anhang.
Die Klasse habe ich schon angepasst und den Konstruktor als constexpr
deklariert. Leider hat das noch nicht geholfen. Hat jemand noch eine
Idee wie man die Klasse erweitern könnte, damit es funktioniert?
Gruß Andreas
Andreas Burnickl schrieb:> Die Klasse habe ich schon angepasst und den Konstruktor als constexpr> deklariert. Leider hat das noch nicht geholfen. Hat jemand noch eine> Idee wie man die Klasse erweitern könnte, damit es funktioniert?
Die Variable Wort1 muss auch mit constexpr markiert werden.
Dr. Sommer schrieb:> Die Variable Wort1 muss auch mit constexpr markiert werden.
Super Sache. Es funktioniert. Vielen Dank für die Hilfe!
[c]
constexpr DisplayWord WordsTable[] PROGMEM
{
DisplayWord(1,2,4),
DisplayWord(5,6,7),
};
[/]
Außerdem musste ich noch den Destruktor löschen, anderfalls kam der
Fehler: "type 'const DisplayWord []' of constexpr variable 'WordsTable'
is not literal". Darf solch eine Klasse keinen Destruktor haben?
Achja kann ich jetzt ohne bedenken jedes Objekt per memcpy kopieren oder
kann es da zu Problemen kommen? Stichwort Serialisierung.
Andreas Burnickl schrieb:> Außerdem musste ich noch den Destruktor löschen, anderfalls kam der> Fehler: "type 'const DisplayWord []' of constexpr variable 'WordsTable'> is not literal". Darf solch eine Klasse keinen Destruktor haben?
Korrekt, da darf kein Destruktor sein. Wann soll der auch aufgerufen
werden?
Andreas Burnickl schrieb:> Achja kann ich jetzt ohne bedenken jedes Objekt per memcpy kopieren oder> kann es da zu Problemen kommen
Da du die Daten ja nicht zwischen verschiedenen Controllern austauschst
und das alles in einem Programm bleibt ist das schon ok. Wäre es kein
AVR bräuchtest du auch kein memcpy, dann würde einfaches kopieren mit =
reichen.