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 | typedef struct |
2 | {
|
3 | unsigned int rest_oben : 5; |
4 | unsigned int subadresse : 3; |
5 | unsigned int rest_unten : 1; |
6 | unsigned int adresse_high : 7; |
7 | } meine_adresse_t; |
8 | |
9 | meine_adresse_t array[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.
:
Bearbeitet durch User
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 | typedef struct |
2 | {
|
3 | unsigned int rest_oben : 4; |
4 | unsigned int plmi : 1; |
5 | unsigned int subadresse : 3; |
6 | unsigned int adresse_high : 8; |
7 | } stbed_t; |
8 | |
9 | typedef struct |
10 | {
|
11 | unsigned int rest_oben : 5; |
12 | unsigned int rm_nr : 3; |
13 | unsigned int adr_rm : 8; |
14 | } albed_t; |
15 | |
16 | typedef struct |
17 | {
|
18 | unsigned int rest : 5; |
19 | unsigned int adr_w : 11; |
20 | } fstep_t; |
21 | |
22 | typedef struct |
23 | {
|
24 | unsigned int rest_oben : 6; |
25 | unsigned int rm_nr : 10; |
26 | } lm_dat_t; |
27 | |
28 | |
29 | typedef struct |
30 | {
|
31 | stbed_t stbed[4]; |
32 | albed_t albed[4]; |
33 | fstep_t step[32]; |
34 | lm_dat_t lm_dat[8]; |
35 | } folge_t; |
36 | |
37 | folge_t folge[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):
1 | folge_t folge[256] EXTMEM; |
2 | |
3 | folge[32].stbed[2].adresse_high = 34; |
4 | folge[5].step[2].adr_w = 7; |
5 | folge[6].albed[0].rm_nr = 1; |
6 | |
7 | int main(void) |
8 | {
|
9 | }
|
bekommt man die genannten Fehlermeldungen
1 | avr-gcc -mmcu=atmega1284p -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT struct_test.o -MF dep/struct_test.o.d -c ../struct_test.c |
2 | ../struct_test.c:45:10: error: expected '=', ',', ';', 'asm' or '__attribute__' before '.' token |
3 | ../struct_test.c:46:9: error: expected '=', ',', ';', 'asm' or '__attribute__' before '.' token |
4 | ../struct_test.c:47:9: error: expected '=', ',', ';', 'asm' or '__attribute__' before '.' token |
Grüße Stefan
:
Bearbeitet durch User
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);
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.