Guten Abend liebe Community,
ich stehe vor einem für mich nicht lösbaren Problem.
Generell würde ich meine Programmierkenntnisse als Vorgeschritten
bezeichnen, jedoch ist das nachfolgende Problem für mich logisch nicht
nachvollziehbar.
Toolchain : Arduino 1.8.19
uC : ESP32 - Sparkfun Thing
Folgender Code löst auf Core 1 ein Core Panic'ed (IllegalInctruction)
aus.
1
voidLC_SetHPD(booleanlvl){
2
bytetestdata=ReadByte(0x06);
3
}
4
5
voidLC_Init(){
6
LC_SetHPD(false);
7
}
8
9
10
byteReadByte(byteadrr){
11
12
}
13
14
voidsetup(){
15
16
delay(1000);
17
Serial.begin(115200);
18
Serial.println("Init System");
19
delay(1000);
20
LC_Init();
21
22
23
}
24
25
26
voidloop(){
27
28
29
}
wenn ich folgende Zeile lösche, gibt es keine Panic Probleme, und der uC
startet auch nicht neu.
1
bytetestdata=ReadByte(0x06);
Auch auf jeder anderen mir zugänglichen Microcontroller Architektur (AVR
8bit, SAMD) läuft der code ohne Probleme.
Nur eben auf dem ESP32 kommt es zu einer Core1 Panic.
Das ganze ist eigentlich ein deutlich umfangreicherer Code, jedoch
konnte ich es auf diesen Sektion reduzieren.
Ich bin extrem gespannt welcher verrückte Mechanismus sich dahinter
versteckt.
Vielen Dank für die Hilfe !
Schalt mal Warnungen an!
Das das da oben compiliert ist ein Wunder.
>byte ReadByte(byte adrr) {>>}
da fehlt ein return wert;
>void LC_SetHPD(boolean lvl) {>> byte testdata = ReadByte(0x06);>>}
und weiter? Was soll mit testdata passieren, das wird wahrscheinlich
wegoptimiert und damit dein komplettes
LC_Init();
Der fehlende return ist mir bewusst, und im eigentlich code wird diese
Funktion zum lesen von i2c verwendet.
jedoch in beiden fällen - gibt es die Core1 Panic.
Sofern der Compiler das nun wegoptimiert , sollte es doch erst recht zu
keinem Panic state kommen ?
Versuche mal, einen Code zu posten, der ohne Warnungen und Fehler
compiliert. Und schreibe ihn nicht aus dem Gedächtnis nach, sondern
benutze C&P.
Am besten poste ihn als Dateianhang (*.c). Kleine Schnipsel im Post
eingebettet, nutzen nur selten was.
Es gibt hoffentlich auch noch eine Funktionsdeklaration für ReadByte die
vor LC_SetHPD() steht. Ansonsten definiert der Compiler sich nämlich
selbst was zusammen. (In diesem Fall sowas wie "int ReadByte(int)"). Auf
ARM oder AVR8 ist dass wegen deren ABI egal. Beim Tensilica Xtensa LX
(Der steckt im ESP32) müsste man deren ABI mal nachlesen.
Flötenschlumpf schrieb:> Darf man überhaupt von nicht durch vier teilbaren Adressen lesen?
Natürlich. x86 kann das ohne besondere Tricksereien, Bei ARM Cortex geht
das in entsprechend getagten Speicherbereichen auch. (Wird dann von der
MMU/MPU implizit auf mehrere Aligned Zugriffe umgemappt) Bei Zugriffen
auf andere Speicherbereiche oder bei älteren ARM CPUs im Allgemeinen
muss der Compiler dann z.B. statt einem 4-Byte Zugriff eben 4 einzelne
1-Byte-Zugriffe machen ud das dann zusammensetzen.
Andreas M. schrieb:> Natürlich.
Sorry, das nun wirklich nicht natürlich. :)
Das es beim ESP32 (und anderen geht) funktioniert, ok.
Aber versuche das z.B. mal auf einem SPARC V8 (z.B. LEON2/3/4) und auch
anderen. Es unterstützt längst nicht jede Architektur den "unligned
access".
Edit: Ich muss eine Einschränkung nachschieben :) Ein Bytezugriff
funktioniert "unaligned" auch beim SPARC. Aber ein Wortzugriff nicht.
Das aber wieder geht z.B. bei x86.
MaWin. schrieb:> Wie kann ein Bytezugriff unaligned sein?
%-/
Ja schon gut aber ich denke, jeder (außer du?) versteht, was ich meinte.
Für dich hatte ich es sogar in "" gestellt.
Flötenschlumpf schrieb:> Darf man überhaupt von nicht durch vier teilbaren Adressen lesen?
Wäre auch mein erster Verdacht gewesen. Beim ESP8266 hab ich mit
1
unsignedinti,j;
2
sscanf(buffer,"%u/%u",&i,&j);
wunderschöne Abbrüche produziert, die mit
1
alignas(4)unsignedinti;
2
alignas(4)unsignedintj;
3
sscanf(char*,"%u/%u",i,j);
behoben wurden.
Aber der hier vorgestellte Code verwendet ja überhaupt keine
Pointer/Referenzen/Adressen, sonst hätte ich das schonmal
angesprochen...
MfG, Arno
Arno schrieb:> Beim ESP8266 hab ich mit> unsigned int i, j;> sscanf(buffer, "%u/%u", &i, &j);>> wunderschöne Abbrüche produziert, die mit
das wäre aber arg kaputt.
A. S. schrieb:> Arno schrieb:>> Beim ESP8266 hab ich mit>> unsigned int i, j;>> sscanf(buffer, "%u/%u", &i, &j);>>>> wunderschöne Abbrüche produziert, die mit>> das wäre aber arg kaputt.
Wie gesagt, war so (ich hab gerade nachgesehen: die entsprechenden
Commits in meinem Code sind von 2018...).
Die Fehlermeldung war vermutlich diese: (von
https://forum.arduino.cc/t/brauche-hilfe-beim-debuggen-esp6266-unaligned-memory-access/651824)
> Exception 9: LoadStoreAlignmentCause: Load or store to an unaligned address
Ich hab jetzt wenig Motivation, das zu testen, ob das immer noch so ist
;)
MfG, Arno
Es gibt beim ESP32 durchaus Speicheradressen, die nur mit 4 byte
alignment adressiert werden dürfen.
Diese liegen allerdings im Instruction Memory, um z.B. den verfügbaren
RAM zu frisieren. Gut zu wissen, aber eher unwahrscheinlich für den TO.
1
Panic'ed(IllegalInctruction)
Der Fehler ist natürlich ärgerlich. Was da in der Toolchain wohl schief
gelaufen ist?
Vielleicht für den Moment mal auf einen anderen Datentypen ausweichen.
Das Programm muss ja nicht allen Programmieridealen genügen.
900ss D. schrieb:> Andreas M. schrieb:>> Natürlich.>> Sorry, das nun wirklich nicht natürlich. :)>> Das es beim ESP32 (und anderen geht) funktioniert, ok.> Aber versuche das z.B. mal auf einem SPARC V8 (z.B. LEON2/3/4) und auch> anderen. Es unterstützt längst nicht jede Architektur den "unligned> access".>> Edit: Ich muss eine Einschränkung nachschieben :) Ein Bytezugriff> funktioniert "unaligned" auch beim SPARC. Aber ein Wortzugriff nicht.> Das aber wieder geht z.B. bei x86.
Zitiere bitte vollständig. Die Frage war: "ob auf nicht durch vier
Teilbare Speicheradressen zugegriffen werden darf". Soweit ich weis gibt
es keine weltweit allgemeingültige Definition, das man das nicht darf.
Wenn, dann ist das eventuell eine architekturspezifische Einschränkung
und selbst dann ist es die Aufgabe des C-Compilers das korrekt
umzusetzen, auch bei Pointern. (Ja man kann den Compiler mittels Casts
zu allem möglichen zwingen, aber wer das tut sollte eben auch genau
wissen was er tut)
Andreas M. schrieb:> Zitiere bitte vollständig.
Es tut mir leid, aber den Wunsch möchte ich dir nicht erfüllen. Dann
werden am Ende die Beiträge kilometerlang und unübersichtlich. Die
Threads werden unnötig lang mit redundanten Informationen. Als Referenz
zu deinem Beitrag reicht das kurze Zitat. Jeder kann dann nachlesen.
Meine Meinung.
Zum Thema "unaligned". Natürlich sorgt der Compiler dafür, dass er
Pointer richtig initialisiert, das ist richtig. Allerdings gibt es sehr
oft Leute, die das nicht wissen dass sie nicht unaligned zugreifen
dürfen und es passiert auch versehentlich, dass man Pointer auf so einer
Maschine falsch benutzt.
Und weiter gibt es den Fall, dass ein Code wieder verwendet wird und
dieser vorher auf einer Architektur lief der unaligned Zugriffe nichts
ausmachten. Spätestens dann hat man ein Problem. Z.B
Protokolldatenverarbeitung im Stream wenn das Protokoll gepackt ist
(siehe Ethernet). Oder bei gepackten Strukturen ist es auch gerne
gesehen, dass unaligned Zugriffe passieren. Die erwähnte SPARC V8
Architektur ist so ein Fall, wo man aufpassen muss. Deshalb mein
Einwand, es ist ist nicht "natürlich".
Andreas M. schrieb:> Natürlich. x86 kann das ohne besondere Tricksereien,.....
Das ist ein ernstes Problem was hier nicht so allgemein als "natürlich"
hingestellt werden sollte. Genause wenig ist eine little Endian Maschine
"natürlich" weil es eben genauso big Endian gibt. Oder sollte der x86
oder ARM das Mass der Dinge sein? Sicher nicht.
Gerade "embedded Entwickler/innen" als Anfänger sollte das bewusst sein.
Ich habe es aber auch leider bei erfahrenen Entwicklern erlebt, dass
diese das nicht beachtet haben und ich wunderten.