Objekte im Flash mit PROGMEM ablegen

Gast #5464849
Lesenswert?

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
Angehängte Dateien:
Gast #5465287
Lesenswert?

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...
Gast #5465299
Lesenswert?

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.
Gast #5466187
Lesenswert?

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:
1
        struct sDisplayWord {
2
            byte Column;
3
            byte Row;
4
            byte Length;
5
        };

Tabelle:

1
const DisplayWords::sDisplayWord DisplayWords::WordsTable[] PROGMEM
2
{
3
    {1,2,4},
4
    {5,6,7},
5
};

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
Angehängte Dateien:
Gast #5466218
Lesenswert?

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.
Angehängte Dateien:
Gast #5466225
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren