Mahlzeit, ich habe ein Problem mit XOR unter Keil MDK-ARM 3.80a mit einem Cortex LPC1768. Ich würde gerne in dem Register LPC_GPIO1->FIOPIN das Bit 28 toggeln. LPC_GPIO1->FIOPIN ^= (1<<28); -> funktioniert leider nicht. LPC_GPIO1->FIOPIN &= ~(1<<28); -> löschen geht aber LPC_GPIO1->FIOPIN |= (1<<28); -> setzen geht auch Im Anhang seht ihr noch den passenden AssemblerCode zu den obigen drei Zeilen. Für mich sieht das eigentlich alles i.O. aus. Jemand eine Idee?
Da stimmt einiges nicht. Bist du sicher, dass Disassembly und Quellcode synchron sind? Dass der Disassembly-Code tatsächlich zum gezeigten Quellcode gehört? Beispielsweise fängt der Interrupt-Handler mit einem Return an. Wenn 0x31C tatsächlich der Einstieg in den Interrupt-Handler ist, dann ist der Rest hinter dem Befehl "BX lr" nur Makulatur. Und dieser Rest ist ebenfalls kompletter Bockmist.
Kann es sein, das die register nicht richtig definiert sind, vermutlich fehlt da ein sehr sehr wichtiges schlüsselwort "volatile"? oder das der code zu stark optimiert wird vom kompiler? hast du die register selber definiert, oder sind die von kail definiert worden? (code posten wenn du es selber gemacht hast) für die erste operation wird ein ldr durchgeführt, aber kein str. Das ergebnis wird nicht in die HW zurückgeschrieben. für die 2. operation wird wieder ausgelesen, und das ergebnis auch wieder zurückgeschrieben. für die 3. Operation, dein xor, wird der startwert von der 2. bzw 1. operation genommen, und verknüpft und auf die hw zurückgeschrieben. Ich vermute, das daher das komische verhalten herkommt, das du beobachtest. das heist, wen bei deimen xor die led wieder ausgehen sollte, aber anbleibt, könnte das durchaus zu dem ASM code passen. wenn vorher die LED aus war.
Michael Graf schrieb:
> für die erste operation wird ein ldr durchgeführt, aber kein str.
Yep, aber ein PC-relativer LDR, womit totsicher nicht der Port
angesprochen wird.
Das müsste doch eigentlich ein THAMB 2 Befehlssatz sein, von daher weiss ich nicht, wie die genau addressieren. Beim ARM Befehlssatz wird normalerweiserelativ addresiert. zumindest hab ich so komische relative sachen zum pc schon öfter gesehen. ok die ziehlposition sieht etwas komisch aus. 0x0000051C sieht nicht nach hw aus, eher nach selbst definierter datenstruktur. daher warscheinlich der volatile fehler.
Michael Graf schrieb: > Beim ARM Befehlssatz wird normalerweiserelativ addresiert. zumindest hab > ich so komische relative sachen zum pc schon öfter gesehen. Klar, aber was rauskommt wenn man zum Wert des PC 508 addiert steht ja rechts daneben. Nämlich 0x51C. Und das liegt definitiv nicht im I/O-Bereich, dazu muss ich nichtmal ins Datasheet schauen. > nach hw aus, eher nach selbst definierter datenstruktur. Yep, das könnte die Ursache sein. Aber dafür gibt's bei den CM3 das CMSIS, muss man anders als bei den ARM7 nicht mehr selber machen.
Also das BX lr gehört sicher noch zur vorherigen Funktion. Die Zuordnung von Assembler Instruktionen zu C Code hat seine Grenzen. Insbesondere wenn Optimierung im Spiel ist. Die PC-relative Adressierung greift mit Sicherheit auf die Adresse des Registers zu. Stichwort: literal pool. Wenn wir mal einen größeren Ausschnitt des Programms sehen könnten (inklusive des pools), dann wäre das sicherlich hilfreich. Außerdem verwirrt die gemischte Darstellung mehr als sie hilft, den Code zu verstehen. Haben wir ja bereits gemerkt :-) Bei diesem Zugriff scheint aber etwas schiefzugehen. Es scheint als würde eine Stufe der Indirektion vergessen. Vorausgesetzt, es handelt sich bei den Strukturen tatsächlich um die entsprechenden GPIO, bzw. SCB Register. Bei mir heißen die etwas anders (MDK ARM 3.70). Gruß Marcus http://www.doulos.com/arm/
Marcus Harnisch schrieb: > Die PC-relative Adressierung greift mit Sicherheit auf die Adresse des > Registers zu. Stichwort: literal pool. Gib mit mal einen Tip, wie du einen C Compiler dazu bringst, eine Adresse mit |= zu verzieren, ohne dass er dich mit Fehler abwirft. Würde mich aber auch sehr interessieren, wie er den Compiler dazu dressiert hat, einen derart schrägen Code zu produzieren.
Marcus Harnisch schrieb: > Also das BX lr gehört sicher noch zur vorherigen Funktion. Die Zuordnung > von Assembler Instruktionen zu C Code hat seine Grenzen. Insbesondere > wenn Optimierung im Spiel ist. Wohl wahr. Aber die exakte Funktionsadresse sollte eigentlich schon kennen, egal wie super er optimiert. Nö, ich glaube da erst einmal garnix mehr, das ist einfach zu hirnrissig was da steht.
So, es gibt neue Erkenntnisse! Wie Marcus schon richtig festgestellt hat, gehört das Return BX lr zu vorigen Funktion. Synchronität sucht man wohl vergebens. Scheinbar ist es die Laufzeit der ISR die hier Probleme macht. void EINT0_IRQHandler(void) { LPC_GPIO1->FIOPIN ^= (1<<28); LPC_SC->EXTINT |= (1<<1); } Verlängere ich die Laufzeit der ISR durch eine Countervariable, die ich einfach hochzähle... void EINT0_IRQHandler(void) { LPC_GPIO1->FIOPIN ^= (1<<28); LPC_SC->EXTINT |= (1<<1); irq_counter++; } funktioniert das Toggeln.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.