C Teile einer Struktur im Flash (const __flash)

Gast #6902146
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"?
Gast #6902155
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.
Angehängte Dateien:
#6902192
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).
Gast #6902214
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.
Gast #6902218
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
Gast #6902231
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.
Gast #6902248
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.
Gast #6902272
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?
Gast #6902335
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.
Gast #6902447
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...
#6902532
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.
Gast #6902625
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.
Gast #6902628
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.

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