Forum: Mikrocontroller und Digitale Elektronik STM32F446- C Programmierung - unerwartetes springen in Infinite Loop


von Jannik H. (erano1)


Lesenswert?

Hallo,

ich arbeite mich gerade mit einem STM32F446 in die 
Microcontrollerprogrammierung in C ein. Aktuell schreibe ich einfache 
Interrupts, was auch funktioniert, bin hierbei aber auf ein, für mich, 
unerwartetes Verhalten gestoßen.
1
GPIO_PinConfig_t gpioa_config_5   = {GPIO_PIN_NO_5, GPIO_MODE_OUT, GPIO_LOW_SPEED, GPIO_PU,GPIO_OP_TYPE_PP,GPIO_AF5};
2
  GPIO_Handle_t gpioa_handle_5     = {(uint32_t*)(GPIOA_BASEADDR),gpioa_config_5};
3
4
  GPIO_PinConfig_t gpioc_config_13   = {GPIO_PIN_NO_13, GPIO_MODE_IT_FT, GPIO_LOW_SPEED, GPIO_PU,GPIO_OP_TYPE_PP,GPIO_AF5};
5
  GPIO_Handle_t gpioc_handle_13     = {(uint32_t*)(GPIOC_BASEADDR),gpioc_config_13};
6
7
  GPIO_PinConfig_t gpiob_config_2   = {GPIO_PIN_NO_2, GPIO_MODE_IT_FT, GPIO_LOW_SPEED, GPIO_PU, GPIO_OP_TYPE_PP,GPIO_AF5};
8
  GPIO_Handle_t gpiob_handle_2     = {(uint32_t*)(GPIOB_BASEADDR),gpiob_config_2};
9
    
10
11
  GPIO_Init(&gpioa_handle_5);
12
  GPIO_Init(&gpiob_handle_13);
13
  GPIO_Init(&gpioc_handle_2);

An Port A hängt eine LED, an C Pin 15 ein Taster und B Pin 2 soll über 
Kabel den Input auf GND ziehen. Durch C15 und B2 soll jeweils ein 
Interrupt ausgelöst werden und die LED zum blinken bringen, was auch 
funktioniert.

Allerdings springt das Programm in den Default Handler(Infinite Loop) 
nach Init von Port C  wenn:
1.
1
 GPIO_Init(&gpioa_handle_5);
2
      GPIO_Init(&gpioc_handle_13);
3
      GPIO_Init(&gpiob_handle_2);
Die Reihenfolge der Initalisierung von Port B und C vertauscht wird.


2.
Init von Port B gar nicht verwendet wird, aber der struct vorher 
trotzdem für Port B drin ist.

Wird die Iinitalisierung des structs auskommentiert, funktioniert das 
Programm alleine mit Port C wieder wie erwartet.


Kann mir jemand erklären, wieso zum einen die Reihenfolge  eine Rolle zu 
spielen scheint, in der die Funktion GPIO_Init jeweils für Port B und C 
ausgeführt werden und zum anderen, wieso das nicht initialisieren von 
gpiob_handle_2 wieder dazu führt, dass für den Port C das Programm nicht 
abstürzt?

von Thilo (Gast)


Lesenswert?

Hi Jannik,

ohne eine wirklich brauchbare Antwort parat zu haben, kann ich dir 
sagen, dass ich vor einiger Zeit ähnliche Symptome in meinem STM-based 
SDR radio hatte. Irgendwann hing sich das Programm auf, was genauer 
betrachtet einfach nur das Anspringen des Default Interrupt Handlers 
(mit siener endless loop) war. Letztlich hatte ich es versäumt, den 
korrekten (meinen eigenen) Interrupt Handler in die Int Table 
einzutragen. Das hatte ich durch das Lesen der Listings für die 
entsprechenden Module rausgefunden, dort stand noch der Default Handler 
drinne.

Ansonsten denke ich (noch) nicht unbedingt, dass es wirklich und 
wahrhaftig nur von der Reihenfolge der GPIO_Init-Routinen abhängt (lasse 
mich aber gerne vom Gegenteil überzeugen), vielleicht ist es einfach nur 
ein Timing Issue, bedingt durch das zitierte Kabel an dem einen Eingang, 
das evtl. nicht auf einem definierten Pegel liegt, sondern in der Luft 
hängt.

Suche auf jeden Fall mal weiter in Richtung "korrekt aufgesetzte 
Interrupt Handler". Viel Erfolg!

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Löst ein Interrupt aus während du noch initialisierst ?
Wessen Defaulthandler ? Welcher Interrupt genau löst aus ?

von HP (Gast)


Lesenswert?

Da wird wohl ein Hardfault ausgeloest.
Irgendwo ist Murx in deinem Brogramm.

von Thilo (Gast)


Lesenswert?

