Forum: Mikrocontroller und Digitale Elektronik C Teile einer Struktur im Flash (const __flash)


von John (Gast)


Lesenswert?

Wie erreicht man, dass Teile (members) einer Struktur aus dem Flash 
gelesen werden?
Mischbetrieb scheint nicht möglich:

    error: '__flash' specified for structure field 'string'

Müssen stattdessen separate Strukturen oder Arrays im Flash angelegt 
werden, auf die per Zeiger verwiesen wird?

Oder gibt es dafür ein "Konstrukt"?

von Oliver S. (oliverso)


Lesenswert?

In welchem Prozessor-Universum mit welchem Compiler bewegst du dich 
denn?

Oliver

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

John schrieb:
> Wie erreicht man, dass Teile (members) einer Struktur aus dem Flash
> gelesen werden?

Durch vorheriges Nachdenken. Sonst nicht.

Mein Vorschlag an dieser Stelle wäre ein void Pointer im struct, der 
seinerseits auf eine Variable im RAM zeigt. Aber für jede Instanz so 
eines Dinges eine separate Variable. Das hatte ich schon mal vor Jahren 
in der Lernbetty vorgeturnt, siehe Anhang. Sowas ist allerdings rein 
manuell ein bissel mühsam, ich hatte die Dateien (*.inc) per Script 
gemacht.

W.S.

von John (Gast)


Lesenswert?

Sorry, ich durfte nicht antworten:

    Als Gast kannst du maximal ... drei Beitraege pro Stunde erstellen.

AVR und GCC, also avr-gcc

von Klaus W. (mfgkw)


Lesenswert?

W.S. schrieb:
> Mein Vorschlag an dieser Stelle wäre ein void Pointer im struct

Ja, das wird natürlich gehen.

Aber sicherheitshalber: das ist dann keine durchgehende struct mit 
Inhalten aus RAM und Flash gemischt.
So etwas lässt sich in C kaum basteln, weil die member einer struct 
durchgehend hintereinander im Speicher liegen (evtl. wegen aligning mit 
ein paar Byte aufgefüllte Zwischenräume).
Etwas in der Art:
1
struct gehtgarnicht
2
{
3
    int   i; // das geht ins RAM
4
    int   j; // das liegt im Flash
5
};
geht nicht (es sei denn, Flash und RAM liegen direkt hintereinander im 
Adressbereich und man zwingt eine einzelne struct genau auf die Grenze).

von John (Gast)


Lesenswert?

Ich versuch's mit zwei Strukturen und dem Pointer, aer krieg's nicht 
hin.
Die Struktur darf ich offenbar nicht als const __flash deklarieren.
Als member schon? Aber die Initialisierung mag er nicht...
1
struct inRAM{
2
    int16_t variable;
3
    const struct inFLASH __flash * ptr;
4
};
5
6
struct inFLASH{
7
    const int16_t constant;
8
    const char * string;
9
};
10
11
struct inRAM array[] = {
12
    {123, {42, const __flash char[]) {"Hello world!"}}},
13
};

    error: initializer element is not constant
    warning: braces around scalar initializer
    etc.

von mh (Gast)


Lesenswert?

John schrieb:
> error: initializer element is not constant
>     warning: braces around scalar initializer
>     etc.

Das ist sicher nicht der

John schrieb:
> etc.

etc. ==
1
<source>:12:5: warning: braces around scalar initializer
2
   12 |     {123, {42, const __flash char[]) {"Hello world!"}}},
3
      |     ^
4
<source>:12:5: note: (near initialization for 'array[0].ptr')
5
<source>:12:12: warning: initialization of 'const __flash struct inFLASH *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
6
   12 |     {123, {42, const __flash char[]) {"Hello world!"}}},
7
      |            ^~
8
<source>:12:12: note: (near initialization for 'array[0].ptr')
9
<source>:12:16: error: expected expression before 'const'
10
   12 |     {123, {42, const __flash char[]) {"Hello world!"}}},
11
      |                ^~~~~
12
<source>:12:16: warning: excess elements in scalar initializer
13
<source>:12:16: note: (near initialization for 'array[0].ptr')
14
<source>:12:36: error: expected '}' before ')' token
15
   12 |     {123, {42, const __flash char[]) {"Hello world!"}}},
16
      |     ~                              ^
17
<source>:12:16: warning: missing initializer for field 'ptr' of 'struct inRAM' [-Wmissing-field-initializers]
18
   12 |     {123, {42, const __flash char[]) {"Hello world!"}}},
19
      |                ^~~~~
20
<source>:5:36: note: 'ptr' declared here
21
    5 |     const struct inFLASH __flash * ptr;
22
      |                                    ^~~
23
<source>:12:36: error: expected '}' before ')' token
24
   12 |     {123, {42, const __flash char[]) {"Hello world!"}}},
25
      |                                    ^
