Hallo zusammen,
ich möchte das erste Mal ein Projekt mit einem Cortex M4 machen und bin
nun das erste Mal bei einem HardFault Fehler gelandet, bei dem ich
einfach keine Ahnung habe, wie der auftreten kann. Deswegen würde ich
mich über eure Hilfe freuen.
Wie folgt: Ich habe die zwei Komponenten Display und ADC (Projekt soll
später mal ein kleines Messgerät werden). Das ganze soll auf einem SAM4S
Xplaind Pro Board mit einem SAM4SD32C.
Die Main sieht momentan so aus
PMC->PMC_PCER0|=(1<<ID_PIOC);// Aktivieren des Taktes fuer PORT C
22
PIOC->PIO_OER=(1<<23);// PC23 als ausgang ?
23
24
while(1)
25
{
26
27
// Togglt !
28
PIOC->PIO_SODR|=(1<<23);
29
Systick_delayms(1000);
30
PIOC->PIO_CODR|=(1<<23);
31
Systick_delayms(1000);
32
33
}
34
}
Wenn ich die Zeilen für eine Komponente auskommentiere, läuft alles wie
es soll. D.h. einzeln laufen die Codes. Sind beide, wie gezeigt
einkommentiert, so springt der Controller beim Debuggen anstatt in
"init_Systick();" in den HardFault_Handler(). Also interessanterweise
bereits vor den Komponenten in einen Fehler.
Woran könnte das liegen?
Danke für eure Hilfe
Setz Dir nen Breakpoint auf Deinen Hardfault-Handler und guck dann an,
wohin der Stackpointer zeigt. Addier 24 drauf, und Du bekommst die
Adresse, wo er abgeschmiert ist. Damit gehst Du dann ins Mapfile und
weißt, in welcher Funktion das war. Oder Du lädst es in den Debugger und
gehst direkt zu der Adresse, dann siehst Du sogar die Zeile.
In System Control Block bekommst Du noch genauere Auskunft, was
schiefgegangen ist. Sollte in Registern wie SCB_CFSR und SCB_HFSR oder
so stehen.
Was sind die 1000, 10000 und die 1024? Passen die nicht zusammen?
Und wenn die nicht zusammengehören, wie wäre es mit passenden Konstanten
und ein paar Kommentaren dazu, warum genau 1000 gewählt wird.
Noch einfacher:
Nimm den Debugger und geh zunächst über die Funktionen drüber, d.h. daß
die Funktionen ausgeführt werden und der Cursor an der nächsten
Programmzeile rauskommt ("Step over" oder so). Dann wirst du bald
merken, wo er sich verabschiedet. Danach machst du einen Restart und
gehst bis zur nun bekannten Funktion, diesmal aber in die Funktion
hinein ("Step into") und machst das wie vorher ("Step over") Zeile für
Zeile. Damit kannst du die Stelle recht schnell eingrenzen. Wenn diese
dann bekannt ist kannst du nochmal zur Sicherheit einen Durchgang machen
ob es reproduzierbar ist. Man kann das Steppen abkürzen mit z.B. "Run to
line" oder so im Debugger.
Aus Erfahrung:
Meistens liegt es an einem kaputten Zeiger bzw. Referenz.
PittyJ schrieb:> Was sind die 1000, 10000 und die 1024? Passen die nicht zusammen?>> Und wenn die nicht zusammengehören, wie wäre es mit passenden Konstanten> und ein paar Kommentaren dazu, warum genau 1000 gewählt wird.
1000 ist hier beim initialisieren eine Angabe in Hz, welche Abtastrate
eingestellt werden soll. Die ist natürlich veränderlich.
1024 ist die Anzahl Daten, die der DMA transportieren soll.
Und die anderen einfach Zahlen zur Ausgabe, die erst später eine
vernünftige Bedeutung bekommen, sie sind nur da um zu sehen, ob das
Display sie richtig anzeigt
Mauselicht schrieb:> Noch einfacher:>> Nimm den Debugger und geh zunächst über die Funktionen drüber, d.h. daß> die Funktionen ausgeführt werden und der Cursor an der nächsten> Programmzeile rauskommt ("Step over" oder so). Dann wirst du bald> merken, wo er sich verabschiedet. Danach machst du einen Restart und> gehst bis zur nun bekannten Funktion, diesmal aber in die Funktion> hinein ("Step into") und machst das wie vorher ("Step over") Zeile für> Zeile. Damit kannst du die Stelle recht schnell eingrenzen. Wenn diese> dann bekannt ist kannst du nochmal zur Sicherheit einen Durchgang machen> ob es reproduzierbar ist. Man kann das Steppen abkürzen mit z.B. "Run to> line" oder so im Debugger.>> Aus Erfahrung:> Meistens liegt es an einem kaputten Zeiger bzw. Referenz.
Wie ich oben schrieb: Der Debugger zeigt, dass der HardFault dann
auftritt, wenn der Controller versucht in die Funktion init_Systick zu
springen. Also taucht der Fehler schon auf, bevor die neu
einkommentierten Codezeilen kommen und das verstehe ich nicht. Denn mit
nur einer Komponente drin, geht die Funktion ja. Ich verstehe halt
nicht, wie sich dann die zweite Komponente auf diese schon vorher
abgearbeitete Funktion auswirken kann
Nop schrieb:> Setz Dir nen Breakpoint auf Deinen Hardfault-Handler und guck dann> an,> wohin der Stackpointer zeigt. Addier 24 drauf, und Du bekommst die> Adresse, wo er abgeschmiert ist. Damit gehst Du dann ins Mapfile und> weißt, in welcher Funktion das war. Oder Du lädst es in den Debugger und> gehst direkt zu der Adresse, dann siehst Du sogar die Zeile.>> In System Control Block bekommst Du noch genauere Auskunft, was> schiefgegangen ist. Sollte in Registern wie SCB_CFSR und SCB_HFSR oder> so stehen.
Werde ich bei Gelegenheit mir anschauen und dann ggf. hier zeigen
Nop schrieb:> Mauselicht schrieb:>> Noch einfacher:>> Geht nicht, wenn das in einem Interrupt oder DMA-Routine abschmiert.> Deswegen Hardfault-Handler, das geht immer.
Es war ja auch gesagt, daß es einzeln lauffähig ist. Und noch besser,
wie nun beschrieben, sogar schon bei der Initialisierung danebengeht.
M. W. schrieb:>> Aus Erfahrung:>> Meistens liegt es an einem kaputten Zeiger bzw. Referenz.>> Wie ich oben schrieb: Der Debugger zeigt, dass der HardFault dann> auftritt, wenn der Controller versucht in die Funktion init_Systick zu> springen.
Wenn das reproduzierbar ist solltest du das mit meiner Methode dort auch
schnell auffinden.
> Also taucht der Fehler schon auf, bevor die neu> einkommentierten Codezeilen kommen und das verstehe ich nicht. Denn mit> nur einer Komponente drin, geht die Funktion ja. Ich verstehe halt> nicht, wie sich dann die zweite Komponente auf diese schon vorher> abgearbeitete Funktion auswirken kann
Aber das zeigt doch, daß etwas mit dem Speicher schiefgeht, also z.B. in
der Instantiierung deiner Funktionen oder eher daß deine Funktionen
falsch in den Speicher abgebildet werden.
Mach mal so wie ich beschrieben habe. Geht am unkompliziertesten,
pragmatisch, ohne viel Gefrickel.
Btw: Falls nicht zu groß wäre vielleicht etwas Einblick in deine
Funktionen hilfreich.
Nop schrieb:> Setz Dir nen Breakpoint auf Deinen Hardfault-Handler und guck dann an,> wohin der Stackpointer zeigt. Addier 24 drauf, und Du bekommst die> Adresse, wo er abgeschmiert ist. Damit gehst Du dann ins Mapfile und> weißt, in welcher Funktion das war. Oder Du lädst es in den Debugger und> gehst direkt zu der Adresse, dann siehst Du sogar die Zeile.
Ähhm,
wenn du bei einem Hardfault mehr als 'bt' eintippen/anklicken musst,
hast du deine IDE/Debugger/etc falsch/unvollständig konfiguriert..
Mauselicht schrieb:> Nimm den Debugger und geh zunächst über die Funktionen drüber,
Wenn der Controller eine Pipeline in der CPU hat, dann kann es auch
passieren, dass der HardFault im Debugger auftritt, wenn du schon in
einer Zeile nach dem kritischen Befehl bist.
M. W. schrieb:> Sind beide, wie gezeigt> einkommentiert, so springt der Controller beim Debuggen anstatt in> "init_Systick();" in den HardFault_Handler(). Also interessanterweise> bereits vor den Komponenten in einen Fehler.
Das Zeuchs sieht wie C++ aus. Könnte das eine große Menge Speicher
versuchen auf dem Stack anzulegen?
Denn bei einem Stack Overflow in main() funktionieren Funktionsaufrufe
nicht mehr richtig.
Ein Hinweis wäre auch der Wert im Stack Register, den man innerhalb des
HardFault Handlers per Debugger ausliest.
640 kByte free! schrieb:> wenn du bei einem Hardfault mehr als 'bt' eintippen/anklicken musst,> hast du deine IDE/Debugger/etc falsch/unvollständig konfiguriert..
Denk mal nach: meinst Du, der OP hätte diese Frage dann gepostet? Und
was hilft dem OP wohl mehr: ihm zu sagen, was er klicken muß, oder ihm
den Mechanismus dahinter nahezubringen? Den Mechanismus, mit dem er dann
auch ein Logging oder einen Bluescreen implementieren könnte, wenn die
IDE nicht am Gerät hängt?
Jim M. schrieb:> M. W. schrieb:>> Sind beide, wie gezeigt>> einkommentiert, so springt der Controller beim Debuggen anstatt in>> "init_Systick();" in den HardFault_Handler(). Also interessanterweise>> bereits vor den Komponenten in einen Fehler.>> Das Zeuchs sieht wie C++ aus. Könnte das eine große Menge Speicher> versuchen auf dem Stack anzulegen?>> Denn bei einem Stack Overflow in main() funktionieren Funktionsaufrufe> nicht mehr richtig.>> Ein Hinweis wäre auch der Wert im Stack Register, den man innerhalb des> HardFault Handlers per Debugger ausliest.
Ja, soll C++ werden. Zugegebenermaßen war ich bis jetzt auch eher mit C
und halt kleineren Controllern unterwegs. Hier wollte ich mal die
Objektorientierung von C++ mit ausnutzen. Das ganze übersteigt aber
scheinbar gerade noch meine Fähigkeiten.
Ich kann mir gut vorstellen, dass der Stack zu viel aufgedrückt bekommen
hat. Jetzt dachte ich, ich kann die Objekte ja eigentlich auch außerhalb
von main anlegen und dann nur dort initialisieren und hab es nun wie
folgt umgeschrieben
PMC->PMC_PCER0|=(1<<ID_PIOC);// Aktivieren des Taktes fuer PORT C
26
PIOC->PIO_OER=(1<<23);// PC23 als ausgang ?
27
28
while(1)
29
{
30
31
// Togglt !
32
PIOC->PIO_SODR|=(1<<23);
33
Systick_delayms(1000);
34
PIOC->PIO_CODR|=(1<<23);
35
Systick_delayms(1000);
36
37
}
38
}
Leider führt das zu den neuen Fehlern im Bild "Fehlerliste.png". Die
dazu gefunden google Sucheinträge helfen mir leider nicht weiter bzw
verstehe ich sie nicht ganz. Kann mir jemand die Fehler erklären und
sagen, wie sie weg gehen?
Danke für eure Hilfe für einen Neuling im Bereich Cortex-M/größerer
Controller
M. W. schrieb:> Danke für eure Hilfe für einen Neuling im Bereich Cortex-M/größerer> Controller
Das hat mit Cortex-M/größerer Controller rein garnix zu tun. Nur damit,
dass du nichtmal deine Werkzeuge beherrschst. Das läßt Schlimmes für die
Sprache ahnen...
Kenne ich so ähnlich mit "undefined reference to '__sbrk'". Hatte ich in
C auch schon. Das kam von einer Benutzung von printf() oder einem
Derivat davon. Sicherlich in deiner Displayfunktion. Der Linker findet
die dazu notwendige binäre Lib nicht. Die Lösung bestand darin, eine
Quelldatei einer Minilib mit einem eigenen printf() oder miniprintf()
oder so ähnlich einzubinden. Bei dir sind aber auch mehrere Funktionen
in Benutzung, die der "ld" nicht findet. Prüfe erstmal die Pfade des
Linkers und ob du überhaupt eine entsprechende Lib oder Libc an Bord
hast oder kommentiere erstmal die Lib-Aufrufe raus.
Es ist auch eine ganz nette Fingerübung den HardFault Handler selber zu
füllen mit einem Registerdump.
(Zusätzlich auch die anderen zu aktivieren und zu nutzen)
Im System Control Block gibts zudem noch Register die genauer
beschreiben warums geknallt hat.
Hier schön beschrieben:
www.keil.com/appnotes/files/apnt209.pdf
c-hater schrieb:> M. W. schrieb:>>> Danke für eure Hilfe für einen Neuling im Bereich Cortex-M/größerer>> Controller>> Das hat mit Cortex-M/größerer Controller rein garnix zu tun. Nur damit,> dass du nichtmal deine Werkzeuge beherrschst. Das läßt Schlimmes für die> Sprache ahnen...
ja, dsa mag sein. Ich bin eher der Hardware-Mensch und bis jetzt sind
mir solche Fehler halt noch nicht aufgetreten und deswegen habe ich auch
kein wissen darüber
Mauselicht schrieb:> Kenne ich so ähnlich mit "undefined reference to '__sbrk'". Hatte> ich in> C auch schon. Das kam von einer Benutzung von printf() oder einem> Derivat davon. Sicherlich in deiner Displayfunktion. Der Linker findet> die dazu notwendige binäre Lib nicht. Die Lösung bestand darin, eine> Quelldatei einer Minilib mit einem eigenen printf() oder miniprintf()> oder so ähnlich einzubinden. Bei dir sind aber auch mehrere Funktionen> in Benutzung, die der "ld" nicht findet. Prüfe erstmal die Pfade des> Linkers und ob du überhaupt eine entsprechende Lib oder Libc an Bord> hast oder kommentiere erstmal die Lib-Aufrufe raus.
printf() oder ähnliches nutze ich gar nicht.
Wie prüfe ich denn die Pfade des Linker in Atmel Studio 7 und was müsste
ich da finden? ich kenne mich damit tatsäcglich gar nicht aus. Bei
meinen kleineren Projekten bis jetzt musste ich mich darum immer nicht
kümmern, da haben die Standardeinstellungen ausgereicht
Oh es geht jetzt!!!
Ich habe bei den ganzen Projekt einstellungen Unter ARM/GNU Linker ->
General -> Additional Specs auf "Use Syscall Stubs
(--specs=nosys.specs)" gestellt. Dann kam nur noch ein "undefined
reference to end"
nach
http://ww1.microchip.com/downloads/en/DeviceDoc/Frequently-Asked-Questions-4.9.3.26.txt
scheint das noch ein Problem mit der Speicherbereichszuweisung zu sein.
Aus dem Linker Skript habe ich dann vor dem end den _ entfernt und es
ging