ich bastle an einer Funktion herum, die mir zwei uint32_t[4] vergleichen soll. Dieser Funktion übergebe ich die Pointer auf die Arrays, während des Vergleichs wird beim Durchsteppen aber an irgendeiner Stelle die Referenz zerstört, danach schlägt der Vergleich fehl.
Leider habe ich außer dem Debugging keine Möglichkeit nachzuvollziehen, was das Programm macht (außer, dass ich weiß, dass es nicht das tut, was ich möchte).
Beim Aufruf der Funktion CompareColors werden die richtigen Adressen übergeben (lt. Debugger liegt background auf 0x0110 und measurement auf 0x0120), mit dem Eintritt in die for-Schleife zeigt er beim ersten Vergleich, dass die Adressen entweder "irgendwas" enthalten, hier wurde immer wieder 0x0940 gezeigt, oder der Debugger sagt "out of scope")
Ich habe auch versucht die Variablen als volatile zu definieren, ebenso habe ich versucht die Funktionsparameter als const zu definieren. In beiden Fällen unterscheidet sich vielleicht die Anzeige, ich habe aber nichts gefunden, mit dem der Vergleich sauber funktioniert. Auch ein Zugriff über reference[0] ändert nichts.
Umgebung:
MPLAB X IDE v6.05
XC8 v2.4
pickit4
Relevanter Code (main ist leicht gekürzt, ist aber für diesen Punkt nicht relevant):
implicit type promotion:
Ich habe diesbezüglich gegoogelt und die Doku für XC8 sagt: "uint32_t Unsigned integer of exactly 32 bits
width.
unsigned long"
Ich verstehe es so, dass xc8 diese Typen unterstützt (und lt. Doku sogar unsigned long long int) und dass der Compiler dafür sorgt, dass diese Variablen richtig verarbeitet werden. Sollte das nicht so sein, bin ich sehr an einer Erklärung interessiert.
volatiles Verständnisproblem:
Ich möchte nicht darauf eingehen, wie sinnlos der Beitrag ist. Ich habe geschrieben, dass das von mir erwartete Verhalten nicht gezeigt wurde. Damit muss ich meine Erwartungen hinterfragen und nach einigem erfolglosen googeln bin ich bei volatile und Compileroptimierungen gelandet. Natürlich ist das Trial and Error, hätte ich eine Lösung, würde ich hier nicht fragen.
Ich bin Anfänger in C und willig zu lernen. Da der Debugger Sachen macht, die ich nicht erklären kann, gibt es die Variante, dass in den paar von mir geposteten Zeilen etwas den Heap umschreibt oder sonst irgendwelche Schweinereien macht (die Init() Funktion schiebt nur Register für die Pin-Definition) oder der Debugger den Ablauf durcheinanderbringt. Beides würde ich verstehen, hätte aber gern verstanden, warum das so ist.
Hallo,
Du verwendest 32 Bit Werte in einem Array. Du möchtest im Array durch Inkrementieren des Pointers den nächsten Wert erreichen.
Ich weiß jetzt nicht, welchen Controller du verwendest aber evtl. musst du um mehrere Bytes inkrementieren um den Pointer zum nächsten Array-Element setzen.
... erkennbar hast du kein Verständnis vom Sinn zu const und volatile und zudem die Vorstellung das dritte als Erklärbär dir das abnehemen, dieses copy&past Verhalten verdient laute Kritik und ist leider typisch für die vielen Anhnungslosen unserer Zeit. Selber arbeiten? Nee warum, die Community macht das alles für mich ...
... und Leseverständnis auch mehr als unzureichend, weil die angebene Lsg. wurde erkennbar auch nicht ausprobiert.
Du verwendest 32 Bit Werte in einem Array. Du möchtest im Array durch
Inkrementieren des Pointers den nächsten Wert erreichen.
Ich weiß jetzt nicht, welchen Controller du verwendest aber evtl. musst
du um mehrere Bytes inkrementieren um den Pointer zum nächsten
Array-Element setzen.
... gehe besser was anderes spielen!
Ein Pointer ist Type und Maschinen abhängig und incrementiert entsprechend, also hier bei 8-bit Maschine viermal.
wenn deine Aussagen auch ohne persönliche Angriffe gingen, könnte ich sogar annehmen, dass das hier ein Forum ist, in dem man bei Unklarheiten nachfragen kann -> man kann offensichtlich nicht alles haben. Ich habe von meinem Code nichts kopiert, ich wüsste noch nicht mal, woher. Bei der Einfachheit der Funktionen gäbe es dafür auch keinen Grund
Zur implicit type promotion:
Die Regeln der impliziten Konvertierung besagen, dass im Falle des Falles nach oben konvertiert wird, int zu long zu long long, bzw. von signed zu unsigned.
Jetzt habe ich schon unsigned long, eine Umwandlung kann das System von mir aus auch machen, das war niemals meine Frage, lasse mich aber gerne erklären, warum das relevant ist.
Meine Frage, zur nochmaligen Erklärung, war, warum der Debugger von MPLAB X beim Durchsteppen durch die Funktion beim Funktionseinstieg die jeweilige Adresse für die beiden Argumente anzeigt (und damit auch Werte der Speicherstelle), nach dem ersten Vergleich (bei dem gerne gecasted werden kann, das ist erst in zweiter Linie für meine Frage relevant) aber weder eine Adresse noch ein Wert angezeigt wird (der Debugger zeigt danach nur mehr "out of scope"). Wenn das ein systemimanentes Problem des Debuggers darstellt kann das natürlich so sein. Wenn der Debugger bekanntermaßen immer einwandfrei und anstandslos Variablen anzeigt (ich arbeite normalerweise mit Visual Studio und bin den Debugger dort gewöhnt, verstehe aber die Schwierigkeiten auf einem Mikrocontroller zu debuggen), habe ich, trotz keiner schreibenden Funktionen (ausgenommen die Zuweisung von i für die Schleife) anscheinend etwas, das die Speicherstelle überschreibt.
Dass volatile normalerweise nur bei etwas wie Interrupts benötigt wird, weiß ich, dass const in der Argumentdeklaration vor der Typzuweisung eigentlich die Adresse, aber nicht den Wert, konstant halten sollte (im Unterschied zu const vor dem Argumentnamen), weiß ich ebenfalls. Nach dem wir jetzt das Wettpissen hinter uns gebracht haben, könnte sich vielleicht jemand finden, der einem Entwickler, der normalerweise eher im C# und Visual Studio Umfeld arbeitet und sich erst kurz mit ATmega auseinandersetzt, vernünftig erklärt, warum ich sehe, was ich sehe.
noch ein Nachsatz:
Ich habe COLORDELTA überprüft, das UL hat gefehlt, ich habe es nachgetragen. Es ändert aber immer noch nichts an dem Verhalten, das ich beim Debuggen sehe.
Daher nochmal zur Klarstellung: Mir geht es gerade um eine Aussage über die Zuverlässigkeit von Debugger-Anzeigen, nicht um den direkten Programmablauf.
Du solltest 2-3 freie Pins deines uC nutzen als "Toggle"-Melder.
Mit Scope in Echtzeit verfolgen wo das Programm hinläuft.
Das ist zuverlässiger als Debugger.
danke für die Info. Das mit den Toggle-Pins hatte ich schon gemacht, mich hat "nur" die Anzeige des Debuggers verwirrt. Seit ich weiß, was ich davon erwarten kann, war es deutlich einfacher sich auf das wesentliche zu konzentrieren, 4 Logikfehler zu finden (wäre auch ohne Debugger gegangen, hat mich aber abgelenkt) und das Programm zu einem angenehmen Ende zu bringen. Jetzt muss ich noch an meiner Hardware rundherum basteln und wenn ich besonders verwegen bin, mache ich mich an die Umstellung auf einen ATtiny85 (dafür hatte ich mal eine Platine entworfen, durch den unklaren Programmlauf bin ich auf einen ATmega gegangen, weil ich dort debuggen konnte).
danke fürs Drüberschauen. Die Initialisierung mit -1 ist gleichbedeutend mit 0xFFFF (das Zweierkomplement bei -1 sieht genauso aus) und hat den Vorteil, dass es mit allen uint funktioniert, egal welche Größe.
Solltest die Frage anders stellen: Benutzt hier irgend jemand Pickit4 und XC-8 für ATmega328P?
Wäre auch vorstellbar, die Microchip Entwickler hatten die Pic Tools nur Quick&Dirty auf Amtel Prozessoren portiert. Wollte halt irgendjemand aus der Marketingabteilung. Ist nur noch nicht aufgefallen, weil die AVR Programmierer bei ihren alten Tools bleiben.
Benutzt hier irgend jemand Pickit4
und XC-8 für ATmega328P?
MPLab Snap (was im wesentlichen ein abgespecktes Pickit4 ist) funktioniert mit Microchip Studio ganz wunderbar mit Atmega328p, egal, welchen C-Compiler man nun verwendet, den kastrierten XC-8 oder den freien gcc. Beide werden mit Microchip Studio mitgeliefert.
es kann sein, dass der Compiler so viel optimiert dass der Debugger damit nicht mehr klar kommt. Dann kann man folgenden Trick verwenden, im main machst du per Hand ein paar Testfälle und schaust dir die Variablen dann an:
volatile int current_TC1 = -1;
volatile int expected_TC1 = 1;
volatile int result_TC1 = -1; //Not executed yet
volatile int current_TC2 = -1;
volatile int expected_TC2= 0;
volatile int result_TC2 = -1; //Not executed yet
volatile int current_TC3 = -1;
volatile int expected_TC3 = 0;
volatile int result_TC3 = -1; //Not executed yet
volatile int current_TCn = -1;
volatile int expected_TCn = 1;
volatile int result_TCn = -1; //Not executed yet
Die Initialisierung mit -1 ist gleichbedeutend
mit 0xFFFF (das Zweierkomplement bei -1 sieht genauso aus) und hat den
Vorteil, dass es mit allen uint funktioniert, egal welche Größe.