Neee,die Routinen-Bezeichnung im Debugger (Hard fault Handler) ist hier 
etwas irreführend. Tatsächlich sind eben alle nicht benutzten 
Interrupt-Vektoren mit einem Sprung zu diesem Default Handler versehen, 
um ein kontrolliertes verhalten zu erreichen. Es ist aber m.E. sehr 
wahrscheinlich einfach nur ein nicht initialisierter, jedoch 
getriggerter Interrupt.

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Im Interrupt Control and State Register oder HardFault Status Register 
sollte das lesbar sein. Die Adresse des Auslösens existiert dann 
entweder auf dem Stack oder in einem seperaten Register.

von Thilo (Gast)


Lesenswert?

Nochmal neee: die Int-Vektoren werden per Jump genutzt und nicht per 
Call. Also steht nirgendwo eine Return-Adresse. Es bleibt einzig das 
auslösende Int Flag. Aber natürlich ist das gesetzt/aktiv, hilft aber 
nicht wirklich dabei, herauszufinden, warum nicht der eigene Int 
Handler, sondern der Default Int Handler genommen wird.

Man hört gar nichts mehr vom OP? Hat er das Problem evtl. schon in 
Eigenregie gelöst und lässt uns hier sinnlos weiter philosophieren? :-)

Wenn ja: lieber OP: dann teile doch Deinen Fehler - und die 
Lösungsfindung - hier mit, damit evtl. auch Andere davon profitieren 
können!

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Erstmal rausfinden was auslöste.

Die Adresse bei der Unterbrochen wurde steht im Stack (autom. stacking 
R0-R3,R12,LR,PC,PSR).
Welcher Interrupt auslöste steht im IPSR. Im LR steht ein Spezialwert 
fürs unstacking.
Beim Hardfault gibt es dies Adresse auch auf dem Stack und der Rest 
steht im NVIC im HFSR.

: Bearbeitet durch User
von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Sind die GPIO-Einheiten alle an ?
"GPIO_PeriClockControl"

von Nop (Gast)


Lesenswert?

Thilo schrieb:
> Nochmal neee: die Int-Vektoren werden per Jump genutzt und nicht
> per Call. Also steht nirgendwo eine Return-Adresse.

Quatsch - wie sollte der Controller nach dem Interrupt denn dann da 
weitermachen, wo er vor dem Interrupt war? Natürlich gibt's irgendwo 
eine Return-Adresse.

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Nop schrieb:
> Thilo schrieb:
>> Nochmal neee: die Int-Vektoren werden per Jump genutzt und nicht
>> per Call. Also steht nirgendwo eine Return-Adresse.
>
> Quatsch - wie sollte der Controller nach dem Interrupt denn dann da
> weitermachen, wo er vor dem Interrupt war? Natürlich gibt's irgendwo
> eine Return-Adresse.

Und die liegt im 8x4er Packet auf dem Stack.

Ich vermute mal weil er (Thilo) im LR nix brauchbares finden konnte.
Das wäre dann eine ARMv4.

Ich empfehle mal die Bibel schlechthin
"The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors"
von Joseph Yiu

: Bearbeitet durch User
von Jannik H. (erano1)


Lesenswert?

Vielen Dank vorab für die vielen Beiträge :)

@Thilo,
Zumindest kann durch das reine Wechseln der Reihenfolge dieses Verhalten 
getriggert oder auch behoben werden. Der Pin ist auf wird durch Pull Up 
auf High gezogen. Habe es auch mit anderen Pins, sollte also auch nicht 
an einen Defekt liegen.

@ Dennis. H

Also zumindest kein gewollter. Beim debuggen wird 
GPIO_Init(&gpioc_handle_2); noch ausgeführt, aber im nächsten Step 
landet man in der Infinite Loop.


Von Dennis H:
"Erstmal rausfinden was auslöste.

Die Adresse bei der Unterbrochen wurde steht im Stack (autom. stacking
R0-R3,R12,LR,PC,PSR).
Welcher Interrupt auslöste steht im IPSR. Im LR steht ein Spezialwert
fürs unstacking.
Beim Hardfault gibt es dies Adresse auch auf dem Stack und der Rest
steht im NVIC im HFSR."

Das werde ich mir mal ansehen, kann durch das debuggen, wie oben 
brereits erwähnt nicht erkennen, durch was der Interrupt ausgelöst wird.

"Sind die GPIO-Einheiten alle an ?
"GPIO_PeriClockControl"

Ja, da ist alles in Ordnung. B und C funktionieren ja unabhängig 
voneinander. Der Fall für B,C auch, wenn zuerst b initialisiert wird und 
dann c. Die Frage ist was z.B. das wechseln der Reihenfolge verändern 
könnte.

: Bearbeitet durch User
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
Noch kein Account? Hier anmelden.