Hallo,
im DB des SAMD21 steht, dass ein DMA-Descriptor-Block
128-bit aligned sein muss.
"Bits 31:0 – DESCADDR[31:0] Next Descriptor Address
This bit group holds the SRAM address of the next descriptor.
The value must be 128-bit aligned."
Da die Adresse des next descriptors aligned sein muss,
und diese Adresse auf das Ende des ganzen Blocks zeigt,
muss ich folglich die ganze Struktur 128-bit aligned
im RAM ablegen können.
Mit welcher Anweisung kann man das erreichen, ohne eine feste Adresse
angeben zu müssen?
Von selbst macht er das ja nicht?
probieren. Aber:
https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes
"If your linker is only able to align variables up to a maximum of
8-byte alignment, then specifying aligned(16) in an _attribute_ still
only provides you with 8-byte alignment. See your linker documentation
for further information."
Du müsstest also rausfinden, was der Linker maximal unterstützt.
Alternativ: in eine eigene section packen, und im Linkerscript diese
entsprechend ausrichten.
Alexxx schrieb:> Da die Adresse des next descriptors aligned sein muss,> und diese Adresse auf das Ende des ganzen Blocks zeigt,> muss ich folglich die ganze Struktur 128-bit aligned> im RAM ablegen können.> Mit welcher Anweisung kann man das erreichen, ohne eine feste Adresse> angeben zu müssen?
in C++:
1
// the array "cacheline" will be aligned to 128-byte boundary
2
alignas(128)charcacheline[128];
In C11 geht es mit dem entsprechenden header (welches alignas als Alias
für _Alignas definiert):
Torsten R. schrieb:> In C11 geht es mit dem entsprechenden header (welches alignas als Alias> für _Alignas definiert):
Auch der wird sich allerdings nicht über potenzielle Restriktionen des
Linkers hinwegsetzen können; diese müsste der TE also zuerst eruieren.
Wenn er das hat, geht's auch ohne C11 mit dem genannten Attribut.
Jörg W. schrieb:> Wenn er das hat, geht's auch ohne C11 mit dem genannten Attribut.
Oder eben ohne GCC :-) Welches C wird den in der Praxis so gesprochen?
(Ich habe immer den Verdacht, viele embedded C-Entwickler wissen das
überhaupt nicht).
Torsten R. schrieb:> Oder eben ohne GCCDas war aber im ${subject} des Threads gefordert.
> Welches C wird den in der Praxis so gesprochen?
Was meinst du damit, welche Version des Standards?
Das dürfte stark von deiner Zielplattform abhängen. Wenn's Microsoft
ist, dann C89, mit paar Ergänzungen, die sie für würdig befunden haben.
:)
Embedded: wir benutzen C99/gnu99 derzeit, als Erweiterung gegenüber C89
dabei vor allem benannte Initialisierung von structs,
Variablendefinitionen so lokal wie möglich, ggf. variable Argumentliste
in Makros (bspw. wenn man printf wrappen möchte). Mittlerweile dürfte
allerdings die Verbreitung C11-tauglicher Compiler gut genug sein, dass
man auch das nehmen könnte. Habe noch nicht getestet, inwiefern sich
unsere aktuellen Projekte einfach „upgraden“ ließen.
Jörg W. schrieb:> Das war aber im ${subject} des Threads gefordert.
Ich würde das jetzt nicht so verstehen wollen, dass die Lösung nur mit
dem GCC funktioniert, sondern eben auch mit dem GCC. :-) (Ich gehe
jetzt mal davon aus, dass der GCC auch C11 unterstützt)
Ich würde im Prinzip immer versuchen, eine Lösung zu finden, die mit den
Standards der Sprache auskommt. Aber klar, wenn die Verwendung neuer
Sprachstandards wie C11 eine Einschränkung darstellt, dann muss halt
eine Compiler spezifische Lösung her (wobei man die Portierbarkeit des
Codes dann auf GCC und < C11 reduziert).
OK, danke schonmal @alle.
Siehe angehängtes Bild (Family-DB Seite 307)
Der Linker ist der, der bei Atmel Studio 7.0 dabe ist ;-)
Weiteres Problem:
Die Struktur ist nur 12Byte lang. Das Ende der
Struktur muss aligned sein, so dass die Anfangsadresse NICHT
128Bit-aligned ist! Grrrr...
- Geht sowas nur mit einer (berechneten) festen Adresse?
- und was bedeutet dieses aligned dann eigentlich?
Muss das letzte Byte der Struktur dann auf Adresse x0xxxF
oder auf x0xxx0 liegen???
Die Brachialmethode wäre natürlich, eine Variable mit vielen Bytes
anzulegen und das Beschreiben der Böcke mit berechneten Zeigern
darin zu machen.
Aber das würde natürlich haufenweise kostbares RAM fressen ...
Es muss doch eine vernünftige Methode geben. Das ASF macht es ja auch
irgend wie. Ich gebe zu, dass ich da zu faul bin, mich durch diesen
ganzen Wirrwar durchzubeißen.
Bei der align-Anweisung wird im INET gesagt, dass dann Lücken
im RAM erzeugt werden. Kann der Compiler nicht kleinere Variablen
zum Auffüllen verwenden?
Jörg W. schrieb:> Du könntest> __attribute__((aligned(16)))> probieren. Aber:>> https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes>> "If your linker is only able to align variables up to a maximum of> 8-byte alignment, then specifying aligned(16) in an attribute still> only provides you with 8-byte alignment. See your linker documentation> for further information."
Wäre ein derartiger Linker nicht inkompatibel zum C++ Standard (habe
nicht in den C Standard geguckt)? Ich konnte im Standard keine
Einschränkung finden. Kennst du einen solchen Linker und weißt ob er
Fehler oder Warnungen ausgibt?
mh schrieb:> Wäre ein derartiger Linker nicht inkompatibel zum C++ Standard
Warum sollte er? Wo garantiert der C++-Standard, dass du alles beliebig
kurios ausrichten lassen kannst? Ich habe da auch nicht reingeschaut,
aber vermute ganz stark, dass man da so gut wie alle Details als
"implementation-defined" standardisiert haben wird, damit alle
existierenden Implementierungen damit benutzbar sind.
Alexxx schrieb:> Die Struktur ist nur 12Byte lang.
Wie kommst du denn darauf? Die ist natürlich 128 Bits (= 16 Bytes lang).
Schau einfach mal in die Appnote:
https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en591729
da gibt's ein Bild:
1
DMA Transfer Descriptor
2
3
The transfer descriptor resides in the SRAM and defines these channel properties.
Jörg W. schrieb:> mh schrieb:>> Wäre ein derartiger Linker nicht inkompatibel zum C++ Standard>> Warum sollte er? Wo garantiert der C++-Standard, dass du alles beliebig> kurios ausrichten lassen kannst? Ich habe da auch nicht reingeschaut,> aber vermute ganz stark, dass man da so gut wie alle Details als> "implementation-defined" standardisiert haben wird, damit alle> existierenden Implementierungen damit benutzbar sind.
Ok ich bin nur blind. Der C++ Standard sagt
1
if the constant expression does not evaluate to an alignment value ([basic.align]), or evaluates to an extended alignment and the implementation does not support that alignment in the context of the declaration, the program is ill-formed.
Es müsste also ne Meldung an irgend einer Stelle geben.
@Jörg W.
>> Schau einfach mal in die Appnote:
Vielen Dank für den Hinweis - die habe ich nicht gekannt. Werde die mal
gewissenhaft durcharbeiten.
>>> Die Struktur ist nur 12Byte lang. -> Wie kommst du denn darauf?
Ich habe nur den Offset-Index bei 20.9 Register Summary - SRAM
angeschaut und der geht bis x0C.
Aber das Register hat ja selbst 4 Byte - ergo 16Byte.
"Asche auf mein Haupt"
>> Der GNU-Linker für arm-none-eabi...
Nochmals vielen Dank für deine Untersuchungen dazu.
Dann sollte es mit __attribute__((aligned(16))) funktionieren,
wenn die Anfangsadresse (Struct-Variable) aligned ist.
Dann ist die DB-Aussage zu DESCADDR missverständlich.
Das letzte Byte von DESCADDR ist dann vor der align-Grenze...
Dann ist meine Anfrage damit beantwortet.
Danke nochmal an Alle...
Jörg W. schrieb:> Torsten R. schrieb:>> Oder eben ohne GCC>> Das war aber im ${subject} des Threads gefordert.>>> Welches C wird den in der Praxis so gesprochen?>> Was meinst du damit, welche Version des Standards?>> Das dürfte stark von deiner Zielplattform abhängen. Wenn's Microsoft> ist, dann C89, mit paar Ergänzungen, die sie für würdig befunden haben.> :)>> Embedded: wir benutzen C99/gnu99 derzeit, als Erweiterung gegenüber C89> dabei vor allem benannte Initialisierung von structs,> Variablendefinitionen so lokal wie möglich, ggf. variable Argumentliste> in Makros (bspw. wenn man printf wrappen möchte). Mittlerweile dürfte> allerdings die Verbreitung C11-tauglicher Compiler gut genug sein, dass> man auch das nehmen könnte. Habe noch nicht getestet, inwiefern sich> unsere aktuellen Projekte einfach „upgraden“ ließen.
Microsoft war lange Zeit weit zurück, hat aber inzwischen aufgeholt, und
unterstützt nun wohl großteils C11.
GCC und LLVM können C17.
IAR kann wohl recht gut C99.
SDCC großteils C17, aber noch mit der ein oder anderen Lücke (und es
gibt eine experimentellen C2X-Modus, der aber noch keine Attribute
kann).
Und dann gibt es noch so Nachzügler wie Raisonance für STM8 oder Keil
für MCS-51, wo es selbst bei C90 große Lücken gibt.