26
<source>:11:24: note: to match this '{'
27
   11 | struct inRAM array[] = {
28
      |                        ^
29
<source>:12:36: error: expected ',' or ';' before ')' token
30
   12 |     {123, {42, const __flash char[]) {"Hello world!"}}},
31
      |                                    ^
32
<source>:12:54: error: expected identifier or '(' before '}' token
33
   12 |     {123, {42, const __flash char[]) {"Hello world!"}}},
34
      |                                                      ^
35
<source>:12:55: error: expected identifier or '(' before '}' token
36
   12 |     {123, {42, const __flash char[]) {"Hello world!"}}},
37
      |                                                       ^
38
<source>:12:56: error: expected identifier or '(' before ',' token
39
   12 |     {123, {42, const __flash char[]) {"Hello world!"}}},
40
      |                                                        ^
41
<source>:13:2: warning: ISO C does not allow extra ';' outside of a function [-Wpedantic]
42
   13 | };
43
      |  ^
44
Compiler returned: 1

von John (Gast)


Lesenswert?

Danke für's Ausprobieren, allerdings weiß ich nicht, was du mir sagen 
willst.
Dass im Beispiel eine Klammer beim cast fehlt?
Ich würde mich freuen, wenn mir jemand eine funktionierende Deklaration 
und Initialisierung zeigt.

von mh (Gast)


Lesenswert?

John schrieb:
> allerdings weiß ich nicht, was du mir sagen willst.
Huch, da ist einiges in meinem Post verloren gegangen.

> Dass im Beispiel eine Klammer beim cast fehlt?
Dass du offensichtlich nicht gepostest hast, was du getestet hast.

> Ich würde mich freuen, wenn mir jemand eine funktionierende Deklaration
> und Initialisierung zeigt.
Guck dir erstmal genau an, was in deiner inRAM Struktur enthalten ist. 
Und womit du es initialisierst.

von John (Gast)


Lesenswert?

mh schrieb:
> Guck dir erstmal genau an, was in deiner inRAM Struktur enthalten ist.
> Und womit du es initialisierst.

Offensichtlich falsch. Offensichtlich sehe ich es nicht. Sei so nett und 
verrate doch, was der Fehler ist.

Mit Pointer auf separates Arrayelement geht es:
1
#include <stdint.h>
2
3
struct inRAM{
4
    int16_t variable;
5
    const struct inFLASH __flash * ptr;
6
};
7
8
struct inFLASH{
9
    const int16_t constant;
10
    const char __flash * string;
11
};
12
13
const struct inFLASH __flash farray[] = {
14
    {42, (const __flash char[]){"Hello"}}
15
};
16
17
struct inRAM array[] = {
18
    {123, &farray[0]},
19
    {-11, (const struct inFLASH __flash *){42, (const __flash char[]){"world"}}},
20
};

Aber die direkte Initialisierung der Struktur und ihres Pointers geht 
nicht, oder mache ich falsch?

von mh (Gast)


Lesenswert?

John schrieb:
> Aber die direkte Initialisierung der Struktur und ihres Pointers geht
> nicht, oder mache ich falsch?
Was ist der vollständige Typ von inRAM.ptr?

> Mit Pointer auf separates Arrayelement geht es:
Womit genau initialisierst du in diesem Fall (was genau ist der Typ des 
Ausdrucks &farray[0])?

Die Antworten auf diese Fragen werden einfacher, wenn du den __flash 
Kram erstmal weglässt, der hat nämlich nichts mit deinem aktuellen 
Problem zu tun.

> Sei so nett und verrate doch, was der Fehler ist.
Wo der Fehler ist sollte jetzt mehr als klar sein. Was der Fehler ist 
musst du schon selbst rausfinden.

von fop (Gast)


Lesenswert?

Klaus W. schrieb:
> Aber sicherheitshalber: das ist dann keine durchgehende struct mit
> Inhalten aus RAM und Flash gemischt.
> So etwas lässt sich in C kaum basteln, weil die member einer struct
> durchgehend hintereinander im Speicher liegen (evtl. wegen aligning mit
> ein paar Byte aufgefüllte Zwischenräume).

Ähm, Ihr wollt da nicht zufällig einen Mikrocontroller passend zu Eurem 
Problem entwickeln ?
Dann noch schnell den Compiler passend abändern.
Wenn das Projekt mal wieder "etwas" aufwändiger wird...

von fop (Gast)


Lesenswert?

Alternativ ginge natürlich Struktur in FRAM legen.

von John (Gast)


Lesenswert?

Ah, ein Didakt.
Vielleicht mag es ja doch jemand erklären, ob und wie man den Compiler 
dazu bekommt, einen Pointer zur inneren Struktur einzubauen?

von mh (Gast)


Lesenswert?

