Forum: Mikrocontroller und Digitale Elektronik STM32L431 Grund für Reset herausfinden.


von technikus (Gast)


Lesenswert?

Hallo Forum,

ich bin STM32 Einsteiger und erstelle mein erstes Projekt.
Zuvor habe ich alle nötigen Module portiert und einige öffentliche 
Quellen genutzt die ich bereits in der AVR Welt eingesetzt habe 
(Scheduler, Tastenentprellung, IRMP, u8g2 Grafik Display Lib etc.).

Entwicklungsumgebung ist Visual GDB in aktueller Version.
HAL, kein RTOS.

Im Projektierungsverlauf führt der STM32 nun sporadisch einen Reset aus.

Ich habe auch bereits einen Code Block ausfindig gemacht. Wenn dieser 
auskommentiert wird, tritt der Fehler nicht auf.
Der Code Block für sich ist aber lauffähig und nicht allein ursächlich 
für den Reset. Der Fehler tritt dann irgendwann später (mal nach 10 
Sekunden, mal nach 3 Minuten) auf.
Letztendlich lösche ich nach abgelaufener Zeit einmalig das Display.
Diese Funktion wird ein dutzend mal an anderen Programmstellen 
aufgerufen.

Ich habe bereits eine Hard Fault Funktion hinzugefügt und einen break 
Point gesetzt. Der BP wird allerdings vorm Reset nicht angesprungen.

Nach google und Forumssuche ist mir nicht klar, wie man hier am besten 
systematisch vorgeht. Ich habe bereits viele Stunden damit verbracht 
auszuschließen und komme nicht weiter.

Ich wäre euch für Unterstütz sehr dankbar.

Gruß
Stefan

von pegel (Gast)


Lesenswert?

Stack zu klein?
In der *.ld einfach mal vergrößern und probieren.

von (Gast)


Lesenswert?

Aufbau der Hardware ist vernünftig?
Stromversorgung stabil?
Eventuell Watchdog aktiviert?

Ich finds geschickter bei der Fehlersuche im Hardfault-Handler oder auch 
bei fehlgeschlagenen asserts direkt einen "bkpt" Befehl auszuführen, das 
verschwendet keine Debug-Resourcen und schlägt immer an.

von Bauform B. (bauformb)


Lesenswert?

Nach einem Reset steht im RCC_CSR Register was den Reset ausgelöst hat, 
also ob der von draußen kam oder vom Watchdog oder wegen Brown Out 
oder... Siehe RM0394 Kapitel Reset and clock control (RCC).

von technikus (Gast)


Lesenswert?

Hi,

danke für die Tipps!
Den Stack werde ich gleich mal vergrößern.

Der Hardfault Handler wird vor dem Reset lt. gesetztem Break Point nicht 
aufgerufen.

Die Stromversorgung ist stabil.
Der Controller geht nicht in den Reset wenn der entsprechende Codeblock 
auskommentiert ist.

Fas Problem ist, dass die St Link Schnittstelle auch abschmiert. So kann 
ich kein entsprechendes Register lesen.
Wenn ich dann eine neue Debug Session starte wird das Programm erneut 
übertragen und der Controller gezielt resettet.
Dann ist die die Reset Quelle Soft Reset.

Watchdog und Brown Out nutze ich nicht.


Stefan

von technikus (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal ein Screenshot vom Debuggen nach Reset

von technikus (Gast)


Lesenswert?

Zum Codeteil der verantwortlich für den Reset ist:

Aufruf 1x pro Sekunde
1
void display_OffTimer(void)
2
{
3
  if (state.displayTime > 0)
4
  {
5
    state.displayTime--;
6
7
    if ((parameter.display.offTime != 0) && (state.displayTime == 0))
8
    {
9
      SET(state.flags, 4);      
10
    }
11
  }
12
  schedule_Remove(display_OffTimer);
13
  schedule_Add(display_OffTimer, SECONDS(1));
14
}

Das flag mit der (testweise) Magic Number wird in der Hauptschleife 
ausgewertet.

1
while(1)
2
{
3
4
if (READ(state.flags, 4))
5
    {
6
      CLR(state.flags, 4);
7
      display_Off(&display, READ(parameter.display.flags, DISP_FLAG_OFFSYMBOL));
8
      
9
    }
10
11
}

- state ist volatile
- parameter.display.offTime ist ein Parameter der nach Init aus einem 
EEPROM gelesen und in einem User Menu editiert und ins EEPROM 
geschrieben wird
- wenn parameter.display.offTime den Wert 0 hat bzw. wenn das Flag nicht 
geschreiben wird oder Display_Off nicht aufgerufen wird, kommt es nicht 
zum Reset.


Vereinfachte Funktion (normalerweise mit Auswertung value, allerdings 
besteht der Fehler auch so)
1
void display_Off(u8g2_t *display, uint8_t value)
2
{
3
  
4
  
5
  u8g2_ClearDisplay(display);
6
  
7
}

von Jim M. (turboj)


Lesenswert?

technikus schrieb:
> Der Hardfault Handler wird vor dem Reset lt. gesetztem Break Point nicht
> aufgerufen.

Und der break Point war auf der allerersten Instruktion im Disassembly?

Ich frage das weil ein komplexer Handler gerne mal versucht was auf den 
Stack zu pushen. Was schief geht wenn SP ungültig ist -> Lockup. Lockup 
ist in vielen µC Designs mit Reset verkoppelt.

technikus schrieb:
> Wenn ich dann eine neue Debug Session starte wird das Programm erneut
> übertragen

Dieses Verhalten sollte man abstellen können. Ist bei Eclipse ein Haken 
in der Debug Konfiguration.

technikus schrieb:
> Display_Off nicht aufgerufen wird

Mach da mal einen Haltepunkt rein und schau Dir den display Pointer 
genau an.

Wenn der auf den flaschen Speicherbereich zeigt, kann der durchaus den 
Stack durcheinander bringen. Was zu o.g. Problem mit Fault und kaputten 
Stack Pointer führt...

von technikus (Gast)


Lesenswert?

Folgendes probiert. Dabugging Option umgestellt damit das Programm nicht 
erneut übertragen wird und folgende Funktion aufgerufen:
1
uint8_t get_system_reset_cause(void)
2
{
3
  uint8_t reset_cause = 0;
4
  if (__HAL_RCC_GET_FLAG(RCC_FLAG_LPWRRST))
5
  {
6
    reset_cause = 1;//"LOW_POWER_RESET";
7
  }
8
  else if (__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST))
9
  {
10
    reset_cause = 2;//"WINDOW_WATCHDOG_RESET";
11
  }
12
  else if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST))
