Hallo,
Eine Frage ich Suche nach einer Möglichkeit 40 Bit in 5 Byte
unterzubringen Das ist ja eigentlich sehr einfach :-), nur würde ich das
gerne über ein C Bitfeld lösen.
Ich komme auf 8 Byte - was für mich auch klar zu erklären ist. Aber gibt
es vielleicht einen Trick dem Compiler doch klar zu machen, das noch
kompakter abzulegen.
1
typedefstruct
2
{
3
/* 2 byte */
4
uint16_tstatus_display;
5
/* 5 byte */
6
uint16_tleft1:5;
7
uint16_tright1:5;
8
uint16_tleft2:5;
9
uint16_tright2:5;
10
uint16_tleft3:5;
11
uint16_tright3:5;
12
uint16_tleft4:5;
13
uint16_tright4:5;
14
}__attribute__((gcc_struct))tx_data;
Alternative wäre natürlich maskieren und schiften. Würdet ihr das auf
einem 32Bit ARM generell vorziehen?
Danke.
Die Frage ist eher wozu das erforderlich ist. Es riecht hier evtl etwas
nach Mikro Optimierung und das ist bekanntlich sch...
Wenn das für die Übertragung mit festgelegten Bit codierten Signalen ist
dann würde ich schieben und verodern. Auf keinen Fall sollte dann ein
Attribut erforderlich sein. Ein biteld geht in c auch ohne
compilerspezifischen Murks.
Implementierung ist generell compilerabhängig.
> Alternative wäre natürlich maskieren und schiften. Würdet ihr das auf> einem 32Bit ARM generell vorziehen?
Immer dann wenn du das genaue Bitlayout benötigst.
Mathias G. schrieb:> Alternative wäre natürlich maskieren und schiften. Würdet ihr das auf> einem 32Bit ARM generell vorziehen?
Ja. Selbst wenn Du es hinbekommst, dass Deine Bitfelder exakt Deine
Datenstruktur abbilden: Die Datenkompaktheit ist compiler-abhängig, das
Ganze ist nicht portabel und passt je nach Alignment des verwendeten µCs
nur zufälltig. Aber das wichtigste: Um die Daten auseinanderzuklamüsern,
muss der Compiler selbst auch maskieren und shiften. Es gibt also keinen
echten Gewinn. Dann mach ich das lieber selbst und ich weiß, was ich
habe.
nachdem das jetzt geklärt wäre, noch was anderes:
Mathias G. schrieb:> } __attribute__((gcc_struct)) tx_data;
... ich glaube nicht, daß das Attribut gcc_struct auf ARM irgendwas
(geschweige denn, was Sinnvolles) tut. Das würd' ich weglassen.
Mathias G. schrieb:> Eine Frage ich Suche nach einer Möglichkeit 40 Bit in 5 Byte> unterzubringen
Die Frage ist, wozu man sich das antun will?
Wenn es nur darum geht, RAM zu sparen, dann würde ich das sein lassen
und einfach je 3 Bits verschenken.
Wenn es darum geht, externe 5-Bit Schieberegister abzubilden, dann würde
ich dafür eine Funktion schreiben, die ein 8Byte-Array entsprechend aufs
SPI ausgibt. Diesen Schrunz durch das ganze Programm zu ziehen, würde
ich sein lassen.
Wenn es ein 5*8 Font werden soll, einfach um 90° gedreht abspeichern,
also 5 Byte je Zeichen.
Hast Du dir mal sizeof(tx_data) angesehen?
Ich würde erwarten, dass entweder die Größe nicht deinen Erwartungen
entspricht, oder aber Padding Bits an stellen sitzen, an denen Du sie
nicht erwartest.
dafür gibt es das Attribute packed
__attribute__((packed))
oder die Option -fpack-struct
siehe gcc onlinedocs
für Kommunikationsprotokolle sehr wichtig!
Hallo,
Vielen Dank euch allen.
Also nein ist für einen Datenübertragung und da müssen die Bits leider
so kompakt aneinander liegen - ich habe das Protokoll nicht gemacht.
"packed" habe ich natürlich auch probiert - bringt nicht wirklich was.
Ich werde es klassisch machen mit maskieren und schieben.
Danke
Mathias G. schrieb:> "packed" habe ich natürlich auch probiert - bringt nicht wirklich was.
Auch mit packed darf C nicht über die Bitgrenzen des Typs hinweg.
Die höchste Packungsdichte hättest Du daher mit 4-Byte-typen, da passen
6- 5-Biter in 32 Bit.
Volle schrieb:> __attribute__((packed))> [...]> für Kommunikationsprotokolle sehr wichtig!
Es ist eher wichtig daß man die Protokolle so designed daß alle Felder
self-aligned sind und sich ohne krumme Offsets zu ergeben lückenlos
zusammenfügen lassen, oder mit anderen Worten: es ist sehr wichtig daß
man es so entwirft daß das packed überhaupt keinen Unterschied machen
würde. Wenn Du irgendwo packed brauchst hast Du einen Designfehler.
Mathias G. schrieb:> "packed" habe ich natürlich auch probiert - bringt nicht wirklich was.
Ich habe es auch mal ausprobiert: Mit arm-none-eabi-gcc 6.2.0 und
__attribute__((packed)) und ohne das gcc_struct-Attribut (das auf dem
ARM sowieso keine Bedutung hat) ist die Struktur 7 Byte groß, d.h. es
verbleiben keine ungenutzten Bits.
Bernd K. schrieb:> Es ist eher wichtig daß man die Protokolle so designed daß alle Felder> self-aligned sind und sich ohne krumme Offsets zu ergeben lückenlos> zusammenfügen lassen, oder mit anderen Worten: es ist sehr wichtig daß> man es so entwirft daß das packed überhaupt keinen Unterschied machen> würde. Wenn Du irgendwo packed brauchst hast Du einen Designfehler.
wie willst du das machen, eventuell muss man bei einer Plattform auf
256bit alignen?
Beim lesen werden die Daten einfach mit Bitoperationen in eine passenden
Struktur kopiert und beim senden in den Sendepuffer. Ich halte es für
sinnlos das ein Programm die genaue Struktur von Daten der Übertragung
abbilden soll.
Peter II schrieb:> wie willst du das machen,
Einfach jedes Element an seiner eigenen Größe ausrichten. Bytes an 1ern,
Zweibytige and 2ern, Vierbytige an 4ern, Achtbytige an 8ern, etc. So
mögen das alle aktuell gängigen CPUs und auch die der letzten 30 Jahre
am liebsten.
> eventuell muss man bei einer Plattform auf> 256bit alignen?
Die will ich sehen. Und ich glaub nicht das zukünftige CPUs in
irgendeiner Hinsicht wieder schlechter werden sollen als heutige.
Ganz egal ob Du es mit nem Struct machst oder sie einzeln aus dem Buffer
herauskratzt, wenn die Daten bereits ordentlich aligned im
Empfangspuffer liegen hat der Compiler ne realistische Chance die
Zugriffe schön zu optimieren ohne umständliche Schiebereien und
Verrenkungen anzustellen.
Bernd K. schrieb:> Ganz egal ob Du es mit nem Struct machst oder sie einzeln aus dem Buffer> herauskratzt, wenn die Daten bereits ordentlich aligned im> Empfangspuffer liegen hat der Compiler ne realistische Chance die> Zugriffe schön zu optimieren ohne umständliche Schiebereien und> Verrenkungen anzustellen.
es ist aber oft so, das man nicht alle Anforderungen zusammen umsetzen
kann.
Bei Ipv4 ist es auch nicht schön aligned. Bei IPv6 haben sie es wieder
besser gemacht, aber dort gibt es dann wieder optionale felder die den
Rest veschieben können.
Bei der Übertragung ist es wichtiger Platzsparend zu übertragen, als auf
ein alignmend zu achten.