Forum: Mikrocontroller und Digitale Elektronik STM32 : QWord


von Pieter (Gast)


Lesenswert?

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

von Was geht ab? (Gast)


Lesenswert?

Bitte den Beispiel Code einstellen und den verwendeten Compiler nennen.

Wie ist uint64_t in deinem Toolset deklariert?

von Brodo Feutel (Gast)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

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).

von Rolf M. (rmagnus)


Lesenswert?

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.

von Pieter (Gast)


Lesenswert?

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

von Stefan F. (Gast)


Lesenswert?

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.

von mh (Gast)


Lesenswert?

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?

von Markus F. (mfro)


Lesenswert?

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.

von mh (Gast)


Lesenswert?

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?

von Pieter (Gast)


Lesenswert?

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

von Stefan F. (Gast)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

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?

von Stefan F. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Was ist das? Meinst du vielleicht ARM Cortex-M3?

Das war doch wohl klar, oder?

von Dr. Sommer (Gast)


Lesenswert?

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?

von Pieter (Gast)


Lesenswert?

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

von Dr. Sommer (Gast)


Lesenswert?

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...

von Stefan F. (Gast)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

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.

von Markus F. (mfro)


Lesenswert?

Dr. Sommer schrieb:
> Da es sich um ein Peripherie-Register handelt,

wo steht das? Der OP wollte doch Speicherbereiche "umladen"?

von Dr. Sommer (Gast)


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

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!

von Dr. Sommer (Gast)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

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.

von mh (Gast)


Lesenswert?

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?.

von W.S. (Gast)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

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.

von Pieter (Gast)


Lesenswert?

moin moin,

da keiner was wirkliches zum Thema sagen wollte oder konnte, klinke ich 
mich nun aus.

VG
Pieter

von Bernd K. (prof7bit)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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!

von Nop (Gast)


Lesenswert?

Pieter schrieb:

> Warum?

Weil Du ein Alignment-Problem hast. Da Du den Sourcetext nicht zeigen 
willst, such den genauen Fehler halt selber.

von Rolf M. (rmagnus)


Lesenswert?

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".

von Jemand (Gast)


Lesenswert?

i8, i16, i32, i64, etc. wäre auch irgendwie zu einfach und eindeutig.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

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/

von Bernd K. (prof7bit)


Lesenswert?

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...

von Pascal (Gast)


Lesenswert?

Pieter schrieb:
> Da ich in Pascal progge...wer kann Pascal?

ich

von Jim M. (turboj)


Lesenswert?

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).

von Carl D. (jcw2)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

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.

von Carl D. (jcw2)


Lesenswert?

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.

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
Noch kein Account? Hier anmelden.