Forum: Mikrocontroller und Digitale Elektronik Objekte im Flash mit PROGMEM ablegen


von Andreas Burnickl (Gast)


Angehängte Dateien:

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

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

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

von Andreas Burnickl (Gast)


Lesenswert?

Ok dann werde ich mir das genauer ansehen. Vielen Dank für die Info.

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Andreas Burnickl schrieb:
> Vielen Dank für die Info.
Gerne doch. :)

von c-hater (Gast)


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...

von Dr. Sommer (Gast)


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.

von Andreas Burnickl (Gast)



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

von Dr. Sommer (Gast)


Lesenswert?

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.

von Andreas Burnickl (Gast)


Angehängte Dateien:

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.

von Dr. Sommer (Gast)


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.

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.