13
  {
14
    reset_cause = 3;//"INDEPENDENT_WATCHDOG_RESET";
15
  }
16
  else if (__HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST))
17
  {
18
    reset_cause = 4;//"SOFTWARE_RESET";    // This reset is induced by calling the ARM CMSIS `NVIC_SystemReset()` function!
19
  }
20
  //  else if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORTRST))
21
  //  {
22
  //    RCC_FLAG_
23
  //    reset_cause = "POWER-ON_RESET (POR) / POWER-DOWN_RESET (PDR)";
24
  //  }
25
    else if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST))
26
  {
27
    reset_cause = 5;//"EXTERNAL_RESET_PIN_RESET";
28
  }
29
  // Needs to come *after* checking the `RCC_FLAG_PORRST` flag in order to ensure first that the reset cause is 
30
  // NOT a POR/PDR reset. See note below. 
31
  else if(__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST))
32
  {
33
    reset_cause = 6;//"BROWNOUT_RESET (BOR)";
34
  }
35
  else
36
  {
37
    reset_cause = 7;// "UNKNOWN";
38
  }
39
  // Clear all the reset flags or else they will remain set during future resets until system power is fully removed.
40
      __HAL_RCC_CLEAR_RESET_FLAGS();
41
  
42
  return reset_cause; 
43
}


Nach einem Reset den Debugger angeworfen und die Funktion hat eine 5 
zurück gegeben (RCC_FLAG_PINRST).

Das verwirrt mich jetzt total. Daraufhin habe ich Datenblatt und Layout 
überprüft. Ich habe am NRST lediglich einen 100nF gegen Masse. Keine 
Lötbrücke, kein Layoutfehler.

Kann jemand etwas mit der Erkenntnis anfangen?

von Bauform B. (bauformb)


Lesenswert?

technikus schrieb:
1
else if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST))
2
   {
3
     reset_cause = 5;//"EXTERNAL_RESET_PIN_RESET";
4
   }
5
   // Needs to come *after* checking the `RCC_FLAG_PORRST` flag in order 
6
 to ensure first that the reset cause is
7
   // NOT a POR/PDR reset. See note below.
8
   else if(__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST))
9
   {
10
     reset_cause = 6;//"BROWNOUT_RESET (BOR)";
Demnach könnte es doch auch ein BOR gewesen sein?
Oder sogar ein POR? Weil das Flag nicht getestet wird?
Von wem stammt eigentlich der Kommentar "Needs..."?

Am einfachsten fände ich es, das komplette Register als 32 Bit Wort 
auszugeben.

von Bulimie-code (Gast)


Lesenswert?

technikus schrieb:
> Ich habe am NRST lediglich einen 100nF gegen Masse

Keinen pullup?

von Bauform B. (bauformb)


Lesenswert?

Die STM32 haben einen internen Pullup und ST empfiehlt, keinen externen 
parallel zu schalten.

von technikus (Gast)


Lesenswert?

@Bauform B: Du hast recht! Ich habe einfach blind einen Codeschnipsel 
aus dem Netz genommen. Das BOR FLAG ist nach einem Reset auch gesetzt...

von technikus (Gast)


Lesenswert?

Tatsächlich hatte die Brwon Out Detection zugeschlagen.

Ich habe eine Power Bank verwendet um den Probeaufbau zu programmieren.
Bei Abschalten des Displays, hat die Gesamtschaltung so wenig Strom 
gebraucht, das die Power Bank abgeschaltet hat. Nach einem Controller 
Reset ist wieder genug Strom geflossen damit die Power Bank wieder 
versorgt hat.

Jetzt, am Netzteil, läuft alles wie gewünscht.

Danke für die Unterstützung, erst recht für den Hinweis alle Flags bei 
der Fehlersuche zu berücksichtigen.


Gruß
Stefan

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.