moin moin,
kleines Problem beim umladen von Speicherwerten.
Gegeben:
Array a und b mit 8Bytes
Pointer x und y auf a[0] und b[0]
Sind die Pointer vom Typ DWord werden 4 Byte umgeladen
Sind die Pointer vom Typ uint64 gibs ein Fault.
Warum?
Ist da was "freizuschalten"?
Danke
Pieter
ein Fault.
Wenn du nicht so faul(t) wärst, hättest du ja den Typ des Faul(t)s
dazuschreiben können.
Ich würde mal auf mangelndes Alignment tippen.
Du bist für QWords vermutlich zu dumm.
Pieter schrieb:> Sind die Pointer vom Typ DWord werden 4 Byte umgeladen
Im ARM Kontext ist:
- Byte = 8bit
- Halfword = 16bit
- Word = 32bit
- Double Word = 64bit
Prüfe die Größen also nochmal, und verwende hier keine Windows
Begriffe... Datentypen mit "word" im Namen gibt's in C auch nicht, also
wenn schon short, int, long...
Pieter schrieb:> Warum?
Vielleicht ist der Pointer kein Vielfaches von 4? Das ist bei Double
Words erforderlich (alignment).
Pieter schrieb:> Array a und b mit 8Bytes> Pointer x und y auf a[0] und b[0]>> Sind die Pointer vom Typ DWord werden 4 Byte umgeladen> Sind die Pointer vom Typ uint64 gibs ein Fault.>> Warum?
Gegenfrage: Warum machst du das? Also warum ist deine Variable als
Byte-Arrays definiert, statt direkt als uint64_t? So handelt man sich
schnell Alignment-Probleme ein, die genau solche Auswirkungen haben.
Du musst also entweder von Hand dafür sorgen, dass dein Array das
richtige Alignment hat, oder du nimmst gleich den richtigen Datentyp,
dann kümmert sich der Compiler automatisch um das korrekte Alignment.
moin Rolf,
die Arrays sind Bestandteil des Datenbuffers vom CAN-Modul und da sind
es nunmal Bytes.
Umladen mit move ist Byteweise und dauert.
Das Umladen als DWord = 4Bytes funktioniert, sind aber auch mehrere
Befehle.
Daher die Idee es mit QWord = 8Bytes in einem Rutsch zu erledigen.
VG
Pieter
Pieter schrieb:> Daher die Idee es mit QWord = 8Bytes in einem Rutsch zu erledigen.
Wie soll ein CPU Kern mit 32bit Registerbreite 8 bytes in einem Rutsch
verarbeiten?
Bevor wir es vergessen: benenne den betroffenen Mikrocontroller, zeige
den Quelltext, benenne den verwendeten Compiler.
Pieter schrieb:> moin Rolf,>> die Arrays sind Bestandteil des Datenbuffers vom CAN-Modul und da sind> es nunmal Bytes.> Umladen mit move ist Byteweise und dauert.> Das Umladen als DWord = 4Bytes funktioniert, sind aber auch mehrere> Befehle.> Daher die Idee es mit QWord = 8Bytes in einem Rutsch zu erledigen.>> VG> Pieter
Umladen, move? Du meinst memcpy?
Kopieren mit unbekanntem (oder nicht passenden) Alignment macht man mit
memcpy().
Wenn man ein bestimmtes Alignment erzwingen will, kann man statt des
eigentlichen Datentyps eine union deklarieren, die zusätzlich zu dem
gewünschten Element noch ein (ansonsten unbenutztes) enthält, daß das
gewünschte Alignment hat (in diesem Fall z.B. uint64_t).
Das erzwingt das größere Alignment für das (eigentlich gewünschte)
Element mit kleinerem Alignment.
Markus F. schrieb:> Wenn man ein bestimmtes Alignment erzwingen will, kann man statt des> eigentlichen Datentyps eine union deklarieren, die zusätzlich zu dem> gewünschten Element noch ein (ansonsten unbenutztes) enthält, daß das> gewünschte Alignment hat (in diesem Fall z.B. uint64_t).>> Das erzwingt das größere Alignment für das (eigentlich gewünschte)> Element mit kleinerem Alignment.
Nimmt man da nicht eher alignas?
moin moin,
danke für die Beiträge.
Da ich in Pascal progge...wer kann Pascal?
Stefanus F. schrieb:> Wie soll ein CPU Kern mit 32bit Registerbreite 8 bytes in einem Rutsch> verarbeiten
mit
LDRD R1, R2, [R0, #0]
werden R1+R2 mit dem Inhalt des Speichers mit Zeigers aus R0 geladen.
Der Mikrocontroller ist ARM-M3 und und ARM-M4.
VG
Pieter
Pieter schrieb:> Da ich in Pascal progge...wer kann Pascal?
Oha, lang ist's her. Da kam gerade Windows 95 auf den Markt.
Pieter schrieb:> mit> LDRD R1, R2, [R0, #0]> werden R1+R2 mit dem Inhalt des Speichers mit Zeigers aus R0 geladen.
Interessant, da habe ich etwas dazu gelernt.
Pieter schrieb:> DWord = 4Bytes
Nochmal: DWord sind 8 Bytes!
Pieter schrieb:> QWord = 8Bytes
QWord sind dementsprechend 16 Bytes.
Pieter schrieb:> Umladen mit move ist Byteweise und dauert.
Move? Du meinst die ARM-Instruktion "mov"? Die verarbeitet Words
(=4Byte), kann aber überhaupt nicht auf den Speicher zugreifen.
Pieter schrieb:> Der Mikrocontroller ist ARM-M3 und und ARM-M4.
Was ist das? Meinst du vielleicht ARM Cortex-M3?
Pieter schrieb:> LDRD R1, R2, [R0, #0]
Und ist das auch der Code der da rauskommt? R0 ist sicher die korrekte
Adresse, welche ein Vielfaches von 4 ist?
Pieter schrieb:> Sind die Pointer vom Typ uint64 gibs ein Fault.
Was steht dann im CFSR? Ist z.B. das UNALIGNED bit gesetzt? Sicher dass
der Fault exakt bei diesem Zugriff geschieht und nicht irgendwann
anders?
Stefanus F. schrieb:> Das war doch wohl klar, oder?
Naja, man darf den verwendeten Prozessor ruhig korrekt benennen, vor
allem wenn "ARM M3" eine völlig unübliche Bezeichnung ist. Welcher STM32
es genau ist wissen wir ja auch noch nicht?
moin moin,
>>Welcher STM32 es genau ist wissen wir ja auch noch nicht?
Ist auch nicht nötig, den es geht nur um die CPU-Core.
"The STM32F10xxx is a family of microcontrollers with different memory
sizes, packages and peripherals"
Da darf einer von genommen werden.
Was bringt der genaue Typ?
VG
Pieter
Pieter schrieb:> Was bringt der genaue Typ?
Der spezifische Typ könnte Errata haben, der CAN-Controller könnte an
einem anderen Bus hängen (APB1/2) welcher sich anders verhält, bei den
F103 gibt es Konflikte mit der USB-Peripherie, beim F105 jedoch nicht,
usw. Aber wenn du den Typ natürlich geheim halten musst...
Pieter schrieb:> Was bringt der genaue Typ?Pieter schrieb:> Ist da was "freizuschalten"?
Wenn da etwas freigeschaltet werden kann/muss, dann ist das sicher
spezifisch für das bestimmte unbekannte Mikrocontroller Modell.
Pieter schrieb:> Ist auch nicht nötig, den es geht nur um die CPU-Core.
Der CPU-Core hat keine Probleme mit LDRD. Da gibt's nichts
freizuschalten; es muss nur die korrekte Adresse und Alignment beachtet
werden. Das Problem liegt also am Peripheriebus oder der Peripherie
selbst, oder sowieso ganz woanders.
Die Richtige Lösung des Problems wurde in der 4. Antwort genannt:
Der besagte Buffer muss als uint64_t definiert sein wenn man in dieser
Weise drauf zugreifen will, dann weiß man automatisch daß das
erforderliche Alignment garantiert ist.
Wenn man es außerdem zusätzlich noch als Bytearray braucht macht man ein
union.
Bernd K. schrieb:> dann weiß man automatisch daß das> erforderliche Alignment garantiert ist.
Da es sich um ein Peripherie-Register handelt, wird die Adresse
hartkodiert, weshalb hier nichts garantiert ist. Die CAN-Daten-Register
sind allerdings korrekt aligned.
Markus F. schrieb:> wo steht das?Pieter schrieb:> die Arrays sind Bestandteil des Datenbuffers vom CAN-Modul und da sind> es nunmal Bytes.
Aber das sind natürlich keine Bytes, sondern zwei 32bit-Register.
Dr. Sommer schrieb:> Pieter schrieb:>> die Arrays sind Bestandteil des Datenbuffers vom CAN-Modul und da sind>> es nunmal Bytes.>> Aber das sind natürlich keine Bytes, sondern zwei 32bit-Register.
Das kann alles mögliche sein, auch ein Bereich im ganz normalen SRAM wo
die Peripherie dann per DMA drauf zugreift (wie es zum Beispiel bei USB
üblich ist) solange der OP nicht sagt welcher gottverdammte Controller
das überhaupt sein soll!
Bernd K. schrieb:> auch ein Bereich im ganz normalen SRAM wo> die Peripherie dann per DMA drauf zugreift (wie es zum Beispiel bei USB> üblich ist)
Nein. Bei allen STM32F1xx sind das zwei schnöde
32bit-Peripherieregister. Der Knackpunkt ist, ob man bei solchen
Peripherieregistern LDRD nutzen kann... Der STM32-CAN kann auch kein
DMA.
Bernd K. schrieb:> solange der OP nicht sagt welcher gottverdammte Controller> das überhaupt sein soll!
Das ist allerdings wirklich wenig verständlich; er vertraut wohl darauf
dass STM32-Kundige wissen, wie das bei allen STM32 aussieht.
Dr. Sommer schrieb:> Bernd K. schrieb:>> solange der OP nicht sagt welcher gottverdammte Controller>> das überhaupt sein soll!>> Das ist allerdings wirklich wenig verständlich; er vertraut wohl darauf> dass STM32-Kundige wissen, wie das bei allen STM32 aussieht.
Er hat ja auch erst im 11. Post preisgegeben, dass es um Pascal und
nicht um C geht. Warum sollte er also den Controller so schnell
preisgeben?.
Dr. Sommer schrieb:> Im ARM Kontext ist:> - Byte = 8bit> - Halfword = 16bit> - Word = 32bit> - Double Word = 64bit
Ach was.
Das Gelaber hatte ich schon vor 20 Jahren bei den 32 bittigen Fujitsu's
und später bei ARM. Es ist einfach nur unsystematisch und deshalb
verwendet man so etwas auch besser nicht, sondern hält sich ganz einfach
an die herkömmlichen Intel-Begriffe. Und da ist ein WORD eben 16 bittig,
DWORD 32 und QWORD 64. Basta.
Aber bei ARM findet man weder DWORD noch QWORD, denn dort gibt es eben
nur int64 als Datentyp und um ein QWORD zu kriegen, muß ein unsigned
davor. Dann hat man das.
Was bleibt? (mal abgesehen von der ewigen fruchtlosen Rechthaberei)
Es bleibt, daß manche Cores mit unausgerichteten Daten eben doch nicht
zurecht kommen oder daß gerade in der Peripherie von ST oftmals übelste
Verrenkungen nötig waren, weil selbige in weiten Teilen nur 16 bittig
ist. Siehe der USB-RAM beim STM32F103. Zugriff 32bittig, aber nur
16bittig belegt. Scheint bei neueren Cores behoben zu sein, aber gerade
bei den älteren Cores hatte ST massiv bei NXP abgekupfert und dabei
einiges falsch gemacht, wohl weil ST eben nicht die Informationen von
Sharp hatte, die NXP beim Aufkauf der BlueStreaks bekommen hatte. Ist
aber ne Weile her.
W.S.
W.S. schrieb:> Es ist einfach nur unsystematisch
Was ist daran unsystematisch?
W.S. schrieb:> verwendet man so etwas auch besser nicht, sondern hält sich ganz einfach> an die herkömmlichen Intel-Begriffe
Warum sollte man sich an Intel-Begriffe halten, wenn man ARM
programmiert?
Im ARMv7M Architecture Reference Manual heißt es:
> The ARMv7-M architecture supports the following data types in memory:> Byte 8 bits.> Halfword 16 bits.> Word 32 bits.
Warum sollte man irgendeine andere Architektur-Definition nehmen? Den
Begriff "Quardword" gibt es hier übrigens nur um Kontext der
Vektor-Float-Extensions, VFP und NEON.
W.S. schrieb:> denn dort gibt es eben> nur int64 als Datentyp und um ein QWORD zu kriegen,
int64 ist aber C-spezifisch, und nicht ARM-spezifisch. Jetzt hast du
also Intel-Begriffe und C-Begriffe mit gleichlautenden, aber
anders-bedeutenden, ARM-Begriffen vermischt. Hurra.
W.S. schrieb:> Siehe der USB-RAM beim STM32F103. Zugriff 32bittig, aber nur> 16bittig belegt
Aber nichts unaligned, also keine größeren Probleme.
Pieter schrieb:> moin moin,>> da keiner was wirkliches zum Thema sagen wollte oder konnte, klinke ich> mich nun aus.
Lol, was für ein Prachtexemplar von Fragesteller, wie im Lehrbuch.
--
Ich bin dafür daß sobald der Threaderöffner anfängt vorsätzlich die
Problemlösung selbst zu sabotieren (wie hier in Post 16 geschehen) der
ganze Thread kommentarlos gelöscht wird.
Pieter schrieb:> da keiner was wirkliches zum Thema sagen wollte oder konnte, klinke ich> mich nun aus.
Was?
Beantworte doch erstmal unsere Rückfragen, damit wir uns mit
vernünftigen Beiträgen beteiligen können. Du hast es in der Hand!
W.S. schrieb:> Dr. Sommer schrieb:>> Im ARM Kontext ist:>> - Byte = 8bit>> - Halfword = 16bit>> - Word = 32bit>> - Double Word = 64bit>> Ach was.>> Das Gelaber hatte ich schon vor 20 Jahren bei den 32 bittigen Fujitsu's> und später bei ARM.
Logisch. Seit es 32-Bit-Architekturen gibt, eben. Denn Word bezeichnet
die native Breite der Architektur. Das Word ist beim x86 nur deshalb 16
Bit breit, weil der mal als 16-Bit-Architektur angefangen hat und man
den Datentyp aus Gründen der Rückwärtskompatibilität nicht geändert hat.
Die Bezeichnung gab es übrigens schon, bevor es Intel überhaupt gab. Auf
der PDP-10 aus den 60er Jahren beispielsweise war ein Word 36 Bit lang.
Es ist einfach nur unsystematisch und deshalb
> verwendet man so etwas auch besser nicht, sondern hält sich ganz einfach> an die herkömmlichen Intel-Begriffe.
"Herkömmlich" ist wie gesagt, dass Word die native Breite bezeichnet.
> Und da ist ein WORD eben 16 bittig, DWORD 32 und QWORD 64. Basta.
Aha, "basta"… "was interessiert mich der Rest der Welt, ich nenne
einfach alles so wie bei Intel, auch wenn das für andere Architekturen
falsch ist".
Mw E. schrieb:> Jemand schrieb:>> i8, i16, i32, i64, etc. wäre auch irgendwie zu einfach und eindeutig.>> Gibts doch!> cstdint / stdint.h und Spaß haben!> http://www.cplusplus.com/reference/cstdint/
Da bricht man sich halt immer die Finger mit den ganzen unterstrich-t.
Ich persönlich machs wie die Kernelhacker und hab mir Abkürzungen
gemacht wie u8, u16, i16, etc...
Jemand schrieb:> i8, i16, i32, i64, etc. wäre auch irgendwie zu einfach und eindeutig
Knallt bei Code von Codegeneratoren, die verwenden dieses Pattern für
"normale" int Variablen sehr gerne. Daher verwender der Standard ein
paar Zeichen mehr.
Das LDRD und STRD auf allen Cortex-M immer bei misalinged address
knallen, musste auch ich auf die harte Tour lernen.
Bei den "normalen" LDR/STR Befehlen kann man das ja auf ARMv7-M
kompatiblen abstellen (bzw. ist das per default abgestellt).
Jim M. schrieb:>> Das LDRD und STRD auf allen Cortex-M immer bei misalinged address> knallen, musste auch ich auf die harte Tour lernen.
Wobei allign dabei bedeutet, auf 8Byte Grenze, es werden ja auch 64Bit
gelesen. Deshalb auch das beschriebene Verhalten, daß 32Bit Zgriffe
funktionierten, aber 64Bit Zugriffe nicht.
Irgendwie erinnere ich mich gelesen zu haben, daß GCC diese beiden
Befehle nicht verwendet. Hier geht es aber um eine nicht näher genannt
Pascal Version. Google bringt dieses Problem übrigens auch mit Keil C in
Verbindung.
Jim M. schrieb:> Bei den "normalen" LDR/STR Befehlen kann man das ja auf ARMv7-M> kompatiblen abstellen (bzw. ist das per default abgestellt).
Ich schalte das aber lieber ein, denn: Laut C(++) Standard sind solche
unaligned Zugriffe verboten. Dass ARMv7M die teilweise erlaubt ist pure
Nettigkeit. ARMv6M (Cortex-M0) erlaubt diese überhaupt nicht. Um
korrekten und portablen Code zu schreiben, vermeide ich solche Zugriffe,
und falls doch einer passiert lass ich mir das per Fault anmeckern.
Carl D. schrieb:> Wobei allign dabei bedeutet, auf 8Byte Grenze, es werden ja auch 64Bit> gelesen.
Nein, auf 4 Byte Grenze!
Carl D. schrieb:> Deshalb auch das beschriebene Verhalten, daß 32Bit Zgriffe> funktionierten, aber 64Bit Zugriffe nicht.
Nein, das hat irgendeinen anderen Grund.
Carl D. schrieb:> Irgendwie erinnere ich mich gelesen zu haben, daß GCC diese beiden> Befehle nicht verwendet.
Doch, tut er. Deshalb auch das lustige Problem, dass bei den kaputten
Linker Scripten von ST, bei denen der Stack falsch aligned ist, wenn man
eine double Variable per Stack übergibt, man einen Crash bekommt, weil
diese per LDRD/STRD zugegriffen wird.
Dr. Sommer schrieb:> Carl D. schrieb:>> Wobei allign dabei bedeutet, auf 8Byte Grenze, es werden ja auch 64Bit>> gelesen.>> Nein, auf 4 Byte Grenze!>> Carl D. schrieb:>> Deshalb auch das beschriebene Verhalten, daß 32Bit Zgriffe>> funktionierten, aber 64Bit Zugriffe nicht.>> Nein, das hat irgendeinen anderen Grund.>> Carl D. schrieb:>> Irgendwie erinnere ich mich gelesen zu haben, daß GCC diese beiden>> Befehle nicht verwendet.>> Doch, tut er. Deshalb auch das lustige Problem, dass bei den kaputten> Linker Scripten von ST, bei denen der Stack falsch aligned ist, wenn man> eine double Variable per Stack übergibt, man einen Crash bekommt, weil> diese per LDRD/STRD zugegriffen wird.
Was jetzt, hat LDRD/STRD das von ARM dokumentierte Verhalten, oder hat
es das nicht.
Ich würde vorschlagen zukünftig sich widersprechende Behauptungen
zumindest auf zwei getrennte Posts aufzuteilen.