John schrieb:
> Ah, ein Didakt.
> Vielleicht mag es ja doch jemand erklären, ob und wie man den Compiler
> dazu bekommt, einen Pointer zur inneren Struktur einzubauen?

Hast du wenigstens versucht meine Fragen zu beantworten?

von Klaus W. (mfgkw)


Lesenswert?

John schrieb:
> Vielleicht mag es ja doch jemand erklären, ob und wie man den Compiler
> dazu bekommt, einen Pointer zur inneren Struktur einzubauen?

Vielleicht bist du ja der aus dem anderen Thread mit einer verwandten 
Frage.
Auch hier: in C++ könnte man sowas bauen, in C nicht. Da müsste man es 
von Hand machen vor Verwendung der struct.

von John (Gast)


Lesenswert?

Ja danke, meine Frage blieb unbeantwortet, daher präzisiert im anderen 
Thread.

John schrieb:
> die direkte Initialisierung der Struktur und ihres Pointers geht nicht,
> oder mache ich falsch?

von John (Gast)


Lesenswert?

mh schrieb:
> Hast du wenigstens versucht meine Fragen zu beantworten?

Dito.
Die struct soll den Pointer haben, sonst macht das Ganze ja überhaupt 
keinen Sinn.
Das Probem ist die unmögliche anonyme Initialisierung.

von John (Gast)


Lesenswert?


von W.S. (Gast)


Lesenswert?

Klaus W. schrieb:
> So etwas lässt sich in C kaum basteln,...

Naja, es läßt sich machen, aber nicht genau so, wie man es ohne 
nachzudenken anfangen würde.

Eines ist klar, verschiedene Einträge in einem Struct können nicht 
einfach auf verschiedene Speichervolumina verteilt werden. Wenn man so 
etwas konstruieren will, dann ist etwas gründlicheres Nachdenken nötig 
als bloß verschiedene Attribute wie 'const' usw. mal probehalber 
davorzuschreiben und dann zu schauen, was der Compiler dazu meint.

Einen Punkt möchte ich hier aber mal dediziert ansprechen: Die Neigung 
von C Programmierern, alles mögliche zusammenzuziehen. Ich empfinde das 
als ausgesprochen schlechten Stil. Mit einer Typdeklaration wie z.B. 
struct... kreiert man sich einen zusammengesetzten Datentyp, aber noch 
keine Variable oder typisierte Konstante dieses Typs (eben noch keine 
Instantiierung). Sowas muß separat von der Typdeklaration erfolgen und 
eigentlich separat davon dann die Zuweisung von Inhalten.

Dann wird auch klar, daß es für jede Instantiierung so einer Struktur im 
Flash eine separate Instantiierung des zugehörigen variablen Teils im 
RAM geben muß. So etwas kann C nicht von selbst leisten. In dem oben 
geposteten Beispiel hatte ich das per Programm (bzw. Script) generieren 
lassen, so daß eindeutig zugeordnete Variablen im RAM dabei entstanden 
und der jeweils konstante Teil im Flash angeordnet werden konnte.

W.S.

von Darth Moan (Gast)


Lesenswert?

John schrieb:
> struct inFLASH{
>     const int16_t constant;
>     const char __flash * string;
> };

Damit eine Struktur const sein kann, muss ihr Inhalt const sein.

const TYPE * ptr;

ist ein Pointer auf etwas Konstantes. Der Pointer selbst ist aber 
variabel.
Das kann also nicht im Flash liegen.

const TYPE * const ptr;

ist ein konstanter Pointer auf etwas Konstantes. Das kann im Flash 
liegen.

Allerdings kenne ich mich mit AVR GCC nicht aus. Vielleicht gibt es da 
noch mehr zu beachten.

von Oliver S. (oliverso)


Lesenswert?

John schrieb:
> struct inRAM array[] = {
>     {123, {42, const __flash char[]) {"Hello world!"}}},

Das ist C++. avr-g++ kennt allerdings __flash nicht, das gibts nur für 
den C-Compiler. Der Ansatz klappt so also eh nicht.

Oliver

von mh (Gast)


Lesenswert?

Darth Moan schrieb:
> Damit eine Struktur const sein kann, muss ihr Inhalt const sein.

Es sollte reichen, wenn es ein const struct inFLASH ist. Damit sollte 
es in jedem Fall illegal sein ein Member der struct zu ändern auch wenn 
der Member kein eigenes const hat.

von Oliver S. (oliverso)


Lesenswert?

John schrieb:
> Das Probem ist die unmögliche anonyme Initialisierung.

Ja, aber was ist daran das Problem? Leg halt ein struct mit den Werten 
im Flash an, und nimm darauf den Pointer.

Oliver

von John (Gast)


Lesenswert?

John schrieb:
> Das Probem ist die unmögliche anonyme Initialisierung.

Ist doch möglich: 
Beitrag "Re: C Construct an unnamed object in-place?"

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.