Hallo,
ich bin auf ein Problem mit den .hex files gestoßen die mir der GNU
RISC-V CrossCompiler 8.3.0 (riscv-none-embed) mit eclipse unter windows
erzeugt.
Die Programme sollen auf einer risc-v 32bit SOC Eigenentwicklung laufen.
Das Problem ist das Konstanten wie z.B. const char values[15] = { 128,
64, 32, 16, 8, 4, 2, 1, 2, 4, 8, 16, 32, 64, 128 }; im erzeugten .hex
file in ihrer "nativen" Größe in diesem Fall jeweils als ein byte
abgespeichert werden und nicht wie es für mich richtg wäre jeweils
erweitert als 4 bytes 32bit word). Mit int oder long funktioniert es
wieder, die werden jeweils als 4 bytes gespeichert. Optionen wie z.B.
mstrict-align oder malign-data ändern leider nichts.
Wenn irgendwie im .hex file gekennzeichnet wäre das jetzt bytes folgen
und kein word wäre das super aber ist nicht der Fall.
Wie kann ich das hinbekommen?
Im Anhang ist mein linker script (denke dort habe ich überall das
alignment auf 4 gesetzt).
Die Konstanten stehen am Ende von .text und werden vom startup-code in
.data kopiert.
Danke
Christian
Christian G. schrieb:> jeweils als ein byte> abgespeichert werden und nicht wie es für mich richtg wäre jeweils> erweitert als 4 bytes 32bit word).
Warum sollte das richtig sein?
Warum gibst du sie als byte an, wenn du sie als Wort abgespeichert haben
möchtest?
MaWin schrieb:> Warum sollte das richtig sein?
... weil es kein erkennbare Unterscheidung zwischen instructions und den
values selber gibt, instructions sind 32bit breit, Datenbus und der
Speicher auch.
Woher soll der loader sonst wissen ob er jetzt gerade ein byte oder ein
word kopieren soll?
> Warum gibst du sie als byte an, wenn du sie als Wort abgespeichert haben> möchtest?
... eigentlich habe ich das so verstanden das egal welcher Datentyp
dieser immer als 32bit word gespeichert wird, was aber anscheinend nicht
stimmt, das erzeugte .hex file ist ja korrekt wenn der Speicher auch als
bytes organisiert ist.
Christian G. schrieb:>> Warum gibst du sie als byte an, wenn du sie als Wort abgespeichert haben>> möchtest?> ... eigentlich habe ich das so verstanden das egal welcher Datentyp> dieser immer als 32bit word gespeichert wird
Das hast du falsch verstanden.
Der Sinn der verschieden großen Integertypen liegt ja u.a. darin, die
Speicherplatzbelegung größerer Arrays jeweils auf das Notwendige
reduzieren zu können.
Christian G. schrieb:> Das Problem ist das Konstanten wie z.B. const char values[15] = { 128,> 64, 32, 16, 8, 4, 2, 1, 2, 4, 8, 16, 32, 64, 128 }; im erzeugten .hex> file in ihrer "nativen" Größe in diesem Fall jeweils als ein byte> abgespeichert werden und nicht wie es für mich richtg wäre jeweils> erweitert als 4 bytes 32bit word).
Wenn Du ein char-Array anlegst, hast Du ein char-Array. Genau das, was
man erwarten würde.
Wenn Du was anderes haben willst, solltest Du das hinschreiben.
Christian G. schrieb:> Woher soll der loader sonst wissen ob er jetzt gerade ein byte oder ein> word kopieren soll?
Der loader kopiert einfach X Bytes, mit X Z.b. 1643. Den kümmert die
Organisation nicht. Einmal X Bytes von Adresse Y im Rom nach Z im RAM.
Wobei .... Das gilt für initialisierte Variablen, Konstanten eigentlich
nur, wenn der Prozessor nicht einfach aus dem Rom lesen kann.
Von daher, ... was möchtest Du?
Oder verwechselst Du das mit Parametern einer Funktion, die wirklich
mindestens int-Breite haben
A. S. schrieb:> Oder verwechselst Du das mit Parametern einer Funktion, die wirklich> mindestens int-Breite haben
Haben sie IMO nicht. Das ist allenfalls üblicherweise so auf CPUs mit
mindestens 16 bit und wenn nicht mehr Parameter übergeben werden, als
Register dafür im ABI vorhanden sind (Rest über den Stack).
Christian G. schrieb:> Die Programme sollen auf einer risc-v 32bit SOC Eigenentwicklung laufen.> Das Problem ist das Konstanten wie z.B. const char values[15] = { 128,> 64, 32, 16, 8, 4, 2, 1, 2, 4, 8, 16, 32, 64, 128 }; im erzeugten .hex> file in ihrer "nativen" Größe in diesem Fall jeweils als ein byte> abgespeichert werden und nicht wie es für mich richtg wäre jeweils> erweitert als 4 bytes 32bit word). Mit int oder long funktioniert es> wieder, die werden jeweils als 4 bytes gespeichert. Optionen wie z.B.> mstrict-align oder malign-data ändern leider nichts.> Wenn irgendwie im .hex file gekennzeichnet wäre das jetzt bytes folgen> und kein word wäre das super aber ist nicht der Fall.>> Wie kann ich das hinbekommen?
Kennt deine RISC-V Eigenentwicklung denn die Assemblerbefehle:
LB, LH, LBU und LBH?
Die sind zuständig um Bytes und Halfwords (16bit) Daten zu laden, und
auf 32 Bits zu erweitern. Der Compiler wird sicher solche Befehle
verwenden, wenn du auf Byte Arrays zugreifst.
Beim laden des Hexfiles die Daten zu ändern, ist keine gute Idee, dann
stimmt ja die nachfolgenden Adressen nicht mehr überein, mit dem was der
Kompiler angenommen hat.
Danke für die ganzen Antworten, ich hatte das echt falsch verstanden,
klar sind die Befehle um bytes / half words zu laden/schreiben
implementiert aber die operieren auf einem 32bit word, ich werde den
Speicherzugriff ändern.
Danke!
Christian G. schrieb:> aber die operieren auf einem 32bit word, ich werde den> Speicherzugriff ändern.
Ich sehe da keinen Widerspruch. Wenn du ein Byte lesen willst, dann
liest du halt 32 Bit, nimmst davon dann die richtigen 8 Bits und wirfst
den Rest weg. Für Halfwords das gleiche.
Es hängt vom Speichersystem ab, ob das fies werden kann (z.B. weil
Adressen 0x2002 noch existiert, aber 0x2003 nicht), aber das kann man ja
per Architekturdekret verbieten.
Ich glaube, das richtige Stichwort ist "alignment": Ein Byte hat ein
Alignment von 1, ein Halfword von 2, ein Word von 4 und so weiter.
S. R. schrieb:> Es hängt vom Speichersystem ab, ob das fies werden kann (z.B. weil> Adressen 0x2002 noch existiert, aber 0x2003 nicht), aber das kann man ja> per Architekturdekret verbieten.
genau das ist das Problem, es wird versucht von einer Adresse zu lesen
die nicht 32bit aligned ist, keine Ahnung ob ich dem compiler das
irgendwie per Parameter etc. verbieten kann, denke die einfachere
Variante ist das ändern meiner CPU da die sich eh im Entwicklungs-
/Test-Stadium befindet.
Glaube das Thema ist damit erledigt, Danke an alle.
RISC-V erwartet, dass du words und halfwords auch von 'unaligned'
Adressen lesen kannst (beim Schreiben dasselbe).
Bei einfachen RISC-V Implementationen wird bei unaligned Zugriff oft
einfach ein Interrupt ausgelöst, und das Ganze dann in Software richtig
behandelt.