Hallo,
es tauchen nach Beitrag "Deklaration von external memory" die
nächsten Fragen auf:
1. Im zu migrierenden asm-Projekt habe ich 2-Byte-Variablen in einem
Array verwendet. Das niederwertige Byte enthält rechtsbündig den 7 Bit
langen high-Teil einer Adresse, das höherwertige Byte enthält
rechtsbündig eine 3 Bit lange Subadresse dieser Adresse. Die beiden
Adressteile werden nicht zusammengesetzt und bei einer Übertragung
getrennt behandelt. Die übrig bleibenden Bits sind mit anderen
Informationen zu dieser Adresse gefüllt. Jetzt habe ich ein Array
definiert mit uint16_t[256][8]. Bei Zugriff werden die Daten in 2
uint8_t zerlegt und weiter behandelt.
Frage:
Macht das so Sinn oder sollte man das ganz anders angehen?
2. Da der EEPROM im Controller vorne und hinten nicht ausreicht, habe
ich einen externen EEPROM über SPI angebunden.
Frage:
Wie bildet man den Aufbau dieses Speichers ab?
Es gibt ja keinen direkten Zugriff auf dieses Teil Hardware, den der
Compiler umsetzen muss (kann). Ich bin noch nicht so weit, aber es wäre
ja bestimmt ganz nett, wenn man mit den eigenen SPI-Routinen für die
Ermittlung der Adressen im externen EEPROM auf ein array[a][b]
EXT_EEPROM zugreifen könnte.
Danke für alle Hinweise.
Thomas
Thomas P. schrieb:> Jetzt habe ich ein Array definiert mit uint16_t[256][8].
Den Zusammenhang zwischen dem von Dir beschriebenen in Assembler
genutzten Array aus "zwei-byte-Variablen" und dem zweidimensionalen
Array hier kann ich nicht so recht erkennen.
Ansonsten kannst Du in C natürlich genau die Art von Bitschiebereien
veranstalten, die Du in Assembler auch betreibst.
Ein Bitfeld ist allerdings eine Konstruktion, die das ganze lesbarer
machen kann:
1
typedefstruct
2
{
3
unsignedintrest_oben:5;
4
unsignedintsubadresse:3;
5
unsignedintrest_unten:1;
6
unsignedintadresse_high:7;
7
}meine_adresse_t;
8
9
meine_adresse_tarray[256];
10
11
...
12
13
array[17].subadresse=2;
14
array[17].adresse_high=19;
"rest_oben" und "rest_unten" sind die von Dir beschriebenen "anderen
Informationen", die man, sofern sie einzelne Bits sind, natürlich auch
weiter aufdröseln kann.
Auf die Elemente des Bitfelds kann wie auf normale Strukturelemente
zugegriffen werden; der Compiler übernimmt für Dich sämtliche Bitshift-
und Maskierungsoperationen.
Soll alternativ noch ein Zugriff auf das Ding als opaker 16-Bit-Wert
geschehen, lässt sich das ganze in eine union mit einem uint16_t
verpacken.
Aber: Was da sinnvoll ist, hängt von der Art der Nutzung ab.
Wenn die Reihenfolge der Elemente im Speicher relevant ist (weil sie
z.B. als direkte Kopie die Daten eines von irgendwo kommenden Protokolls
abbilden), muss die Reihenfolge der Bitfeldelemente gegbenenfalls
angepasst werden.
Rufus Τ. Firefly schrieb:> Den Zusammenhang zwischen dem von Dir beschriebenen in Assembler> genutzten Array aus "zwei-byte-Variablen" und dem zweidimensionalen> Array hier kann ich nicht so recht erkennen.
Die Beschreibung trifft auf ein Element des Arrays zu. Es gibt pro Zeile
also 8 solcher Elemente, von denen 0-8 gültig sein können.
> Soll alternativ noch ein Zugriff auf das Ding als opaker 16-Bit-Wert> geschehen, lässt sich das ganze in eine union mit einem uint16_t> verpacken.
Ein alternativer Zugriff muss möglich sein, da dieses Array derzeit bei
jedem Start aus dem EEPROM in den RAM gelesen werden muss. Keine Ahnung,
wie man das am besten umsetzt. Wird wohl nur byteweise gehen, wenn ich
das Datenblatt des EEPROM anschaue.
> Wenn die Reihenfolge der Elemente im Speicher relevant ist (weil sie> z.B. als direkte Kopie die Daten eines von irgendwo kommenden Protokolls> abbilden), muss die Reihenfolge der Bitfeldelemente gegbenenfalls> angepasst werden.
Wird wohl auch zutreffen, da in einer späteren Ausbaustufe die Daten
über USB kommen und auch geliefert werden sollen und dann in die
verschiedenen Arrays einzusortieren sind. Ich glaube, ich sollte die
Datenanordnung noch einmal neu konzipieren. Die alte Lösung hat stark
Rücksicht auf die Zugriffsgeschwindigkeit und einfache Zeigerverwaltung
genommen und die Wartbarkeit stand im Hintergrund (Änderungen waren auch
nie notwendig).
Thomas
Ich glaube, ich habe das jetzt verstanden, zumindest im Ansatz. Etwas
auf mein Vorhaben angepasst könnte das so aussehen:
1
typedefstruct
2
{
3
unsignedintrest_oben:4;
4
unsignedintplmi:1;
5
unsignedintsubadresse:3;
6
unsignedintadresse_high:8;
7
}stbed_t;
8
9
typedefstruct
10
{
11
unsignedintrest_oben:5;
12
unsignedintrm_nr:3;
13
unsignedintadr_rm:8;
14
}albed_t;
15
16
typedefstruct
17
{
18
unsignedintrest:5;
19
unsignedintadr_w:11;
20
}fstep_t;
21
22
typedefstruct
23
{
24
unsignedintrest_oben:6;
25
unsignedintrm_nr:10;
26
}lm_dat_t;
27
28
29
typedefstruct
30
{
31
stbed_tstbed[4];
32
albed_talbed[4];
33
fstep_tstep[32];
34
lm_dat_tlm_dat[8];
35
}folge_t;
36
37
folge_tfolge[256]EXTMEM;
Und wie greift man nun auf die Daten zu?
In deinem Beispiel
array[17].subadresse = 2;
array[17].adresse_high = 19;
als auch mein Versuch mit
folge[32].stbed[2].adresse_high = 34;
wirft den gleichen Fehler
error: expected '=', ',', ';', 'asm' or '__attribute__' before '.' token
und ich habe hier keinen blassen Schimmer, was ich falsch mache.
Bitte um Nachhilfe.
Thomas
Thomas P. schrieb:> wirft den gleichen Fehler>> error: expected '=', ',', ';', 'asm' or '__attribute__' before '.' token>> und ich habe hier keinen blassen Schimmer, was ich falsch mache.> Bitte um Nachhilfe.
bei derartigen Fehlermeldungen ist der eigentliche Fehler meist in den
Zeilen davor zu finden. Das könnte auch ein vergessenes Include File
sein. Zum Beispiel ein Include File, in dem die ganzen Strukturen
definiert sind.
Thomas P. schrieb:> folge[32].stbed[2].adresse_high = 34;
So heißen Deine Datentypen ja auch nicht.
folge[5].step[2].adr_w = 7;
oder
folge[6].albed[0].rm_nr = 1;
Das muss funktionieren.
Rufus Τ. Firefly schrieb:> Thomas P. schrieb:>> folge[32].stbed[2].adresse_high = 34;>> So heißen Deine Datentypen ja auch nicht.
Eh... doch! Oder?
> folge[5].step[2].adr_w = 7;>> oder>> folge[6].albed[0].rm_nr = 1;>> Das muss funktionieren.
Und was ist da der Unterschied zum Thomas' Beispiel?
Rufus Τ. Firefly schrieb:> folge[32].stbed[2].adresse_high = 34;>> So heißen Deine Datentypen ja auch nicht.
Hallo Rufus,
das Problem dürfte an anderer Stelle liegen:
Die nachstehenden Ausdrücke compilieren sauber - wenn sie an an der
richtigen Stelle stehen.
Die vom OP zitierten Fehlermeldungen bekomme ich genau dann, wenn die
Zuweisungen außerhalb einer Funktion stehen. Baut man so was (Auszug):
Eric B. schrieb:> Eh... doch! Oder?>>>
Äh, ich war etwas oberflächlich und hielt "stbed" für einen typo.
Leise rieselt Asche auf mein ergrauendes Haupt.
Stefan hat den eigentlichen Fehler aber wohl gefunden:
Zuweisungen außerhalb einer Funktion sind nicht möglich.
Stefan Wagner schrieb:> Rufus Τ. Firefly schrieb:>> folge[32].stbed[2].adresse_high = 34;>>>> So heißen Deine Datentypen ja auch nicht.>> Hallo Rufus,>> das Problem dürfte an anderer Stelle liegen:> Die nachstehenden Ausdrücke compilieren sauber - wenn sie an an der> richtigen Stelle stehen.
Hallo Stefan,
Du hast Recht, blöder Anfängerfehler, obwohl ich es gerade erst gelesen
habe.
Ich schreibe freiwillig ohne copy&paste 100 mal "Anweisungen sind nur
innerhalb von Funktionen zulässig".
Vielen Dank für die Unterstützung.
Thomas
Nachdem die Kuh im Punkt 1 vom Eis ist, möchte ich gerne noch einmal auf
die 2. Frage zurückkommen:
Da der EEPROM im Controller vorne und hinten nicht ausreicht, habe
ich einen externen EEPROM über SPI angebunden.
Frage:
Wie bildet man den Aufbau dieses Speichers ab?
Es gibt ja keinen direkten Zugriff auf dieses Teil Hardware, den der
Compiler umsetzen muss (kann). Ich bin noch nicht so weit, aber es wäre
ja bestimmt ganz nett, wenn man mit den eigenen SPI-Routinen für die
Ermittlung der Adressen im externen EEPROM auf ein array[a][b]
EXT_EEPROM zugreifen könnte.
Wie fängt man das am besten an?
Es gibt auch noch eine Zusatzfrage:
Kann man den Compiler/Linker überreden, die Auslastung des selbst
definierten EXTMEM beim build mit auszugeben? Und wenn ja, wie geht es?
Thomas
Thomas P. schrieb:> aber es wäre ja bestimmt ganz nett, wenn man mit den eigenen> SPI-Routinen für die Ermittlung der Adressen im externen EEPROM auf ein> array[a][b] EXT_EEPROM zugreifen könnte.
Keine Chance. Du wirst statt des Arrayzugriffs eigene Funktionen
verwenden müssen, à la
wert = ReadExtEEPROM(a, b);
und
WriteExtEEEPROM(a, b, wert);